diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/ConflictAPI.java b/src/main/java/xyz/alexcrea/cuanvil/api/ConflictAPI.java index 8047382..3336a7e 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/api/ConflictAPI.java +++ b/src/main/java/xyz/alexcrea/cuanvil/api/ConflictAPI.java @@ -44,7 +44,7 @@ public class ConflictAPI { * @return True if successful. */ public static boolean addConflict(@NotNull ConflictBuilder builder, boolean overrideDeleted){ - FileConfiguration config = ConfigHolder.CONFLICT_HOLDER.getConfig(); + FileConfiguration config = ConfigHolder.CONFLICT_HOLDER.get(); // Test if conflict can be added if(!overrideDeleted && ConfigHolder.CONFLICT_HOLDER.isDeleted(builder.getName())) return false; @@ -86,10 +86,11 @@ public class ConflictAPI { * @return True if successful. */ public static boolean writeConflict(@NotNull ConflictBuilder builder, boolean updatePlanned){ - FileConfiguration config = ConfigHolder.CONFLICT_HOLDER.getConfig(); + FileConfiguration config = ConfigHolder.CONFLICT_HOLDER.acquiredWrite(); String name = builder.getName(); if(name.contains(".")) { + ConfigHolder.CONFLICT_HOLDER.releaseWrite(); CustomAnvil.instance.getLogger().warning("Conflict " + name +" contain \".\" in its name but should not. this conflict is ignored."); logConflictOrigin(builder); return false; @@ -107,6 +108,7 @@ public class ConflictAPI { prepareSaveTask(); if(updatePlanned) prepareUpdateTask(); + ConfigHolder.CONFLICT_HOLDER.releaseWrite(); return true; } diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApi.java b/src/main/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApi.java index 32db73b..01785b2 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApi.java +++ b/src/main/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApi.java @@ -41,19 +41,27 @@ public class CustomAnvilRecipeApi { * @return True if successful. */ public static boolean addRecipe(@NotNull AnvilRecipeBuilder builder, boolean overrideDeleted){ - FileConfiguration config = ConfigHolder.CUSTOM_RECIPE_HOLDER.getConfig(); + FileConfiguration config = ConfigHolder.CUSTOM_RECIPE_HOLDER.acquiredWrite(); String name = builder.getName(); - if(!overrideDeleted && ConfigHolder.CUSTOM_RECIPE_HOLDER.isDeleted(builder.getName())) return false; - if(config.contains(builder.getName())) return false; + if(!overrideDeleted && ConfigHolder.CUSTOM_RECIPE_HOLDER.isDeleted(builder.getName())) { + ConfigHolder.CUSTOM_RECIPE_HOLDER.releaseWrite(); + return false; + } + if(config.contains(builder.getName())) { + ConfigHolder.CUSTOM_RECIPE_HOLDER.releaseWrite(); + return false; + } if(builder.getName().contains(".")) { + ConfigHolder.CUSTOM_RECIPE_HOLDER.releaseWrite(); 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){ + ConfigHolder.CUSTOM_RECIPE_HOLDER.releaseWrite(); 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."); @@ -66,6 +74,7 @@ public class CustomAnvilRecipeApi { // Add to registry ConfigHolder.CUSTOM_RECIPE_HOLDER.getRecipeManager().cleanAddNew(recipe); + ConfigHolder.CUSTOM_RECIPE_HOLDER.releaseWrite(); // Save to file recipe.saveToFile(false, false); diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java b/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java index 32a62c3..2d0cac6 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java +++ b/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java @@ -169,12 +169,13 @@ public class EnchantmentApi { * @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(); + FileConfiguration config = ConfigHolder.DEFAULT_CONFIG.acquiredWrite(); if(!override && config.contains(enchantment.getName())) return false; writeDefaultConfig(config, enchantment); prepareSaveTask(); + ConfigHolder.DEFAULT_CONFIG.releaseWrite(); return true; } diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/MaterialGroupApi.java b/src/main/java/xyz/alexcrea/cuanvil/api/MaterialGroupApi.java index dd34eb6..a87f055 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/api/MaterialGroupApi.java +++ b/src/main/java/xyz/alexcrea/cuanvil/api/MaterialGroupApi.java @@ -114,7 +114,7 @@ public class MaterialGroupApi { } private static void writeKnownGroup(@NotNull String groupType, @NotNull AbstractMaterialGroup group){ - FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig(); + FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.acquiredWrite(); String basePath = group.getName() + "."; Set materialSet = group.getNonGroupInheritedMaterials(); @@ -128,10 +128,11 @@ public class MaterialGroupApi { config.set(basePath + ItemGroupManager.GROUP_LIST_PATH, materialGroupSEtToStringList(groupSet)); } + ConfigHolder.ITEM_GROUP_HOLDER.releaseWrite(); } private static void writeUnknownGroup(@NotNull AbstractMaterialGroup group) { - FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig(); + FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.acquiredWrite(); String basePath = group.getName() + "."; EnumSet materials = group.getMaterials(); @@ -141,6 +142,7 @@ public class MaterialGroupApi { config.set(basePath + ItemGroupManager.MATERIAL_LIST_PATH, materialSetToStringList(materials)); } + ConfigHolder.ITEM_GROUP_HOLDER.releaseWrite(); } public static List materialSetToStringList(@NotNull Set materials){ diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/UnitRepairApi.java b/src/main/java/xyz/alexcrea/cuanvil/api/UnitRepairApi.java index d471b19..1a7db05 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/api/UnitRepairApi.java +++ b/src/main/java/xyz/alexcrea/cuanvil/api/UnitRepairApi.java @@ -62,7 +62,7 @@ public class UnitRepairApi { * @return true if successful. */ public static boolean addUnitRepair(@NotNull Material unit, @NotNull Material repairable, double value, boolean overrideDeleted){ - FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); + FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.get(); String path = unit.name().toLowerCase() + "." + repairable.name().toLowerCase(); if(!overrideDeleted && ConfigHolder.UNIT_REPAIR_HOLDER.isDeleted(path)) return false; @@ -82,7 +82,7 @@ public class UnitRepairApi { * @return true if successful. */ public static boolean setUnitRepair(@NotNull Material unit, @NotNull Material repairable, double value){ - FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); + FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.acquiredWrite(); String repairableName = repairable.name().toLowerCase(); String path = unit.name().toLowerCase() + "." + repairableName; @@ -100,6 +100,7 @@ public class UnitRepairApi { repairConfigGui.updateValueForGeneric(unit, true); } + ConfigHolder.UNIT_REPAIR_HOLDER.releaseWrite(); return true; } @@ -115,7 +116,7 @@ public class UnitRepairApi { String unitName = unit.name(); String repairableName = repairable.name(); - FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); + FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.acquiredWrite(); config.set(unitName.toLowerCase() + repairableName.toUpperCase(), null); config.set(unitName.toUpperCase() + repairableName.toLowerCase(), null); config.set(unitName.toUpperCase() + repairableName.toUpperCase(), null); @@ -138,6 +139,7 @@ public class UnitRepairApi { } else lastValue = true; + ConfigHolder.UNIT_REPAIR_HOLDER.releaseWrite(); // We only need to "delete" as the lower case to be counted as deleted ConfigHolder.UNIT_REPAIR_HOLDER.delete(unitName.toLowerCase() + repairableName.toLowerCase()); @@ -184,7 +186,7 @@ public class UnitRepairApi { public static List> getUnitRepairs(){ List> mutableList = new ArrayList<>(); - FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); + FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.get(); for (String unitKey : config.getKeys(false)) { // Test if config section exist if(!config.isConfigurationSection(unitKey)) continue; diff --git a/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java b/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java index 2037e23..bce0f6d 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java +++ b/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java @@ -15,7 +15,7 @@ import java.io.IOException; import java.util.logging.Level; @SuppressWarnings("unused") -public abstract class ConfigHolder { +public abstract class ConfigHolder extends LockStoredObject { // Available configuration: public static DefaultConfigHolder DEFAULT_CONFIG; @@ -70,18 +70,29 @@ public abstract class ConfigHolder { // usefull part of the file private static final File BACKUP_FOLDER = new File(CustomAnvil.instance.getDataFolder(), "backup"); - protected FileConfiguration configuration; protected ConfigHolder() { - + super(null); } public abstract boolean reloadFromDisk(boolean hardFail); - public abstract void reload(); + public final void reload(){ + acquiredWrite(); + reloadWriteLocked(); + releaseWrite(); + } + public abstract void reloadWriteLocked(); + + /** + * + * @deprecated use {@link #get()} + * @return the stored config + */ + @Deprecated public FileConfiguration getConfig() { - return configuration; + return get(); } // Config name and files @@ -118,15 +129,19 @@ public abstract class ConfigHolder { CustomAnvil.instance.getLogger().severe("Could not save config: can't delete existing file."); return false; } - FileConfiguration config = getConfig(); + + long readStamp = this.lock.readLock(); + FileConfiguration config = unsafeGet(); try { config.save(base); } catch (IOException e) { e.printStackTrace(); CustomAnvil.instance.getLogger().severe("Could not save config..."); + this.lock.unlockRead(readStamp); return false; } + this.lock.unlockRead(readStamp); CustomAnvil.Companion.log(getConfigFileName()+" saved successfully"); return true; } @@ -173,14 +188,17 @@ public abstract class ConfigHolder { @Override public boolean reloadFromDisk(boolean hardFail) { + acquiredWrite(); CustomAnvil.instance.saveDefaultConfig(); CustomAnvil.instance.reloadConfig(); - this.configuration = CustomAnvil.instance.getConfig(); + + setStored(CustomAnvil.instance.getConfig()); + releaseWrite(); return true; } @Override - public void reload() { + public void reloadWriteLocked() { }// Nothing to do } @@ -203,10 +221,14 @@ public abstract class ConfigHolder { public boolean reloadFromDisk(boolean hardFail) { YamlConfiguration configuration = CustomAnvil.instance.reloadResource( getConfigFileName() + getConfigFileExtension(), hardFail); - if (configuration == null) return false; + if (configuration == null) { + return false; + } - this.configuration = configuration; - reload(); + acquiredWrite(); + setStored(configuration); + reloadWriteLocked(); + releaseWrite(); return true; } @@ -284,7 +306,7 @@ public abstract class ConfigHolder { // Add to the deleted config this.deletedListConfig.set(objectPath, true); - this.getConfig().set(objectPath, null); + this.unsafeGet().set(objectPath, null); // Save the deleted config (may not be the most efficient, but I will handle it later) if(doSave){ @@ -337,12 +359,12 @@ public abstract class ConfigHolder { } @Override - public void reload() { + public void reloadWriteLocked() { // not the most efficient way for in game reload TODO optimise this.itemGroupsManager = new ItemGroupManager(); - this.itemGroupsManager.prepareGroups(this.configuration); + this.itemGroupsManager.prepareGroups(getWhileWrite()); - if (CONFLICT_HOLDER.getConfig() != null) { + if (CONFLICT_HOLDER.unsafeGet() != null) { CONFLICT_HOLDER.reload(); } } @@ -365,10 +387,10 @@ public abstract class ConfigHolder { // We assume this is called after item group manager reload;, @Override - public void reload() { + public void reloadWriteLocked() { // not the most efficient way for in game reload TODO optimise this.conflictManager = new EnchantConflictManager(); - this.conflictManager.prepareConflicts(this.configuration, ITEM_GROUP_HOLDER.getItemGroupsManager()); + this.conflictManager.prepareConflicts(getWhileWrite(), ITEM_GROUP_HOLDER.getItemGroupsManager()); } } @@ -382,7 +404,7 @@ public abstract class ConfigHolder { } @Override - public void reload() { + public void reloadWriteLocked() { } // Do nothing } @@ -402,9 +424,9 @@ public abstract class ConfigHolder { } @Override - public void reload() { + public void reloadWriteLocked() { this.recipeManager = new CustomAnvilRecipeManager(); - this.recipeManager.prepareRecipes(this.configuration); + this.recipeManager.prepareRecipes(getWhileWrite()); } } diff --git a/src/main/java/xyz/alexcrea/cuanvil/config/LockStoredObject.java b/src/main/java/xyz/alexcrea/cuanvil/config/LockStoredObject.java new file mode 100644 index 0000000..1e7c0bc --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/config/LockStoredObject.java @@ -0,0 +1,62 @@ +package xyz.alexcrea.cuanvil.config; + +import java.util.concurrent.locks.StampedLock; + +/** + * Bad implementation to acquire an object in a thread safe way + * Made for read heavy case + * @param The type of object to store + */ +public class LockStoredObject { + + private T stored; + protected final StampedLock lock; + + LockStoredObject(T toStore){ + this.stored = toStore; + this.lock = new StampedLock(); + } + + public T get(){ + long stamp = this.lock.tryOptimisticRead(); + T stored = this.stored; + if (this.lock.validate(stamp)) + return stored; + + stamp = this.lock.readLock(); + try {stored = this.stored;} + finally {this.lock.unlockRead(stamp);} + return stored; + } + + private long writeStamp; + public final T acquiredWrite(){ + writeStamp = lock.writeLock(); + return stored; + } + + public final void releaseWrite(){ + lock.unlockWrite(this.writeStamp); + } + + public void isWriteLocked(){ + if(!lock.isWriteLocked()){ + throw new IllegalStateException("Lock is not write locked"); + } + } + + public final void setStored(T toStore){ + isWriteLocked(); + this.stored = toStore; + } + + public T getWhileWrite(){ + isWriteLocked(); + return stored; + } + + public T unsafeGet(){ + return stored; + } + +} 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 e9525f4..6cd1706 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 @@ -54,10 +54,11 @@ public class EnchantConflictGui extends MappedGuiListConfigGui getEveryDisplayableInstanceOfGeneric() { ArrayList materials = new ArrayList<>(); - for (String matName : ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().getKeys(false)) { + for (String matName : ConfigHolder.UNIT_REPAIR_HOLDER.get().getKeys(false)) { Material mat = Material.getMaterial(matName.toUpperCase()); if(mat != null){ materials.add(mat); diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java index 0bf2a03..1f1b1ae 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java @@ -83,7 +83,9 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui & EnumSettingGui.ConfigurableEnum> @Override public boolean onSave() { - holder.config.getConfig().set(holder.configPath, this.now.configName()); + holder.config.acquiredWrite().set(holder.configPath, this.now.configName()); + holder.config.releaseWrite(); if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { return holder.config.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/IntSettingsGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/IntSettingsGui.java index af977e9..54143c1 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/IntSettingsGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/IntSettingsGui.java @@ -262,7 +262,8 @@ public class IntSettingsGui extends AbstractSettingGui { @Override public boolean onSave() { - holder.config.getConfig().set(holder.configPath, now); + holder.config.acquiredWrite().set(holder.configPath, now); + holder.config.releaseWrite(); if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { return holder.config.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); @@ -340,7 +341,7 @@ public class IntSettingsGui extends AbstractSettingGui { * @return The configured value for the associated setting. */ public int getConfiguredValue() { - return this.config.getConfig().getInt(this.configPath, this.defaultVal); + return this.config.get().getInt(this.configPath, this.defaultVal); } @Override diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/ItemSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/ItemSettingGui.java index 3df2af8..73c3efe 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/ItemSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/ItemSettingGui.java @@ -146,7 +146,8 @@ public class ItemSettingGui extends AbstractSettingGui { @Override public boolean onSave() { - holder.config.getConfig().set(holder.configPath, this.now); + holder.config.acquiredWrite().set(holder.configPath, this.now); + holder.config.releaseWrite(); if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { return holder.config.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); @@ -211,7 +212,7 @@ public class ItemSettingGui extends AbstractSettingGui { * @return The configured value for the associated setting. */ public ItemStack getConfiguredValue() { - return this.config.getConfig().getItemStack(this.configPath, this.defaultVal); + return this.config.get().getItemStack(this.configPath, this.defaultVal); } @NotNull diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java b/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java index 248cc5f..ce20c5a 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java +++ b/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java @@ -10,7 +10,7 @@ import xyz.alexcrea.cuanvil.config.WorkPenaltyType; public class PluginSetDefault { public static void reAddMissingDefault(){ - FileConfiguration config = ConfigHolder.DEFAULT_CONFIG.getConfig(); + FileConfiguration config = ConfigHolder.DEFAULT_CONFIG.acquiredWrite(); int nbSet = 0; @@ -29,6 +29,8 @@ public class PluginSetDefault { nbSet+= trySetDefault(config, ConfigOptions.WORK_PENALTY_TYPE, WorkPenaltyType.DEFAULT.configName()); nbSet+= trySetDefault(config, ConfigOptions.DEFAULT_LIMIT_PATH, ConfigOptions.DEFAULT_ENCHANT_LIMIT); + ConfigHolder.DEFAULT_CONFIG.releaseWrite(); + if(nbSet > 0){ CustomAnvil.instance.getLogger().info("Adding " + nbSet + " absent default config values."); ConfigHolder.DEFAULT_CONFIG.saveToDisk(true); diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/Update_1_21.java b/src/main/java/xyz/alexcrea/cuanvil/update/Update_1_21.java index af21989..176756c 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/update/Update_1_21.java +++ b/src/main/java/xyz/alexcrea/cuanvil/update/Update_1_21.java @@ -14,7 +14,7 @@ public class Update_1_21 { public static void handleUpdate(){ // Assume if version path is not null then it's 1.21 - String oldVersion = ConfigHolder.DEFAULT_CONFIG.getConfig().getString(UpdateUtils.MINECRAFT_VERSION_PATH); + String oldVersion = ConfigHolder.DEFAULT_CONFIG.get().getString(UpdateUtils.MINECRAFT_VERSION_PATH); if(oldVersion != null){ Version version = Version.fromString(oldVersion); @@ -33,10 +33,10 @@ public class Update_1_21 { private static void doUpdate() { CustomAnvil.instance.getLogger().info("Updating config to support 1.21 ..."); - FileConfiguration baseConfig = ConfigHolder.DEFAULT_CONFIG.getConfig(); - FileConfiguration groupConfig = ConfigHolder.ITEM_GROUP_HOLDER.getConfig(); - FileConfiguration conflictConfig = ConfigHolder.CONFLICT_HOLDER.getConfig(); - FileConfiguration unitConfig = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); + FileConfiguration baseConfig = ConfigHolder.DEFAULT_CONFIG.acquiredWrite(); + FileConfiguration groupConfig = ConfigHolder.ITEM_GROUP_HOLDER.acquiredWrite(); + FileConfiguration conflictConfig = ConfigHolder.CONFLICT_HOLDER.acquiredWrite(); + FileConfiguration unitConfig = ConfigHolder.UNIT_REPAIR_HOLDER.acquiredWrite(); // Add mace to groups groupConfig.set("mace.type", "include"); @@ -84,10 +84,17 @@ public class Update_1_21 { // Set version string as 1.21 baseConfig.set(UpdateUtils.MINECRAFT_VERSION_PATH, "1.21"); - // Save + // Release write and save + ConfigHolder.DEFAULT_CONFIG.releaseWrite(); ConfigHolder.DEFAULT_CONFIG.saveToDisk(true); + + ConfigHolder.ITEM_GROUP_HOLDER.releaseWrite(); ConfigHolder.ITEM_GROUP_HOLDER.saveToDisk(true); + + ConfigHolder.CONFLICT_HOLDER.releaseWrite(); ConfigHolder.CONFLICT_HOLDER.saveToDisk(true); + + ConfigHolder.UNIT_REPAIR_HOLDER.releaseWrite(); ConfigHolder.UNIT_REPAIR_HOLDER.saveToDisk(true); // imply reload of CONFLICT_HOLDER diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_6_2.java b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_6_2.java index d004d2d..6e552c5 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_6_2.java +++ b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_6_2.java @@ -14,7 +14,7 @@ public class PUpdate_1_6_2 { private static final String[] toUpdate = new String[] {"restriction_density", "restriction_breach", "restriction_wind_burst"}; public static void handleUpdate(@Nonnull Set toSave) { - FileConfiguration config = ConfigHolder.CONFLICT_HOLDER.getConfig(); + FileConfiguration config = ConfigHolder.CONFLICT_HOLDER.acquiredWrite(); boolean conflictUpdated = false; for (String restriction : toUpdate) { @@ -34,6 +34,7 @@ public class PUpdate_1_6_2 { conflictUpdated = true; } } + ConfigHolder.CONFLICT_HOLDER.releaseWrite(); if(conflictUpdated){ toSave.add(ConfigHolder.CONFLICT_HOLDER); @@ -43,13 +44,14 @@ public class PUpdate_1_6_2 { } // Then we add the unit repair - config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig(); + config = ConfigHolder.UNIT_REPAIR_HOLDER.acquiredWrite(); String unitRepairPath = "breeze_rod.mace"; if(!config.isConfigurationSection(unitRepairPath)){ config.set(unitRepairPath, 0.25); toSave.add(ConfigHolder.UNIT_REPAIR_HOLDER); } + ConfigHolder.UNIT_REPAIR_HOLDER.releaseWrite(); } diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PluginUpdates.java b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PluginUpdates.java index cc0901b..86a6d7c 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PluginUpdates.java +++ b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PluginUpdates.java @@ -13,7 +13,7 @@ public class PluginUpdates { private static final String CONFIG_VERSION_PATH = "configVersion"; public static void handlePluginUpdate(){ - String versionString = ConfigHolder.DEFAULT_CONFIG.getConfig().getString(CONFIG_VERSION_PATH); + String versionString = ConfigHolder.DEFAULT_CONFIG.get().getString(CONFIG_VERSION_PATH); Version current = versionString == null ? new Version(0) : Version.fromString(versionString); Set toSave = new HashSet<>(); @@ -28,7 +28,9 @@ public class PluginUpdates { private static void finishConfiguration(@Nonnull String newVersion, @Nonnull Set toSave) { CustomAnvil.instance.getLogger().info("Configuration file updated to " + newVersion); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(CONFIG_VERSION_PATH, newVersion); + + ConfigHolder.DEFAULT_CONFIG.acquiredWrite().set(CONFIG_VERSION_PATH, newVersion); + ConfigHolder.DEFAULT_CONFIG.releaseWrite(); toSave.add(ConfigHolder.DEFAULT_CONFIG); for (ConfigHolder configHolder : toSave) { diff --git a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt index f192ff9..9c867f5 100644 --- a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt +++ b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt @@ -125,8 +125,7 @@ object ConfigOptions { val doCapCost: Boolean get() { return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(CAP_ANVIL_COST, DEFAULT_CAP_ANVIL_COST) + .get().getBoolean(CAP_ANVIL_COST, DEFAULT_CAP_ANVIL_COST) } /** @@ -135,8 +134,7 @@ object ConfigOptions { val maxAnvilCost: Int get() { return ConfigHolder.DEFAULT_CONFIG - .config - .getInt(MAX_ANVIL_COST, DEFAULT_MAX_ANVIL_COST) + .get().getInt(MAX_ANVIL_COST, DEFAULT_MAX_ANVIL_COST) .takeIf { it in MAX_ANVIL_COST_RANGE } ?: DEFAULT_MAX_ANVIL_COST } @@ -147,8 +145,7 @@ object ConfigOptions { val doRemoveCostLimit: Boolean get() { return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(REMOVE_ANVIL_COST_LIMIT, DEFAULT_REMOVE_ANVIL_COST_LIMIT) + .get().getBoolean(REMOVE_ANVIL_COST_LIMIT, DEFAULT_REMOVE_ANVIL_COST_LIMIT) } /** @@ -157,8 +154,7 @@ object ConfigOptions { val doReplaceTooExpensive: Boolean get() { return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(REPLACE_TOO_EXPENSIVE, DEFAULT_REPLACE_TOO_EXPENSIVE) + .get().getBoolean(REPLACE_TOO_EXPENSIVE, DEFAULT_REPLACE_TOO_EXPENSIVE) } /** @@ -167,8 +163,7 @@ object ConfigOptions { val itemRepairCost: Int get() { return ConfigHolder.DEFAULT_CONFIG - .config - .getInt(ITEM_REPAIR_COST, DEFAULT_ITEM_REPAIR_COST) + .get().getInt(ITEM_REPAIR_COST, DEFAULT_ITEM_REPAIR_COST) .takeIf { it in REPAIR_COST_RANGE } ?: DEFAULT_ITEM_REPAIR_COST } @@ -179,8 +174,7 @@ object ConfigOptions { val unitRepairCost: Int get() { return ConfigHolder.DEFAULT_CONFIG - .config - .getInt(UNIT_REPAIR_COST, DEFAULT_UNIT_REPAIR_COST) + .get().getInt(UNIT_REPAIR_COST, DEFAULT_UNIT_REPAIR_COST) .takeIf { it in REPAIR_COST_RANGE } ?: DEFAULT_UNIT_REPAIR_COST } @@ -191,8 +185,7 @@ object ConfigOptions { val itemRenameCost: Int get() { return ConfigHolder.DEFAULT_CONFIG - .config - .getInt(ITEM_RENAME_COST, DEFAULT_ITEM_RENAME_COST) + .get().getInt(ITEM_RENAME_COST, DEFAULT_ITEM_RENAME_COST) .takeIf { it in ITEM_RENAME_COST_RANGE } ?: DEFAULT_ITEM_RENAME_COST } @@ -203,8 +196,7 @@ object ConfigOptions { val sacrificeIllegalCost: Int get() { return ConfigHolder.DEFAULT_CONFIG - .config - .getInt(SACRIFICE_ILLEGAL_COST, DEFAULT_SACRIFICE_ILLEGAL_COST) + .get().getInt(SACRIFICE_ILLEGAL_COST, DEFAULT_SACRIFICE_ILLEGAL_COST) .takeIf { it in SACRIFICE_ILLEGAL_COST_RANGE } ?: DEFAULT_SACRIFICE_ILLEGAL_COST } @@ -215,8 +207,7 @@ object ConfigOptions { val allowColorCode: Boolean get() { return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(ALLOW_COLOR_CODE, DEFAULT_ALLOW_COLOR_CODE) + .get().getBoolean(ALLOW_COLOR_CODE, DEFAULT_ALLOW_COLOR_CODE) } /** @@ -225,8 +216,7 @@ object ConfigOptions { val allowHexadecimalColor: Boolean get() { return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(ALLOW_HEXADECIMAL_COLOR, DEFAULT_ALLOW_HEXADECIMAL_COLOR) + .get().getBoolean(ALLOW_HEXADECIMAL_COLOR, DEFAULT_ALLOW_HEXADECIMAL_COLOR) } /** @@ -240,8 +230,7 @@ object ConfigOptions { val permissionNeededForColor: Boolean get() { return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(PERMISSION_NEEDED_FOR_COLOR, DEFAULT_PERMISSION_NEEDED_FOR_COLOR) + .get().getBoolean(PERMISSION_NEEDED_FOR_COLOR, DEFAULT_PERMISSION_NEEDED_FOR_COLOR) } /** @@ -250,8 +239,7 @@ object ConfigOptions { val useOfColorCost: Int get() { return ConfigHolder.DEFAULT_CONFIG - .config - .getInt(USE_OF_COLOR_COST, DEFAULT_USE_OF_COLOR_COST) + .get().getInt(USE_OF_COLOR_COST, DEFAULT_USE_OF_COLOR_COST) .takeIf { it in USE_OF_COLOR_COST_RANGE } ?: DEFAULT_USE_OF_COLOR_COST } @@ -263,8 +251,7 @@ object ConfigOptions { get() { return WorkPenaltyType.fromString( ConfigHolder.DEFAULT_CONFIG - .config - .getString(WORK_PENALTY_TYPE)); + .get().getString(WORK_PENALTY_TYPE)); } /** @@ -273,8 +260,7 @@ object ConfigOptions { private val defaultEnchantLimit: Int get() { return ConfigHolder.DEFAULT_CONFIG - .config - .getInt(DEFAULT_LIMIT_PATH, DEFAULT_ENCHANT_LIMIT) + .get().getInt(DEFAULT_LIMIT_PATH, DEFAULT_ENCHANT_LIMIT) } /** @@ -283,8 +269,7 @@ object ConfigOptions { val debugLog: Boolean get() { return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(DEBUG_LOGGING, DEFAULT_DEBUG_LOG) + .get().getBoolean(DEBUG_LOGGING, DEFAULT_DEBUG_LOG) } /** @@ -293,8 +278,7 @@ object ConfigOptions { val verboseDebugLog: Boolean get() { return ConfigHolder.DEFAULT_CONFIG - .config - .getBoolean(VERBOSE_DEBUG_LOGGING, DEFAULT_VERBOSE_DEBUG_LOG) + .get().getBoolean(VERBOSE_DEBUG_LOGGING, DEFAULT_VERBOSE_DEBUG_LOG) } /** diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt index 06d4393..1494e8f 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt @@ -37,7 +37,7 @@ object DependencyManager { } else BukkitScheduler() // Packet Manager - val forceProtocolib = ConfigHolder.DEFAULT_CONFIG.config.getBoolean("force_protocolib", false) + val forceProtocolib = ConfigHolder.DEFAULT_CONFIG.get().getBoolean("force_protocolib", false) packetManager = PacketManagerSelector.selectPacketManager(forceProtocolib) externGuiTester = GuiTesterSelector.selectGuiTester diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt index 114dbe3..8c52756 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt @@ -62,7 +62,7 @@ class AnvilCustomRecipe( } fun getFromConfig(name: String): AnvilCustomRecipe? { - return getFromConfig(name, ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getConfigurationSection(name)) + return getFromConfig(name, ConfigHolder.CUSTOM_RECIPE_HOLDER.unsafeGet().getConfigurationSection(name)) } } @@ -75,7 +75,7 @@ class AnvilCustomRecipe( } fun saveToFile(writeFile: Boolean, doBackup: Boolean){ - val fileConfig = ConfigHolder.CUSTOM_RECIPE_HOLDER.config + val fileConfig = ConfigHolder.CUSTOM_RECIPE_HOLDER.acquiredWrite() fileConfig["$name.$EXACT_COUNT_CONFIG"] = exactCount //fileConfig.set("$name.$EXACT_LEFT_CONFIG", exactLeft) @@ -86,7 +86,7 @@ class AnvilCustomRecipe( fileConfig["$name.$LEFT_ITEM_CONFIG"] = leftItem fileConfig["$name.$RIGHT_ITEM_CONFIG"] = rightItem fileConfig["$name.$RESULT_ITEM_CONFIG"] = resultItem - + ConfigHolder.CUSTOM_RECIPE_HOLDER.releaseWrite() if (writeFile) { ConfigHolder.CUSTOM_RECIPE_HOLDER.saveToDisk(doBackup) @@ -99,28 +99,28 @@ class AnvilCustomRecipe( } fun updateFromFile(){ - this.exactCount = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getBoolean( + this.exactCount = ConfigHolder.CUSTOM_RECIPE_HOLDER.get().getBoolean( "$name.$EXACT_COUNT_CONFIG", DEFAULT_EXACT_COUNT_CONFIG ) - this.xpCostPerCraft = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getInt( + this.xpCostPerCraft = ConfigHolder.CUSTOM_RECIPE_HOLDER.get().getInt( "$name.$XP_COST_CONFIG", DEFAULT_XP_COST_CONFIG ) // Update items - val leftItem = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getItemStack( + val leftItem = ConfigHolder.CUSTOM_RECIPE_HOLDER.get().getItemStack( "$name.$LEFT_ITEM_CONFIG", DEFAULT_LEFT_ITEM_CONFIG ) - this.rightItem = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getItemStack( + this.rightItem = ConfigHolder.CUSTOM_RECIPE_HOLDER.get().getItemStack( "$name.$RIGHT_ITEM_CONFIG", DEFAULT_RIGHT_ITEM_CONFIG ) - this.resultItem = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getItemStack( + this.resultItem = ConfigHolder.CUSTOM_RECIPE_HOLDER.get().getItemStack( "$name.$RESULT_ITEM_CONFIG", DEFAULT_RESULT_ITEM_CONFIG ) diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/UnitRepairUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/UnitRepairUtil.kt index 2047e79..13d09df 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/UnitRepairUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/UnitRepairUtil.kt @@ -20,7 +20,7 @@ object UnitRepairUtil { other: ItemStack? ): Double? { if (other == null) return null - val config = ConfigHolder.UNIT_REPAIR_HOLDER.config + val config = ConfigHolder.UNIT_REPAIR_HOLDER.get() // Get configuration section if exist val otherName = other.type.name.lowercase() var section = config.getConfigurationSection(otherName)