diff --git a/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java b/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java new file mode 100644 index 0000000..0ad0d61 --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java @@ -0,0 +1,239 @@ +package xyz.alexcrea.cuanvil.config; + +import com.google.common.io.Files; +import io.delilaheve.CustomAnvil; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import xyz.alexcrea.cuanvil.group.EnchantConflictManager; +import xyz.alexcrea.cuanvil.group.ItemGroupManager; + +import java.io.File; +import java.io.IOException; + +public abstract class ConfigHolder { + + // Available configuration: + public static DefaultConfigHolder DEFAULT_CONFIG; + public static ItemGroupConfigHolder ITEM_GROUP_HOLDER; + public static ConflictConfigHolder CONFLICT_HOLDER; + public static UnitRepairHolder UNIT_REPAIR_HOLDER; + + public static boolean loadConfig(){ + DEFAULT_CONFIG = new DefaultConfigHolder(); + ITEM_GROUP_HOLDER = new ItemGroupConfigHolder(); + CONFLICT_HOLDER = new ConflictConfigHolder(); + UNIT_REPAIR_HOLDER = new UnitRepairHolder(); + + return reloadAllFromDisk(true); + } + + public static boolean reloadAllFromDisk(boolean hardfail){ + + boolean sucess = DEFAULT_CONFIG.reloadFromDisk(hardfail); + if(!sucess) return false; + sucess = ITEM_GROUP_HOLDER.reloadFromDisk(hardfail); + if(!sucess) return false; + sucess = CONFLICT_HOLDER.reloadFromDisk(hardfail); + if(!sucess) return false; + sucess = UNIT_REPAIR_HOLDER.reloadFromDisk(hardfail); + return sucess; + } + + + // usefull part of the file + private static final File BACKUP_FOLDER = new File(CustomAnvil.instance.getDataFolder(), "backup"); + + protected FileConfiguration configuration; + protected ConfigHolder(){ + + } + + public abstract boolean reloadFromDisk(boolean hardFail); + public abstract void reload(); + public FileConfiguration getConfig(){ + return configuration; + } + + // Config name and files + protected abstract String getConfigFileName(); + + protected String getConfigFileExtension(){ + return ".yml"; + } + protected File getConfigFile(){ + return new File(CustomAnvil.instance.getDataFolder(), getConfigFileName()+getConfigFileExtension()); + } + protected File getFirstBackup(){ + return new File(BACKUP_FOLDER, getConfigFileName()+"-first"+getConfigFileExtension()); + } + protected File getLastBackup(){ + return new File(BACKUP_FOLDER, getConfigFileName()+"-latest"+getConfigFileExtension()); + } + + // Save logic + public boolean saveToDisk(boolean doBackup){ + if(!doBackup){ + if(!saveBackup()){ + CustomAnvil.instance.getLogger().severe("Could not save backup. see above."); + return false; + } + } + File base = getConfigFile(); + // if file exist and can't be deleted the file, then we gave up. + if(base.exists() && !base.delete()) { + CustomAnvil.instance.getLogger().severe("Could not save config: can't delete existing file."); + return false; + } + FileConfiguration config = getConfig(); + try { + config.save(base); + } catch (IOException e) { + e.printStackTrace(); + CustomAnvil.instance.getLogger().severe("Could not save config..."); + return false; + } + + + return true; + } + + public boolean saveBackup(){ + File base = getConfigFile(); + if(!base.exists()) return true; // We did back up everything we had to (nothing in this case) + boolean sufficientSuccess = false; + + BACKUP_FOLDER.mkdirs(); + // save first backup if do not exist + File firstBackup = getFirstBackup(); + if(!firstBackup.exists()){ + try { + Files.copy(base, firstBackup); + sufficientSuccess = true; + } catch (IOException e) { + e.printStackTrace(); + } + } + // save last backup + File lastBackup = getLastBackup(); + // if file exist and can't be deleted the file, then we gave up. + if(lastBackup.exists() && !lastBackup.delete()){ + return sufficientSuccess; + } + + try { + Files.move(base, lastBackup); + sufficientSuccess = true; + } catch (IOException e) { + e.printStackTrace(); + } + + return sufficientSuccess; + } + + public static class DefaultConfigHolder extends ConfigHolder{ + + @Override + protected String getConfigFileName() { + return "config"; + } + + @Override + public boolean reloadFromDisk(boolean hardFail) { + CustomAnvil.instance.reloadConfig(); + this.configuration = CustomAnvil.instance.getConfig(); + return true; + } + + @Override + public void reload() {}// Nothing to do + + } + + // Abstract class for non default config + public abstract static class ResourceConfigHolder extends ConfigHolder{ + + String resourceName; + private ResourceConfigHolder(String resourceName){ + this.resourceName = resourceName; + } + + @Override + protected String getConfigFileName() { + return resourceName; + } + + @Override + public boolean reloadFromDisk(boolean hardFail) { + YamlConfiguration configuration = CustomAnvil.instance.reloadResource( + getConfigFileName()+getConfigFileExtension(), hardFail); + if(configuration == null) return false; + this.configuration = configuration; + reload(); + return true; + } + + } + + // Class for itemGroupsManager config + public static class ItemGroupConfigHolder extends ResourceConfigHolder{ + private final static String FILE_NAME = "item_groups"; + + ItemGroupManager itemGroupsManager; + private ItemGroupConfigHolder() { + super(FILE_NAME); + } + + public ItemGroupManager getItemGroupsManager() { + return itemGroupsManager; + } + + @Override + public void reload() { + // not the most efficient way for in game reload TODO optimise + this.itemGroupsManager = new ItemGroupManager(); + this.itemGroupsManager.prepareGroups(this.configuration); + + if(CONFLICT_HOLDER.getConfig() != null){ + CONFLICT_HOLDER.reload(); + } + } + + } + + // Class for enchant conflict config + public static class ConflictConfigHolder extends ResourceConfigHolder{ + private final static String FILE_NAME = "enchant_conflict"; + + EnchantConflictManager conflictManager; + private ConflictConfigHolder() { + super(FILE_NAME); + } + + public EnchantConflictManager getConflictManager() { + return conflictManager; + } + + // We assume this is called after item group manager reload;, + @Override + public void reload() { + // not the most efficient way for in game reload TODO optimise + this.conflictManager = new EnchantConflictManager(); + this.conflictManager.prepareConflicts(this.configuration, ITEM_GROUP_HOLDER.getItemGroupsManager()); + } + + } + + // Class for unit repair config + public static class UnitRepairHolder extends ResourceConfigHolder{ + private final static String ITEM_GROUP_FILE_NAME = "unit_repair_item"; + + private UnitRepairHolder() { + super(ITEM_GROUP_FILE_NAME); + } + @Override + public void reload() {} // Do nothing + + } + + +} diff --git a/src/main/kotlin/io/delilaheve/AnvilEventListener.kt b/src/main/kotlin/io/delilaheve/AnvilEventListener.kt index 110a651..d6d3cf9 100644 --- a/src/main/kotlin/io/delilaheve/AnvilEventListener.kt +++ b/src/main/kotlin/io/delilaheve/AnvilEventListener.kt @@ -23,6 +23,7 @@ import org.bukkit.inventory.AnvilInventory import org.bukkit.inventory.InventoryView.Property.REPAIR_COST import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.Repairable +import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.group.ConflictType import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair import kotlin.math.min @@ -320,7 +321,7 @@ class AnvilEventListener : Listener { // count enchant as illegal enchant if it conflicts with another enchant or not in result if((enchantment.key !in resultEnchsKeys)){ resultEnchsKeys.add(enchantment.key) - val conflictType = CustomAnvil.conflictManager.isConflicting(resultEnchsKeys,result.type,enchantment.key) + val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(resultEnchsKeys,result.type,enchantment.key) resultEnchsKeys.remove(enchantment.key) if(ConflictType.BIG_CONFLICT == conflictType){ diff --git a/src/main/kotlin/io/delilaheve/CustomAnvil.kt b/src/main/kotlin/io/delilaheve/CustomAnvil.kt index 1fee6ea..1bb48f7 100644 --- a/src/main/kotlin/io/delilaheve/CustomAnvil.kt +++ b/src/main/kotlin/io/delilaheve/CustomAnvil.kt @@ -6,9 +6,8 @@ import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.plugin.java.JavaPlugin import xyz.alexcrea.cuanvil.command.ReloadExecutor import xyz.alexcrea.cuanvil.command.TestExecutor +import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.util.Metrics -import xyz.alexcrea.cuanvil.group.EnchantConflictManager -import xyz.alexcrea.cuanvil.group.ItemGroupManager import xyz.alexcrea.cuanvil.util.MetricsUtil import java.io.File import java.io.FileReader @@ -37,17 +36,8 @@ class CustomAnvil : JavaPlugin() { // Test command name const val commandTestName = "test" - // Item Grouping Configuration file name - const val itemGroupingConfigFilePath = "item_groups.yml" - // Conflict Configuration file name - const val enchantConflicConfigFilePath = "enchant_conflict.yml" - // Unit Repair Configuration file name - const val unitRepairFilePath = "unit_repair_item.yml" - // Current plugin instance lateinit var instance: CustomAnvil - // Current item grouping configuration instance - lateinit var conflictManager: EnchantConflictManager // Configuration for unit repair lateinit var unitRepairConfig: YamlConfiguration @@ -76,7 +66,9 @@ class CustomAnvil : JavaPlugin() { logger.warning("Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus") } - val success = reloadAllConfigs(true) + // Load config + + val success = ConfigHolder.loadConfig(); if(!success) return // Load metrics @@ -92,36 +84,8 @@ class CustomAnvil : JavaPlugin() { ) } - fun reloadAllConfigs(hardFailSafe: Boolean): Boolean{ - saveDefaultConfig() - reloadConfig() - - // Load material grouping config - val itemGroupConfig = reloadResource(itemGroupingConfigFilePath, hardFailSafe) ?: return false - // Read material groups from config - val itemGroupsManager = ItemGroupManager() - itemGroupsManager.prepareGroups(itemGroupConfig) - - // Load enchantment conflicts config - val conflictConfig = reloadResource(enchantConflicConfigFilePath, hardFailSafe) ?: return false - // Read conflicts from config and material group manager - val conflictManager = EnchantConflictManager() - conflictManager.prepareConflicts(conflictConfig,itemGroupsManager) - - // Load unit repair config - val unitRepairConfig = reloadResource(unitRepairFilePath, hardFailSafe) ?: return false - - // Set the global variable - CustomAnvil.conflictManager = conflictManager - CustomAnvil.unitRepairConfig = unitRepairConfig - - // Test if is default config - MetricsUtil.testIfConfigIsDefault(config, itemGroupConfig, conflictConfig, unitRepairConfig) - return true - } - - private fun reloadResource(resourceName: String, - hardFailSafe:Boolean = true): YamlConfiguration?{ + fun reloadResource(resourceName: String, + hardFailSafe:Boolean = true): YamlConfiguration?{ // Save default resource val file = File(dataFolder,resourceName) if(!file.exists()){ diff --git a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt index 1a235b2..2761d4d 100644 --- a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt +++ b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt @@ -3,6 +3,7 @@ package io.delilaheve.util import io.delilaheve.CustomAnvil import io.delilaheve.util.EnchantmentUtil.enchantmentName import org.bukkit.enchantments.Enchantment +import xyz.alexcrea.cuanvil.config.ConfigHolder /** * Config option accessors @@ -71,7 +72,7 @@ object ConfigOptions { */ private val defaultEnchantLimit: Int get() { - return CustomAnvil.instance + return ConfigHolder.DEFAULT_CONFIG .config .getInt(DEFAULT_LIMIT_PATH, DEFAULT_ENCHANT_LIMIT) } @@ -81,7 +82,7 @@ object ConfigOptions { */ val limitRepairCost: Boolean get() { - return CustomAnvil.instance + return ConfigHolder.DEFAULT_CONFIG .config .getBoolean(LIMIT_REPAIR_COST, DEFAULT_LIMIT_REPAIR) } @@ -91,7 +92,7 @@ object ConfigOptions { */ val limitRepairValue: Int get() { - return CustomAnvil.instance + return ConfigHolder.DEFAULT_CONFIG .config .getInt(LIMIT_REPAIR_VALUE, DEFAULT_LIMIT_REPAIR_VALUE) .takeIf { it in REPAIR_LIMIT_RANGE } @@ -103,7 +104,7 @@ object ConfigOptions { */ val itemRepairCost: Int get() { - return CustomAnvil.instance + return ConfigHolder.DEFAULT_CONFIG .config .getInt(ITEM_REPAIR_COST, DEFAULT_ITEM_REPAIR_COST) .takeIf { it in REPAIR_COST_RANGE } @@ -115,7 +116,7 @@ object ConfigOptions { */ val unitRepairCost: Int get() { - return CustomAnvil.instance + return ConfigHolder.DEFAULT_CONFIG .config .getInt(UNIT_REPAIR_COST, DEFAULT_UNIT_REPAIR_COST) .takeIf { it in REPAIR_COST_RANGE } @@ -127,7 +128,7 @@ object ConfigOptions { */ val itemRenameCost: Int get() { - return CustomAnvil.instance + return ConfigHolder.DEFAULT_CONFIG .config .getInt(ITEM_RENAME_COST, DEFAULT_ITEM_RENAME_COST) .takeIf { it in ITEM_RENAME_COST_RANGE } @@ -139,7 +140,7 @@ object ConfigOptions { */ val sacrificeIllegalCost: Int get() { - return CustomAnvil.instance + return ConfigHolder.DEFAULT_CONFIG .config .getInt(SACRIFICE_ILLEGAL_COST, DEFAULT_SACRIFICE_ILLEGAL_COST) .takeIf { it in SACRIFICE_ILLEGAL_COST_RANGE } @@ -150,7 +151,7 @@ object ConfigOptions { */ val removeRepairLimit: Boolean get() { - return CustomAnvil.instance + return ConfigHolder.DEFAULT_CONFIG .config .getBoolean(REMOVE_REPAIR_LIMIT, DEFAULT_REMOVE_LIMIT) } @@ -160,7 +161,7 @@ object ConfigOptions { */ val debugLog: Boolean get() { - return CustomAnvil.instance + return ConfigHolder.DEFAULT_CONFIG .config .getBoolean(DEBUG_LOGGING, DEFAULT_DEBUG_LOG) } diff --git a/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt b/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt index ff61cbb..f2f90d6 100644 --- a/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt +++ b/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt @@ -4,6 +4,7 @@ import io.delilaheve.CustomAnvil import org.bukkit.Material import org.bukkit.enchantments.Enchantment import org.bukkit.entity.HumanEntity +import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.group.ConflictType import kotlin.math.max import kotlin.math.min @@ -34,7 +35,7 @@ object EnchantmentUtil { // Add the enchantment if it doesn't have conflicts, or, if player is allowed to bypass enchantment restrictions this[enchantment] = level if(!player.hasPermission(CustomAnvil.bypassFusePermission) && - (CustomAnvil.conflictManager.isConflicting(this.keys,mat,enchantment) != ConflictType.NO_CONFLICT)){ + (ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this.keys,mat,enchantment) != ConflictType.NO_CONFLICT)){ this.remove(enchantment) } @@ -42,7 +43,7 @@ object EnchantmentUtil { // Enchantment already in result list else{ // ... and they are conflicting - if((CustomAnvil.conflictManager.isConflicting(this.keys,mat,enchantment) != ConflictType.NO_CONFLICT) + if((ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this.keys,mat,enchantment) != ConflictType.NO_CONFLICT) && !player.hasPermission(CustomAnvil.bypassFusePermission)){ return@forEach } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt index b92b569..9b20c0f 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt @@ -4,6 +4,7 @@ import io.delilaheve.CustomAnvil import org.bukkit.command.Command import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandSender +import xyz.alexcrea.cuanvil.config.ConfigHolder class ReloadExecutor : CommandExecutor { override fun onCommand(sender: CommandSender, cmd: Command, cmdstr: String, args: Array): Boolean { @@ -30,7 +31,7 @@ class ReloadExecutor : CommandExecutor { */ private fun commandBody(hardfail: Boolean): Boolean{ try { - return CustomAnvil.instance.reloadAllConfigs(hardfail) + return ConfigHolder.reloadAllFromDisk(hardfail); }catch (e: Exception){ e.printStackTrace() return false diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt index add081f..4ebc510 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt @@ -4,9 +4,7 @@ import io.delilaheve.CustomAnvil import org.bukkit.Material import org.bukkit.NamespacedKey import org.bukkit.configuration.ConfigurationSection -import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.enchantments.Enchantment -import kotlin.collections.ArrayList class EnchantConflictManager { @@ -29,7 +27,7 @@ class EnchantConflictManager { private lateinit var conflictMap: HashMap> // Read and prepare all conflict - fun prepareConflicts(config: YamlConfiguration, itemManager: ItemGroupManager){ + fun prepareConflicts(config: ConfigurationSection, itemManager: ItemGroupManager){ conflictMap = HashMap() val keys = config.getKeys(false) @@ -140,7 +138,7 @@ class EnchantConflictManager { } -enum class ConflictType(){ +enum class ConflictType{ NO_CONFLICT, SMALL_CONFLICT, BIG_CONFLICT diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/ItemGroupManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/ItemGroupManager.kt index f157870..a7c927a 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/ItemGroupManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/ItemGroupManager.kt @@ -3,9 +3,7 @@ package xyz.alexcrea.cuanvil.group import io.delilaheve.CustomAnvil import org.bukkit.Material import org.bukkit.configuration.ConfigurationSection -import org.bukkit.configuration.file.YamlConfiguration import java.util.* -import kotlin.collections.HashMap class ItemGroupManager { @@ -23,7 +21,7 @@ class ItemGroupManager { private lateinit var groupMap : HashMap // Read and create material groups - fun prepareGroups(config: YamlConfiguration){ + fun prepareGroups(config: ConfigurationSection){ groupMap = HashMap() val keys = config.getKeys(false) @@ -35,7 +33,7 @@ class ItemGroupManager { } // Create group by key - private fun createGroup(config: YamlConfiguration, + private fun createGroup(config: ConfigurationSection, keys: Set, key: String): AbstractMaterialGroup { val groupSection = config.getConfigurationSection(key)!! @@ -60,7 +58,7 @@ class ItemGroupManager { // Read Group elements private fun readGroup(group: AbstractMaterialGroup, groupSection: ConfigurationSection, - config: YamlConfiguration, + config: ConfigurationSection, keys: Set){ // Read material to include in this group policy val materialList = groupSection.getStringList(MATERIAL_LIST_PATH) diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/UnitRepairUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/UnitRepairUtil.kt index b01d37f..a71d912 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/UnitRepairUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/UnitRepairUtil.kt @@ -1,8 +1,8 @@ package xyz.alexcrea.cuanvil.util -import io.delilaheve.CustomAnvil import org.bukkit.configuration.ConfigurationSection import org.bukkit.inventory.ItemStack +import xyz.alexcrea.cuanvil.config.ConfigHolder object UnitRepairUtil { @@ -19,15 +19,14 @@ object UnitRepairUtil { other: ItemStack? ): Double? { if(other == null) return null - val config = CustomAnvil.unitRepairConfig + val config = ConfigHolder.UNIT_REPAIR_HOLDER.config // Get configuration section if exist val otherName = other.type.name.uppercase() var section = config.getConfigurationSection(otherName) if(section == null){ section = config.getConfigurationSection(otherName.lowercase()) - if(section == null) { - return null - } + if(section == null) return null + } // Get repair amount var userDefault = config.getDouble(UNIT_REPAIR_DEFAULT_PATH, DEFAULT_DEFAULT_UNIT_REPAIR)