getExcludedGroupNames() {
+ return excludedGroupNames;
+ }
+
+ /**
+ * Gets maximum number of conflicting enchantment before conflict is active.
+ *
+ * This value represent how many enchantment contained on this conflict can be applied to before conflict is considered active.
+ * That mean new enchantment will not be able to be added to the item and present enchantment will not have its level upgraded.
+ *
+ * In vanilla. material restriction have this value set to 0 and enchantment conflict set to 1.
+ *
+ * @return the max number of conflicting enchantment before conflict. 0 by default.
+ */
+ public int getMaxBeforeConflict() {
+ return maxBeforeConflict;
+ }
+
+ /**
+ * Sets conflict name.
+ *
+ * @param name The name
+ * @return This conflict builder instance.
+ */
+ public ConflictBuilder setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Sets maximum number of conflicting enchantment before conflict is active.
+ *
+ * This value represent how many enchantment contained on this conflict can be applied to before conflict is considered active.
+ * That mean new enchantment will not be able to be added to the item and present enchantment will not have its level upgraded.
+ *
+ * In vanilla. material restriction have this value set to 0 and enchantment conflict set to 1.
+ *
+ * @param maxBeforeConflict The max before conflict
+ * @return This conflict builder instance.
+ */
+ public ConflictBuilder setMaxBeforeConflict(int maxBeforeConflict) {
+ this.maxBeforeConflict = maxBeforeConflict;
+ return this;
+ }
+
+ /**
+ * Add a conflicting enchantment by name.
+ *
+ * @param enchantmentName The enchantment name
+ * @return This conflict builder instance.
+ */
+ @NotNull
+ public ConflictBuilder addEnchantment(@NotNull String enchantmentName){
+ enchantmentNames.add(enchantmentName);
+ return this;
+ }
+
+ /**
+ * Add a conflicting enchantment by key.
+ *
+ * @param enchantmentKey The enchantment key
+ * @return This conflict builder instance.
+ */
+ @NotNull
+ public ConflictBuilder addEnchantment(@NotNull NamespacedKey enchantmentKey){
+ enchantmentKeys.add(enchantmentKey);
+ return this;
+ }
+
+ /**
+ * Add a conflicting enchantment by instance.
+ *
+ * @param enchantment The enchantment
+ * @return This conflict builder instance.
+ */
+ @NotNull
+ public ConflictBuilder addEnchantment(@NotNull CAEnchantment enchantment){
+ addEnchantment(enchantment.getKey());
+ return this;
+ }
+
+ /**
+ * Remove conflicting enchantment by name.
+ *
+ * @param enchantmentName The enchantment name
+ * @return This conflict builder instance.
+ */
+ @NotNull
+ public ConflictBuilder removeEnchantment(@NotNull String enchantmentName){
+ enchantmentNames.remove(enchantmentName);
+ return this;
+ }
+
+ /**
+ * Remove conflicting enchantment by key.
+ *
+ * @param enchantmentKey The enchantment key
+ * @return This conflict builder instance.
+ */
+ @NotNull
+ public ConflictBuilder removeEnchantment(@NotNull NamespacedKey enchantmentKey){
+ enchantmentKeys.remove(enchantmentKey);
+ return removeEnchantment(enchantmentKey.getKey());
+ }
+
+ /**
+ * Remove enchantment by instance.
+ *
+ * @param enchantment The enchantment
+ * @return This conflict builder instance.
+ */
+ @NotNull
+ public ConflictBuilder removeEnchantment(@NotNull CAEnchantment enchantment){
+ return removeEnchantment(enchantment.getKey());
+ }
+
+ /**
+ * Add an excluded group by name.
+ *
+ * If left item of an anvil craft is included on one of the excluded group it will ignore this conflict.
+ *
+ * This allows to create conflict only for some item. Material restriction can be written like that.
+ *
+ * For example: If we exclude a material group containing every pickaxe and add efficiency enchantment
+ * with {@link #setMaxBeforeConflict(int) maxBeforeConflict} set to 0.
+ * Then only pickaxe will be able to have efficiency.
+ *
+ * @param groupName The group name
+ * @return This conflict builder instance.
+ */
+ @NotNull
+ public ConflictBuilder addExcludedGroup(@NotNull String groupName){
+ excludedGroupNames.add(groupName);
+ return this;
+ }
+
+ /**
+ * Add an excluded group by instance.
+ *
+ * If left item of an anvil craft is included on one of the excluded group it will ignore this conflict.
+ *
+ * This allows to create conflict only for some item. Material restriction can be written like that.
+ *
+ * For example: If we exclude a material group containing every pickaxe and add efficiency enchantment
+ * with {@link #setMaxBeforeConflict(int) maxBeforeConflict} set to 0.
+ * Then only pickaxe will be able to have efficiency.
+ *
+ * @param group The group
+ * @return this conflict builder instance.
+ */
+ @NotNull
+ public ConflictBuilder addExcludedGroup(@NotNull AbstractMaterialGroup group){
+ return addExcludedGroup(group.getName());
+ }
+
+ /**
+ * Remove an excluded group by name.
+ *
+ * If left item of an anvil craft is included on one of the excluded group it will ignore this conflict.
+ *
+ * This allows to create conflict only for some item. Material restriction can be written like that.
+ *
+ * For example: If we exclude a material group containing every pickaxe and add efficiency enchantment
+ * with {@link #setMaxBeforeConflict(int) maxBeforeConflict} set to 0.
+ * Then only pickaxe will be able to have efficiency.
+ *
+ * @param groupName The group name
+ * @return This conflict builder instance.
+ */
+ @NotNull
+ public ConflictBuilder removeExcludedGroup(@NotNull String groupName){
+ excludedGroupNames.remove(groupName);
+ return this;
+ }
+
+ /**
+ * Remove an excluded group by instance.
+ *
+ * If left item of an anvil craft is included on one of the excluded group it will ignore this conflict.
+ *
+ * This allows to create conflict only for some item. Material restriction can be written like that.
+ *
+ * For example: If we exclude a material group containing every pickaxe and add efficiency enchantment
+ * with {@link #setMaxBeforeConflict(int) maxBeforeConflict} set to 0.
+ * Then only pickaxe will be able to have efficiency.
+ *
+ * @param group The group
+ * @return This conflict builder instance.
+ */
+ @NotNull
+ public ConflictBuilder removeExcludedGroup(@NotNull AbstractMaterialGroup group){
+ return removeExcludedGroup(group.getName());
+ }
+
+ /**
+ * Copy this conflict builder.
+ *
+ * @return A copy of this conflict builder.
+ */
+ @NotNull
+ public ConflictBuilder copy() {
+ ConflictBuilder copy = new ConflictBuilder(this.name, this.source);
+
+ setMaxBeforeConflict(this.maxBeforeConflict);
+
+ // Set Enchantments
+ for (NamespacedKey key : this.enchantmentKeys) {
+ copy.addEnchantment(key);
+ }
+ for (String enchantName : this.enchantmentNames) {
+ copy.addEnchantment(enchantName);
+ }
+
+ // Set Groups
+ for (String groupName : this.excludedGroupNames) {
+ copy.addExcludedGroup(groupName);
+ }
+
+ return copy;
+ }
+ /**
+ * Build a new Enchant conflict group by this builder.
+ * @return An Enchant conflict group with this builder parameters.
+ */
+ public EnchantConflictGroup build(){
+ AbstractMaterialGroup materials = extractGroups();
+ EnchantConflictGroup conflict = new EnchantConflictGroup(getName(), materials, getMaxBeforeConflict());
+ appendEnchantments(conflict);
+
+ return conflict;
+ }
+
+ /**
+ * Register this conflict if not yet registered.
+ * Equivalent to {@link ConflictAPI#addConflict(ConflictBuilder)}
+ * @return True if successful.
+ */
+ public boolean registerIfAbsent(){
+ return ConflictAPI.addConflict(this);
+ }
+
+ /**
+ * Append builders stored enchantments into conflict.
+ *
+ * @param conflict The conflict target
+ */
+ protected void appendEnchantments(@NotNull EnchantConflictGroup conflict){
+ for (String enchantmentName : getEnchantmentNames()){
+ if(appendEnchantment(conflict, EnchantmentApi.getByName(enchantmentName))){
+ CustomAnvil.instance.getLogger().warning("Could not find enchantment " + enchantmentName + " for conflict " + getName());
+ ConflictAPI.logConflictOrigin(this);
+ }
+ }
+ for (NamespacedKey enchantmentKey : getEnchantmentKeys()){
+ if(!appendEnchantment(conflict, EnchantmentApi.getByKey(enchantmentKey))){
+ CustomAnvil.instance.getLogger().warning("Could not find enchantment " + enchantmentKey + " for conflict " + getName());
+ ConflictAPI.logConflictOrigin(this);
+ }
+ }
+ }
+
+ /**
+ * Append an enchantment.
+ *
+ * @param conflict The conflict target
+ * @param enchantment The enchantment
+ * @return True if successful.
+ */
+ protected static boolean appendEnchantment(@NotNull EnchantConflictGroup conflict, @Nullable CAEnchantment enchantment){
+ if(enchantment == null)
+ return false;
+ conflict.addEnchantment(enchantment);
+ return true;
+ }
+
+ /**
+ * Extract group abstract material group.
+ *
+ * @return The abstract material group from the builder.
+ */
+ protected AbstractMaterialGroup extractGroups(){
+ ItemGroupManager itemGroupManager = ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager();
+ IncludeGroup group = new IncludeGroup(EnchantConflictManager.DEFAULT_GROUP_NAME);
+
+ for (String groupName : getExcludedGroupNames()) {
+ AbstractMaterialGroup materialGroup = itemGroupManager.get(groupName);
+
+ if(materialGroup == null){
+ CustomAnvil.instance.getLogger().warning("Material group " + groupName + " do not exist but is ask by conflict " + getName());
+ ConflictAPI.logConflictOrigin(this);
+ continue;
+ }
+
+ group.addToPolicy(materialGroup);
+ }
+
+ return group;
+ }
+
+}
diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApi.java b/src/main/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApi.java
new file mode 100644
index 0000000..69bfad2
--- /dev/null
+++ b/src/main/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApi.java
@@ -0,0 +1,108 @@
+package xyz.alexcrea.cuanvil.api;
+
+import io.delilaheve.CustomAnvil;
+import org.bukkit.Bukkit;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.jetbrains.annotations.NotNull;
+import xyz.alexcrea.cuanvil.config.ConfigHolder;
+import xyz.alexcrea.cuanvil.gui.config.global.CustomRecipeConfigGui;
+import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Custom Anvil api for custom anvil recipes.
+ */
+@SuppressWarnings("unused")
+public class CustomAnvilRecipeApi {
+
+ private CustomAnvilRecipeApi(){}
+
+ private static int saveChangeTask = -1;
+
+ /**
+ * Write and add a custom anvil recipe.
+ * Will not write the recipe if it already exists.
+ *
+ * @param builder The recipe builder to be based on
+ * @return True if successful.
+ */
+ public static boolean addRecipe(@NotNull AnvilRecipeBuilder builder){
+ FileConfiguration config = ConfigHolder.CUSTOM_RECIPE_HOLDER.getConfig();
+ String name = builder.getName();
+
+ if(config.contains(builder.getName())) return false;
+ if(builder.getName().contains(".")) {
+ CustomAnvil.instance.getLogger().warning("Custom anvil recipe " + name + " contain \".\" in its name but should not. this recipe is ignored.");
+ return false;
+ }
+
+ AnvilCustomRecipe recipe = builder.build();
+ if(recipe == null){
+ CustomAnvil.instance.getLogger().warning("Custom anvil recipe " + name + " could not be parsed.");
+ if(builder.getLeftItem() == null){
+ CustomAnvil.instance.getLogger().warning("It look like left item of the recipe is null.");
+ }
+ if(builder.getResultItem() == null){
+ CustomAnvil.instance.getLogger().warning("It look like result item of the recipe is null.");
+ }
+ return false;
+ }
+
+ // Add to registry
+ ConfigHolder.CUSTOM_RECIPE_HOLDER.getRecipeManager().cleanAddNew(recipe);
+
+ // Save to file
+ recipe.saveToFile(false, false);
+ prepareSaveTask();
+
+ // Add from gui
+ CustomRecipeConfigGui.INSTANCE.updateValueForGeneric(recipe, true);
+
+ return true;
+ }
+
+ /**
+ * Remove a custom anvil recipe.
+ *
+ * @param recipe The recipe to remove
+ * @return True if successful.
+ */
+ public static boolean removeRecipe(@NotNull AnvilCustomRecipe recipe){
+ // Remove from registry
+ ConfigHolder.CUSTOM_RECIPE_HOLDER.getRecipeManager().cleanRemove(recipe);
+
+ // Write as null and save to file
+ ConfigHolder.CUSTOM_RECIPE_HOLDER.getConfig().set(recipe.getName(), null);
+ prepareSaveTask();
+
+ // Remove from gui
+ CustomRecipeConfigGui.INSTANCE.removeGeneric(recipe);
+
+ return true;
+ }
+
+ /**
+ * Prepare a task to save custom recipe configuration.
+ */
+ private static void prepareSaveTask() {
+ if(saveChangeTask != -1) return;
+
+ saveChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
+ ConfigHolder.CONFLICT_HOLDER.saveToDisk(true);
+ saveChangeTask = -1;
+ }, 0L);
+ }
+
+ /**
+ * Get every registered recipes.
+ * @return An immutable collection of recipes.
+ */
+ @NotNull
+ public static List getRegisteredRecipes(){
+ List mutableList = ConfigHolder.CUSTOM_RECIPE_HOLDER.getRecipeManager().getRecipeList();
+ return Collections.unmodifiableList(mutableList);
+ }
+
+}
diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java b/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java
new file mode 100644
index 0000000..b950938
--- /dev/null
+++ b/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java
@@ -0,0 +1,207 @@
+package xyz.alexcrea.cuanvil.api;
+
+import io.delilaheve.CustomAnvil;
+import org.bukkit.Bukkit;
+import org.bukkit.NamespacedKey;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.enchantments.Enchantment;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import xyz.alexcrea.cuanvil.config.ConfigHolder;
+import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
+import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry;
+import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
+import xyz.alexcrea.cuanvil.enchant.bulk.BulkCleanEnchantOperation;
+import xyz.alexcrea.cuanvil.enchant.bulk.BulkGetEnchantOperation;
+import xyz.alexcrea.cuanvil.enchant.wrapped.CAVanillaEnchantment;
+import xyz.alexcrea.cuanvil.gui.config.global.EnchantCostConfigGui;
+import xyz.alexcrea.cuanvil.gui.config.global.EnchantLimitConfigGui;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Custom Anvil api for enchantment registry.
+ */
+@SuppressWarnings("unused")
+public class EnchantmentApi {
+
+ private static int saveChangeTask = -1;
+
+ private EnchantmentApi() {}
+
+ /**
+ * Register an enchantment.
+ *
+ * @param enchantment The enchantment to register
+ * @return True if successful.
+ */
+ public static boolean registerEnchantment(@NotNull CAEnchantment enchantment){
+ if(!CAEnchantmentRegistry.getInstance().register(enchantment)) return false;
+
+ // Add enchantment to gui.
+ if(EnchantCostConfigGui.getInstance() != null){
+ EnchantCostConfigGui.getInstance().updateValueForGeneric(enchantment, true);
+ }
+ if(EnchantLimitConfigGui.getInstance() != null){
+ EnchantLimitConfigGui.getInstance().updateValueForGeneric(enchantment, true);
+ }
+
+ // Write default if do not exist
+ writeDefaultConfig(enchantment, false);
+
+ return true;
+ }
+
+ /**
+ * Register an enchantment by minecraft registered enchantment instance.
+ *
+ * @param enchantment The enchantment to register
+ * @param defaultRarity The default rarity of the provided enchantment
+ * @return True if successful.
+ */
+ public static boolean registerEnchantment(@NotNull Enchantment enchantment, @Nullable EnchantmentRarity defaultRarity){
+ if(defaultRarity == null)
+ return registerEnchantment(new CAVanillaEnchantment(enchantment));
+
+ return registerEnchantment(new CAVanillaEnchantment(enchantment, defaultRarity));
+ }
+
+ /**
+ * Register an enchantment by minecraft registered enchantment instance.
+ *
+ * Please note that this function assume the provided enchantment is registered into minecraft registry.
+ *
+ * @param enchantment The enchantment to register
+ * @return True if successful.
+ */
+ public static boolean registerEnchantment(@NotNull Enchantment enchantment){
+ return registerEnchantment(new CAVanillaEnchantment(enchantment));
+ }
+
+ /**
+ * Unregister an enchantment.
+ *
+ * @param enchantment The enchantment to unregister
+ * @return True if successful.
+ */
+ public static boolean unregisterEnchantment(@Nullable CAEnchantment enchantment){
+ // Remove from gui
+ if(EnchantCostConfigGui.getInstance() != null){
+ EnchantCostConfigGui.getInstance().removeGeneric(enchantment);
+ }
+ if(EnchantLimitConfigGui.getInstance() != null){
+ EnchantLimitConfigGui.getInstance().removeGeneric(enchantment);
+ }
+
+ return CAEnchantmentRegistry.getInstance().unregister(enchantment);
+ }
+
+ /**
+ * Unregister an enchantment by its key.
+ *
+ * @param key The enchantment key to unregister
+ * @return True if successful.
+ */
+ public static boolean unregisterEnchantment(@NotNull NamespacedKey key){
+ CAEnchantment enchantment = CAEnchantmentRegistry.getInstance().getByKey(key);
+ return unregisterEnchantment(enchantment);
+ }
+
+ /**
+ * Unregister an enchantment by his bukkit enchantment.
+ *
+ * @param enchantment The enchantment to unregister
+ * @return True if successful.
+ */
+ public static boolean unregisterEnchantment(@NotNull Enchantment enchantment){
+ return unregisterEnchantment(enchantment.getKey());
+ }
+
+ /**
+ * Get by key an enchantment.
+ *
+ * @param key The key used to fetch
+ * @return The custom anvil enchantment of this key. null if not found.
+ */
+ @Nullable
+ public static CAEnchantment getByKey(@NotNull NamespacedKey key){
+ return CAEnchantmentRegistry.getInstance().getByKey(key);
+ }
+
+ /**
+ * Get by name an enchantment.
+ *
+ * @param name The name used to fetch
+ * @return The custom anvil enchantment of this name. null if not found.
+ */
+ @Nullable
+ public static CAEnchantment getByName(@NotNull String name){
+ return CAEnchantmentRegistry.getInstance().getByName(name);
+ }
+
+ /**
+ * Get every registered custom anvil enchantments.
+ * @return An immutable map of enchantment key as map key and custom anvil enchantment as value.
+ */
+ @NotNull
+ public static Map getRegisteredEnchantments(){
+ return Collections.unmodifiableMap(CAEnchantmentRegistry.getInstance().registeredEnchantments());
+ }
+
+ /**
+ * Write the default level and rarity configuration of the enchantment.
+ * @param enchantment The enchantment to write default configuration
+ * @param override If it should override old configuration
+ * @return Return false if override is false and a configuration exist. true otherwise.
+ */
+ public static boolean writeDefaultConfig(CAEnchantment enchantment, boolean override){
+ FileConfiguration config = ConfigHolder.DEFAULT_CONFIG.getConfig();
+ if(!override && config.contains(enchantment.getName())) return false;
+
+ writeDefaultConfig(config, enchantment);
+
+ prepareSaveTask();
+ return true;
+ }
+
+
+ private static void writeDefaultConfig(FileConfiguration defaultConfig, CAEnchantment enchantment) {
+ defaultConfig.set("enchant_limits." + enchantment.getKey().getKey(), enchantment.defaultMaxLevel());
+
+ String basePath = "enchant_values." + enchantment.getKey().getKey();
+ EnchantmentRarity rarity = enchantment.defaultRarity();
+
+ defaultConfig.set(basePath + ".item", rarity.getItemValue());
+ defaultConfig.set(basePath + ".book", rarity.getBookValue());
+ }
+
+ /**
+ * Prepare a task to save custom recipe configuration.
+ */
+ private static void prepareSaveTask() {
+ if(saveChangeTask != -1) return;
+
+ saveChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
+ ConfigHolder.DEFAULT_CONFIG.saveToDisk(true);
+ saveChangeTask = -1;
+ }, 0L);
+ }
+
+ /**
+ * Add a bulk get operator.
+ * @param operation An optimised get enchantments operation
+ */
+ public static void addBulkGet(@NotNull BulkGetEnchantOperation operation){
+ CAEnchantmentRegistry.getInstance().getOptimisedGetOperators().add(operation);
+ }
+
+ /**
+ * Add a bulk clean operator.
+ * @param operation An optimised clean enchantments operation
+ */
+ public static void addBulkClean(@NotNull BulkCleanEnchantOperation operation){
+ CAEnchantmentRegistry.getInstance().getOptimisedCleanOperators().add(operation);
+ }
+
+}
diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/MaterialGroupApi.java b/src/main/java/xyz/alexcrea/cuanvil/api/MaterialGroupApi.java
new file mode 100644
index 0000000..b3283aa
--- /dev/null
+++ b/src/main/java/xyz/alexcrea/cuanvil/api/MaterialGroupApi.java
@@ -0,0 +1,205 @@
+package xyz.alexcrea.cuanvil.api;
+
+import io.delilaheve.CustomAnvil;
+import io.delilaheve.util.ConfigOptions;
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import xyz.alexcrea.cuanvil.config.ConfigHolder;
+import xyz.alexcrea.cuanvil.group.AbstractMaterialGroup;
+import xyz.alexcrea.cuanvil.group.ExcludeGroup;
+import xyz.alexcrea.cuanvil.group.IncludeGroup;
+import xyz.alexcrea.cuanvil.group.ItemGroupManager;
+import xyz.alexcrea.cuanvil.gui.config.global.GroupConfigGui;
+
+import java.util.*;
+
+/**
+ * Custom Anvil api for material group registry.
+ */
+@SuppressWarnings("unused")
+public class MaterialGroupApi {
+
+ private MaterialGroupApi(){}
+
+ private static int saveChangeTask = -1;
+ private static int reloadChangeTask = -1;
+
+ /**
+ * Write and add a group.
+ * Will not write the group if it already exists.
+ *
+ * @param group the group to add
+ * @return true if successful.
+ */
+ public static boolean addMaterialGroup(@NotNull AbstractMaterialGroup group){
+ ItemGroupManager itemGroupManager = ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager();
+ if(itemGroupManager.get(group.getName()) != null) return false;
+ itemGroupManager.getGroupMap().put(group.getName(), group);
+
+ if(!writeMaterialGroup(group, false)) return false;
+
+ if(group instanceof IncludeGroup includeGroup){
+ GroupConfigGui.INSTANCE.updateValueForGeneric(includeGroup, true);
+ }
+
+ if(ConfigOptions.INSTANCE.getVerboseDebugLog()){
+ CustomAnvil.instance.getLogger().info("Registered group " + group.getName());
+ }
+
+ return true;
+ }
+
+ /**
+ * Write a material group to the config file and plan an update of groups.
+ *
+ * You may want to use {@link #addMaterialGroup(AbstractMaterialGroup)} instead as it is more performance in most case as this function will reload every conflict.
+ *
+ * @param group the group to write
+ * @return true if successful.
+ */
+ public static boolean writeMaterialGroup(@NotNull AbstractMaterialGroup group){
+ return writeMaterialGroup(group, true);
+ }
+
+ /**
+ * Write a material group to the config file.
+ *
+ * You should use {@link #addMaterialGroup(AbstractMaterialGroup)} or {@link #writeMaterialGroup(AbstractMaterialGroup)} instead
+ *
+ * @param group the group to write
+ * @param updatePlanned if we should plan a global update for material groups
+ * @return true if successful.
+ */
+ public static boolean writeMaterialGroup(@NotNull AbstractMaterialGroup group, boolean updatePlanned){
+ String name = group.getName();
+ if(name.contains(".")) {
+ CustomAnvil.instance.getLogger().warning("Group " + name +" contain . in its name but should not. this material group is ignored.");
+ return false;
+ }
+
+ if(group instanceof IncludeGroup includeGroup){
+ writeKnownGroup("include", includeGroup);
+ }else if(group instanceof ExcludeGroup excludeGroup){
+ writeKnownGroup("exclude", excludeGroup);
+ }else{
+ writeUnknownGroup(group);
+ }
+
+ prepareSaveTask();
+ if(updatePlanned) prepareUpdateTask();
+
+ return true;
+ }
+
+ private static void writeKnownGroup(@NotNull String groupType, @NotNull AbstractMaterialGroup group){
+ FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig();
+
+ String basePath = group.getName() + ".";
+ Set materialSet = group.getNonGroupInheritedMaterials();
+ Set groupSet = group.getGroups();
+
+ config.set(basePath + ItemGroupManager.GROUP_TYPE_PATH, groupType);
+ if(!materialSet.isEmpty()){
+ config.set(basePath + ItemGroupManager.MATERIAL_LIST_PATH, materialSetToStringList(materialSet));
+ }
+ if(!groupSet.isEmpty()){
+ config.set(basePath + ItemGroupManager.GROUP_LIST_PATH, materialGroupSEtToStringList(groupSet));
+ }
+
+ }
+
+ private static void writeUnknownGroup(@NotNull AbstractMaterialGroup group) {
+ FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig();
+
+ String basePath = group.getName() + ".";
+ EnumSet materials = group.getMaterials();
+
+ config.set(basePath + ItemGroupManager.GROUP_TYPE_PATH, "include");
+ if(!materials.isEmpty()){
+ config.set(basePath + ItemGroupManager.MATERIAL_LIST_PATH, materialSetToStringList(materials));
+ }
+
+ }
+
+ public static List materialSetToStringList(@NotNull Set materials){
+ return materials.stream().map(material -> material.getKey().getKey().toLowerCase()).toList();
+ }
+
+ public static List materialGroupSEtToStringList(@NotNull Set groups){
+ return groups.stream().map(AbstractMaterialGroup::getName).toList();
+ }
+
+ /**
+ * Remove a material group.
+ * Caution ! It will not be removed from depending conflict or other material group at runtime.
+ * For that reason, it is not recommended to use this function.
+ *
+ * @param group The recipe to remove
+ * @return True if successful.
+ */
+ public static boolean removeGroup(@NotNull AbstractMaterialGroup group){
+ // Remove from registry
+ ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager().groupMap.remove(group.getName());
+
+ // Write as null and save to file
+ ConfigHolder.ITEM_GROUP_HOLDER.getConfig().set(group.getName(), null);
+ prepareSaveTask();
+
+ // Remove from gui
+ if(group instanceof IncludeGroup includeGroup){
+ GroupConfigGui.INSTANCE.removeGeneric(includeGroup);
+ }
+
+ return true;
+ }
+
+ /**
+ * Prepare a task to reload every conflict.
+ */
+ private static void prepareSaveTask() {
+ if(saveChangeTask != -1) return;
+
+ saveChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
+ ConfigHolder.ITEM_GROUP_HOLDER.saveToDisk(true);
+ saveChangeTask = -1;
+ }, 0L);
+ }
+
+ /**
+ * Prepare a task to save configuration.
+ */
+ private static void prepareUpdateTask() {
+ if(reloadChangeTask != -1) return;
+
+ reloadChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
+ ConfigHolder.ITEM_GROUP_HOLDER.reload();
+ GroupConfigGui.INSTANCE.reloadValues();
+ reloadChangeTask = -1;
+ }, 0L);
+
+ }
+
+ /**
+ * Get by name a group.
+ *
+ * @param groupName the group name used to fetch
+ * @return the abstract group of this name. null if not found.
+ */
+ @Nullable
+ public static AbstractMaterialGroup getGroup(@NotNull String groupName){
+ return ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager().get(groupName);
+ }
+
+ /**
+ * Get every registered material groups.
+ * @return An immutable map of group name as its key and group as mapped value.
+ */
+ @NotNull
+ public static Map getRegisteredGroups(){
+ return Collections.unmodifiableMap(ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager().getGroupMap());
+ }
+
+}
diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEvent.java
new file mode 100644
index 0000000..24691db
--- /dev/null
+++ b/src/main/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEvent.java
@@ -0,0 +1,19 @@
+package xyz.alexcrea.cuanvil.api.event;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class CAConfigReadyEvent extends Event {
+
+ private static final HandlerList HANDLERS = new HandlerList();
+
+ public static HandlerList getHandlerList() {
+ return HANDLERS;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLERS;
+ }
+
+}
diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEvent.java
new file mode 100644
index 0000000..3e2fdf8
--- /dev/null
+++ b/src/main/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEvent.java
@@ -0,0 +1,18 @@
+package xyz.alexcrea.cuanvil.api.event;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class CAEnchantRegistryReadyEvent extends Event {
+
+ private static final HandlerList HANDLERS = new HandlerList();
+
+ public static HandlerList getHandlerList() {
+ return HANDLERS;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLERS;
+ }
+}
diff --git a/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java b/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java
index 8999b8b..3cfaf03 100644
--- a/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java
+++ b/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java
@@ -20,21 +20,38 @@ public abstract class ConfigHolder {
public static UnitRepairHolder UNIT_REPAIR_HOLDER;
public static CustomAnvilCraftHolder CUSTOM_RECIPE_HOLDER;
- public static boolean loadConfig() {
+ /**
+ * Load default configuration.
+ * @return True if successful.
+ */
+ public static boolean loadDefaultConfig() {
DEFAULT_CONFIG = new DefaultConfigHolder();
+
+ return DEFAULT_CONFIG.reloadFromDisk(true);
+ }
+
+ /**
+ * Load non default configuration.
+ * @return True if successful.
+ */
+ public static boolean loadNonDefaultConfig() {
ITEM_GROUP_HOLDER = new ItemGroupConfigHolder();
CONFLICT_HOLDER = new ConflictConfigHolder();
UNIT_REPAIR_HOLDER = new UnitRepairHolder();
CUSTOM_RECIPE_HOLDER = new CustomAnvilCraftHolder();
- return reloadAllFromDisk(true);
+ return removeNonDefaultFromDisk(true);
}
public static boolean reloadAllFromDisk(boolean hardfail) {
-
boolean sucess = DEFAULT_CONFIG.reloadFromDisk(hardfail);
if (!sucess) return false;
- sucess = ITEM_GROUP_HOLDER.reloadFromDisk(hardfail);
+
+ return removeNonDefaultFromDisk(hardfail);
+ }
+
+ private static boolean removeNonDefaultFromDisk(boolean hardfail){
+ boolean sucess = ITEM_GROUP_HOLDER.reloadFromDisk(hardfail);
if (!sucess) return false;
sucess = CONFLICT_HOLDER.reloadFromDisk(hardfail);
if (!sucess) return false;
@@ -192,7 +209,7 @@ public abstract class ConfigHolder {
// Class for itemGroupsManager config
public static class ItemGroupConfigHolder extends ResourceConfigHolder {
- private final static String FILE_NAME = "item_groups";
+ private static final String FILE_NAME = "item_groups";
ItemGroupManager itemGroupsManager;
@@ -219,7 +236,7 @@ public abstract class ConfigHolder {
// Class for enchant conflict config
public static class ConflictConfigHolder extends ResourceConfigHolder {
- private final static String FILE_NAME = "enchant_conflict";
+ private static final String FILE_NAME = "enchant_conflict";
EnchantConflictManager conflictManager;
@@ -243,7 +260,7 @@ public abstract class ConfigHolder {
// Class for unit repair config
public static class UnitRepairHolder extends ResourceConfigHolder {
- private final static String ITEM_GROUP_FILE_NAME = "unit_repair_item";
+ private static final String ITEM_GROUP_FILE_NAME = "unit_repair_item";
private UnitRepairHolder() {
@@ -259,7 +276,7 @@ public abstract class ConfigHolder {
// Class for custom anvil craft
public static class CustomAnvilCraftHolder extends ResourceConfigHolder {
- private final static String CUSTOM_RECIPE_FILE_NAME = "custom_recipes";
+ private static final String CUSTOM_RECIPE_FILE_NAME = "custom_recipes";
CustomAnvilRecipeManager recipeManager;
private CustomAnvilCraftHolder() {
diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantment.java
index 4a9a766..0303733 100644
--- a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantment.java
+++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantment.java
@@ -1,28 +1,25 @@
package xyz.alexcrea.cuanvil.enchant;
-import io.delilaheve.util.ItemUtil;
-import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.HumanEntity;
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.dependency.DependencyManager;
-import xyz.alexcrea.cuanvil.dependency.EnchantmentSquaredDependency;
-import xyz.alexcrea.cuanvil.group.ConflictType;
+import xyz.alexcrea.cuanvil.enchant.bulk.BulkCleanEnchantOperation;
+import xyz.alexcrea.cuanvil.enchant.bulk.BulkGetEnchantOperation;
import xyz.alexcrea.cuanvil.group.EnchantConflictGroup;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
-import java.util.function.Supplier;
/**
* Represent an enchantment compatible with Custom Anvil.
- * One issue with custom anvil is: it does not handle well duplicate key name (ignoring namespace) as the plugin was coded with vanilla enchantment in head
+ * One issue with custom anvil is: it does not handle well duplicate key name (ignoring namespace)
+ * as the plugin was initially coded with vanilla enchantment in head
*/
+@SuppressWarnings("unused")
public interface CAEnchantment {
@@ -54,10 +51,16 @@ public interface CAEnchantment {
int defaultMaxLevel();
/**
- * Check if the enchantment have specialised group operation.
- * @return If the enchantment is optimised for group operation.
+ * Check if the enchantment have specialised get bulk operation.
+ * @return If the enchantment is optimised for get bulk operation.
*/
- boolean isOptimised();
+ boolean isGetOptimised();
+
+ /**
+ * Check if the enchantment have specialised clean bulk operation.
+ * @return If the enchantment is optimised for clean bulk operation.
+ */
+ boolean isCleanOptimised();
/**
* Check if the player is allowed to use this enchantment.
@@ -91,14 +94,20 @@ public interface CAEnchantment {
/**
* Get current level of the enchantment.
- * @param item Item to search the level for.
+ * @param item Item to search the level for. Should not get changed.
+ * @return Current leve of this enchantment on item. or 0 if absent.
*/
- int getLevel(@NotNull ItemStack item);
+ default 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.
+ * @param item Item to search the level for. Should not get changed.
+ * @param meta Meta of the provided item. Should not get changed.
* @return Current leve of this enchantment on item. or 0 if absent.
*/
int getLevel(@NotNull ItemStack item, @NotNull ItemMeta meta);
@@ -137,29 +146,23 @@ public interface CAEnchantment {
* @param item Item to be cleared from enchantments.
*/
static void clearEnchants(@NotNull ItemStack item){
+ // Optimised enchantment clean using item stack
+ for (BulkCleanEnchantOperation cleanOperator : CAEnchantmentRegistry.getInstance().getOptimisedCleanOperators()) {
+ cleanOperator.bulkClear(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)
- );
+ // Optimised enchantment clean using item meta
+ for (BulkCleanEnchantOperation cleanOperator : CAEnchantmentRegistry.getInstance().getOptimisedCleanOperators()) {
+ cleanOperator.bulkClear(item, meta);
}
- // Clean Enchant Squared enchants
- EnchantmentSquaredDependency enchantmentSquared = DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility();
- if(enchantmentSquared != null){
- enchantmentSquared.clearEnchantments(item);
- }
+ item.setItemMeta(meta);
// Clean unoptimised enchants
- for (CAEnchantment enchant : CAEnchantmentRegistry.getInstance().unoptimisedValues()) {
+ for (CAEnchantment enchant : CAEnchantmentRegistry.getInstance().unoptimisedCleanValues()) {
if(enchant.isEnchantmentPresent(item)){
enchant.removeFrom(item);
}
@@ -179,25 +182,13 @@ public interface CAEnchantment {
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(registry.getByKey(enchantment.getKey()), level)
- );
- } else {
- item.getEnchantments().forEach(
- (enchantment, level) -> enchantments.put(registry.getByKey(enchantment.getKey()), level)
- );
- }
-
- // Enchants Squared get
- EnchantmentSquaredDependency enchantmentSquared = DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility();
- if(enchantmentSquared != null){
- enchantmentSquared.getEnchantmentsSquared(item, enchantments);
+ // Optimised enchantment get
+ for (BulkGetEnchantOperation getOperator : CAEnchantmentRegistry.getInstance().getOptimisedGetOperators()) {
+ getOperator.bulkGet(enchantments, item, meta);
}
// Unoptimised enchantment get
- findEnchantsFromSelectedList(item, meta, enchantments, registry.unoptimisedValues());
+ findEnchantsFromSelectedList(item, meta, enchantments, registry.unoptimisedGetValues());
return enchantments;
}
@@ -226,6 +217,8 @@ public interface CAEnchantment {
/**
* Gets an array of all the registered enchantments.
+ *
+ * @param key The enchantment key
* @return Array of enchantment.
*/
static @Nullable CAEnchantment getByKey(@NotNull NamespacedKey key){
@@ -234,6 +227,7 @@ public interface CAEnchantment {
/**
* Gets a list of all the unoptimised enchantments.
+ * @param name The enchantment name
* @return List of enchantment.
*/
static @Nullable CAEnchantment getByName(@NotNull String name){
diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentBase.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentBase.java
index 7ea4666..05718d5 100644
--- a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentBase.java
+++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentBase.java
@@ -1,21 +1,22 @@
package xyz.alexcrea.cuanvil.enchant;
-import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import xyz.alexcrea.cuanvil.group.ConflictType;
import xyz.alexcrea.cuanvil.group.EnchantConflictGroup;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
-import java.util.function.Supplier;
+/**
+ * Default implementation of an enchantment compatible with Custom Anvil.
+ * One issue with custom anvil is: it does not handle well duplicate key name (ignoring namespace)
+ * as the plugin was initially coded with vanilla enchantment in head
+ */
public abstract class CAEnchantmentBase implements CAEnchantment {
@NotNull
@@ -71,7 +72,12 @@ public abstract class CAEnchantmentBase implements CAEnchantment {
}
@Override
- public boolean isOptimised(){
+ public boolean isGetOptimised(){
+ return false;
+ }
+
+ @Override
+ public boolean isCleanOptimised(){
return false;
}
@@ -80,12 +86,6 @@ public abstract class CAEnchantmentBase implements CAEnchantment {
return true;
}
- public int getLevel(@NotNull ItemStack item){
- ItemMeta meta = item.getItemMeta();
- if(meta == null) return 0;
- return getLevel(item, meta);
- }
-
public boolean isEnchantmentPresent(@NotNull ItemStack item){
ItemMeta meta = item.getItemMeta();
if(meta == null) return false;
diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentRegistry.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentRegistry.java
index c00c7c2..1e7cd54 100644
--- a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentRegistry.java
+++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentRegistry.java
@@ -5,13 +5,12 @@ import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import xyz.alexcrea.cuanvil.dependency.DependencyManager;
+import xyz.alexcrea.cuanvil.enchant.bulk.BukkitEnchantBulkOperation;
+import xyz.alexcrea.cuanvil.enchant.bulk.BulkCleanEnchantOperation;
+import xyz.alexcrea.cuanvil.enchant.bulk.BulkGetEnchantOperation;
import xyz.alexcrea.cuanvil.enchant.wrapped.CAVanillaEnchantment;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
+import java.util.*;
import java.util.logging.Level;
public class CAEnchantmentRegistry {
@@ -24,29 +23,38 @@ public class CAEnchantmentRegistry {
// Register enchantment functions
private final HashMap byKeyMap;
private final HashMap byNameMap;
- private final List unoptimisedValues;
+
+ private final List unoptimisedGetValues;
+ private final List unoptimisedCleanValues;
+
+ private final List optimisedGetOperators;
+ private final List optimisedCleanOperators;
private CAEnchantmentRegistry() {
byKeyMap = new HashMap<>();
byNameMap = new HashMap<>();
- unoptimisedValues = new ArrayList<>();
+
+ unoptimisedGetValues = new ArrayList<>();
+ unoptimisedCleanValues = new ArrayList<>();
+
+ optimisedGetOperators = new ArrayList<>();
+ optimisedCleanOperators = 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 void registerStartupEnchantments(){
+ public void registerBukkit(){
+ // Register enchantment
for (Enchantment enchantment : Enchantment.values()) {
register(new CAVanillaEnchantment(enchantment));
}
- if(DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility() != null){
- DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility().registerEnchantments();
- }
- if(DependencyManager.INSTANCE.getEcoEnchantCompatibility() != null){
- DependencyManager.INSTANCE.getEcoEnchantCompatibility().registerEnchantments();
- }
+ // Add bukkit enchantment bulk operation
+ BukkitEnchantBulkOperation bukkitOperation = new BukkitEnchantBulkOperation();
+ optimisedGetOperators.add(bukkitOperation);
+ optimisedCleanOperators.add(bukkitOperation);
}
@@ -56,13 +64,14 @@ public class CAEnchantmentRegistry {
* 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.
+ * @return If the operation was successful.
*/
- public void register(@NotNull CAEnchantment enchantment){
+ public boolean register(@NotNull CAEnchantment enchantment){
if(byKeyMap.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;
+ return false;
}
if(byNameMap.containsKey(enchantment.getName())){
CustomAnvil.instance.getLogger().log(Level.WARNING,
@@ -74,9 +83,14 @@ public class CAEnchantmentRegistry {
byKeyMap.put(enchantment.getKey(), enchantment);
byNameMap.put(enchantment.getName(), enchantment);
- if(!enchantment.isOptimised()){
- unoptimisedValues.add(enchantment);
+ if(!enchantment.isGetOptimised()){
+ unoptimisedGetValues.add(enchantment);
}
+ if(!enchantment.isCleanOptimised()){
+ unoptimisedCleanValues.add(enchantment);
+ }
+
+ return true;
}
/**
@@ -87,13 +101,17 @@ public class CAEnchantmentRegistry {
* 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.
+ * @return If the operation was successful.
*/
- public void unregister(CAEnchantment enchantment){
- if(enchantment == null) return;
+
+ public boolean unregister(@Nullable CAEnchantment enchantment){
+ if(enchantment == null) return false;
byKeyMap.remove(enchantment.getKey());
byNameMap.remove(enchantment.getName());
- unoptimisedValues.remove(enchantment);
+ unoptimisedGetValues.remove(enchantment);
+ unoptimisedCleanValues.remove(enchantment);
+ return true;
}
/**
@@ -101,7 +119,8 @@ public class CAEnchantmentRegistry {
* @param key Key to fetch.
* @return Registered enchantment. null if absent.
*/
- public @Nullable CAEnchantment getByKey(@NotNull NamespacedKey key){
+ @Nullable
+ public CAEnchantment getByKey(@NotNull NamespacedKey key){
return byKeyMap.get(key);
}
@@ -110,13 +129,14 @@ public class CAEnchantmentRegistry {
* @param name Name to fetch.
* @return Registered enchantment. null if absent.
*/
- public @Nullable CAEnchantment getByName(@NotNull String name){
+ @Nullable
+ public CAEnchantment getByName(@NotNull String name){
return byNameMap.get(name);
}
/**
* Gets an array of all the registered enchantments.
- * @return Array of enchantment.
+ * @return Array of enchantments.
*/
@NotNull
public Collection values() {
@@ -124,12 +144,45 @@ public class CAEnchantmentRegistry {
}
/**
- * Gets a list of all the unoptimised enchantments.
- * @return List of enchantment.
+ * Gets a map of all the registered enchantments.
+ * @return Map of enchantments.
+ */
+ public Map registeredEnchantments() {
+ return byKeyMap;
+ }
+
+ /**
+ * Gets a list of all the unoptimised get operation enchantments.
+ * @return List of unoptimised enchantments.
*/
@NotNull
- public List unoptimisedValues() {
- return unoptimisedValues;
+ public List unoptimisedGetValues() {
+ return unoptimisedGetValues;
+ }
+
+ /**
+ * Gets a list of all the unoptimised clean operation enchantments.
+ * @return List of unoptimised enchantments.
+ */
+ @NotNull
+ public List unoptimisedCleanValues() {
+ return unoptimisedCleanValues;
+ }
+
+ /**
+ * Get "clean optimised operation" for get enchantments.
+ * @return Get mutable "clean enchantments optimised operation" list.
+ */
+ public List getOptimisedCleanOperators() {
+ return optimisedCleanOperators;
+ }
+
+ /**
+ * Get "get optimised operation" for get enchantments.
+ * @return Get mutable "get enchantments optimised operation" list.
+ */
+ public List getOptimisedGetOperators() {
+ return optimisedGetOperators;
}
}
diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/EnchantmentRarity.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/EnchantmentRarity.java
index 50fdfdf..57ccb72 100644
--- a/src/main/java/xyz/alexcrea/cuanvil/enchant/EnchantmentRarity.java
+++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/EnchantmentRarity.java
@@ -1,31 +1,31 @@
package xyz.alexcrea.cuanvil.enchant;
-// because spigot (1.18) do not support enchantment rarity, I need to do it myself...
-public enum EnchantmentRarity {
+// because spigot (1.18) do not look like to provide access to enchantment rarity I need to do it myself...
+public class EnchantmentRarity {
- NO_RARITY(0, 0),
- COMMON(1),
- UNCOMMON(2),
- RARE(4),
- VERY_RARE(8);
+ public static final EnchantmentRarity NO_RARITY = new EnchantmentRarity(0, 0);
+ public static final EnchantmentRarity COMMON = new EnchantmentRarity(1);
+ public static final EnchantmentRarity UNCOMMON = new EnchantmentRarity(2);
+ public static final EnchantmentRarity RARE = new EnchantmentRarity(4);
+ public static final EnchantmentRarity VERY_RARE = new EnchantmentRarity(8);
private final int itemValue;
private final int bookValue;
- EnchantmentRarity(int itemValue, int bookValue) {
+ public EnchantmentRarity(int itemValue, int bookValue) {
this.itemValue = itemValue;
this.bookValue = bookValue;
}
- EnchantmentRarity(int itemValue) {
+ public EnchantmentRarity(int itemValue) {
this(itemValue, Math.max(1, itemValue / 2));
}
- public int getBookValue() {
+ public final int getBookValue() {
return bookValue;
}
- public int getItemValue() {
+ public final int getItemValue() {
return itemValue;
}
diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BukkitEnchantBulkOperation.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BukkitEnchantBulkOperation.java
new file mode 100644
index 0000000..d34bd49
--- /dev/null
+++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BukkitEnchantBulkOperation.java
@@ -0,0 +1,47 @@
+package xyz.alexcrea.cuanvil.enchant.bulk;
+
+import io.delilaheve.util.ItemUtil;
+import org.bukkit.Material;
+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.api.EnchantmentApi;
+import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
+
+import java.util.Map;
+
+public class BukkitEnchantBulkOperation implements BulkGetEnchantOperation, BulkCleanEnchantOperation {
+
+ @Override
+ public void bulkGet(@NotNull Map enchantmentList, @NotNull ItemStack item, @NotNull ItemMeta meta) {
+ if (ItemUtil.INSTANCE.isEnchantedBook(item)) {
+ ((EnchantmentStorageMeta)meta).getStoredEnchants().forEach((enchantment, level) ->
+ enchantmentList.put(EnchantmentApi.getByKey(enchantment.getKey()), level)
+ );
+ } else {
+ item.getEnchantments().forEach((enchantment, level) ->
+ enchantmentList.put(EnchantmentApi.getByKey(enchantment.getKey()), level)
+ );
+ }
+ }
+
+ @Override
+ public void bulkClear(@NotNull ItemStack item) {
+ if (item.getType() != Material.ENCHANTED_BOOK) {
+ item.getEnchantments().forEach((enchantment, leve) ->
+ item.removeEnchantment(enchantment)
+ );
+ }
+ }
+
+ @Override
+ public void bulkClear(@NotNull ItemStack item, @NotNull ItemMeta meta) {
+ if (item.getType() == Material.ENCHANTED_BOOK) {
+ EnchantmentStorageMeta bookMeta = (EnchantmentStorageMeta) meta;
+ bookMeta.getStoredEnchants().forEach((enchantment, leve) ->
+ bookMeta.removeStoredEnchant(enchantment)
+ );
+ }
+ }
+}
diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BulkCleanEnchantOperation.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BulkCleanEnchantOperation.java
new file mode 100644
index 0000000..4b1a225
--- /dev/null
+++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BulkCleanEnchantOperation.java
@@ -0,0 +1,28 @@
+package xyz.alexcrea.cuanvil.enchant.bulk;
+
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Bulk operation for clean enchantments operations.
+ */
+public interface BulkCleanEnchantOperation {
+
+ /**
+ * Bulk clear part of the enchantments from this item.
+ * The item can be edited freely. If you need the meta it is preferred to use {@link #bulkClear(ItemStack, ItemMeta)} if possible
+ * @param item The item to clear enchantment from.
+ */
+ void bulkClear(@NotNull ItemStack item);
+
+ /**
+ * Bulk clear part of the enchantments from this item meta.
+ * Item should not be edited as meta will be applied later.
+ * If you need to edit the item and do not need the meta use {@link #bulkClear(ItemStack)}
+ * @param item The item source of the item meta. should not be edited.
+ * @param meta The item meta to clear enchantment from.
+ */
+ void bulkClear(@NotNull ItemStack item, @NotNull ItemMeta meta);
+
+}
diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BulkGetEnchantOperation.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BulkGetEnchantOperation.java
new file mode 100644
index 0000000..a985edd
--- /dev/null
+++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/BulkGetEnchantOperation.java
@@ -0,0 +1,23 @@
+package xyz.alexcrea.cuanvil.enchant.bulk;
+
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.jetbrains.annotations.NotNull;
+import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
+
+import java.util.Map;
+
+/**
+ * Bulk operation for get enchantments operations.
+ */
+public interface BulkGetEnchantOperation {
+
+ /**
+ * Bulk get part of the stored enchantment of this item.
+ * @param enchantmentList Mutable map of collected enchantment. should b
+ * @param item The item to get enchantment from. Should not get edited.
+ * @param meta The item meta to get enchantment from. Should not get edited.
+ */
+ void bulkGet(@NotNull Map enchantmentList, @NotNull ItemStack item, @NotNull ItemMeta meta);
+
+}
diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/EnchantSquaredBulkOperation.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/EnchantSquaredBulkOperation.java
new file mode 100644
index 0000000..59bd6ec
--- /dev/null
+++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/bulk/EnchantSquaredBulkOperation.java
@@ -0,0 +1,37 @@
+package xyz.alexcrea.cuanvil.enchant.bulk;
+
+import me.athlaeos.enchantssquared.managers.CustomEnchantManager;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.jetbrains.annotations.NotNull;
+import xyz.alexcrea.cuanvil.dependency.DependencyManager;
+import xyz.alexcrea.cuanvil.dependency.EnchantmentSquaredDependency;
+import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
+
+import java.util.Collections;
+import java.util.Map;
+
+public class EnchantSquaredBulkOperation implements BulkGetEnchantOperation, BulkCleanEnchantOperation {
+
+ @Override
+ public void bulkGet(@NotNull Map enchantmentList, @NotNull ItemStack item, @NotNull ItemMeta meta) {
+ EnchantmentSquaredDependency enchantmentSquared = DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility();
+ if(enchantmentSquared != null){
+ enchantmentSquared.getEnchantmentsSquared(item, enchantmentList);
+ }
+ }
+
+
+ @Override
+ public void bulkClear(@NotNull ItemStack item) {
+ EnchantmentSquaredDependency enchantmentSquared = DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility();
+ if(enchantmentSquared != null){
+ CustomEnchantManager.getInstance().setItemEnchants(item, Collections.emptyMap());
+ }
+ }
+
+ @Override
+ public void bulkClear(@NotNull ItemStack item, @NotNull ItemMeta meta) {
+ // item meta is not preferred for enchantment squared clear
+ }
+}
diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEcoEnchant.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEcoEnchant.java
index 31991f4..f4ae757 100644
--- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEcoEnchant.java
+++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEcoEnchant.java
@@ -5,13 +5,11 @@ import com.willfp.ecoenchants.target.EnchantmentTarget;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
+import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
-import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment;
-import xyz.alexcrea.cuanvil.group.ConflictType;
import java.util.Map;
-import java.util.function.Supplier;
public class CAEcoEnchant extends CAVanillaEnchantment implements AdditionalTestEnchantment {
diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEnchantSquaredEnchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEnchantSquaredEnchantment.java
index ffc9415..b3f91a9 100644
--- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEnchantSquaredEnchantment.java
+++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAEnchantSquaredEnchantment.java
@@ -27,14 +27,19 @@ public class CAEnchantSquaredEnchantment extends CAEnchantmentBase {
}
@Override
- public boolean isOptimised() {
+ public boolean isGetOptimised() {
+ return true;
+ }
+
+ @Override
+ public boolean isCleanOptimised() {
return true;
}
@Override
public boolean isAllowed(@NotNull HumanEntity human) {
- if(human instanceof Player){
- return this.enchant.hasPermission((Player) human);
+ if(human instanceof Player player){
+ return this.enchant.hasPermission(player);
}
// Not really ideal for maintainability but will probably never be executed. (At least I hope)
boolean required = CustomEnchantManager.getInstance().isRequirePermissions();
diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAVanillaEnchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAVanillaEnchantment.java
index 9fef4c1..136abc3 100644
--- a/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAVanillaEnchantment.java
+++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/wrapped/CAVanillaEnchantment.java
@@ -13,6 +13,9 @@ import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
import java.util.Locale;
+/**
+ * Custom Anvil enchantment implementation for vanilla registered enchantment.
+ */
public class CAVanillaEnchantment extends CAEnchantmentBase {
private final @NotNull Enchantment enchantment;
@@ -29,7 +32,12 @@ public class CAVanillaEnchantment extends CAEnchantmentBase {
}
@Override
- public boolean isOptimised() {
+ public boolean isGetOptimised() {
+ return true;
+ }
+
+ @Override
+ public boolean isCleanOptimised() {
return true;
}
diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java
index 3b6ae2c..b6c1062 100644
--- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java
+++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java
@@ -16,7 +16,7 @@ import java.util.Collections;
public class MainConfigGui extends ChestGui {
- private final static MainConfigGui INSTANCE = new MainConfigGui();
+ private static final MainConfigGui INSTANCE = new MainConfigGui();
public static MainConfigGui getInstance() {
return INSTANCE;
@@ -58,7 +58,7 @@ public class MainConfigGui extends ChestGui {
enchantLimitMeta.setLore(Collections.singletonList("\u00A77Click here to open enchantment level limit menu"));
enchantLimitItemstack.setItemMeta(enchantLimitMeta);
- GuiItem enchantLimitItem = GuiGlobalItems.goToGuiItem(enchantLimitItemstack, EnchantLimitConfigGui.INSTANCE);
+ GuiItem enchantLimitItem = GuiGlobalItems.goToGuiItem(enchantLimitItemstack, new EnchantLimitConfigGui());
pane.bindItem('2', enchantLimitItem);
// enchant cost item
@@ -70,7 +70,7 @@ public class MainConfigGui extends ChestGui {
enchantCostMeta.setLore(Collections.singletonList("\u00A77Click here to open enchantment costs menu"));
enchantCostItemstack.setItemMeta(enchantCostMeta);
- GuiItem enchantCostItem = GuiGlobalItems.goToGuiItem(enchantCostItemstack, EnchantCostConfigGui.INSTANCE);
+ GuiItem enchantCostItem = GuiGlobalItems.goToGuiItem(enchantCostItemstack, new EnchantCostConfigGui());
pane.bindItem('3', enchantCostItem);
// Enchantment Conflicts item
diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java
index 513a6f9..4d900dc 100644
--- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java
+++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java
@@ -12,6 +12,7 @@ import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.dependency.protocolib.PacketManager;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
@@ -31,8 +32,9 @@ import java.util.Collections;
*/
public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
- private static BasicConfigGui INSTANCE;
+ private static BasicConfigGui INSTANCE = null;
+ @Nullable
public static BasicConfigGui getInstance() {
return INSTANCE;
}
@@ -43,7 +45,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
*/
public BasicConfigGui(PacketManager packetManager) {
super(4, "\u00A78Basic Config", CustomAnvil.instance);
- INSTANCE = this;
+ if(INSTANCE == null) INSTANCE = this;
this.packetManager = packetManager;
init();
diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantConflictGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantConflictGui.java
index 6020df6..c4181df 100644
--- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantConflictGui.java
+++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantConflictGui.java
@@ -18,7 +18,7 @@ import java.util.Collection;
public class EnchantConflictGui extends MappedGuiListConfigGui {
- public final static EnchantConflictGui INSTANCE = new EnchantConflictGui();
+ public static final EnchantConflictGui INSTANCE = new EnchantConflictGui();
static {
INSTANCE.init();
@@ -36,7 +36,7 @@ public class EnchantConflictGui extends MappedGuiListConfigGui extends MappedElementListConfigGui< T, S > {
- public MappedGuiListConfigGui(@NotNull String title) {
+ protected MappedGuiListConfigGui(@NotNull String title) {
super(title);
}
diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/EnchantConflictSubSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/EnchantConflictSubSettingGui.java
index 8c17f39..56c4420 100644
--- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/EnchantConflictSubSettingGui.java
+++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/EnchantConflictSubSettingGui.java
@@ -118,10 +118,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
EnchantConflictManager manager = ConfigHolder.CONFLICT_HOLDER.getConflictManager();
// Remove from enchantment
- for (CAEnchantment enchantment : this.enchantConflict.getEnchants()) {
- enchantment.removeConflict(this.enchantConflict);
- }
- manager.conflictList.remove(this.enchantConflict);
+ manager.removeConflict(this.enchantConflict);
// Remove from parent
this.parent.removeGeneric(this.enchantConflict);
diff --git a/src/main/kotlin/io/delilaheve/CustomAnvil.kt b/src/main/kotlin/io/delilaheve/CustomAnvil.kt
index 02423a6..6c4facf 100644
--- a/src/main/kotlin/io/delilaheve/CustomAnvil.kt
+++ b/src/main/kotlin/io/delilaheve/CustomAnvil.kt
@@ -4,6 +4,8 @@ import io.delilaheve.util.ConfigOptions
import org.bukkit.Bukkit
import org.bukkit.configuration.file.YamlConfiguration
import org.bukkit.plugin.java.JavaPlugin
+import xyz.alexcrea.cuanvil.api.event.CAConfigReadyEvent
+import xyz.alexcrea.cuanvil.api.event.CAEnchantRegistryReadyEvent
import xyz.alexcrea.cuanvil.command.EditConfigExecutor
import xyz.alexcrea.cuanvil.command.ReloadExecutor
import xyz.alexcrea.cuanvil.config.ConfigHolder
@@ -80,8 +82,6 @@ class CustomAnvil : JavaPlugin() {
override fun onEnable() {
instance = this
- val pluginManager = Bukkit.getPluginManager();
-
// Disable old plugin name if exist
val potentialPlugin = Bukkit.getPluginManager().getPlugin("UnsafeEnchantsPlus")
if (potentialPlugin != null) {
@@ -90,40 +90,53 @@ class CustomAnvil : JavaPlugin() {
logger.warning("Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus")
}
- // Load dependency
- DependencyManager.loadDependency()
-
- // Register enchantments
- CAEnchantmentRegistry.getInstance().registerStartupEnchantments()
+ // Add commands
+ prepareCommand()
// Load chat listener
chatListener = ChatEventListener()
- pluginManager.registerEvents(chatListener, this)
+ server.pluginManager.registerEvents(chatListener, this)
+
+ // Load dependency
+ DependencyManager.loadDependency()
+
+ // Register anvil events
+ server.pluginManager.registerEvents(AnvilEventListener(DependencyManager.packetManager), this)
+
+ // Load metrics
+ Metrics(this, bstatsPluginId)
+
+ // Load other thing later.
+ // It is so other dependent plugins can implement there event listener before we fire them.
+ Bukkit.getScheduler().scheduleSyncDelayedTask(this, {loadEnchantmentSystem()}, 0L)
+ }
+
+ private fun loadEnchantmentSystem(){
+ // Load default configuration
+ if (!ConfigHolder.loadDefaultConfig()) return
+
+ // Register enchantments
+ CAEnchantmentRegistry.getInstance().registerBukkit()
+ DependencyManager.registerEnchantments()
+
+ val enchantReadyEvent = CAEnchantRegistryReadyEvent()
+ server.pluginManager.callEvent(enchantReadyEvent)
// Load config
- val success = ConfigHolder.loadConfig()
- if (!success) return
+ if (!ConfigHolder.loadNonDefaultConfig()) return
// temporary: handle 1.21 update
Update_1_21.handleUpdate()
- // Handle custom enchant config
- DependencyManager.handleConfigChanges(this)
+ val configReadyEvent = CAConfigReadyEvent()
+ server.pluginManager.callEvent(configReadyEvent)
// Load gui constants //TODO maybe something better later
MainConfigGui.getInstance().init(DependencyManager.packetManager)
GuiSharedConstant.loadConstants()
- // Load metrics
- Metrics(this, bstatsPluginId)
-
- // Add commands to reload the plugin
- prepareCommand()
-
- server.pluginManager.registerEvents(
- AnvilEventListener(DependencyManager.packetManager),
- this
- )
+ // Register enchantment of compatible plugin and load configuration change.
+ DependencyManager.handleCompatibilityConfig()
}
fun reloadResource(
diff --git a/src/main/kotlin/io/delilaheve/util/ItemUtil.kt b/src/main/kotlin/io/delilaheve/util/ItemUtil.kt
index 3c415f6..a85af39 100644
--- a/src/main/kotlin/io/delilaheve/util/ItemUtil.kt
+++ b/src/main/kotlin/io/delilaheve/util/ItemUtil.kt
@@ -29,7 +29,6 @@ object ItemUtil {
fun ItemStack.setEnchantmentsUnsafe(enchantments: Map) {
CAEnchantment.clearEnchants(this)
- //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/command/ReloadExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt
index 151ba6b..ca5a205 100644
--- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt
+++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt
@@ -36,8 +36,8 @@ class ReloadExecutor : CommandExecutor {
// Then update all global gui containing value from config
BasicConfigGui.getInstance()?.updateGuiValues()
- EnchantCostConfigGui.INSTANCE.updateGuiValues()
- EnchantLimitConfigGui.INSTANCE.updateGuiValues()
+ EnchantCostConfigGui.getInstance()?.updateGuiValues()
+ EnchantLimitConfigGui.getInstance()?.updateGuiValues()
EnchantConflictGui.INSTANCE.reloadValues()
GroupConfigGui.INSTANCE.reloadValues()
diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt
index 57e27d7..f3962d5 100644
--- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt
+++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt
@@ -1,11 +1,9 @@
package xyz.alexcrea.cuanvil.dependency
import org.bukkit.Bukkit
-import org.bukkit.plugin.Plugin
import xyz.alexcrea.cuanvil.dependency.protocolib.NoProtocoLib
import xyz.alexcrea.cuanvil.dependency.protocolib.PacketManager
import xyz.alexcrea.cuanvil.dependency.protocolib.ProtocoLibWrapper
-import java.io.File
object DependencyManager {
@@ -19,7 +17,7 @@ object DependencyManager {
// ProtocolLib dependency
packetManager =
if(pluginManager.isPluginEnabled("ProtocolLib")) ProtocoLibWrapper()
- else NoProtocoLib()
+ else NoProtocoLib()
// Enchantment Squared dependency
if(pluginManager.isPluginEnabled("EnchantsSquared")){
@@ -35,11 +33,14 @@ object DependencyManager {
}
- fun handleConfigChanges(plugin: Plugin) {
- val folder = File(plugin.dataFolder, "compatibility")
-
+ fun handleCompatibilityConfig() {
enchantmentSquaredCompatibility?.registerPluginConfiguration()
- ecoEnchantCompatibility?.registerPluginConfiguration(folder)
+
+ }
+
+ fun registerEnchantments() {
+ enchantmentSquaredCompatibility?.registerEnchantments()
+ ecoEnchantCompatibility?.registerEnchantments()
}
diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/EcoEnchantDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/EcoEnchantDependency.kt
index e37237e..713a03c 100644
--- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/EcoEnchantDependency.kt
+++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/EcoEnchantDependency.kt
@@ -2,14 +2,10 @@ package xyz.alexcrea.cuanvil.dependency
import com.willfp.ecoenchants.enchant.EcoEnchants
import io.delilaheve.CustomAnvil
-import org.bukkit.configuration.file.YamlConfiguration
import org.bukkit.event.inventory.PrepareAnvilEvent
import org.bukkit.plugin.Plugin
-import xyz.alexcrea.cuanvil.config.ConfigHolder
-import xyz.alexcrea.cuanvil.enchant.CAEnchantment
-import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
+import xyz.alexcrea.cuanvil.api.EnchantmentApi
import xyz.alexcrea.cuanvil.enchant.wrapped.CAEcoEnchant
-import java.io.File
class EcoEnchantDependency(private val ecoEnchantPlugin: Plugin) {
@@ -22,57 +18,14 @@ class EcoEnchantDependency(private val ecoEnchantPlugin: Plugin) {
}
fun registerEnchantments() {
- val registery = CAEnchantmentRegistry.getInstance()
- for (ecoEnchant in EcoEnchants.values()) {
- val enchantments: CAEnchantment = CAEcoEnchant(ecoEnchant)
-
- registery.unregister(registery.getByKey(ecoEnchant.enchantment.key)) // As eco enchants are considered real enchantment, we need to unregister it.
- registery.register(enchantments)
- }
- }
-
- fun registerPluginConfiguration(folder: File){
- val compatibilityFile = File(folder, "ecoEnchant.yml")
-
- if(compatibilityFile.exists()){
- folder.mkdirs()
- compatibilityFile.createNewFile()
- }
-
- val config = YamlConfiguration.loadConfiguration(compatibilityFile)
- val defaultConfig = ConfigHolder.DEFAULT_CONFIG.config
- var doSave = false
+ CustomAnvil.instance.logger.info("Preparing Eco Enchant compatibility...")
for (ecoEnchant in EcoEnchants.values()) {
- val enchantment = CAEnchantmentRegistry.getInstance().getByKey(ecoEnchant.enchantmentKey)
-
- if(enchantment == null){
- CustomAnvil.instance.logger.warning("Could not find " + ecoEnchant.enchantmentKey + "testing compatibility.")
- continue
- }
-
- // Write enchantment value if needed
- val testPath = "default.${enchantment.key.key}"
- if(!config.getBoolean(testPath, false)){
- doSave = true
- config[testPath] = true
-
- defaultConfig["enchant_limits.${enchantment.key.key}"] = enchantment.defaultMaxLevel()
-
- val rarity = enchantment.defaultRarity()
- defaultConfig["enchant_values.${enchantment.key.key}.item"] = rarity.itemValue
- defaultConfig["enchant_values.${enchantment.key.key}.book"] = rarity.bookValue
-
- }
- }
-
- if(doSave){
- config.save(compatibilityFile)
- ConfigHolder.DEFAULT_CONFIG.saveToDisk(true)
-
- CustomAnvil.instance.logger.info("Saved default for new eco enchant enchantments.")
+ EnchantmentApi.unregisterEnchantment(ecoEnchant.enchantment) // As eco enchants is loaded before custom anvil and register enchantment to registry, we need to unregister old "vanilla" enchant.
+ EnchantmentApi.registerEnchantment(CAEcoEnchant(ecoEnchant))
}
+ CustomAnvil.instance.logger.info("Eco Enchant should now work as expected !")
}
}
diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/EnchantmentSquaredDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/EnchantmentSquaredDependency.kt
index 15aa46e..6a913ec 100644
--- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/EnchantmentSquaredDependency.kt
+++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/EnchantmentSquaredDependency.kt
@@ -3,14 +3,19 @@ package xyz.alexcrea.cuanvil.dependency
import io.delilaheve.CustomAnvil
import me.athlaeos.enchantssquared.enchantments.CustomEnchant
import me.athlaeos.enchantssquared.managers.CustomEnchantManager
+import org.bukkit.Material
import org.bukkit.NamespacedKey
import org.bukkit.event.inventory.PrepareAnvilEvent
import org.bukkit.inventory.ItemStack
import org.bukkit.plugin.Plugin
-import xyz.alexcrea.cuanvil.config.ConfigHolder
+import xyz.alexcrea.cuanvil.api.ConflictBuilder
+import xyz.alexcrea.cuanvil.api.EnchantmentApi
+import xyz.alexcrea.cuanvil.api.MaterialGroupApi
import xyz.alexcrea.cuanvil.enchant.CAEnchantment
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
+import xyz.alexcrea.cuanvil.enchant.bulk.EnchantSquaredBulkOperation
import xyz.alexcrea.cuanvil.enchant.wrapped.CAEnchantSquaredEnchantment
+import xyz.alexcrea.cuanvil.group.IncludeGroup
import java.util.*
class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin) {
@@ -31,14 +36,18 @@ class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin)
}
fun registerEnchantments(){
+ CustomAnvil.instance.logger.info("Preparing Enchantment Squared compatibility...")
+
+ // Register enchantments
for (enchant in CustomEnchantManager.getInstance().allEnchants.values) {
- CAEnchantmentRegistry.getInstance().register(
- CAEnchantSquaredEnchantment(
- enchant
- )
- )
+ EnchantmentApi.registerEnchantment(CAEnchantSquaredEnchantment(enchant))
}
+ // Register bulk operation
+ val bulkOpperations = EnchantSquaredBulkOperation()
+ EnchantmentApi.addBulkGet(bulkOpperations)
+ EnchantmentApi.addBulkClean(bulkOpperations)
+
}
fun getEnchantmentsSquared(item: ItemStack, enchantments: MutableMap) {
@@ -50,10 +59,6 @@ class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin)
}
- fun clearEnchantments(item: ItemStack) {
- CustomEnchantManager.getInstance().removeAllEnchants(item)
- }
-
fun getKeyFromEnchant(enchant: CustomEnchant): NamespacedKey{
return NamespacedKey.fromString(enchant.type.lowercase(Locale.getDefault()), this.enchantmentSquaredPlugin)!!
}
@@ -61,14 +66,8 @@ class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin)
return CAEnchantment.getByKey(getKeyFromEnchant(enchant))!!
}
-
- private val IS_READY_PATH = "enchantment_square_ready"
fun registerPluginConfiguration(){
- val defaultConfig = ConfigHolder.DEFAULT_CONFIG.config
- val isReady = defaultConfig.getBoolean(IS_READY_PATH, false)
- if(isReady) return
-
- CustomAnvil.instance.logger.info("Preparing configuration for Enchantment Squared...")
+ CustomAnvil.instance.logger.info("Preparing Enchantment Squared config...")
// Prepare enchantments
val esEnchantments = ArrayList()
@@ -76,91 +75,62 @@ class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin)
esEnchantments.add(getWrappedEnchant(enchant) as CAEnchantSquaredEnchantment)
}
- // Write default level limit and xp cost
- for (enchantment in esEnchantments) {
- defaultConfig["enchant_limits.${enchantment.key.key}"] = enchantment.defaultMaxLevel()
-
- val rarity = enchantment.defaultRarity()
- defaultConfig["enchant_values.${enchantment.key.key}.item"] = rarity.itemValue
- defaultConfig["enchant_values.${enchantment.key.key}.book"] = rarity.bookValue
- }
-
// Write groups and conflicts
writeMissingGroups()
writeMaterialRestriction(esEnchantments)
writeEnchantmentConflicts(esEnchantments)
- // Set ready
- defaultConfig[IS_READY_PATH] = true
-
- // Save
- ConfigHolder.DEFAULT_CONFIG.saveToDisk(true)
- ConfigHolder.ITEM_GROUP_HOLDER.saveToDisk(true)
- ConfigHolder.CONFLICT_HOLDER.saveToDisk(true)
-
- // Reload
- ConfigHolder.ITEM_GROUP_HOLDER.reload()
-
CustomAnvil.instance.logger.info("Enchantment Squared should now work as expected !")
}
private fun writeMissingGroups(){
// Write group that do not exist on custom anvil.
// (Tools group regroup most of the tool items. I did not create a seperated group for theses)
- val groupConfig = ConfigHolder.ITEM_GROUP_HOLDER.config
- if(!groupConfig.isConfigurationSection("pickaxes")){
- groupConfig["pickaxes.type"] = "include"
- groupConfig["pickaxes.items"] = listOf("wooden_pickaxe", "stone_pickaxe", "iron_pickaxe", "diamond_pickaxe", "golden_pickaxe", "netherite_pickaxe")
- }
+ val pickaxes = IncludeGroup("pickaxes")
+ pickaxes.addAll(Material.WOODEN_PICKAXE, Material.STONE_PICKAXE, Material.IRON_PICKAXE, Material.DIAMOND_PICKAXE, Material.GOLDEN_PICKAXE, Material.NETHERITE_PICKAXE)
+ MaterialGroupApi.addMaterialGroup(pickaxes)
- if(!groupConfig.isConfigurationSection("shovels")){
- groupConfig["shovels.type"] = "include"
- groupConfig["shovels.items"] = listOf("wooden_shovel", "stone_shovel", "iron_shovel", "diamond_shovel", "golden_shovel", "netherite_shovel")
- }
+ val shovels = IncludeGroup("shovels")
+ shovels.addAll(Material.WOODEN_SHOVEL, Material.STONE_SHOVEL, Material.IRON_SHOVEL, Material.DIAMOND_SHOVEL, Material.GOLDEN_SHOVEL, Material.NETHERITE_SHOVEL)
+ MaterialGroupApi.addMaterialGroup(shovels)
- if(!groupConfig.isConfigurationSection("hoes")){
- groupConfig["hoes.type"] = "include"
- groupConfig["hoes.items"] = listOf("wooden_hoe", "stone_hoe", "iron_hoe", "diamond_hoe", "golden_hoe", "netherite_hoe")
- }
+ val hoes = IncludeGroup("hoes")
+ hoes.addAll(Material.WOODEN_HOE, Material.STONE_HOE, Material.IRON_HOE, Material.DIAMOND_HOE, Material.GOLDEN_HOE, Material.NETHERITE_HOE)
+ MaterialGroupApi.addMaterialGroup(hoes)
- if(!groupConfig.isConfigurationSection("shield")){
- groupConfig["shield.type"] = "include"
- groupConfig["shield.items"] = listOf("shield")
- }
+ val shield = IncludeGroup("shield")
+ shield.addToPolicy(Material.SHIELD)
+ MaterialGroupApi.addMaterialGroup(shield)
- if(!groupConfig.isConfigurationSection("elytra")){
- groupConfig["elytra.type"] = "include"
- groupConfig["elytra.items"] = listOf("elytra")
- }
+ val elytra = IncludeGroup("elytra")
+ elytra.addToPolicy(Material.ELYTRA)
+ MaterialGroupApi.addMaterialGroup(elytra)
- if(!groupConfig.isConfigurationSection("trinkets")){
- groupConfig["trinkets.type"] = "include"
- groupConfig["trinkets.items"] = listOf("rotten_flesh")
- }
+ val trinkets = IncludeGroup("trinkets")
+ trinkets.addToPolicy(Material.ROTTEN_FLESH)
+ MaterialGroupApi.addMaterialGroup(trinkets)
}
private fun writeMaterialRestriction(esEnchantments: List){
- val conflictConfig = ConfigHolder.CONFLICT_HOLDER.config
for (enchantment in esEnchantments) {
- val restrictionName = "restriction_${enchantment.key.key}"
- if(!conflictConfig.isConfigurationSection(restrictionName)){
- conflictConfig["$restrictionName.enchantments"] = listOf(enchantment.name)
+ val conflict = ConflictBuilder("restriction_${enchantment.key.key}", CustomAnvil.instance)
+ conflict.addEnchantment(enchantment)
- // Get allowed groups
- val listOfAllowed = ArrayList()
- listOfAllowed.add("enchanted_book") // enchanted book is allowed in any case.
+ // enchanted book is allowed in any case.
+ conflict.addExcludedGroup("enchanted_book")
- for (esGroup in enchantment.enchant.compatibleItems) {
- val caGroup = esGroupToCAGroup(esGroup)
- if(caGroup == null){
- CustomAnvil.instance.logger.info("Could not find equivalent custom anvil group for $esGroup")
- continue
- }
- listOfAllowed.add(caGroup)
+ // Get allowed groups
+ for (esGroup in enchantment.enchant.compatibleItems) {
+ val caGroup = esGroupToCAGroup(esGroup)
+ if(caGroup == null){
+ CustomAnvil.instance.logger.info("Could not find equivalent custom anvil group for $esGroup")
+ continue
}
- conflictConfig["$restrictionName.notAffectedGroups"] = listOfAllowed
+ conflict.addExcludedGroup(caGroup)
}
+
+ conflict.registerIfAbsent()
}
}
@@ -181,18 +151,12 @@ class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin)
}
private fun writeConflict(enchantment1: CAEnchantment, enchantment2: CAEnchantment){
- val conflictConfig = ConfigHolder.CONFLICT_HOLDER.config
- val conflictPath = "${enchantment1.name}_with_${enchantment2.name}_conflict"
+ val conflict = ConflictBuilder("${enchantment1.name}_with_${enchantment2.name}_conflict", CustomAnvil.instance)
- if(!conflictConfig.isConfigurationSection(conflictPath)){
- conflictConfig["$conflictPath.enchantments"] = listOf(enchantment1.name, enchantment2.name)
-
- val empty: List = Collections.emptyList()
- conflictConfig["$conflictPath.notAffectedGroups"] = empty
-
- conflictConfig["$conflictPath.maxEnchantmentBeforeConflict"] = 1
- }
+ conflict.addEnchantment(enchantment1).addEnchantment(enchantment2)
+ conflict.setMaxBeforeConflict(1)
+ conflict.registerIfAbsent()
}
/**
diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/AbstractMaterialGroup.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/AbstractMaterialGroup.kt
index 289f058..ec6e7bc 100644
--- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/AbstractMaterialGroup.kt
+++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/AbstractMaterialGroup.kt
@@ -25,13 +25,37 @@ abstract class AbstractMaterialGroup(private val name: String) {
/**
* Push a material to this group to follow this group policy
+ * @return this instance.
*/
- abstract fun addToPolicy(mat: Material)
+ abstract fun addToPolicy(mat: Material): AbstractMaterialGroup
+
+ /**
+ * Push a list of material to this group to follow this group policy
+ * @return this instance.
+ */
+ fun addAll(vararg materials: Material): AbstractMaterialGroup {
+ for (material in materials) {
+ addToPolicy(material)
+ }
+ return this
+ }
/**
* Push a group to this group to follow this group policy
+ * @return this instance.
*/
- abstract fun addToPolicy(other: AbstractMaterialGroup)
+ abstract fun addToPolicy(other: AbstractMaterialGroup): AbstractMaterialGroup
+
+ /**
+ * Push a list of group to this group to follow this group policy
+ * @return this instance.
+ */
+ fun addAll(vararg otherList: AbstractMaterialGroup): AbstractMaterialGroup {
+ for (group in otherList) {
+ addToPolicy(group)
+ }
+ return this
+ }
/**
* Get the group contained material as a set
diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt
index be8d085..c58c6bf 100644
--- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt
+++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt
@@ -5,7 +5,7 @@ import org.bukkit.Material
import xyz.alexcrea.cuanvil.enchant.CAEnchantment
class EnchantConflictGroup(
- private val name: String,
+ val name: String,
private val cantConflict: AbstractMaterialGroup,
var minBeforeBlock: Int
) {
diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt
index b2d54d4..abebcbc 100644
--- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt
+++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt
@@ -9,7 +9,6 @@ import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment
import xyz.alexcrea.cuanvil.enchant.CAEnchantment
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
import java.util.*
-import kotlin.collections.ArrayList
class EnchantConflictManager {
@@ -28,7 +27,7 @@ class EnchantConflictManager {
private const val FUTURE_USE_PATH = "useInFuture"
// Default name for a joining group
- private const val DEFAULT_GROUP_NAME = "joinedGroup"
+ const val DEFAULT_GROUP_NAME = "joinedGroup"
// 1.20.5 compatibility TODO better update system
private val SWEEPING_EDGE_ENCHANT =
@@ -53,12 +52,21 @@ class EnchantConflictManager {
val section = config.getConfigurationSection(key)!!
val conflict = createConflict(section, itemManager, key)
- addConflictToEnchantments(conflict)
- conflictList.add(conflict)
+ addConflict(conflict)
}
}
+ fun addConflict(conflict: EnchantConflictGroup){
+ addConflictToEnchantments(conflict)
+ conflictList.add(conflict)
+ }
+
+ fun removeConflict(conflict: EnchantConflictGroup){
+ removeConflictFromEnchantments(conflict)
+ conflictList.remove(conflict)
+ }
+
// Add the conflict to enchantments
private fun addConflictToEnchantments(conflict: EnchantConflictGroup) {
conflict.getEnchants().forEach { enchant ->
@@ -66,6 +74,13 @@ class EnchantConflictManager {
}
}
+ // Remove the conflict from enchantments
+ private fun removeConflictFromEnchantments(conflict: EnchantConflictGroup) {
+ conflict.getEnchants().forEach { enchant ->
+ enchant.removeConflict(conflict)
+ }
+ }
+
// create and read a conflict from a yaml section
private fun createConflict(
section: ConfigurationSection,
@@ -140,7 +155,7 @@ class EnchantConflictManager {
): AbstractMaterialGroup {
val group = itemManager.get(groupName)
if (group == null) {
- CustomAnvil.instance.logger.warning("Group $groupName do not exist but is ask by conflict $conflictName")
+ CustomAnvil.instance.logger.warning("Material group $groupName do not exist but is ask by conflict $conflictName")
return IncludeGroup("error_placeholder")
}
@@ -175,7 +190,7 @@ class EnchantConflictManager {
if(doConflict){
return ConflictType.ENCHANTMENT_CONFLICT
}
-;
+
}
}
@@ -188,14 +203,14 @@ class EnchantConflictManager {
}
- return result;
+ return result
}
private fun createPartialResult(item: ItemStack, enchantments: Map): ItemStack {
val newItem = item.clone()
CAEnchantment.clearEnchants(newItem)
- enchantments.forEach{//TODO maybe bulk add if possible
+ enchantments.forEach{
enchantment -> enchantment.key.addEnchantmentUnsafe(newItem, enchantment.value)
}
diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/ExcludeGroup.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/ExcludeGroup.kt
index 247cb83..7684c3f 100644
--- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/ExcludeGroup.kt
+++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/ExcludeGroup.kt
@@ -20,14 +20,18 @@ class ExcludeGroup(name: String) : AbstractMaterialGroup(name) {
return false
}
- override fun addToPolicy(mat: Material) {
+ override fun addToPolicy(mat: Material): ExcludeGroup {
includedMaterial.remove(mat)
groupItems.remove(mat)
+
+ return this
}
- override fun addToPolicy(other: AbstractMaterialGroup) {
+ override fun addToPolicy(other: AbstractMaterialGroup): ExcludeGroup {
includedGroup.add(other)
groupItems.removeAll(other.getMaterials())
+
+ return this
}
override fun setGroups(groups: MutableSet) {
diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/IncludeGroup.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/IncludeGroup.kt
index 968ceb1..848789f 100644
--- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/IncludeGroup.kt
+++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/IncludeGroup.kt
@@ -20,14 +20,18 @@ class IncludeGroup(name: String) : AbstractMaterialGroup(name) {
return false
}
- override fun addToPolicy(mat: Material) {
+ override fun addToPolicy(mat: Material): IncludeGroup {
includedMaterial.add(mat)
groupItems.add(mat)
+
+ return this
}
- override fun addToPolicy(other: AbstractMaterialGroup) {
+ override fun addToPolicy(other: AbstractMaterialGroup): IncludeGroup {
includedGroup.add(other)
groupItems.addAll(other.getMaterials())
+
+ return this
}
override fun setGroups(groups: MutableSet) {
diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt
index c7e3038..114dbe3 100644
--- a/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt
+++ b/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt
@@ -7,7 +7,7 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant
class AnvilCustomRecipe(
- private val name: String,
+ val name: String,
var exactCount: Boolean,
//var exactLeft: Boolean,
//var exactRight: Boolean,
@@ -74,25 +74,30 @@ class AnvilCustomRecipe(
}
- fun saveToFile(){
+ fun saveToFile(writeFile: Boolean, doBackup: Boolean){
val fileConfig = ConfigHolder.CUSTOM_RECIPE_HOLDER.config
- fileConfig.set("$name.$EXACT_COUNT_CONFIG", exactCount)
+ fileConfig["$name.$EXACT_COUNT_CONFIG"] = exactCount
//fileConfig.set("$name.$EXACT_LEFT_CONFIG", exactLeft)
//fileConfig.set("$name.$EXACT_RIGHT_CONFIG", exactRight)
- fileConfig.set("$name.$XP_COST_CONFIG", xpCostPerCraft)
+ fileConfig["$name.$XP_COST_CONFIG"] = xpCostPerCraft
- fileConfig.set("$name.$LEFT_ITEM_CONFIG", leftItem)
- fileConfig.set("$name.$RIGHT_ITEM_CONFIG", rightItem)
- fileConfig.set("$name.$RESULT_ITEM_CONFIG", resultItem)
+ fileConfig["$name.$LEFT_ITEM_CONFIG"] = leftItem
+ fileConfig["$name.$RIGHT_ITEM_CONFIG"] = rightItem
+ fileConfig["$name.$RESULT_ITEM_CONFIG"] = resultItem
- if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) {
- ConfigHolder.CUSTOM_RECIPE_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE)
+ if (writeFile) {
+ ConfigHolder.CUSTOM_RECIPE_HOLDER.saveToDisk(doBackup)
}
}
+ @Deprecated("Should use saveToFile(Boolean, Boolean) instead") //TODO determine when an where to save/do backup and remove use of variable like TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE
+ fun saveToFile(){
+ saveToFile(GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE, GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE)
+ }
+
fun updateFromFile(){
this.exactCount = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getBoolean(
"$name.$EXACT_COUNT_CONFIG",