diff --git a/.gitignore b/.gitignore index e0d53d8..a73dd02 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .gradle .idea build +test-server/ \ No newline at end of file diff --git a/src/main/java/com/extendedclip/deluxemenus/config/DeluxeMenusConfig.java b/src/main/java/com/extendedclip/deluxemenus/config/DeluxeMenusConfig.java index 63a3235..5b1a553 100644 --- a/src/main/java/com/extendedclip/deluxemenus/config/DeluxeMenusConfig.java +++ b/src/main/java/com/extendedclip/deluxemenus/config/DeluxeMenusConfig.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.function.BiConsumer; import java.util.logging.Level; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -35,6 +36,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.banner.PatternType; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -667,7 +669,7 @@ public void loadMenu(FileConfiguration c, String key, boolean mainConfig) { } final int updateInterval = c.getInt(pre + "update_interval", 10); - builder.updateInterval(updateInterval > 1 ? updateInterval : 10); + builder.updateInterval(updateInterval > 0 ? updateInterval : 10); Map> items = loadMenuItems(c, key, mainConfig); @@ -734,6 +736,8 @@ private Map> loadMenuItems(FileConfiguration continue; } + checkForDeprecatedItemOptions(c.getConfigurationSection(currentPath), name); + MenuItemOptions.MenuItemOptionsBuilder builder = MenuItemOptions.builder() .material(material) .baseColor(Optional.ofNullable(c.getString(currentPath + "base_color")) @@ -1092,13 +1096,14 @@ private RequirementList getRequirements(FileConfiguration c, String path) { continue; } - RequirementType type = RequirementType.getType(c.getString(rPath + ".type")); + String stringType = c.getString(rPath + ".type"); + RequirementType type = RequirementType.getType(stringType); if (type == null) { DeluxeMenus.debug( DebugLevel.HIGHEST, Level.WARNING, - "Requirement type at path: " + rPath + " is not a valid requirement type!" + "Requirement type '" + stringType + "' at path '" + rPath + "' is not valid!" ); continue; } @@ -1496,6 +1501,27 @@ public void onClick(@NotNull final MenuHolder holder) { return handler; } + private void checkForDeprecatedItemOptions(ConfigurationSection config, String menuName) { + final BiConsumer oldItemFlagOptionCheck = (option, itemFlag) -> { + if (!config.contains(option)) { + return; + } + + DeluxeMenus.debug( + DebugLevel.HIGHEST, + Level.WARNING, + String.format( + "Option '%s' of item '%s' in menu '%s' is deprecated and will be removed in the future. Replace it with item_flags: [%s].", + option, config.getName(), menuName, itemFlag + ) + ); + }; + + oldItemFlagOptionCheck.accept("hide_attributes", ItemFlag.HIDE_ATTRIBUTES); + oldItemFlagOptionCheck.accept("hide_enchantments", ItemFlag.HIDE_ENCHANTS); + oldItemFlagOptionCheck.accept("hide_unbreakable", ItemFlag.HIDE_UNBREAKABLE); + } + public void debug(String... messages) { DeluxeMenus.debug(DebugLevel.LOWEST, Level.INFO, messages); } diff --git a/src/main/java/com/extendedclip/deluxemenus/menu/MenuItem.java b/src/main/java/com/extendedclip/deluxemenus/menu/MenuItem.java index 296ce09..1d506c3 100644 --- a/src/main/java/com/extendedclip/deluxemenus/menu/MenuItem.java +++ b/src/main/java/com/extendedclip/deluxemenus/menu/MenuItem.java @@ -232,7 +232,7 @@ public ItemStack getItemStack(@NotNull final MenuHolder holder) { // This checks if a lore should be kept from the hooked item, and then if a lore exists on the item // ItemMeta.getLore is nullable. In that case, we just create a new ArrayList so we don't add stuff to a null list. List itemLore = Objects.requireNonNullElse(itemMeta.getLore(), new ArrayList<>()); - // Ensures backwards compadibility with how hooked items are currently handled + // Ensures backwards compatibility with how hooked items are currently handled LoreAppendMode mode = this.options.loreAppendMode().orElse(LoreAppendMode.OVERRIDE); if (!this.options.hasLore() && this.options.loreAppendMode().isEmpty()) mode = LoreAppendMode.IGNORE; switch (mode) { @@ -254,28 +254,10 @@ public ItemStack getItemStack(@NotNull final MenuHolder holder) { itemMeta.setLore(lore); - if (!this.options.itemFlags().isEmpty()) { - for (final ItemFlag flag : this.options.itemFlags()) { - itemMeta.addItemFlags(flag); - } - } - - if (this.options.hideAttributes()) { - itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); - } - - if (this.options.hideEnchants()) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); - } - if (this.options.unbreakable()) { itemMeta.setUnbreakable(true); } - if (this.options.hideUnbreakable()) { - itemMeta.addItemFlags(ItemFlag.HIDE_UNBREAKABLE); - } - if (VersionHelper.HAS_ARMOR_TRIMS && ItemUtils.hasArmorMeta(itemStack)) { final Optional trimMaterialName = this.options.trimMaterial(); final Optional trimPatternName = this.options.trimPattern(); @@ -371,7 +353,7 @@ public ItemStack getItemStack(@NotNull final MenuHolder holder) { } if (!(itemMeta instanceof EnchantmentStorageMeta) && !this.options.enchantments().isEmpty()) { - itemStack.addUnsafeEnchantments(this.options.enchantments()); + this.options.enchantments().forEach((enchantment, level) -> itemMeta.addEnchant(enchantment, level, true)); } if (this.options.lightLevel().isPresent() && itemMeta instanceof BlockDataMeta) { @@ -409,6 +391,18 @@ public ItemStack getItemStack(@NotNull final MenuHolder holder) { } } + if (!this.options.itemFlags().isEmpty()) { + for (final ItemFlag flag : this.options.itemFlags()) { + itemMeta.addItemFlags(flag); + + if (flag == ItemFlag.HIDE_ATTRIBUTES && VersionHelper.HAS_DATA_COMPONENTS) { + itemMeta.setAttributeModifiers(null); + } + } + } + + itemStack.setItemMeta(itemMeta); + if (NbtProvider.isAvailable()) { if (this.options.nbtString().isPresent()) { final String tag = holder.setPlaceholdersAndArguments(this.options.nbtString().get()); diff --git a/src/main/java/com/extendedclip/deluxemenus/menu/options/MenuItemOptions.java b/src/main/java/com/extendedclip/deluxemenus/menu/options/MenuItemOptions.java index 8174ce9..3c0400e 100644 --- a/src/main/java/com/extendedclip/deluxemenus/menu/options/MenuItemOptions.java +++ b/src/main/java/com/extendedclip/deluxemenus/menu/options/MenuItemOptions.java @@ -12,10 +12,13 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; public class MenuItemOptions { @@ -37,12 +40,9 @@ public class MenuItemOptions { private final Map enchantments; private final List potionEffects; private final List bannerMeta; - private final List itemFlags; + private final Set itemFlags = new HashSet<>(); private final boolean unbreakable; - private final boolean hideAttributes; - private final boolean hideEnchants; - private final boolean hideUnbreakable; private final boolean displayNameHasPlaceholders; private final boolean loreHasPlaceholders; @@ -92,11 +92,8 @@ private MenuItemOptions(final @NotNull MenuItemOptionsBuilder builder) { this.enchantments = builder.enchantments; this.potionEffects = builder.potionEffects; this.bannerMeta = builder.bannerMeta; - this.itemFlags = builder.itemFlags; + this.itemFlags.addAll(builder.itemFlags); this.unbreakable = builder.unbreakable; - this.hideAttributes = builder.hideAttributes; - this.hideEnchants = builder.hideEnchants; - this.hideUnbreakable = builder.hideUnbreakable; this.displayNameHasPlaceholders = builder.displayNameHasPlaceholders; this.loreHasPlaceholders = builder.loreHasPlaceholders; this.nbtString = builder.nbtString; @@ -193,7 +190,7 @@ public void headType(final @Nullable HeadType headType) { return bannerMeta; } - public @NotNull List itemFlags() { + public @NotNull Set itemFlags() { return itemFlags; } @@ -201,18 +198,6 @@ public boolean unbreakable() { return unbreakable; } - public boolean hideAttributes() { - return hideAttributes; - } - - public boolean hideEnchants() { - return hideEnchants; - } - - public boolean hideUnbreakable() { - return hideUnbreakable; - } - public boolean displayNameHasPlaceholders() { return displayNameHasPlaceholders; } @@ -331,9 +316,6 @@ public boolean updatePlaceholders() { .bannerMeta(this.bannerMeta) .itemFlags(this.itemFlags) .unbreakable(this.unbreakable) - .hideAttributes(this.hideAttributes) - .hideEnchants(this.hideEnchants) - .hideUnbreakable(this.hideUnbreakable) .nbtString(this.nbtString) .nbtInt(this.nbtInt) .nbtStrings(this.nbtStrings) @@ -376,12 +358,9 @@ public static class MenuItemOptionsBuilder { private Map enchantments = Collections.emptyMap(); private List potionEffects = Collections.emptyList(); private List bannerMeta = Collections.emptyList(); - private List itemFlags = Collections.emptyList(); + private final Set itemFlags = new HashSet<>(); private boolean unbreakable; - private boolean hideAttributes; - private boolean hideEnchants; - private boolean hideUnbreakable; private boolean displayNameHasPlaceholders; private boolean loreHasPlaceholders; @@ -499,8 +478,8 @@ public MenuItemOptionsBuilder bannerMeta(final @NotNull List bannerMeta return this; } - public MenuItemOptionsBuilder itemFlags(final @NotNull List itemFlags) { - this.itemFlags = itemFlags; + public MenuItemOptionsBuilder itemFlags(final @NotNull Collection itemFlags) { + this.itemFlags.addAll(itemFlags); return this; } @@ -509,18 +488,36 @@ public MenuItemOptionsBuilder unbreakable(final boolean unbreakable) { return this; } + /** + * @deprecated Use {@link #itemFlags(Collection)} with {@link ItemFlag#HIDE_ATTRIBUTES} + */ + @Deprecated() public MenuItemOptionsBuilder hideAttributes(final boolean hideAttributes) { - this.hideAttributes = hideAttributes; + if (hideAttributes) { + this.itemFlags.add(ItemFlag.HIDE_ATTRIBUTES); + } return this; } + /** + * @deprecated Use {@link #itemFlags(Collection)} with {@link ItemFlag#HIDE_ENCHANTS} + */ + @Deprecated public MenuItemOptionsBuilder hideEnchants(final boolean hideEnchants) { - this.hideEnchants = hideEnchants; + if (hideEnchants) { + this.itemFlags.add(ItemFlag.HIDE_ENCHANTS); + } return this; } + /** + * @deprecated Use {@link #itemFlags(Collection)} with {@link ItemFlag#HIDE_UNBREAKABLE} + */ + @Deprecated public MenuItemOptionsBuilder hideUnbreakable(final boolean hideUnbreakable) { - this.hideUnbreakable = hideUnbreakable; + if (hideUnbreakable) { + this.itemFlags.add(ItemFlag.HIDE_UNBREAKABLE); + } return this; } diff --git a/src/main/java/com/extendedclip/deluxemenus/utils/VersionHelper.java b/src/main/java/com/extendedclip/deluxemenus/utils/VersionHelper.java index 5aaa392..49b239e 100644 --- a/src/main/java/com/extendedclip/deluxemenus/utils/VersionHelper.java +++ b/src/main/java/com/extendedclip/deluxemenus/utils/VersionHelper.java @@ -21,6 +21,8 @@ public final class VersionHelper { private static final String PACKAGE_NAME = Bukkit.getServer().getClass().getPackage().getName(); public static final String NMS_VERSION = PACKAGE_NAME.substring(PACKAGE_NAME.lastIndexOf('.') + 1); + // Data components + private static final int V1_20_5 = 1_20_5; // ArmorTrims private static final int V1_19_4 = 1194; // PlayerProfile API @@ -42,6 +44,10 @@ public final class VersionHelper { private static final boolean IS_PAPER = checkPaper(); + /** + * Checks if the current version includes the Data Components + */ + public static final boolean HAS_DATA_COMPONENTS = CURRENT_VERSION >= V1_20_5; /** * Checks if the current version includes the ArmorTrims API diff --git a/src/main/resources/advanced_menu.yml b/src/main/resources/advanced_menu.yml index 5f0e484..a32a676 100644 --- a/src/main/resources/advanced_menu.yml +++ b/src/main/resources/advanced_menu.yml @@ -23,7 +23,8 @@ items: slot: 11 priority: 1 update: true - hide_attributes: true + item_flags: + - HIDE_ATTRIBUTES display_name: '&bExample Kit' lore: - '' @@ -46,7 +47,8 @@ items: slot: 11 priority: 2 update: true - hide_attributes: true + item_flags: + - HIDE_ATTRIBUTES display_name: '&cExample Kit Unavailable' lore: - '&7This kit is on cooldown!' @@ -62,7 +64,8 @@ items: slot: 11 priority: 3 update: true - hide_attributes: true + item_flags: + - HIDE_ATTRIBUTES display_name: '&7Example Kit' lore: - '&7You do not have permission for this kit!'