From c5c32ce3864f4653ed85f82507d436b86cbc90c8 Mon Sep 17 00:00:00 2001 From: alexcrea <42614139+alexcrea@users.noreply.github.com> Date: Wed, 12 Feb 2025 22:40:23 +0100 Subject: [PATCH] Better work penalty (#52) - Created per use type work penalty (rename/merge/repair) - auto migration of previous work penalty system. - new exclusive work penalty per use type --- build.gradle.kts | 2 +- defaultconfigs/1.18/config.yml | 14 +- defaultconfigs/1.21/config.yml | 14 +- .../cuanvil/config/WorkPenaltyType.java | 138 ++++------ .../gui/config/global/BasicConfigGui.java | 48 +--- .../settings/WorkPenaltyTypeSettingGui.java | 244 ++++++++++++++++++ .../cuanvil/update/PluginSetDefault.java | 2 - .../cuanvil/update/plugin/PUpdate_1_6_7.java | 2 - .../cuanvil/update/plugin/PUpdate_1_8_0.java | 66 +++++ .../cuanvil/update/plugin/PluginUpdates.java | 13 +- .../io/delilaheve/util/ConfigOptions.kt | 51 +++- .../cuanvil/listener/PrepareAnvilListener.kt | 9 +- .../xyz/alexcrea/cuanvil/util/AnvilUseType.kt | 28 +- .../xyz/alexcrea/cuanvil/util/AnvilXpUtil.kt | 67 ++++- src/main/resources/config.yml | 14 +- 15 files changed, 494 insertions(+), 218 deletions(-) create mode 100644 src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/WorkPenaltyTypeSettingGui.java create mode 100644 src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_8_0.java diff --git a/build.gradle.kts b/build.gradle.kts index 45ea74c..a69431a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,7 +16,7 @@ plugins { } group = "xyz.alexcrea" -version = "1.7.1" +version = "1.8.0" repositories { // EcoEnchants diff --git a/defaultconfigs/1.18/config.yml b/defaultconfigs/1.18/config.yml index dd24558..10d6ef9 100644 --- a/defaultconfigs/1.18/config.yml +++ b/defaultconfigs/1.18/config.yml @@ -72,18 +72,6 @@ permission_needed_for_color: true # Valid values include 0 to 1000. use_of_color_cost: 0 -# Work penalty increase the price for every anvil use. -# This config allow you to choose the comportment of work penalty. -# Vanilla work penalty formula can be represented as 2 * previous_penalty + 1. with start value equal to 0 -# See https://minecraft.wiki/w/Anvil_mechanics#Anvil_uses for more detail -# -# Valid work penalty type is: -# - default: work penalty added and increased -# - increase_only: work penalty increased but not added -# - add_only: work penalty added but not increased -# - disabled: work penalty disabled -work_penalty_type: default - # Default limit to apply to any enchants missing from enchant_limits # # Valid values include 1 to 1000 @@ -294,4 +282,4 @@ debug_log_verbose: false # ProtocoLib may also be used if the server is in an "unsupported" version even if this option is disabled. force_protocolib: false -configVersion: 1.6.2 +configVersion: 1.8.0 diff --git a/defaultconfigs/1.21/config.yml b/defaultconfigs/1.21/config.yml index dd24558..10d6ef9 100644 --- a/defaultconfigs/1.21/config.yml +++ b/defaultconfigs/1.21/config.yml @@ -72,18 +72,6 @@ permission_needed_for_color: true # Valid values include 0 to 1000. use_of_color_cost: 0 -# Work penalty increase the price for every anvil use. -# This config allow you to choose the comportment of work penalty. -# Vanilla work penalty formula can be represented as 2 * previous_penalty + 1. with start value equal to 0 -# See https://minecraft.wiki/w/Anvil_mechanics#Anvil_uses for more detail -# -# Valid work penalty type is: -# - default: work penalty added and increased -# - increase_only: work penalty increased but not added -# - add_only: work penalty added but not increased -# - disabled: work penalty disabled -work_penalty_type: default - # Default limit to apply to any enchants missing from enchant_limits # # Valid values include 1 to 1000 @@ -294,4 +282,4 @@ debug_log_verbose: false # ProtocoLib may also be used if the server is in an "unsupported" version even if this option is disabled. force_protocolib: false -configVersion: 1.6.2 +configVersion: 1.8.0 diff --git a/src/main/java/xyz/alexcrea/cuanvil/config/WorkPenaltyType.java b/src/main/java/xyz/alexcrea/cuanvil/config/WorkPenaltyType.java index 95edca6..75b0861 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/config/WorkPenaltyType.java +++ b/src/main/java/xyz/alexcrea/cuanvil/config/WorkPenaltyType.java @@ -1,114 +1,66 @@ package xyz.alexcrea.cuanvil.config; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.jetbrains.annotations.NotNull; +import com.google.common.collect.ImmutableMap; import org.jetbrains.annotations.Nullable; -import xyz.alexcrea.cuanvil.gui.config.settings.AbstractSettingGui; -import xyz.alexcrea.cuanvil.gui.config.settings.EnumSettingGui; +import xyz.alexcrea.cuanvil.util.AnvilUseType; -import java.util.ArrayList; -import java.util.List; +import java.util.EnumMap; -public enum WorkPenaltyType implements EnumSettingGui.ConfigurableEnum { - DEFAULT("default", true, true, "§aDefault", Material.LIME_TERRACOTTA), - ADDITIVE("add_only", false, true, "§eAdd Only", Material.YELLOW_TERRACOTTA), - INCREASE("increase_only", true, false, "§eIncrease Only", Material.YELLOW_TERRACOTTA), - DISABLED("disabled", false, false, "§cDisabled", Material.RED_TERRACOTTA), - ; +public class WorkPenaltyType { - private final String name; - private final boolean penaltyIncrease; - private final boolean penaltyAdditive; + public record WorkPenaltyPart( + boolean penaltyIncrease, + boolean penaltyAdditive, + boolean exclusivePenaltyIncrease, + boolean exclusivePenaltyAdditive + ) { - private final String configName; - private final Material configMaterial; + @Override + public boolean equals(Object obj) { + if(!(obj instanceof WorkPenaltyPart other)) return false; - WorkPenaltyType(String name, boolean penaltyIncrease, boolean penaltyAdditive, String configName, Material configMaterial) { - this.name = name; - this.penaltyIncrease = penaltyIncrease; - this.penaltyAdditive = penaltyAdditive; - this.configName = configName; - this.configMaterial = configMaterial; - } - - public boolean isPenaltyIncreasing() { - return penaltyIncrease; - } - - public boolean isPenaltyAdditive() { - return penaltyAdditive; - } - - private boolean doRepresentThisType(String toTest){ - return name.equalsIgnoreCase(toTest); - } - - @NotNull - public static WorkPenaltyType fromString(@Nullable String toTest){ - if(toTest == null) return DEFAULT; - - // Test if it matches any of values - for (WorkPenaltyType value : values()) { - if(value.doRepresentThisType(toTest)){ - return value; - } + return other.penaltyIncrease == this.penaltyIncrease && + other.penaltyAdditive == this.penaltyAdditive && + other.exclusivePenaltyIncrease == this.exclusivePenaltyIncrease && + other.exclusivePenaltyAdditive == this.exclusivePenaltyAdditive; } - // Use default if not found - return DEFAULT; + public WorkPenaltyPart(boolean penaltyIncrease, boolean penaltyAdditive) { + this(penaltyIncrease, penaltyAdditive, false, false); + } } - @NotNull - public static WorkPenaltyType next(@NotNull WorkPenaltyType now){ - return switch (now){ - case DEFAULT -> ADDITIVE; - case ADDITIVE -> INCREASE; - case INCREASE -> DISABLED; - case DISABLED -> DEFAULT; + private final EnumMap partMap; - }; + public WorkPenaltyType(@Nullable EnumMap partMap) { + this.partMap = new EnumMap<>(partMap != null ? partMap : new EnumMap<>(AnvilUseType.class)); + } + public ImmutableMap getPartMap() { + return ImmutableMap.copyOf(partMap); + } + + public WorkPenaltyPart getPenaltyInfo(AnvilUseType type) { + return partMap.getOrDefault(type, type.getDefaultPenalty()); + } + + public boolean isPenaltyIncreasing(AnvilUseType type) { + return partMap.getOrDefault(type, type.getDefaultPenalty()).penaltyIncrease; + } + + public boolean isPenaltyAdditive(AnvilUseType type) { + return partMap.getOrDefault(type, type.getDefaultPenalty()).penaltyAdditive; } @Override - public ItemStack configurationGuiItem() { - ItemStack displayedItem = new ItemStack(this.configMaterial); - ItemMeta valueMeta = displayedItem.getItemMeta(); - assert valueMeta != null; + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof WorkPenaltyType that)) return false; - valueMeta.setDisplayName(this.configName); - - List lore = new ArrayList<>(); - - lore.add(configDisplayForAdd()); - lore.add(configDisplayForIncrease()); - lore.add(""); - - lore.add(AbstractSettingGui.CLICK_LORE); - valueMeta.setLore(lore); - - displayedItem.setItemMeta(valueMeta); - - return displayedItem; + for (AnvilUseType type : AnvilUseType.getEntries()) { + if(!getPenaltyInfo(type).equals(that.getPenaltyInfo(type))) return false; + } + return true; } - public String configDisplayForAdd(){ - return ("§7Add penalty: " + (penaltyAdditive ? "§aYes" : "§cNo")); - } - - public String configDisplayForIncrease(){ - return ("§7Increase penalty: " + (penaltyIncrease ? "§aYes" : "§cNo")); - } - - @Override - public String configName() { - return this.name; - } - - @Override - public String configurationGuiName() { - return this.configName; - } } 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 d689921..a07cb3c 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 @@ -14,13 +14,12 @@ 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.config.WorkPenaltyType; import xyz.alexcrea.cuanvil.dependency.packet.PacketManager; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; import xyz.alexcrea.cuanvil.gui.config.settings.BoolSettingsGui; -import xyz.alexcrea.cuanvil.gui.config.settings.EnumSettingGui; import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui; +import xyz.alexcrea.cuanvil.gui.config.settings.WorkPenaltyTypeSettingGui; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; @@ -28,7 +27,6 @@ import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.List; /** * Global config to edit basic basic settings. @@ -89,8 +87,6 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui { private IntSettingsGui.IntSettingFactory itemRenameCost; // r character private IntSettingsGui.IntSettingFactory sacrificeIllegalEnchantCost; // S character - private EnumSettingGui.EnumSettingFactory workPenaltyType; // W character - private BoolSettingsGui.BoolSettingFactory allowColorCode; // c character private BoolSettingsGui.BoolSettingFactory allowHexColor; // h character @@ -211,46 +207,6 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui { ConfigOptions.DEFAULT_SACRIFICE_ILLEGAL_COST, 1, 5, 10, 50, 100); - // ------------- - // Work Penalty - // ------------- - - this.workPenaltyType = new EnumSettingGui.EnumSettingFactory<>("§8Work Penalty Type", this, - ConfigOptions.WORK_PENALTY_TYPE, ConfigHolder.DEFAULT_CONFIG - ) { - @NotNull - @Override - public WorkPenaltyType getConfiguredValue() { - return ConfigOptions.INSTANCE.getWorkPenaltyType(); - } - - @NotNull - @Override - public WorkPenaltyType getDefault() { - return WorkPenaltyType.DEFAULT; - } - - @NotNull - @Override - public List getDisplayLore(WorkPenaltyType value) { - return List.of( - "§7Work penalty increase the price for every anvil use.", - "§7This config allow you to choose the comportment of work penalty.", - "", - value.configDisplayForAdd(), - value.configDisplayForIncrease() - - ); - } - - @NotNull - @Override - public WorkPenaltyType next(@NotNull WorkPenaltyType now) { - return WorkPenaltyType.next(now); - } - - }; - // ------------- // Color config // ------------- @@ -377,7 +333,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui { pane.bindItem('S', illegalCostItem); // work penalty type - GuiItem workPenaltyType = this.workPenaltyType.getItem(Material.DAMAGED_ANVIL, "§aWork Penalty Type"); + GuiItem workPenaltyType = WorkPenaltyTypeSettingGui.getDisplayItem(this, Material.DAMAGED_ANVIL, "§aWork Penalty Type"); pane.bindItem('W', workPenaltyType); // allow color code diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/WorkPenaltyTypeSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/WorkPenaltyTypeSettingGui.java new file mode 100644 index 0000000..2df9a58 --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/WorkPenaltyTypeSettingGui.java @@ -0,0 +1,244 @@ +package xyz.alexcrea.cuanvil.gui.config.settings; + +import com.github.stefvanschie.inventoryframework.gui.GuiItem; +import com.github.stefvanschie.inventoryframework.pane.PatternPane; +import com.github.stefvanschie.inventoryframework.pane.util.Pattern; +import io.delilaheve.CustomAnvil; +import io.delilaheve.util.ConfigOptions; +import org.bukkit.Material; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.HumanEntity; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import xyz.alexcrea.cuanvil.config.ConfigHolder; +import xyz.alexcrea.cuanvil.config.WorkPenaltyType; +import xyz.alexcrea.cuanvil.gui.config.global.BasicConfigGui; +import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; +import xyz.alexcrea.cuanvil.util.AnvilUseType; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +public class WorkPenaltyTypeSettingGui extends AbstractSettingGui { + + private static final String INCREASING_EXPLANATION = "§eIncreasing§7: will penalty be increased (in item)"; + private static final String ADDING_EXPLANATION = "§eAdditive§7: will penalty be added to the cost"; + + private static final String SHARED_EXPLANATION = "§eShared§7: Vanilla, shared penalty. it will be kept from before the plugin installation."; + private static final String EXCLUSIVE_EXPLANATION = "§eExclusive§7: Custom, per anvil use type penalty. it will be lost after plugin uninstallation"; + + private final @NotNull WorkPenaltyType currentType; + private final @NotNull Map items; + + public WorkPenaltyTypeSettingGui(@NotNull BasicConfigGui parent) { + super(4, "§8Work Penalty Type", parent); + + this.currentType = ConfigOptions.INSTANCE.getWorkPenaltyType(); + this.items = new EnumMap<>(this.currentType.getPartMap()); + + for (AnvilUseType type : AnvilUseType.getEntries()) { + updateGuiForType(type); + } + } + + public static GuiItem getDisplayItem(@NotNull BasicConfigGui parent, + @NotNull Material itemMat, + @NotNull String name) { + List displayLore = new ArrayList<>(); + + displayLore.add("§7Work penalty increase the price for every anvil use."); + displayLore.add("§7This config allow you to choose the comportment of work penalty."); + displayLore.add(INCREASING_EXPLANATION); + displayLore.add(ADDING_EXPLANATION); + displayLore.add(""); + displayLore.add("§7About shared/exclusive penalty:"); + displayLore.add(SHARED_EXPLANATION); + displayLore.add(EXCLUSIVE_EXPLANATION); + + ItemStack item = new ItemStack(itemMat); + + ItemMeta meta = item.getItemMeta(); + meta.setDisplayName(name); + meta.setLore(displayLore); + + item.setItemMeta(meta); + + return new GuiItem(item, (event) -> { + event.setCancelled(true); + HumanEntity player = event.getWhoClicked(); + + // Do not allow to open inventory if player do not have edit configuration permission + if (!player.hasPermission(CustomAnvil.editConfigPermission)) { + player.closeInventory(); + player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); + return; + } + new WorkPenaltyTypeSettingGui(parent).show(player); + }, CustomAnvil.instance); + } + + @Override + protected Pattern getGuiPattern() { + return new Pattern( // Yeah that a mess + "00a1z9Z00", + "00b2y8Y00", + "00c3x7X00", + "B004w600S" + ); + } + + public void updateGuiForType(AnvilUseType type) { + PatternPane pane = getPane(); + int ordinal = type.ordinal(); + + int display = 'z' - ordinal; + int increment = 'a' + ordinal; + int additive = '1' + ordinal; + int exclusiveIncrement = 'Z' - ordinal; + int exclusiveAdditive = '9' - ordinal; + + WorkPenaltyType.WorkPenaltyPart part = items.get(type); + String increasingStr = (part.penaltyIncrease() ? "§a" : "§c") + "Increasing"; + String additiveStr = (part.penaltyAdditive() ? "§a" : "§c") + "Additive"; + String exclusiveIncreasingStr = (part.exclusivePenaltyIncrease() ? "§a" : "§c") + "Increasing"; + String exclusiveAdditiveStr = (part.exclusivePenaltyAdditive() ? "§a" : "§c") + "Additive"; + + // Display item + ItemStack displayItem = new ItemStack(type.getDisplayMat()); + + ArrayList displayLore = new ArrayList<>(); + displayLore.add("§eShared§7: " + additiveStr + " §7| " + increasingStr); + displayLore.add("§eExclusive§7: " + exclusiveAdditiveStr + " §7| " + exclusiveIncreasingStr); + + ItemMeta meta = displayItem.getItemMeta(); + meta.setDisplayName("§e" + type.getDisplayName()); + meta.setLore(displayLore); + displayItem.setItemMeta(meta); + + pane.bindItem(display, new GuiItem(displayItem, (event) -> { + event.setCancelled(true); + })); + + // Can probably put this in a function but this works so + // "Increment" item + ItemStack incrementItem = new ItemStack(part.penaltyIncrease() ? Material.GREEN_TERRACOTTA : Material.RED_TERRACOTTA); + + meta = incrementItem.getItemMeta(); + meta.setDisplayName(increasingStr); + meta.setLore(List.of(INCREASING_EXPLANATION)); + meta.setLore(List.of(SHARED_EXPLANATION)); + incrementItem.setItemMeta(meta); + + pane.bindItem(increment, new GuiItem(incrementItem, (event) -> { + event.setCancelled(true); + + WorkPenaltyType.WorkPenaltyPart newPart = new WorkPenaltyType.WorkPenaltyPart( + !part.penaltyIncrease(), part.penaltyAdditive(), + part.exclusivePenaltyIncrease(), part.exclusivePenaltyAdditive()); + items.replace(type, newPart); + updateGuiForType(type); + update(); + })); + + // "Additive" item + ItemStack additiveItem = new ItemStack(part.penaltyAdditive() ? Material.GREEN_TERRACOTTA : Material.RED_TERRACOTTA); + + meta = additiveItem.getItemMeta(); + meta.setDisplayName(additiveStr); + meta.setLore(List.of(ADDING_EXPLANATION)); + meta.setLore(List.of(SHARED_EXPLANATION)); + additiveItem.setItemMeta(meta); + + pane.bindItem(additive, new GuiItem(additiveItem, (event) -> { + event.setCancelled(true); + + WorkPenaltyType.WorkPenaltyPart newPart = new WorkPenaltyType.WorkPenaltyPart( + part.penaltyIncrease(), !part.penaltyAdditive(), + part.exclusivePenaltyIncrease(), part.exclusivePenaltyAdditive()); + items.replace(type, newPart); + updateGuiForType(type); + update(); + })); + + // exclusive "Increment" item + ItemStack exclusiveIncrementItem = new ItemStack(part.exclusivePenaltyIncrease() ? Material.GREEN_TERRACOTTA : Material.RED_TERRACOTTA); + + meta = exclusiveIncrementItem.getItemMeta(); + meta.setDisplayName(exclusiveIncreasingStr); + meta.setLore(List.of(INCREASING_EXPLANATION)); + meta.setLore(List.of(EXCLUSIVE_EXPLANATION)); + exclusiveIncrementItem.setItemMeta(meta); + + pane.bindItem(exclusiveIncrement, new GuiItem(exclusiveIncrementItem, (event) -> { + event.setCancelled(true); + + WorkPenaltyType.WorkPenaltyPart newPart = new WorkPenaltyType.WorkPenaltyPart( + part.penaltyIncrease(), part.penaltyAdditive(), + !part.exclusivePenaltyIncrease(), part.exclusivePenaltyAdditive()); + items.replace(type, newPart); + updateGuiForType(type); + update(); + })); + + // exclusive "Additive" item + ItemStack exclusiveAdditiveItem = new ItemStack(part.exclusivePenaltyAdditive() ? Material.GREEN_TERRACOTTA : Material.RED_TERRACOTTA); + + meta = exclusiveAdditiveItem.getItemMeta(); + meta.setDisplayName(exclusiveAdditiveStr); + meta.setLore(List.of(ADDING_EXPLANATION)); + meta.setLore(List.of(EXCLUSIVE_EXPLANATION)); + exclusiveAdditiveItem.setItemMeta(meta); + + pane.bindItem(exclusiveAdditive, new GuiItem(exclusiveAdditiveItem, (event) -> { + event.setCancelled(true); + + WorkPenaltyType.WorkPenaltyPart newPart = new WorkPenaltyType.WorkPenaltyPart( + part.penaltyIncrease(), part.penaltyAdditive(), + part.exclusivePenaltyIncrease(), !part.exclusivePenaltyAdditive()); + items.replace(type, newPart); + updateGuiForType(type); + update(); + })); + } + + @Override + public boolean onSave() { + return saveWorkPenalty(items); + } + + public static boolean saveWorkPenalty(Map partEnum) { + String path = ConfigOptions.WORK_PENALTY_ROOT; + ConfigHolder configHolder = ConfigHolder.DEFAULT_CONFIG; + FileConfiguration config = configHolder.getConfig(); + + partEnum.forEach((key, value) -> { + String partPath = path + "." + key.getTypeName(); + + if (key.getDefaultPenalty().equals(value)) { + config.set(partPath, null); + return; + } + + config.set(partPath + '.' + ConfigOptions.WORK_PENALTY_INCREASE, value.penaltyIncrease()); + config.set(partPath + '.' + ConfigOptions.WORK_PENALTY_ADDITIVE, value.penaltyAdditive()); + config.set(partPath + '.' + ConfigOptions.EXCLUSIVE_WORK_PENALTY_INCREASE, value.exclusivePenaltyIncrease()); + config.set(partPath + '.' + ConfigOptions.EXCLUSIVE_WORK_PENALTY_ADDITIVE, value.exclusivePenaltyAdditive()); + }); + + return configHolder.saveToDisk(true); + } + + @Override + public boolean hadChange() { + for (AnvilUseType type : items.keySet()) { + if (!currentType.getPenaltyInfo(type).equals(items.get(type))) { + return true; + } + } + + return false; + } +} diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java b/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java index 248cc5f..e890918 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java +++ b/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java @@ -5,7 +5,6 @@ import io.delilaheve.util.ConfigOptions; import org.bukkit.configuration.file.FileConfiguration; import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.config.WorkPenaltyType; public class PluginSetDefault { @@ -26,7 +25,6 @@ public class PluginSetDefault { nbSet+= trySetDefault(config, ConfigOptions.ALLOW_HEXADECIMAL_COLOR, ConfigOptions.DEFAULT_ALLOW_HEXADECIMAL_COLOR); nbSet+= trySetDefault(config, ConfigOptions.PERMISSION_NEEDED_FOR_COLOR, ConfigOptions.DEFAULT_PERMISSION_NEEDED_FOR_COLOR); nbSet+= trySetDefault(config, ConfigOptions.USE_OF_COLOR_COST, ConfigOptions.DEFAULT_USE_OF_COLOR_COST); - nbSet+= trySetDefault(config, ConfigOptions.WORK_PENALTY_TYPE, WorkPenaltyType.DEFAULT.configName()); nbSet+= trySetDefault(config, ConfigOptions.DEFAULT_LIMIT_PATH, ConfigOptions.DEFAULT_ENCHANT_LIMIT); if(nbSet > 0){ diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_6_7.java b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_6_7.java index f77bced..ee544dc 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_6_7.java +++ b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_6_7.java @@ -20,8 +20,6 @@ public class PUpdate_1_6_7 { toSave.add(ConfigHolder.DEFAULT_CONFIG); } - - } } diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_8_0.java b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_8_0.java new file mode 100644 index 0000000..7685f92 --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PUpdate_1_8_0.java @@ -0,0 +1,66 @@ +package xyz.alexcrea.cuanvil.update.plugin; + +import io.delilaheve.util.ConfigOptions; +import org.bukkit.configuration.file.FileConfiguration; +import xyz.alexcrea.cuanvil.config.ConfigHolder; +import xyz.alexcrea.cuanvil.config.WorkPenaltyType; +import xyz.alexcrea.cuanvil.gui.config.settings.WorkPenaltyTypeSettingGui; +import xyz.alexcrea.cuanvil.util.AnvilUseType; + +import javax.annotation.Nonnull; +import java.util.EnumMap; +import java.util.Set; + +public class PUpdate_1_8_0 { + + private static final String WORK_PENALTY_TYPE = "work_penalty_type"; + + public static void handleUpdate(@Nonnull Set toSave) { + FileConfiguration config = ConfigHolder.DEFAULT_CONFIG.getConfig(); + + // We migrate the work penalty type if it exists + String penaltyTypeValue = config.getString(WORK_PENALTY_TYPE); + if (penaltyTypeValue == null) return; + + EnumMap partEnum; + partEnum = new EnumMap<>(ConfigOptions.INSTANCE.getWorkPenaltyType().getPartMap()); + + boolean keepIncrease; + boolean keepAdditive; + + switch (penaltyTypeValue.toLowerCase()) { + case "add_only": + keepIncrease = false; + keepAdditive = true; + break; + case "increase_only": + keepIncrease = true; + keepAdditive = false; + break; + case "disabled": + keepIncrease = false; + keepAdditive = false; + break; + default: + keepIncrease = true; + keepAdditive = true; + } + + for (AnvilUseType type : partEnum.keySet()) { + WorkPenaltyType.WorkPenaltyPart part = partEnum.get(type); + part = new WorkPenaltyType.WorkPenaltyPart( + keepIncrease & part.penaltyIncrease(), + keepAdditive & part.penaltyAdditive(), + part.exclusivePenaltyIncrease(), + part.exclusivePenaltyAdditive()); + partEnum.replace(type, part); + } + + if(WorkPenaltyTypeSettingGui.saveWorkPenalty(partEnum)){ + config.set(WORK_PENALTY_TYPE, null); + } + + toSave.add(ConfigHolder.DEFAULT_CONFIG); + } + +} 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 2069b03..548c6d1 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PluginUpdates.java +++ b/src/main/java/xyz/alexcrea/cuanvil/update/plugin/PluginUpdates.java @@ -12,21 +12,26 @@ public class PluginUpdates { private static final String CONFIG_VERSION_PATH = "configVersion"; - public static void handlePluginUpdate(){ + public static void handlePluginUpdate() { String versionString = ConfigHolder.DEFAULT_CONFIG.getConfig().getString(CONFIG_VERSION_PATH); Version current = versionString == null ? new Version(0) : Version.fromString(versionString); Set toSave = new HashSet<>(); - if(new Version(1, 6, 2).greaterThan(current)){ + if (new Version(1, 6, 2).greaterThan(current)) { PUpdate_1_6_2.handleUpdate(toSave); // We assume 1.6.7 will run. TODO a better system instead of that I guess } - if(new Version(1, 6, 7).greaterThan(current)){ + if (new Version(1, 6, 7).greaterThan(current)) { PUpdate_1_6_7.handleUpdate(toSave); - finishConfiguration("1.6.7", toSave); + // We assume 1.8.0 will run. + } + if (new Version(1, 8, 0).greaterThan(current)) { + PUpdate_1_8_0.handleUpdate(toSave); + + finishConfiguration("1.8.0", toSave); } } diff --git a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt index dc47bc6..50bbc25 100644 --- a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt +++ b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt @@ -4,7 +4,10 @@ import io.delilaheve.CustomAnvil import io.delilaheve.util.EnchantmentUtil.enchantmentName import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.config.WorkPenaltyType +import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart import xyz.alexcrea.cuanvil.enchant.CAEnchantment +import xyz.alexcrea.cuanvil.util.AnvilUseType +import java.util.EnumMap /** * Config option accessors @@ -34,7 +37,11 @@ object ConfigOptions { const val PERMISSION_NEEDED_FOR_COLOR = "permission_needed_for_color" const val USE_OF_COLOR_COST = "use_of_color_cost" - const val WORK_PENALTY_TYPE = "work_penalty_type" + const val WORK_PENALTY_ROOT = "work_penalty" + const val WORK_PENALTY_INCREASE = "shared_increase" + const val WORK_PENALTY_ADDITIVE = "shared_additive" + const val EXCLUSIVE_WORK_PENALTY_INCREASE = "exclusive_increase" + const val EXCLUSIVE_WORK_PENALTY_ADDITIVE = "exclusive_additive" const val DEFAULT_LIMIT_PATH = "default_limit" @@ -113,7 +120,7 @@ object ConfigOptions { private const val DEFAULT_ENCHANT_VALUE = 0 // Default max before merge disabled (negative mean enabled) - const val DEFAULT_MAX_BEFORE_MERGE_DISABLED = -1; + const val DEFAULT_MAX_BEFORE_MERGE_DISABLED = -1 // ------------- // Get methods @@ -257,16 +264,38 @@ object ConfigOptions { } /** - * How many xp should use of color should cost + * How work penalties should work */ val workPenaltyType: WorkPenaltyType get() { - return WorkPenaltyType.fromString( - ConfigHolder.DEFAULT_CONFIG - .config - .getString(WORK_PENALTY_TYPE)); + val penaltyMap = EnumMap(AnvilUseType::class.java) + + for (type in AnvilUseType.entries) { + penaltyMap[type] = workPenaltyPart(type) + } + + return WorkPenaltyType(penaltyMap) } + /** + * How work penalty should work + */ + fun workPenaltyPart(type: AnvilUseType): WorkPenaltyPart { + val config = ConfigHolder.DEFAULT_CONFIG.config + val path = WORK_PENALTY_ROOT + "." + type.typeName + + // Find values + val defaultPenalty = type.defaultPenalty + val section = config.getConfigurationSection(path) ?: return defaultPenalty + + val penaltyIncrease = section.getBoolean(WORK_PENALTY_INCREASE, defaultPenalty.penaltyIncrease) + val penaltyAdditive = section.getBoolean(WORK_PENALTY_ADDITIVE, defaultPenalty.penaltyAdditive) + val exclusivePenaltyIncrease = section.getBoolean(EXCLUSIVE_WORK_PENALTY_INCREASE, defaultPenalty.exclusivePenaltyIncrease) + val exclusivePenaltyAdditive = section.getBoolean(EXCLUSIVE_WORK_PENALTY_ADDITIVE, defaultPenalty.exclusivePenaltyAdditive) + + return WorkPenaltyPart(penaltyIncrease, penaltyAdditive, exclusivePenaltyIncrease, exclusivePenaltyAdditive) + } + /** * Default enchantment limit */ @@ -303,11 +332,11 @@ object ConfigOptions { fun enchantLimit(enchantment: CAEnchantment): Int { // Test namespace var limit = enchantLimit(enchantment.key.toString()) - if(limit != null) return limit; + if(limit != null) return limit // Test legacy (name only) limit = enchantLimit(enchantment.enchantmentName) - if(limit != null) return limit; + if(limit != null) return limit // get default (and test old legacy if present) return getDefaultLevel(enchantment.enchantmentName) @@ -348,11 +377,11 @@ object ConfigOptions { ): Int { // Test namespace var limit = enchantmentValue(enchantment.key.toString(), isFromBook) - if(limit != null) return limit; + if(limit != null) return limit // Test legacy (name only) limit = enchantmentValue(enchantment.enchantmentName, isFromBook) - if(limit != null) return limit; + if(limit != null) return limit // get default (and test old legacy if present) return getDefaultValue(enchantment, isFromBook) diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt index 77cd6ac..4950452 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt @@ -23,8 +23,6 @@ import xyz.alexcrea.cuanvil.util.AnvilUseType import xyz.alexcrea.cuanvil.util.AnvilXpUtil import xyz.alexcrea.cuanvil.util.CustomRecipeUtil import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair -import java.util.logging.Level - /** * Listener for anvil events */ @@ -93,7 +91,12 @@ class PrepareAnvilListener : Listener { event.result = resultItem if(DependencyManager.tryTreatAnvilResult(event, resultItem)) return true - AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, recipe.xpCostPerCraft * amount, true) + + // Maybe add an option on custom craft to ignore/not ignore penalty ?? + var xpCost = recipe.xpCostPerCraft * amount + xpCost += AnvilXpUtil.calculatePenalty(first, null, resultItem, AnvilUseType.CUSTOM_CRAFT) + + AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, xpCost, true) return true } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilUseType.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilUseType.kt index 2e4a893..c0048de 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilUseType.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilUseType.kt @@ -1,9 +1,29 @@ package xyz.alexcrea.cuanvil.util -enum class AnvilUseType { +import org.bukkit.Material +import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart - RENAME_ONLY, - MERGE, - UNIT_REPAIR +enum class AnvilUseType(val typeName: String, + val defaultPenalty: WorkPenaltyPart, + val displayName: String, val displayMat: Material + ) { + + RENAME_ONLY("rename_only", + WorkPenaltyPart(false, true), + "Rename Only", Material.NAME_TAG + ), + MERGE("merge", + WorkPenaltyPart(true, true), + "Merge", Material.ANVIL + ), + UNIT_REPAIR("unit_repair", + WorkPenaltyPart(true, true), + "Unit Repair", Material.DIAMOND + ), + CUSTOM_CRAFT("custom_craft", + WorkPenaltyPart(false, false), + "Custom Craft", Material.CRAFTING_TABLE + ), + ; } \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilXpUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilXpUtil.kt index 5a03b9c..887748e 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilXpUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilXpUtil.kt @@ -6,6 +6,7 @@ import io.delilaheve.util.EnchantmentUtil.enchantmentName import io.delilaheve.util.ItemUtil.findEnchantments import io.delilaheve.util.ItemUtil.isEnchantedBook import org.bukkit.GameMode +import org.bukkit.NamespacedKey import org.bukkit.entity.HumanEntity import org.bukkit.entity.Player import org.bukkit.inventory.AnvilInventory @@ -13,6 +14,7 @@ import org.bukkit.inventory.InventoryView import org.bukkit.inventory.InventoryView.Property.REPAIR_COST import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.Repairable +import org.bukkit.persistence.PersistentDataType import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.group.ConflictType @@ -20,6 +22,8 @@ import kotlin.math.min object AnvilXpUtil { + const val EXCLUSIVE_PENALTY_PREFIX = "repair_cost" + /** * Display xp needed for the work on the anvil inventory */ @@ -34,7 +38,8 @@ object AnvilXpUtil { val finalAnvilCost = if ( !ignoreRules && !ConfigOptions.doRemoveCostLimit && - ConfigOptions.doCapCost) { + ConfigOptions.doCapCost + ) { min(anvilCost, ConfigOptions.maxAnvilCost) } else { anvilCost @@ -47,17 +52,18 @@ object AnvilXpUtil { CustomAnvil.instance, player, Runnable { inventory.maximumRepairCost = - if (ConfigOptions.doRemoveCostLimit || ignoreRules) - { Int.MAX_VALUE } - else - { ConfigOptions.maxAnvilCost + 1 } + if (ConfigOptions.doRemoveCostLimit || ignoreRules) { + Int.MAX_VALUE + } else { + ConfigOptions.maxAnvilCost + 1 + } inventory.repairCost = finalAnvilCost view.setProperty(REPAIR_COST, finalAnvilCost) player.openInventory.setProperty(REPAIR_COST, finalAnvilCost) - if(player is Player){ - if(player.gameMode != GameMode.CREATIVE ){ + if (player is Player) { + if (player.gameMode != GameMode.CREATIVE) { val bypassToExpensive = (ConfigOptions.doReplaceTooExpensive) && (finalAnvilCost >= 40) && finalAnvilCost < inventory.maximumRepairCost @@ -77,22 +83,26 @@ object AnvilXpUtil { fun calculatePenalty(left: ItemStack, right: ItemStack?, result: ItemStack, useType: AnvilUseType): Int { // Extracted From https://minecraft.fandom.com/wiki/Anvil_mechanics#Enchantment_equation // Calculate work penalty - val penaltyType = ConfigOptions.workPenaltyType + val penaltyType = ConfigOptions.workPenaltyPart(useType) val leftPenalty = (left.itemMeta as? Repairable)?.repairCost ?: 0 + val leftExclusivePenalty = findExclusivePenalty(left, useType) val rightPenalty = if (right == null) 0 else (right.itemMeta as? Repairable)?.repairCost ?: 0 - + val rightExclusivePenalty = findExclusivePenalty(right, useType) // Increase penalty on fusing or unit repair - if(penaltyType.isPenaltyIncreasing && (right != null || AnvilUseType.UNIT_REPAIR == useType)){ + if (penaltyType.penaltyIncrease) { result.itemMeta?.let { (it as? Repairable)?.repairCost = leftPenalty * 2 + 1 result.itemMeta = it - } } + if (penaltyType.exclusivePenaltyIncrease) { + val resultPenalty = leftExclusivePenalty * 2 + 1 + setExclusivePenalty(result, resultPenalty, useType) + } CustomAnvil.log( "Calculated penalty: " + @@ -101,9 +111,40 @@ object AnvilXpUtil { "result penalty: ${(result.itemMeta as? Repairable)?.repairCost ?: "none"}" ) - if(!penaltyType.isPenaltyAdditive) return 0 + var resultSum = 0 + if (penaltyType.penaltyAdditive) { + resultSum += leftPenalty + rightPenalty + } + if (penaltyType.exclusivePenaltyAdditive) { + resultSum += leftExclusivePenalty + rightExclusivePenalty + } - return leftPenalty + rightPenalty + return resultSum + } + + private fun setExclusivePenalty( + result: ItemStack, + resultPenalty: Int, + useType: AnvilUseType + ) { + val tagPath = EXCLUSIVE_PENALTY_PREFIX + "_" + useType.typeName + val key = NamespacedKey(CustomAnvil.instance, tagPath) + + val meta = result.itemMeta!! + meta.persistentDataContainer.set(key, PersistentDataType.INTEGER, resultPenalty) + result.itemMeta = meta + } + + private fun findExclusivePenalty( + left: ItemStack?, + useType: AnvilUseType + ): Int { + if (left == null) return 0 + val tagPath = EXCLUSIVE_PENALTY_PREFIX + "_" + useType.typeName + val key = NamespacedKey(CustomAnvil.instance, tagPath) + + val meta = left.itemMeta!! + return meta.persistentDataContainer.get(key, PersistentDataType.INTEGER) ?: return 0 } /** diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index ebab437..10d6ef9 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -72,18 +72,6 @@ permission_needed_for_color: true # Valid values include 0 to 1000. use_of_color_cost: 0 -# Work penalty increase the price for every anvil use. -# This config allow you to choose the comportment of work penalty. -# Vanilla work penalty formula can be represented as 2 * previous_penalty + 1. with start value equal to 0 -# See https://minecraft.wiki/w/Anvil_mechanics#Anvil_uses for more detail -# -# Valid work penalty type is: -# - default: work penalty added and increased -# - increase_only: work penalty increased but not added -# - add_only: work penalty added but not increased -# - disabled: work penalty disabled -work_penalty_type: default - # Default limit to apply to any enchants missing from enchant_limits # # Valid values include 1 to 1000 @@ -294,4 +282,4 @@ debug_log_verbose: false # ProtocoLib may also be used if the server is in an "unsupported" version even if this option is disabled. force_protocolib: false -configVersion: 1.6.7 +configVersion: 1.8.0