diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/WrappedEnchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/WrappedEnchantment.java new file mode 100644 index 0000000..efe277c --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/WrappedEnchantment.java @@ -0,0 +1,316 @@ +package xyz.alexcrea.cuanvil.enchant; + +import io.delilaheve.CustomAnvil; +import io.delilaheve.util.ItemUtil; +import org.bukkit.NamespacedKey; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.EnchantmentStorageMeta; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import xyz.alexcrea.cuanvil.enchant.wrapped.VanillaEnchant; + +import java.util.*; +import java.util.logging.Level; + +/** + * Represent any enchantment. + * One issue with the plugin is: it does not handle well duplicate key name (ignoring namespace) as the plugin was coded with vanilla enchantment in head + */ +public abstract class WrappedEnchantment { + + @NotNull + private final NamespacedKey key; + @NotNull + private final String name; + @NotNull + private final EnchantmentRarity defaultRarity; + private final int defaultMaxLevel; + + /** + * Constructor of Wrapped Enchantment. + * @param key The enchantment's key. + * @param defaultRarity Default rarity the enchantment should be. + * @param defaultMaxLevel Default max level the enchantment can be applied with. + */ + public WrappedEnchantment( + @NotNull NamespacedKey key, + @Nullable EnchantmentRarity defaultRarity, + int defaultMaxLevel){ + this.key = key; + this.name = key.getKey(); + this.defaultMaxLevel = defaultMaxLevel; + + if(defaultRarity == null) this.defaultRarity = EnchantmentRarity.COMMON; + else this.defaultRarity = defaultRarity; + } + + /** + * Get the default rarity of this enchant. + * @return The default rarity of this enchant. + */ + public final EnchantmentRarity defaultRarity(){ + return defaultRarity; + } + + /** + * Get the enchantment key. + * @return The enchantment key. + */ + @NotNull + public final NamespacedKey getKey(){ + return key; + } + + /** + * Get the enchantment name. + * @return The enchantment name. + */ + @NotNull + public final String getName(){ + return name; + } + + /** + * Get the default maximum level of this enchantment. + * @return The default maximum level of this enchantment. + */ + public final int defaultMaxLevel(){return defaultMaxLevel;} + + /** + * If the enchantment have specialised group operation. + * @return If the enchantment is optimised for group operation. + */ + protected boolean isOptimised(){ + return false; + } + + /** + * Get current level of the enchantment. + * @param item Item to search the level for. + */ + public int getLevel(@NotNull ItemStack item){ + ItemMeta meta = item.getItemMeta(); + if(meta == null) return 0; + return getLevel(item, meta); + } + + /** + * Get current level of the enchantment. + * @param item Item to search the level for. + * @param meta Meta of the provided item. It will not be changed and not be set on the item. + * @return Current leve of this enchantment on item. or 0 if absent. + */ + public abstract int getLevel(@NotNull ItemStack item, @NotNull ItemMeta meta); + + /** + * Check if this enchantment is present on the provided level. + * @param item The item to set the enchantment level. + * @return If the enchantment have been found. + */ + public boolean isEnchantmentPresent(@NotNull ItemStack item){ + ItemMeta meta = item.getItemMeta(); + if(meta == null) return false; + return isEnchantmentPresent(item, meta); + } + + /** + * Check if this enchantment is present on the provided level. + * @param item The item to set the enchantment level. + * @param meta Meta of the provided item. It will not be changed and not be set on the item. + * @return If the enchantment have been found. + */ + public abstract boolean isEnchantmentPresent(@NotNull ItemStack item, @NotNull ItemMeta meta); + + /** + * Force add an enchantment at the provided level. + * @param item The item to set the enchantment level. + * @param level The level to set the enchantment to. + */ + public abstract void addEnchantmentUnsafe(@NotNull ItemStack item, int level); + + /** + * Remove this enchantment from the provided ItemStack. + * @param item The item to remove the enchantment. + */ + public abstract void removeFrom(@NotNull ItemStack item); + + // Static functions + + /** + * Clear every enchantment from this item. + * @param item Item to be cleared from enchantments. + */ + public static void clearEnchants(@NotNull ItemStack item){ + ItemMeta meta = item.getItemMeta(); + if(meta == null) return; + + // Clean Vanilla enchants + if (ItemUtil.INSTANCE.isEnchantedBook(item)) { + EnchantmentStorageMeta bookMeta = (EnchantmentStorageMeta) meta; + bookMeta.getStoredEnchants().forEach( + (enchantment, leve) -> bookMeta.removeStoredEnchant(enchantment) + ); + } else { + item.getEnchantments().forEach( + (enchantment, leve) -> item.removeEnchantment(enchantment) + ); + } + + // Clean unoptimised enchants + for (WrappedEnchantment enchant : unoptimisedValues()) { + if(enchant.isEnchantmentPresent(item)){ + enchant.removeFrom(item); + } + } + + } + + /** + * Get enchantments of an item. + * @param item Item to get enchantment from. + * @return A map of the set enchantments and there's respective levels. + */ + public static Map getEnchants(@NotNull ItemStack item){ //TODO faster method to find vanilla enchantment + Map enchantments = new HashMap<>(); + + ItemMeta meta = item.getItemMeta(); + if(meta == null) return enchantments; + + // Vanilla optimised get + if (ItemUtil.INSTANCE.isEnchantedBook(item)) { + ((EnchantmentStorageMeta)meta).getStoredEnchants().forEach( + (enchantment, level) -> enchantments.put(getByKey(enchantment.getKey()), level) + ); + } else { + item.getEnchantments().forEach( + (enchantment, level) -> enchantments.put(getByKey(enchantment.getKey()), level) + ); + } + + // Unoptimised enchantment get + findEnchantsFromSelectedList(item, meta, enchantments, unoptimisedValues()); + + return enchantments; + } + + + /** + * Find enchantments of an item. only test the enchantment from the list. + * @param item Item to get enchantment from. + * @param meta Meta of the provided item. + * @param enchantments Map of enchantment to complete. + * @param enchantmentToTest Enchantment to test + */ + private static void findEnchantsFromSelectedList( + @NotNull ItemStack item, + @NotNull ItemMeta meta, + @NotNull Map enchantments, + @NotNull Collection enchantmentToTest){ + + for (WrappedEnchantment enchantment : enchantmentToTest) { + if(enchantment.isEnchantmentPresent(item, meta)){ + enchantments.put(enchantment, enchantment.getLevel(item, meta)); + } + } + + } + + + // Register enchantment functions + private static final HashMap BY_KEY = new HashMap<>(); + private static final HashMap BY_NAME = new HashMap<>(); + private static final List UNOPTIMISED_ENCHANTMENT = new ArrayList<>(); + + /** + * This should only be called on main of custom anvil. + * If called more than one time, chance of thing being broken will be high. + */ + public static void registerEnchantments(){ + for (Enchantment enchantment : Enchantment.values()) { + register(new VanillaEnchant(enchantment)); + } + + } + + /** + * Can be used to register new enchantment. + *

+ * No guarantee that the enchantment will be present on the config gui if registered late. + * (By late I mean after custom anvil startup.) + * @param enchantment The enchantment to be registered. + */ + public static void register(@NotNull WrappedEnchantment enchantment){ + if(BY_KEY.containsKey(enchantment.getKey())){ + CustomAnvil.instance.getLogger().log(Level.WARNING, + "Duplicate registered enchantment. This should NOT happen.", + new IllegalStateException(enchantment.getKey()+" enchantment was already registered")); + return; + } + if(BY_NAME.containsKey(enchantment.getName())){ + CustomAnvil.instance.getLogger().log(Level.WARNING, + "Duplicate registered enchantment name. There will have issue. " + + "\nI hope this do not happen to you on a production server. If it do, there is probably a plugin trying to register an enchantment with the same name than another one", + new IllegalStateException(enchantment.getKey()+" enchantment name was already registered")); + } + + BY_KEY.put(enchantment.getKey(), enchantment); + BY_NAME.put(enchantment.getName(), enchantment); + + if(!enchantment.isOptimised()){ + UNOPTIMISED_ENCHANTMENT.add(enchantment); + } + } + + /** + * Can be used to unregister new enchantment. + * Please be cautious with this function. + * It should probably rarely be used. + *

+ * No guarantee that the enchantment will absent if the config guis if unregistered late. + * (By late I mean after custom anvil startup.) + * @param enchantment The enchantment to be unregistered. + */ + public static void unregister(@NotNull WrappedEnchantment enchantment){ + BY_KEY.remove(enchantment.getKey()); + BY_NAME.remove(enchantment.getName()); + } + + /** + * Gets the enchantment by the provided key. + * @param key Key to fetch. + * @return Registered enchantment. null if absent. + */ + public static @Nullable WrappedEnchantment getByKey(@NotNull NamespacedKey key){ + return BY_KEY.get(key); + } + + /** + * Gets the enchantment by the provided name. + * @param name Name to fetch. + * @return Registered enchantment. null if absent. + */ + public static @Nullable WrappedEnchantment getByName(@NotNull String name){ + return BY_NAME.get(name); + } + + /** + * Gets an array of all the registered enchantments. + * @return Array of enchantment. + */ + @NotNull + public static WrappedEnchantment[] values() { + return BY_KEY.values().toArray(new WrappedEnchantment[0]); + } + + /** + * Gets a list of all the unoptimised enchantments. + * @return List of enchantment. + */ + @NotNull + private static List unoptimisedValues() { + return UNOPTIMISED_ENCHANTMENT; + } + +} diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/VanillaEnchant.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/VanillaEnchant.java new file mode 100644 index 0000000..3347d0e --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/VanillaEnchant.java @@ -0,0 +1,87 @@ +package xyz.alexcrea.cuanvil.enchant.wrapped; + +import io.delilaheve.util.ItemUtil; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.EnchantmentStorageMeta; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import xyz.alexcrea.cuanvil.enchant.EnchantmentProperties; +import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity; +import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment; + +import java.util.Locale; + +public class VanillaEnchant extends WrappedEnchantment { + + private final @NotNull Enchantment enchantment; + + public VanillaEnchant(@NotNull Enchantment enchantment){ + super(enchantment.getKey(), + getRarity(enchantment), + enchantment.getMaxLevel()); + this.enchantment = enchantment; + + } + + @Override + protected boolean isOptimised() { + return true; + } + + @Override + public int getLevel(@NotNull ItemStack item, @NotNull ItemMeta meta) { + if (ItemUtil.INSTANCE.isEnchantedBook(item)) { + return ((EnchantmentStorageMeta)meta).getStoredEnchantLevel(this.enchantment); + } else { + return meta.getEnchantLevel(this.enchantment); + } + } + + @Override + public boolean isEnchantmentPresent(@NotNull ItemStack item, @NotNull ItemMeta meta) { + if (ItemUtil.INSTANCE.isEnchantedBook(item)) { + EnchantmentStorageMeta bookMeta = ((EnchantmentStorageMeta)meta); + + return bookMeta.getStoredEnchants().containsKey(this.enchantment); + }else{ + return item.containsEnchantment(this.enchantment); + } + } + + @Override + public void addEnchantmentUnsafe(@NotNull ItemStack item, int level) { + if (ItemUtil.INSTANCE.isEnchantedBook(item)) { + EnchantmentStorageMeta bookMeta = ((EnchantmentStorageMeta)item.getItemMeta()); + + assert bookMeta != null; + bookMeta.addStoredEnchant(this.enchantment, level, true); + item.setItemMeta(bookMeta); + } else { + item.addUnsafeEnchantment(this.enchantment, level); + } + + } + + @Override + public void removeFrom(@NotNull ItemStack item) { + if (ItemUtil.INSTANCE.isEnchantedBook(item)) { + EnchantmentStorageMeta bookMeta = ((EnchantmentStorageMeta)item.getItemMeta()); + + assert bookMeta != null; + bookMeta.removeStoredEnchant(this.enchantment); + item.setItemMeta(bookMeta); + }else{ + item.removeEnchantment(this.enchantment); + } + + } + + public static EnchantmentRarity getRarity(Enchantment enchantment){ + try {return EnchantmentProperties.valueOf(enchantment.getKey().getKey().toUpperCase(Locale.ENGLISH)).getRarity();} + catch (IllegalArgumentException ignored) {} + + return EnchantmentRarity.COMMON; + } + +} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectEnchantmentContainer.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectEnchantmentContainer.java index ee6ce77..95bf586 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectEnchantmentContainer.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/SelectEnchantmentContainer.java @@ -1,15 +1,15 @@ package xyz.alexcrea.cuanvil.gui.config; -import org.bukkit.enchantments.Enchantment; +import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment; import java.util.Set; public interface SelectEnchantmentContainer { - Set getSelectedEnchantments(); + Set getSelectedEnchantments(); - boolean setSelectedEnchantments(Set enchantments); + boolean setSelectedEnchantments(Set enchantments); - Set illegalEnchantments(); + Set illegalEnchantments(); } diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/AbstractEnchantConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/AbstractEnchantConfigGui.java index 7c6d31e..4bbd48a 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/AbstractEnchantConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/AbstractEnchantConfigGui.java @@ -4,7 +4,7 @@ import com.github.stefvanschie.inventoryframework.gui.GuiItem; import com.github.stefvanschie.inventoryframework.pane.Orientable; import com.github.stefvanschie.inventoryframework.pane.OutlinePane; import io.delilaheve.CustomAnvil; -import org.bukkit.enchantments.Enchantment; +import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.config.settings.AbstractSettingGui; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; @@ -55,7 +55,7 @@ public abstract class AbstractEnchantConfigGui(); - for (Enchantment enchant : GuiSharedConstant.SORTED_ENCHANTMENT_LIST) { + for (WrappedEnchantment enchant : GuiSharedConstant.SORTED_ENCHANTMENT_LIST) { T factory = getFactoryFromEnchant(enchant); bookItemFactoryList.add(factory); @@ -80,7 +80,7 @@ public abstract class AbstractEnchantConfigGui enchantLore = new ArrayList<>(); enchantLore.add("\u00A77Allow you to select a list of \u00A75Enchantments \u00A77that this conflict should include"); - Set enchants = getSelectedEnchantments(); + Set enchants = getSelectedEnchantments(); if (enchants.isEmpty()) { enchantLore.add("\u00A77There is no included enchantment for this conflict."); } else { enchantLore.add("\u00A77List of included enchantment for this conflict:"); - Iterator enchantIterator = enchants.iterator(); + Iterator enchantIterator = enchants.iterator(); boolean greaterThanMax = enchants.size() > 5; int maxindex = (greaterThanMax ? 4 : enchants.size()); @@ -243,12 +243,12 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl // Select enchantment container methods @Override - public Set getSelectedEnchantments() { + public Set getSelectedEnchantments() { return this.enchantConflict.getEnchants(); } @Override - public boolean setSelectedEnchantments(Set enchantments) { + public boolean setSelectedEnchantments(Set enchantments) { if (!this.shouldWork) { CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict + " enchants but sub config is destroyed"); return false; @@ -260,7 +260,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl // Save on file configuration String[] enchantKeys = new String[enchantments.size()]; int index = 0; - for (Enchantment enchantment : enchantments) { + for (WrappedEnchantment enchantment : enchantments) { enchantKeys[index++] = enchantment.getKey().getKey(); } ConfigHolder.CONFLICT_HOLDER.getConfig().set(enchantConflict + ".enchantments", enchantKeys); @@ -280,7 +280,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl } @Override - public Set illegalEnchantments() { + public Set illegalEnchantments() { return Collections.emptySet(); } diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantSelectSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantSelectSettingGui.java index f4d3337..6eeef37 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantSelectSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantSelectSettingGui.java @@ -13,6 +13,7 @@ import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; +import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.config.SelectEnchantmentContainer; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; @@ -29,7 +30,7 @@ public class EnchantSelectSettingGui extends AbstractSettingGui { SelectEnchantmentContainer enchantContainer; int page; - Set selectedEnchant; + Set selectedEnchant; public EnchantSelectSettingGui(@NotNull String title, ValueUpdatableGui parent, SelectEnchantmentContainer enchantContainer, int page) { super(6, title, parent); @@ -64,8 +65,8 @@ public class EnchantSelectSettingGui extends AbstractSettingGui { filledEnchant.align(OutlinePane.Alignment.BEGIN); filledEnchant.setOrientation(Orientable.Orientation.HORIZONTAL); - Set illegalEnchant = this.enchantContainer.illegalEnchantments(); - for (Enchantment enchant : GuiSharedConstant.SORTED_ENCHANTMENT_LIST) { + Set illegalEnchant = this.enchantContainer.illegalEnchantments(); + for (WrappedEnchantment enchant : GuiSharedConstant.SORTED_ENCHANTMENT_LIST) { if (illegalEnchant.contains(enchant)) { return; } @@ -76,7 +77,7 @@ public class EnchantSelectSettingGui extends AbstractSettingGui { } - private GuiItem getGuiItemFromEnchant(Enchantment enchantment) { + private GuiItem getGuiItemFromEnchant(WrappedEnchantment enchantment) { boolean isIn = this.selectedEnchant.contains(enchantment); Material usedMaterial; @@ -122,7 +123,7 @@ public class EnchantSelectSettingGui extends AbstractSettingGui { item.setItemMeta(meta); } - private Consumer getEnchantItemConsumer(Enchantment enchant, GuiItem guiItem) { + private Consumer getEnchantItemConsumer(WrappedEnchantment enchant, GuiItem guiItem) { return event -> { event.setCancelled(true); @@ -151,7 +152,7 @@ public class EnchantSelectSettingGui extends AbstractSettingGui { @Override public boolean hadChange() { - Set baseGroup = this.enchantContainer.getSelectedEnchantments(); + Set baseGroup = this.enchantContainer.getSelectedEnchantments(); return baseGroup.size() != this.selectedEnchant.size() || !baseGroup.containsAll(this.selectedEnchant); } diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiSharedConstant.java b/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiSharedConstant.java index d8bebca..1c33af2 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiSharedConstant.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiSharedConstant.java @@ -5,9 +5,9 @@ import com.github.stefvanschie.inventoryframework.pane.Pane; import com.github.stefvanschie.inventoryframework.pane.PatternPane; import com.github.stefvanschie.inventoryframework.pane.util.Pattern; import org.bukkit.Material; -import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment; import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; import java.util.Arrays; @@ -17,10 +17,10 @@ import java.util.List; public class GuiSharedConstant { - public static final List SORTED_ENCHANTMENT_LIST; + public static final List SORTED_ENCHANTMENT_LIST; static { - SORTED_ENCHANTMENT_LIST = Arrays.asList(Enchantment.values()); + SORTED_ENCHANTMENT_LIST = Arrays.asList(WrappedEnchantment.values()); SORTED_ENCHANTMENT_LIST.sort(Comparator.comparing(ench -> ench.getKey().getKey())); } diff --git a/src/main/kotlin/io/delilaheve/AnvilEventListener.kt b/src/main/kotlin/io/delilaheve/AnvilEventListener.kt index 53fedd0..ead5a1a 100644 --- a/src/main/kotlin/io/delilaheve/AnvilEventListener.kt +++ b/src/main/kotlin/io/delilaheve/AnvilEventListener.kt @@ -452,6 +452,7 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener { if (ConflictType.BIG_CONFLICT == conflictType) { illegalPenalty += ConfigOptions.sacrificeIllegalCost + CustomAnvil.verboseLog("Big conflict. Adding illegal price penalty") } continue } diff --git a/src/main/kotlin/io/delilaheve/CustomAnvil.kt b/src/main/kotlin/io/delilaheve/CustomAnvil.kt index ec0ed16..7d3503a 100644 --- a/src/main/kotlin/io/delilaheve/CustomAnvil.kt +++ b/src/main/kotlin/io/delilaheve/CustomAnvil.kt @@ -7,6 +7,7 @@ import org.bukkit.plugin.java.JavaPlugin import xyz.alexcrea.cuanvil.command.EditConfigExecutor import xyz.alexcrea.cuanvil.command.ReloadExecutor import xyz.alexcrea.cuanvil.config.ConfigHolder +import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment import xyz.alexcrea.cuanvil.gui.config.MainConfigGui import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant import xyz.alexcrea.cuanvil.listener.ChatEventListener @@ -93,6 +94,9 @@ class CustomAnvil : JavaPlugin() { logger.warning("Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus") } + // Register enchantments + WrappedEnchantment.registerEnchantments() + // Load ProtocolLib dependency if exist packetManager = if(pluginManager.isPluginEnabled("ProtocolLib")) { ProtocoLibWrapper(); } diff --git a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt index 2ee3749..0fefdf2 100644 --- a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt +++ b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt @@ -2,8 +2,8 @@ package io.delilaheve.util import io.delilaheve.CustomAnvil import io.delilaheve.util.EnchantmentUtil.enchantmentName -import org.bukkit.enchantments.Enchantment import xyz.alexcrea.cuanvil.config.ConfigHolder +import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment /** * Config option accessors @@ -239,7 +239,7 @@ object ConfigOptions { /** * Get the given [enchantment]'s limit */ - fun enchantLimit(enchantment: Enchantment): Int { + fun enchantLimit(enchantment: WrappedEnchantment): Int { return enchantLimit(enchantment.enchantmentName) } @@ -273,7 +273,7 @@ object ConfigOptions { * it's source [isFromBook] */ fun enchantmentValue( - enchantment: Enchantment, + enchantment: WrappedEnchantment, isFromBook: Boolean ): Int { return enchantmentValue(enchantment.enchantmentName, isFromBook) @@ -309,22 +309,4 @@ object ConfigOptions { return DEFAULT_ENCHANT_VALUE } - /** - * Get an array of key of basic config options - */ - fun getBasicConfigKeys(): Array { - return arrayOf( - DEFAULT_LIMIT_PATH, - CAP_ANVIL_COST, - MAX_ANVIL_COST, - REPLACE_TOO_EXPENSIVE, - ITEM_REPAIR_COST, - UNIT_REPAIR_COST, - ITEM_RENAME_COST, - SACRIFICE_ILLEGAL_COST, - REMOVE_ANVIL_COST_LIMIT - ) - } - - } diff --git a/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt b/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt index 0f1639c..9d3f95a 100644 --- a/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt +++ b/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt @@ -2,9 +2,9 @@ package io.delilaheve.util import io.delilaheve.CustomAnvil import org.bukkit.Material -import org.bukkit.enchantments.Enchantment import org.bukkit.entity.HumanEntity import xyz.alexcrea.cuanvil.config.ConfigHolder +import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment import xyz.alexcrea.cuanvil.group.ConflictType import kotlin.math.max import kotlin.math.min @@ -17,17 +17,17 @@ object EnchantmentUtil { /** * Enchantment name without namespace */ - val Enchantment.enchantmentName: String + val WrappedEnchantment.enchantmentName: String get() = key.key /** * Combine 2 sets of enchantments according to our configuration */ - fun Map.combineWith( - other: Map, + fun Map.combineWith( + other: Map, mat: Material, player: HumanEntity - ) = mutableMapOf().apply { + ) = mutableMapOf().apply { putAll(this@combineWith) other.forEach { (enchantment, level) -> // Get max level or 255 if player can bypass diff --git a/src/main/kotlin/io/delilaheve/util/ItemUtil.kt b/src/main/kotlin/io/delilaheve/util/ItemUtil.kt index 7eed593..6c627ba 100644 --- a/src/main/kotlin/io/delilaheve/util/ItemUtil.kt +++ b/src/main/kotlin/io/delilaheve/util/ItemUtil.kt @@ -1,11 +1,9 @@ package io.delilaheve.util -import io.delilaheve.CustomAnvil import org.bukkit.Material.ENCHANTED_BOOK -import org.bukkit.enchantments.Enchantment import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.Damageable -import org.bukkit.inventory.meta.EnchantmentStorageMeta +import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment import kotlin.math.ceil import kotlin.math.max import kotlin.math.min @@ -23,44 +21,19 @@ object ItemUtil { /** * Find the enchantment map for this [ItemStack] and return it as a [MutableMap] */ - fun ItemStack.findEnchantments() = if (isEnchantedBook()) { - (itemMeta as? EnchantmentStorageMeta)?.storedEnchants ?: emptyMap() - } else { - itemMeta?.enchants ?: emptyMap() - } + fun ItemStack.findEnchantments(): MutableMap = WrappedEnchantment.getEnchants(this) /** * Apply an [enchantments] map to this [ItemStack] */ - fun ItemStack.setEnchantmentsUnsafe(enchantments: Map) { - if (isEnchantedBook()) { - /* For some god-forsaken reason, item meta is not mutable - * so, we have to get the instance, modify it, then set it - * back to the item... #BecauseMinecraft */ - val bookMeta = (itemMeta as? EnchantmentStorageMeta) - bookMeta?.replaceEnchants(enchantments) - itemMeta = bookMeta - } else { - itemMeta?.enchants?.forEach { (enchant, _) -> - removeEnchantment(enchant) - } - addUnsafeEnchantments(enchantments) - } - } + fun ItemStack.setEnchantmentsUnsafe(enchantments: Map) { + WrappedEnchantment.clearEnchants(this) - /** - * Apply an [enchantments] map to this book - */ - private fun EnchantmentStorageMeta.replaceEnchants( - enchantments: Map - ) { - storedEnchants.forEach { (enchant, _) -> - removeStoredEnchant(enchant) - } - enchantments.forEach { (enchant, level) -> - val added = addStoredEnchant(enchant, level, true) - CustomAnvil.log("${enchant.key} added to item? $added") + //TODO maybe faster methode to add vanilla enchantment. maybe move this function to wrapped enchantment + enchantments.forEach { (enchantment, level) -> + enchantment.addEnchantmentUnsafe(this, level) } + } /** diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt index 76a07d8..2885237 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt @@ -2,7 +2,7 @@ package xyz.alexcrea.cuanvil.group import io.delilaheve.CustomAnvil import org.bukkit.Material -import org.bukkit.enchantments.Enchantment +import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment class EnchantConflictGroup( private val name: String, @@ -10,14 +10,15 @@ class EnchantConflictGroup( var minBeforeBlock: Int ) { - private val enchantments = HashSet() + private val enchantments = HashSet() - fun addEnchantment(enchant: Enchantment) { + fun addEnchantment(enchant: WrappedEnchantment) { enchantments.add(enchant) } - fun allowed(enchants: Set, mat: Material): Boolean { + fun allowed(enchants: Set, mat: Material): Boolean { if (enchantments.size < minBeforeBlock) { + CustomAnvil.verboseLog("Conflicting bc of to many enchantments") return true } @@ -31,6 +32,7 @@ class EnchantConflictGroup( if (enchantment !in enchantments) continue CustomAnvil.verboseLog("Enchant ${enchantment.key} is in: ${enchantAmount + 1}/$minBeforeBlock ") if (++enchantAmount > minBeforeBlock) { + CustomAnvil.verboseLog("it is not allowed bc of to many enchantment in conflict") return false } @@ -42,11 +44,11 @@ class EnchantConflictGroup( return this.cantConflict } - fun getEnchants(): HashSet { + fun getEnchants(): HashSet { return enchantments } - fun setEnchants(enchants: Set) { + fun setEnchants(enchants: Set) { enchantments.clear() enchantments.addAll(enchants) } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt index e295396..d41eb38 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt @@ -5,6 +5,7 @@ import org.bukkit.Material import org.bukkit.NamespacedKey import org.bukkit.configuration.ConfigurationSection import org.bukkit.enchantments.Enchantment +import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment class EnchantConflictManager { @@ -27,12 +28,12 @@ class EnchantConflictManager { // 1.20.5 compatibility TODO better update system private val SWEEPING_EDGE_ENCHANT = - Enchantment.getByKey(NamespacedKey.minecraft("sweeping_edge")) ?: - Enchantment.SWEEPING_EDGE + WrappedEnchantment.getByKey(NamespacedKey.minecraft("sweeping_edge")) ?: + WrappedEnchantment.getByKey(Enchantment.SWEEPING_EDGE.key) } - private lateinit var conflictMap: HashMap> + private lateinit var conflictMap: HashMap> lateinit var conflictList: ArrayList // Read and prepare all conflict @@ -58,14 +59,14 @@ class EnchantConflictManager { } } - fun addConflictToConflictMap(enchant: Enchantment, conflict: EnchantConflictGroup) { + fun addConflictToConflictMap(enchant: WrappedEnchantment, conflict: EnchantConflictGroup) { if (!conflictMap.containsKey(enchant)) { conflictMap[enchant] = ArrayList() } conflictMap[enchant]!!.add(conflict) } - fun removeConflictFromMap(enchant: Enchantment, conflict: EnchantConflictGroup): Boolean { + fun removeConflictFromMap(enchant: WrappedEnchantment, conflict: EnchantConflictGroup): Boolean { return conflictMap[enchant]!!.remove(conflict) } @@ -100,7 +101,7 @@ class EnchantConflictManager { return conflict } - private fun getEnchantByName(enchantName: String): Enchantment? { + private fun getEnchantByName(enchantName: String): WrappedEnchantment? { // Temporary solution for 1.20.5 when(enchantName){ @@ -109,8 +110,7 @@ class EnchantConflictManager { } } - val enchantKey = NamespacedKey.minecraft(enchantName) - return Enchantment.getByKey(enchantKey) + return WrappedEnchantment.getByName(enchantName) } @@ -151,7 +151,7 @@ class EnchantConflictManager { return group } - fun isConflicting(base: Set, mat: Material, newEnchant: Enchantment): ConflictType { + fun isConflicting(base: Set, mat: Material, newEnchant: WrappedEnchantment): ConflictType { CustomAnvil.verboseLog("Testing conflict for ${newEnchant.key} on ${mat.key}") val conflictList = conflictMap[newEnchant] ?: return ConflictType.NO_CONFLICT CustomAnvil.verboseLog("Did not get skipped") @@ -159,13 +159,14 @@ class EnchantConflictManager { var result = ConflictType.NO_CONFLICT for (conflict in conflictList) { CustomAnvil.verboseLog("Is against $conflict") - val conflicting = conflict.allowed(base, mat) - CustomAnvil.verboseLog("Was against $conflict and conflicting: $conflicting ") - if (!conflicting) { + val allowed = conflict.allowed(base, mat) + CustomAnvil.verboseLog("Was against $conflict and conflicting: ${!allowed} ") + if (!allowed) { if (conflict.getEnchants().size <= 1) { result = ConflictType.SMALL_CONFLICT CustomAnvil.verboseLog("Small conflict, continuing") } else { + CustomAnvil.verboseLog("Big conflict, probably stoping") return ConflictType.BIG_CONFLICT } }