From 962455bf22e34a253789e7bd65a56ca9a695a86b Mon Sep 17 00:00:00 2001 From: ali-afk Date: Tue, 18 Feb 2025 18:22:47 +0300 Subject: [PATCH 1/8] Add curseChanceScales bool to config, default is TRUE. Add maxCurseChance int to config, default is 75. Fix some typos in config descriptions. Move entries around for easier reading. --- .../cursery/config/CommonConfiguration.java | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/cursery/config/CommonConfiguration.java b/src/main/java/com/cursery/config/CommonConfiguration.java index 3720c85..dddbfe5 100644 --- a/src/main/java/com/cursery/config/CommonConfiguration.java +++ b/src/main/java/com/cursery/config/CommonConfiguration.java @@ -24,7 +24,9 @@ public class CommonConfiguration implements ICommonConfig public boolean showDesc = true; public boolean visualSuccess = true; public boolean onlynotechanted = false; + public boolean curseChanceScales = true; public int basecursechance = 5; + public int maxCurseChance = 75; public CommonConfiguration() { @@ -35,10 +37,10 @@ public JsonObject serialize() { final JsonObject root = new JsonObject(); - final JsonObject entry = new JsonObject(); - entry.addProperty("desc:", "Should enchanted books show a hint for curse magic, default:true"); - entry.addProperty("showDesc", showDesc); - root.add("showDesc", entry); + final JsonObject entry0 = new JsonObject(); + entry0.addProperty("desc:", "Should enchanted books show a hint for curse magic, default:true"); + entry0.addProperty("showDesc", showDesc); + root.add("showDesc", entry0); final JsonObject entry1 = new JsonObject(); entry1.addProperty("desc:", "Add a curse id here to exclude it from beeing applied. " @@ -56,18 +58,13 @@ public JsonObject serialize() entry2.addProperty("excludeTreasure", excludeTreasure); root.add("excludeTreasure", entry2); - final JsonObject entry7 = new JsonObject(); - entry7.addProperty("desc:", "Should curses only be applied on enchanting unenchanted items, recommended to increase base chance when enabling, default:false"); - entry7.addProperty("onlynotechanted", onlynotechanted); - root.add("onlynotechanted", entry7); - final JsonObject entry3 = new JsonObject(); - entry3.addProperty("desc:", "Base curse application chance, scales up the more enchants the item has. Default:5 %"); + entry3.addProperty("desc:", "Base curse application chance, default:5 %"); entry3.addProperty("basecursechance", basecursechance); root.add("basecursechance", entry3); final JsonObject entry4 = new JsonObject(); - entry4.addProperty("desc:", "Whether to log debug messages about curse chances beeing rolled, default = false"); + entry4.addProperty("desc:", "Whether to log debug messages about curse chances being rolled, default = false"); entry4.addProperty("debugTries", debugTries); root.add("debugTries", entry4); @@ -76,6 +73,23 @@ public JsonObject serialize() entry5.addProperty("visualSuccess", visualSuccess); root.add("visualSuccess", entry5); + final JsonObject entry6 = new JsonObject(); + entry6.addProperty("desc:", "Whether curse chance should scale the more enchantment levels an item has, " + + "If FALSE, curseChance = baseCurseChance, default:true"); + entry6.addProperty("curseChanceScales", curseChanceScales); + root.add("curseChanceScales", entry6); + + final JsonObject entry7 = new JsonObject(); + entry7.addProperty("desc:", "Should curses only be applied on enchanting unenchanted items, recommended to increase base chance when enabling, default:false"); + entry7.addProperty("onlynotechanted", onlynotechanted); + root.add("onlynotechanted", entry7); + + final JsonObject entry8 = new JsonObject(); + entry8.addProperty("desc:", "Maximum curse application chance, ignored if curseChanceScales is FALSE, default: 75 %"); + entry8.addProperty("maxCurseChance", maxCurseChance); + root.add("maxCurseChance", entry8); + + return root; } @@ -86,6 +100,8 @@ public void deserialize(JsonObject data) debugTries = data.get("debugTries").getAsJsonObject().get("debugTries").getAsBoolean(); visualSuccess = data.get("visualSuccess").getAsJsonObject().get("visualSuccess").getAsBoolean(); basecursechance = data.get("basecursechance").getAsJsonObject().get("basecursechance").getAsInt(); + maxCurseChance = data.get("maxCurseChance").getAsJsonObject().get("maxCurseChance").getAsInt(); + curseChanceScales = data.get("curseChanceScales").getAsJsonObject().get("curseChanceScales").getAsBoolean(); onlynotechanted = data.get("onlynotechanted").getAsJsonObject().get("onlynotechanted").getAsBoolean(); excludedCurses = new ArrayList<>(); for (final JsonElement element : data.get("excludedCurses").getAsJsonObject().get("excludedCurses").getAsJsonArray()) From 310c52d32c2f834ecff89dcaa7100fd46942c624 Mon Sep 17 00:00:00 2001 From: ali-afk Date: Tue, 18 Feb 2025 20:15:23 +0300 Subject: [PATCH 2/8] Changed curse logic to reflect toggling curseChanceScaling and maximumCurseChance. --- .../cursery/enchant/CurseEnchantmentHelper.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java b/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java index 057fe2a..cca798e 100644 --- a/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java +++ b/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java @@ -10,6 +10,7 @@ import net.minecraft.world.item.enchantment.Enchantment; import net.minecraftforge.registries.ForgeRegistries; +import java.util.function.Supplier; import java.util.*; /** @@ -143,17 +144,24 @@ private static boolean rollAndApplyCurseTo( final int levelSum, final Map newEnchants) { + + Supplier curseChance = () -> Cursery.config.getCommonConfig().basecursechance; + if (Cursery.config.getCommonConfig().curseChanceScales) + { + curseChance = () -> Math.min(Cursery.config.getCommonConfig().maxCurseChance, + Cursery.config.getCommonConfig().basecursechance + levelSum - (stack.getEnchantmentValue() >> 1)); + } + // Each level has the same chance, so its the same to apply enchant V vs I to V boolean appliedCurse = false; for (int i = 0; i < newLevel; i++) { if (Cursery.config.getCommonConfig().debugTries) { - Cursery.LOGGER.info("Rolling new curse for " + stack + " addedEnchLevels: " + newLevel + " totalEnchantLevels: " + levelSum + " chance:" + Math.min(75, - Cursery.config.getCommonConfig().basecursechance + levelSum - (stack.getEnchantmentValue() >> 1))); + Cursery.LOGGER.info("Rolling new curse for " + stack + " addedEnchLevels: " + newLevel + " totalEnchantLevels: " + levelSum + " chance:" + curseChance.get()); } - if (rand.nextInt(100) < Math.min(75, Cursery.config.getCommonConfig().basecursechance + levelSum - (stack.getEnchantmentValue() >> 1))) + if (rand.nextInt(100) < curseChance.get()) { if (Cursery.config.getCommonConfig().debugTries) { From 73c00dcbeae1fc5aa21f3516b3e972337057f806 Mon Sep 17 00:00:00 2001 From: ali-afk Date: Wed, 19 Feb 2025 13:33:58 +0300 Subject: [PATCH 3/8] Add curseEveryXLevels option to config. Changed curse logic to reflect curseEveryXLevels override. Make config look neater. Add debug logging to new configs --- .../cursery/config/CommonConfiguration.java | 95 ++++++++++----- .../enchant/CurseEnchantmentHelper.java | 111 ++++++++++++------ 2 files changed, 141 insertions(+), 65 deletions(-) diff --git a/src/main/java/com/cursery/config/CommonConfiguration.java b/src/main/java/com/cursery/config/CommonConfiguration.java index dddbfe5..6b04028 100644 --- a/src/main/java/com/cursery/config/CommonConfiguration.java +++ b/src/main/java/com/cursery/config/CommonConfiguration.java @@ -18,16 +18,22 @@ public class CommonConfiguration implements ICommonConfig { - public List excludedCurses = new ArrayList<>(); - public boolean excludeTreasure = false; public boolean debugTries = false; public boolean showDesc = true; + + public List excludedCurses = new ArrayList<>(); + public boolean excludeTreasure = false; + + public boolean onlyUnEnchanted = false; public boolean visualSuccess = true; - public boolean onlynotechanted = false; + public boolean curseChanceScales = true; - public int basecursechance = 5; + public int baseCurseChance = 5; public int maxCurseChance = 75; + public int curseEveryXLevels = 0; + + public CommonConfiguration() { excludedCurses.add("minecraft:vanishing_curse"); @@ -38,72 +44,79 @@ public JsonObject serialize() final JsonObject root = new JsonObject(); final JsonObject entry0 = new JsonObject(); - entry0.addProperty("desc:", "Should enchanted books show a hint for curse magic, default:true"); - entry0.addProperty("showDesc", showDesc); - root.add("showDesc", entry0); + entry0.addProperty("desc:", "Whether to log debug messages about curse chances being rolled. Default: false"); + entry0.addProperty("debugTries", debugTries); + root.add("debugTries", entry0); final JsonObject entry1 = new JsonObject(); - entry1.addProperty("desc:", "Add a curse id here to exclude it from beeing applied. " - + "To put multiple values seperate them by commas like this: [\"minecraft:curse\", \"mod:curse;\"] "); + entry1.addProperty("desc:", "Should enchanted books show a hint for curse magic. Default: true"); + entry1.addProperty("showDesc", showDesc); + root.add("showDesc", entry1); + + final JsonObject entry2 = new JsonObject(); + entry2.addProperty("desc:", "Add a curse id here to exclude it from being applied. " + + "To put multiple values separate them by commas like this: [\"minecraft:curse\", \"mod:curse;\"] "); final JsonArray list1 = new JsonArray(); for (final String name : excludedCurses) { list1.add(name); } - entry1.add("excludedCurses", list1); + entry2.add("excludedCurses", list1); root.add("excludedCurses", entry1); - final JsonObject entry2 = new JsonObject(); - entry2.addProperty("desc:", "Should applying treasure enchants be excluded, default:false"); - entry2.addProperty("excludeTreasure", excludeTreasure); - root.add("excludeTreasure", entry2); - final JsonObject entry3 = new JsonObject(); - entry3.addProperty("desc:", "Base curse application chance, default:5 %"); - entry3.addProperty("basecursechance", basecursechance); - root.add("basecursechance", entry3); + entry3.addProperty("desc:", "Should applying treasure enchants be excluded. Default: false"); + entry3.addProperty("excludeTreasure", excludeTreasure); + root.add("excludeTreasure", entry3); final JsonObject entry4 = new JsonObject(); - entry4.addProperty("desc:", "Whether to log debug messages about curse chances being rolled, default = false"); - entry4.addProperty("debugTries", debugTries); - root.add("debugTries", entry4); + entry4.addProperty("desc:", "Should curses only be applied on enchanting unenchanted items, recommended to increase base chance when enabling. Default: false"); + entry4.addProperty("onlyUnEnchanted", onlyUnEnchanted); + root.add("onlyUnEnchanted", entry4); final JsonObject entry5 = new JsonObject(); - entry5.addProperty("desc:", "Should enchanting success play a sound and show particles, default:true"); + entry5.addProperty("desc:", "Should enchanting success play a sound and show particles. Default: true"); entry5.addProperty("visualSuccess", visualSuccess); root.add("visualSuccess", entry5); final JsonObject entry6 = new JsonObject(); entry6.addProperty("desc:", "Whether curse chance should scale the more enchantment levels an item has, " - + "If FALSE, curseChance = baseCurseChance, default:true"); + + "If FALSE, curseChance = baseCurseChance. Default: true"); entry6.addProperty("curseChanceScales", curseChanceScales); root.add("curseChanceScales", entry6); final JsonObject entry7 = new JsonObject(); - entry7.addProperty("desc:", "Should curses only be applied on enchanting unenchanted items, recommended to increase base chance when enabling, default:false"); - entry7.addProperty("onlynotechanted", onlynotechanted); - root.add("onlynotechanted", entry7); + entry7.addProperty("desc:", "Base curse application chance. Default:5 %"); + entry7.addProperty("basecursechance", baseCurseChance); + root.add("basecursechance", entry7); final JsonObject entry8 = new JsonObject(); - entry8.addProperty("desc:", "Maximum curse application chance, ignored if curseChanceScales is FALSE, default: 75 %"); + entry8.addProperty("desc:", "Maximum curse application chance, ignored if curseChanceScales is FALSE. Default: 75 %"); entry8.addProperty("maxCurseChance", maxCurseChance); root.add("maxCurseChance", entry8); + final JsonObject entry9 = new JsonObject(); + entry9.addProperty("desc:", "Applies a curse every X enchantment levels, disabled if X = 0." + + "Completely disables curseChance settings. Default: 0 "); + entry9.addProperty("curseEveryXLevels", curseEveryXLevels); + root.add("curseEveryXLevels", entry9); + return root; } public void deserialize(JsonObject data) { + debugTries = data.get("debugTries").getAsJsonObject().get("debugTries").getAsBoolean(); showDesc = data.get("showDesc").getAsJsonObject().get("showDesc").getAsBoolean(); + excludedCurses = new ArrayList<>(); excludeTreasure = data.get("excludeTreasure").getAsJsonObject().get("excludeTreasure").getAsBoolean(); - debugTries = data.get("debugTries").getAsJsonObject().get("debugTries").getAsBoolean(); + onlyUnEnchanted = data.get("onlyUnEnchanted").getAsJsonObject().get("onlyUnEnchanted").getAsBoolean(); visualSuccess = data.get("visualSuccess").getAsJsonObject().get("visualSuccess").getAsBoolean(); - basecursechance = data.get("basecursechance").getAsJsonObject().get("basecursechance").getAsInt(); - maxCurseChance = data.get("maxCurseChance").getAsJsonObject().get("maxCurseChance").getAsInt(); curseChanceScales = data.get("curseChanceScales").getAsJsonObject().get("curseChanceScales").getAsBoolean(); - onlynotechanted = data.get("onlynotechanted").getAsJsonObject().get("onlynotechanted").getAsBoolean(); - excludedCurses = new ArrayList<>(); + baseCurseChance = data.get("baseCurseChance").getAsJsonObject().get("baseCurseChance").getAsInt(); + maxCurseChance = data.get("maxCurseChance").getAsJsonObject().get("maxCurseChance").getAsInt(); + curseEveryXLevels = data.get("curseEveryXLevels").getAsJsonObject().get("curseEveryXLevels").getAsInt(); for (final JsonElement element : data.get("excludedCurses").getAsJsonObject().get("excludedCurses").getAsJsonArray()) { excludedCurses.add(element.getAsString()); @@ -157,5 +170,23 @@ public void parseConfig() { Cursery.LOGGER.error("Unable to retrieve curses from registry"); } + + if (baseCurseChance < 0 || baseCurseChance > 100) + { + Cursery.LOGGER.warn(String.format("BaseCurseChance was set to '%d' yet must be within interval 0 <= X <= 100. Setting back to 5.", baseCurseChance)); + baseCurseChance = 5; + } + + if (maxCurseChance < 0 || maxCurseChance > 100) + { + Cursery.LOGGER.warn(String.format("MaxCurseChance was set to '%d' yet must be within interval 0 <= X <= 100. Setting back to 75.", maxCurseChance)); + maxCurseChance = 75; + } + + if (curseEveryXLevels < 0) + { + Cursery.LOGGER.warn(String.format("CurseEveryXLevels was set to '%d' yet must be within interval X >= 0. Setting back to 0.", curseEveryXLevels)); + curseEveryXLevels = 0; + } } } diff --git a/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java b/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java index cca798e..c6708bd 100644 --- a/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java +++ b/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java @@ -61,7 +61,7 @@ public static boolean checkForRandomCurse(final ItemStack stack, final Map newEnchants) { - Supplier curseChance = () -> Cursery.config.getCommonConfig().basecursechance; + Supplier curseChance = () -> Cursery.config.getCommonConfig().baseCurseChance; if (Cursery.config.getCommonConfig().curseChanceScales) { curseChance = () -> Math.min(Cursery.config.getCommonConfig().maxCurseChance, - Cursery.config.getCommonConfig().basecursechance + levelSum - (stack.getEnchantmentValue() >> 1)); + Cursery.config.getCommonConfig().baseCurseChance + levelSum - (stack.getEnchantmentValue() >> 1)); + } + + boolean isCurseApplied = false; + + // CurseEveryXLevels overrides curseChance mechanic + if (Cursery.config.getCommonConfig().curseEveryXLevels != 0) + { + if (Cursery.config.getCommonConfig().debugTries) + { + Cursery.LOGGER.info("CurseEveryXLevels override is TRUE. Skipping curseChance settings."); + } + + int curseInterval = Cursery.config.getCommonConfig().curseEveryXLevels; + int startStripe = (int) Math.ceil((double) levelSum / curseInterval); + int endStripe = (int) Math.floor((double) (levelSum + newLevel) / curseInterval); + + int cursesPassed = Math.max(0, endStripe - startStripe + 1); + for (int i = 0; i < cursesPassed; i++) + { + if (Cursery.config.getCommonConfig().debugTries) + { + Cursery.LOGGER.info("Rolling new curse for " + stack + " addedEnchLevels: " + newLevel + + " totalEnchantLevels: " + levelSum + " overriden by curseEveryXLevels"); + } + isCurseApplied = applyCurseTo(stack, newEnchants); + } + return isCurseApplied; + } + + if (Cursery.config.getCommonConfig().debugTries) + { + Cursery.LOGGER.info("CurseEveryXLevels override is FALSE."); } // Each level has the same chance, so its the same to apply enchant V vs I to V - boolean appliedCurse = false; for (int i = 0; i < newLevel; i++) { if (Cursery.config.getCommonConfig().debugTries) { - Cursery.LOGGER.info("Rolling new curse for " + stack + " addedEnchLevels: " + newLevel + " totalEnchantLevels: " + levelSum + " chance:" + curseChance.get()); + Cursery.LOGGER.info("Rolling new curse for " + stack + " addedEnchLevels: " + newLevel + + " totalEnchantLevels: " + levelSum + " chance:" + curseChance.get()); } if (rand.nextInt(100) < curseChance.get()) + { + isCurseApplied = applyCurseTo(stack, newEnchants); + } + } + return isCurseApplied; + } + + /** + * Applies curse to item. Helper method to rollAndApplyCurseTo() + * + * @param stack item + * @param newEnchants new enchantments on the stack + * @return true if curse is applied. + */ + private static boolean applyCurseTo( + final ItemStack stack, + final Map newEnchants) + { + if (Cursery.config.getCommonConfig().debugTries) + { + Cursery.LOGGER.info("Trying to apply curse to: " + stack); + } + + for (int j = 0; j < 15; j++) + { + final Enchantment curse = getRandomCurse(); + if (curse == null) + { + continue; + } + + final int currentLevel = newEnchants.getOrDefault(curse, 0); + if (currentLevel < curse.getMaxLevel() && curse.canEnchant(stack) && isCompatibleWithAll(curse, newEnchants)) { if (Cursery.config.getCommonConfig().debugTries) { - Cursery.LOGGER.info("Trying to apply curse to: " + stack); + Cursery.LOGGER.info("Applying curse " + ForgeRegistries.ENCHANTMENTS.getKey(curse) + " to: " + stack); } - for (int j = 0; j < 15; j++) - { - final Enchantment curse = getRandomCurse(); - if (curse == null) - { - continue; - } - - final int currentLevel = newEnchants.getOrDefault(curse, 0); - if (currentLevel < curse.getMaxLevel() && curse.canEnchant(stack) && isCompatibleWithAll(curse, newEnchants)) - { - if (Cursery.config.getCommonConfig().debugTries) - { - Cursery.LOGGER.info("Applying curse " + ForgeRegistries.ENCHANTMENTS.getKey(curse) + " to: " + stack); - } - - enchantManually(stack, curse, currentLevel + 1); - newEnchants.put(curse, currentLevel + 1); - appliedCurse = true; - break; - } - } + enchantManually(stack, curse, currentLevel + 1); + newEnchants.put(curse, currentLevel + 1); + return true; } } - - return appliedCurse; + return false; } /** From df0ed4247507105b622df8aa8aab2fe9b74d621a Mon Sep 17 00:00:00 2001 From: ali-afk Date: Wed, 19 Feb 2025 17:19:41 +0300 Subject: [PATCH 4/8] Fix curseEveryXLevels logic. Fix config typos. --- .../cursery/config/CommonConfiguration.java | 10 +++--- .../enchant/CurseEnchantmentHelper.java | 31 ++++++++++--------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/cursery/config/CommonConfiguration.java b/src/main/java/com/cursery/config/CommonConfiguration.java index 6b04028..4a8f5fb 100644 --- a/src/main/java/com/cursery/config/CommonConfiguration.java +++ b/src/main/java/com/cursery/config/CommonConfiguration.java @@ -62,7 +62,7 @@ public JsonObject serialize() list1.add(name); } entry2.add("excludedCurses", list1); - root.add("excludedCurses", entry1); + root.add("excludedCurses", entry2); final JsonObject entry3 = new JsonObject(); entry3.addProperty("desc:", "Should applying treasure enchants be excluded. Default: false"); @@ -86,9 +86,9 @@ public JsonObject serialize() root.add("curseChanceScales", entry6); final JsonObject entry7 = new JsonObject(); - entry7.addProperty("desc:", "Base curse application chance. Default:5 %"); - entry7.addProperty("basecursechance", baseCurseChance); - root.add("basecursechance", entry7); + entry7.addProperty("desc:", "Base curse application chance. Default: 5 %"); + entry7.addProperty("baseCurseChance", baseCurseChance); + root.add("baseCurseChance", entry7); final JsonObject entry8 = new JsonObject(); entry8.addProperty("desc:", "Maximum curse application chance, ignored if curseChanceScales is FALSE. Default: 75 %"); @@ -96,7 +96,7 @@ public JsonObject serialize() root.add("maxCurseChance", entry8); final JsonObject entry9 = new JsonObject(); - entry9.addProperty("desc:", "Applies a curse every X enchantment levels, disabled if X = 0." + entry9.addProperty("desc:", "Applies a curse every X enchantment levels, disabled if X = 0. " + "Completely disables curseChance settings. Default: 0 "); entry9.addProperty("curseEveryXLevels", curseEveryXLevels); root.add("curseEveryXLevels", entry9); diff --git a/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java b/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java index c6708bd..b4aa14e 100644 --- a/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java +++ b/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java @@ -78,7 +78,7 @@ public static boolean checkForRandomCurse(final ItemStack stack, final Map addedLevels = new ArrayList<>(); - boolean appliedCurse = false; + boolean isCurseApplied = false; // Compare enchants for (final Map.Entry newEnchant : newEnchants.entrySet()) { @@ -104,12 +104,12 @@ public static boolean checkForRandomCurse(final ItemStack stack, final Map newEnchants) { - Supplier curseChance = () -> Cursery.config.getCommonConfig().baseCurseChance; - if (Cursery.config.getCommonConfig().curseChanceScales) - { - curseChance = () -> Math.min(Cursery.config.getCommonConfig().maxCurseChance, - Cursery.config.getCommonConfig().baseCurseChance + levelSum - (stack.getEnchantmentValue() >> 1)); - } - boolean isCurseApplied = false; // CurseEveryXLevels overrides curseChance mechanic @@ -163,11 +156,12 @@ private static boolean rollAndApplyCurseTo( } int curseInterval = Cursery.config.getCommonConfig().curseEveryXLevels; - int startStripe = (int) Math.ceil((double) levelSum / curseInterval); - int endStripe = (int) Math.floor((double) (levelSum + newLevel) / curseInterval); - int cursesPassed = Math.max(0, endStripe - startStripe + 1); - for (int i = 0; i < cursesPassed; i++) + int existingCursesPassed = (int) Math.ceil((double) (levelSum + 1) / curseInterval); + int totalCursesPassed = (int) Math.floor((double) (levelSum + newLevel) / curseInterval); + int cursesToApply = totalCursesPassed - existingCursesPassed + 1; + + for (int i = 0; i < cursesToApply; i++) { if (Cursery.config.getCommonConfig().debugTries) { @@ -184,6 +178,13 @@ private static boolean rollAndApplyCurseTo( Cursery.LOGGER.info("CurseEveryXLevels override is FALSE."); } + Supplier curseChance = () -> Cursery.config.getCommonConfig().baseCurseChance; + if (Cursery.config.getCommonConfig().curseChanceScales) + { + curseChance = () -> Math.min(Cursery.config.getCommonConfig().maxCurseChance, + Cursery.config.getCommonConfig().baseCurseChance + levelSum - (stack.getEnchantmentValue() >> 1)); + } + // Each level has the same chance, so its the same to apply enchant V vs I to V for (int i = 0; i < newLevel; i++) { From 5deff0beb15bfa47513d52a8806e2b97f956a942 Mon Sep 17 00:00:00 2001 From: ali-afk Date: Wed, 19 Feb 2025 17:41:37 +0300 Subject: [PATCH 5/8] - curseEveryXLevels no longer overrides curseChance. Both work together now. - Make some one-line if-statements in parts of code easier to read. - Clarify curseEveryXLevels config description. --- .../cursery/config/CommonConfiguration.java | 12 ++---- .../enchant/CurseEnchantmentHelper.java | 42 ++++++++----------- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/cursery/config/CommonConfiguration.java b/src/main/java/com/cursery/config/CommonConfiguration.java index 4a8f5fb..567b7ae 100644 --- a/src/main/java/com/cursery/config/CommonConfiguration.java +++ b/src/main/java/com/cursery/config/CommonConfiguration.java @@ -96,8 +96,8 @@ public JsonObject serialize() root.add("maxCurseChance", entry8); final JsonObject entry9 = new JsonObject(); - entry9.addProperty("desc:", "Applies a curse every X enchantment levels, disabled if X = 0. " - + "Completely disables curseChance settings. Default: 0 "); + entry9.addProperty("desc:", "Applies a curse every X enchantment levels, " + + "no other curses are applied by curseChance each time this occurs. Disabled if X = 0. Default: 0 "); entry9.addProperty("curseEveryXLevels", curseEveryXLevels); root.add("curseEveryXLevels", entry9); @@ -160,26 +160,22 @@ public void parseConfig() CurseEnchantmentHelper.curseWeightMap.put(enchantmentEntry.getValue(), weight); } else - { Cursery.LOGGER.info("Excluding curse: " + ForgeRegistries.ENCHANTMENTS.getKey(enchantmentEntry.getValue()) + " as config disables it"); - } } } if (totalCurseWeight == 0) - { Cursery.LOGGER.error("Unable to retrieve curses from registry"); - } if (baseCurseChance < 0 || baseCurseChance > 100) { - Cursery.LOGGER.warn(String.format("BaseCurseChance was set to '%d' yet must be within interval 0 <= X <= 100. Setting back to 5.", baseCurseChance)); + Cursery.LOGGER.warn(String.format("BaseCurseChance was set to '%d' yet must be within the interval 0 <= X <= 100. Setting back to 5.", baseCurseChance)); baseCurseChance = 5; } if (maxCurseChance < 0 || maxCurseChance > 100) { - Cursery.LOGGER.warn(String.format("MaxCurseChance was set to '%d' yet must be within interval 0 <= X <= 100. Setting back to 75.", maxCurseChance)); + Cursery.LOGGER.warn(String.format("MaxCurseChance was set to '%d' yet must be within the interval 0 <= X <= 100. Setting back to 75.", maxCurseChance)); maxCurseChance = 75; } diff --git a/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java b/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java index b4aa14e..4415a2b 100644 --- a/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java +++ b/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java @@ -146,20 +146,23 @@ private static boolean rollAndApplyCurseTo( { boolean isCurseApplied = false; + int curseInterval = Cursery.config.getCommonConfig().curseEveryXLevels; - // CurseEveryXLevels overrides curseChance mechanic - if (Cursery.config.getCommonConfig().curseEveryXLevels != 0) + // Checks how many curses in the interval have been passed. + // Disables (sets = 0) curseEveryXLevels if it equals 0. + int existingCursesPassed = curseInterval == 0 ? 0 : (int) Math.ceil((double) (levelSum + 1) / curseInterval); + int totalCursesPassed = curseInterval == 0 ? 0 : (int) Math.floor((double) (levelSum + newLevel) / curseInterval); + int cursesToApply = curseInterval == 0 ? 0 : totalCursesPassed - existingCursesPassed + 1; + + if (cursesToApply == 0) { if (Cursery.config.getCommonConfig().debugTries) - { - Cursery.LOGGER.info("CurseEveryXLevels override is TRUE. Skipping curseChance settings."); - } - - int curseInterval = Cursery.config.getCommonConfig().curseEveryXLevels; - - int existingCursesPassed = (int) Math.ceil((double) (levelSum + 1) / curseInterval); - int totalCursesPassed = (int) Math.floor((double) (levelSum + newLevel) / curseInterval); - int cursesToApply = totalCursesPassed - existingCursesPassed + 1; + Cursery.LOGGER.info("CurseEveryXLevels override is FALSE."); + } + else + { + if (Cursery.config.getCommonConfig().debugTries) + Cursery.LOGGER.info("CurseEveryXLevels override is TRUE."); for (int i = 0; i < cursesToApply; i++) { @@ -173,31 +176,24 @@ private static boolean rollAndApplyCurseTo( return isCurseApplied; } - if (Cursery.config.getCommonConfig().debugTries) - { - Cursery.LOGGER.info("CurseEveryXLevels override is FALSE."); - } - - Supplier curseChance = () -> Cursery.config.getCommonConfig().baseCurseChance; + Supplier curseChance; if (Cursery.config.getCommonConfig().curseChanceScales) { curseChance = () -> Math.min(Cursery.config.getCommonConfig().maxCurseChance, Cursery.config.getCommonConfig().baseCurseChance + levelSum - (stack.getEnchantmentValue() >> 1)); } + else + curseChance = () -> Cursery.config.getCommonConfig().baseCurseChance; // Each level has the same chance, so its the same to apply enchant V vs I to V for (int i = 0; i < newLevel; i++) { if (Cursery.config.getCommonConfig().debugTries) - { Cursery.LOGGER.info("Rolling new curse for " + stack + " addedEnchLevels: " + newLevel + " totalEnchantLevels: " + levelSum + " chance:" + curseChance.get()); - } if (rand.nextInt(100) < curseChance.get()) - { isCurseApplied = applyCurseTo(stack, newEnchants); - } } return isCurseApplied; } @@ -214,9 +210,7 @@ private static boolean applyCurseTo( final Map newEnchants) { if (Cursery.config.getCommonConfig().debugTries) - { Cursery.LOGGER.info("Trying to apply curse to: " + stack); - } for (int j = 0; j < 15; j++) { @@ -230,9 +224,7 @@ private static boolean applyCurseTo( if (currentLevel < curse.getMaxLevel() && curse.canEnchant(stack) && isCompatibleWithAll(curse, newEnchants)) { if (Cursery.config.getCommonConfig().debugTries) - { Cursery.LOGGER.info("Applying curse " + ForgeRegistries.ENCHANTMENTS.getKey(curse) + " to: " + stack); - } enchantManually(stack, curse, currentLevel + 1); newEnchants.put(curse, currentLevel + 1); From d177003d1e13eed5d5b5aa47153c82c11bd9e4ec Mon Sep 17 00:00:00 2001 From: ali-afk Date: Wed, 19 Feb 2025 22:18:01 +0300 Subject: [PATCH 6/8] - Fix bug where an existing curse's level cannot be incremented because it is flagged incompatible by isCompatibleWithAll() - Fix bug in enchantManually() where curse with previous level was not removed when level was incremented. - Make sure guaranteedCursesToApply are not counted as part of newLevel in rollAndApplyCurseTo() - Better curse scaling logic: faster in the beginning, slower later on. - Clarified config to reflect scaling logic changes. --- .../cursery/config/CommonConfiguration.java | 5 +- .../enchant/CurseEnchantmentHelper.java | 60 +++++++++++++------ 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/cursery/config/CommonConfiguration.java b/src/main/java/com/cursery/config/CommonConfiguration.java index 567b7ae..bc39f80 100644 --- a/src/main/java/com/cursery/config/CommonConfiguration.java +++ b/src/main/java/com/cursery/config/CommonConfiguration.java @@ -81,12 +81,13 @@ public JsonObject serialize() final JsonObject entry6 = new JsonObject(); entry6.addProperty("desc:", "Whether curse chance should scale the more enchantment levels an item has, " - + "If FALSE, curseChance = baseCurseChance. Default: true"); + + "If FALSE, curseChance = baseCurseChance - item enchantability. Default: true"); entry6.addProperty("curseChanceScales", curseChanceScales); root.add("curseChanceScales", entry6); final JsonObject entry7 = new JsonObject(); - entry7.addProperty("desc:", "Base curse application chance. Default: 5 %"); + entry7.addProperty("desc:", "Base curse application chance, varies with item enchantability " + + "(minCurseChance = base - enchantability). Default: 5 %"); entry7.addProperty("baseCurseChance", baseCurseChance); root.add("baseCurseChance", entry7); diff --git a/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java b/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java index 4415a2b..e13c0f5 100644 --- a/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java +++ b/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java @@ -146,15 +146,15 @@ private static boolean rollAndApplyCurseTo( { boolean isCurseApplied = false; - int curseInterval = Cursery.config.getCommonConfig().curseEveryXLevels; + int guaranteedCurseInterval = Cursery.config.getCommonConfig().curseEveryXLevels; // Checks how many curses in the interval have been passed. - // Disables (sets = 0) curseEveryXLevels if it equals 0. - int existingCursesPassed = curseInterval == 0 ? 0 : (int) Math.ceil((double) (levelSum + 1) / curseInterval); - int totalCursesPassed = curseInterval == 0 ? 0 : (int) Math.floor((double) (levelSum + newLevel) / curseInterval); - int cursesToApply = curseInterval == 0 ? 0 : totalCursesPassed - existingCursesPassed + 1; + // Only makes a difference when curseEveryXLevels is enabled (i.e > 0) + int existingGuaranteedCursesPassed = guaranteedCurseInterval == 0 ? 0 : (int) Math.ceil((double) (levelSum + 1) / guaranteedCurseInterval); + int totalGuaranteedCursesPassed = guaranteedCurseInterval == 0 ? 0 : (int) Math.floor((double) (levelSum + newLevel) / guaranteedCurseInterval); + int guaranteedCursesToApply = guaranteedCurseInterval == 0 ? 0 : totalGuaranteedCursesPassed - existingGuaranteedCursesPassed + 1; - if (cursesToApply == 0) + if (guaranteedCursesToApply == 0) { if (Cursery.config.getCommonConfig().debugTries) Cursery.LOGGER.info("CurseEveryXLevels override is FALSE."); @@ -164,32 +164,42 @@ private static boolean rollAndApplyCurseTo( if (Cursery.config.getCommonConfig().debugTries) Cursery.LOGGER.info("CurseEveryXLevels override is TRUE."); - for (int i = 0; i < cursesToApply; i++) + for (int i = 0; i < guaranteedCursesToApply; i++) { if (Cursery.config.getCommonConfig().debugTries) { - Cursery.LOGGER.info("Rolling new curse for " + stack + " addedEnchLevels: " + newLevel - + " totalEnchantLevels: " + levelSum + " overriden by curseEveryXLevels"); + Cursery.LOGGER.info("Rolling new curse for " + stack + " guaranteedCursesToApply: " + guaranteedCursesToApply + + " totalEnchantLevels: " + levelSum + " curseChance overridden by curseEveryXLevels"); } isCurseApplied = applyCurseTo(stack, newEnchants); } - return isCurseApplied; } + // Makes sure the item is not cursed again for each level the guaranteed curse was applied. + int levelsLeftToApply = newLevel - guaranteedCursesToApply; + Supplier curseChance; + int minCurseChance = Cursery.config.getCommonConfig().baseCurseChance - (stack.getEnchantmentValue() >> 1); + int curseChanceRange = Cursery.config.getCommonConfig().maxCurseChance - Cursery.config.getCommonConfig().baseCurseChance; + if (Cursery.config.getCommonConfig().curseChanceScales) { - curseChance = () -> Math.min(Cursery.config.getCommonConfig().maxCurseChance, - Cursery.config.getCommonConfig().baseCurseChance + levelSum - (stack.getEnchantmentValue() >> 1)); + // Scaling rate varies with the marked number. + // Ideally should be kept between -0.0125 <= X <= -0.0175 + // Anything greater or lower will lead to extremely fast or slow scaling rates respectively. + curseChance = () -> (int) Math.ceil( + minCurseChance + curseChanceRange * (1 - Math.exp(/*Important*/-0.015/*Important*/ * levelSum)) + ); } else - curseChance = () -> Cursery.config.getCommonConfig().baseCurseChance; + curseChance = () -> minCurseChance; + // Each level has the same chance, so its the same to apply enchant V vs I to V - for (int i = 0; i < newLevel; i++) + for (int i = 0; i < levelsLeftToApply; i++) { if (Cursery.config.getCommonConfig().debugTries) - Cursery.LOGGER.info("Rolling new curse for " + stack + " addedEnchLevels: " + newLevel + Cursery.LOGGER.info("Rolling new curse for " + stack + " addedEnchLevels: " + levelsLeftToApply + " totalEnchantLevels: " + levelSum + " chance:" + curseChance.get()); if (rand.nextInt(100) < curseChance.get()) @@ -245,13 +255,15 @@ private static boolean isCompatibleWithAll(final Enchantment enchantment, final { for (final Map.Entry entry : newEnchants.entrySet()) { + // Makes sure to break (and hence return true) if an existing curse is rolled. + if (enchantment == entry.getKey()) + break; + if (!entry.getKey().isCompatibleWith(enchantment)) { if (Cursery.config.getCommonConfig().debugTries) - { - Cursery.LOGGER.info( - "Curse " + ForgeRegistries.ENCHANTMENTS.getKey(enchantment) + " is not compatible with " + ForgeRegistries.ENCHANTMENTS.getKey(entry.getKey())); - } + Cursery.LOGGER.info("Curse " + ForgeRegistries.ENCHANTMENTS.getKey(enchantment) + + " is not compatible with " + ForgeRegistries.ENCHANTMENTS.getKey(entry.getKey())); return false; } @@ -304,9 +316,19 @@ public static void enchantManually(final ItemStack stack, Enchantment enchantmen } ListTag listnbt = stack.getTag().getList("Enchantments", 10); + + // Makes sure to remove nbt tag of the existing curse with its previous level + if (level > 1) + { + CompoundTag compoundnbt = new CompoundTag(); + compoundnbt.putString("id", String.valueOf((Object) ForgeRegistries.ENCHANTMENTS.getKey(enchantment))); + compoundnbt.putShort("lvl", (short) ((byte) level - 1)); + listnbt.remove(compoundnbt); + } CompoundTag compoundnbt = new CompoundTag(); compoundnbt.putString("id", String.valueOf((Object) ForgeRegistries.ENCHANTMENTS.getKey(enchantment))); compoundnbt.putShort("lvl", (short) ((byte) level)); + listnbt.add(compoundnbt); } From 5fad56cdd4fcbbd7e4eb5e7e4b806c8e25665baa Mon Sep 17 00:00:00 2001 From: ali-afk Date: Fri, 21 Feb 2025 17:14:42 +0300 Subject: [PATCH 7/8] - Add better debug statements to enchantManually(). - Add KintsugiRemixEnchantmentMenuMixin for [Kintsugi](https://github.com/avivbeeri/kintsugi "Go to GitHub") mod compat, [Curseforge](https://www.curseforge.com/minecraft/mc-mods/kintsugi "Go to Curseforge") --- build.gradle | 1 + .../enchant/CurseEnchantmentHelper.java | 11 +++- .../KintsugiRemixEnchantmentMenuMixin.java | 62 +++++++++++++++++++ src/main/resources/cursery.mixins.json | 1 + 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/cursery/mixin/KintsugiRemixEnchantmentMenuMixin.java diff --git a/build.gradle b/build.gradle index abdf6f2..238640d 100644 --- a/build.gradle +++ b/build.gradle @@ -95,6 +95,7 @@ dependencies { minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}" //21 compileOnly(fg.deobf("curse.maven:quarkoddities-301051:3575623")) compileOnly(fg.deobf("curse.maven:quark-243121:3919164")) + compileOnly(fg.deobf("curse.maven:kintsugi-908206:5229196")) implementation(fg.deobf("curse.maven:cupboard-326652:4669193")) annotationProcessor "org.spongepowered:mixin:0.8.5:processor" } diff --git a/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java b/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java index e13c0f5..4360863 100644 --- a/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java +++ b/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java @@ -317,14 +317,23 @@ public static void enchantManually(final ItemStack stack, Enchantment enchantmen ListTag listnbt = stack.getTag().getList("Enchantments", 10); - // Makes sure to remove nbt tag of the existing curse with its previous level + // Makes sure to remove nbt tag of the existing enchantment with its previous level if (level > 1) { + if (Cursery.config.getCommonConfig().debugTries) { + Cursery.LOGGER.info("Removing enchantment: " + enchantment.getDescriptionId() + + ",\n with level: " + (level - 1) + " from item to replace it with level: " + level); + } CompoundTag compoundnbt = new CompoundTag(); compoundnbt.putString("id", String.valueOf((Object) ForgeRegistries.ENCHANTMENTS.getKey(enchantment))); compoundnbt.putShort("lvl", (short) ((byte) level - 1)); listnbt.remove(compoundnbt); } + + if (Cursery.config.getCommonConfig().debugTries) { + Cursery.LOGGER.info("Adding back enchantment: " + enchantment.getDescriptionId() + + ",\n with level: " + level); + } CompoundTag compoundnbt = new CompoundTag(); compoundnbt.putString("id", String.valueOf((Object) ForgeRegistries.ENCHANTMENTS.getKey(enchantment))); compoundnbt.putShort("lvl", (short) ((byte) level)); diff --git a/src/main/java/com/cursery/mixin/KintsugiRemixEnchantmentMenuMixin.java b/src/main/java/com/cursery/mixin/KintsugiRemixEnchantmentMenuMixin.java new file mode 100644 index 0000000..8e31004 --- /dev/null +++ b/src/main/java/com/cursery/mixin/KintsugiRemixEnchantmentMenuMixin.java @@ -0,0 +1,62 @@ +package com.cursery.mixin; + +import com.cursery.Cursery; +import com.cursery.enchant.CurseEnchantmentHelper; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.Enchantment; +import net.infinitelimit.kintsugi.menus.RemixEnchantmentMenu; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.Map; + +@Mixin(RemixEnchantmentMenu.class) +public abstract class KintsugiRemixEnchantmentMenuMixin +{ + private Map previousEnchants; + + @Inject(method = "calculateResultItem", at = @At("HEAD"), remap = false) + private void delayApplyingCurse(final ItemStack itemStack, final ItemStack fuelStack, final CallbackInfo ci) { + CurseEnchantmentHelper.delayNext = true; + CurseEnchantmentHelper.delayItem = itemStack.getItem(); + previousEnchants = itemStack.getAllEnchantments(); + } + + @Inject(method = "onTake", at = @At("HEAD"), remap = false) + private void curseItemOnTake(final Player pPlayer, final ItemStack pStack, final CallbackInfo ci) { + if (Cursery.config.getCommonConfig().debugTries) { + Cursery.LOGGER.info("calculateResultItem: delayed the curse."); + Cursery.LOGGER.info("Previous Enchantments:" + formatEnchantments(previousEnchants)); + Cursery.LOGGER.info("onTake: Retrieving new enchantments."); + } + + Map existingEnchants = pStack.getAllEnchantments(); + + if (Cursery.config.getCommonConfig().debugTries) { + Cursery.LOGGER.info("New Enchantments:" + formatEnchantments(existingEnchants)); + Cursery.LOGGER.info("Checking for random curse for stack: " + pStack); + } + + boolean isCurseApplied = CurseEnchantmentHelper.checkForRandomCurse(pStack, previousEnchants, existingEnchants); + + if (Cursery.config.getCommonConfig().debugTries) { + Cursery.LOGGER.info(isCurseApplied ? "Curse applied!" : "Curse was not applied."); + } + } + + + /** + * Helper method to format enchantments map into a readable string. + */ + private String formatEnchantments(Map enchantments) { + if (enchantments == null || enchantments.isEmpty()) { + return " None"; + } + StringBuilder sb = new StringBuilder(); + enchantments.forEach((enchant, level) -> sb.append("\n - ").append(enchant.getDescriptionId()).append(": Level ").append(level)); + return sb.toString(); + } + +} diff --git a/src/main/resources/cursery.mixins.json b/src/main/resources/cursery.mixins.json index 8cea302..f53f05f 100644 --- a/src/main/resources/cursery.mixins.json +++ b/src/main/resources/cursery.mixins.json @@ -8,6 +8,7 @@ "AttributeModifierManagerMixin", "EnchantmentHelperMixin", "ItemStackMixin", + "KintsugiRemixEnchantmentMenuMixin", "QuarkEnchanterCompat", "QuarkEnchanterTECompat" ], From a901791f18e0376119751e4c3ea8b50d910afded Mon Sep 17 00:00:00 2001 From: ali-afk Date: Fri, 21 Feb 2025 17:14:42 +0300 Subject: [PATCH 8/8] - Add better debug statements to enchantManually(). - Add KintsugiRemixEnchantmentMenuMixin for Kintsugi mod compat, Curseforge: https://www.curseforge.com/minecraft/mc-mods/kintsugi, Github: https://github.com/avivbeeri/kintsugi --- build.gradle | 1 + .../enchant/CurseEnchantmentHelper.java | 11 +++- .../KintsugiRemixEnchantmentMenuMixin.java | 62 +++++++++++++++++++ src/main/resources/cursery.mixins.json | 1 + 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/cursery/mixin/KintsugiRemixEnchantmentMenuMixin.java diff --git a/build.gradle b/build.gradle index abdf6f2..238640d 100644 --- a/build.gradle +++ b/build.gradle @@ -95,6 +95,7 @@ dependencies { minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}" //21 compileOnly(fg.deobf("curse.maven:quarkoddities-301051:3575623")) compileOnly(fg.deobf("curse.maven:quark-243121:3919164")) + compileOnly(fg.deobf("curse.maven:kintsugi-908206:5229196")) implementation(fg.deobf("curse.maven:cupboard-326652:4669193")) annotationProcessor "org.spongepowered:mixin:0.8.5:processor" } diff --git a/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java b/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java index e13c0f5..4360863 100644 --- a/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java +++ b/src/main/java/com/cursery/enchant/CurseEnchantmentHelper.java @@ -317,14 +317,23 @@ public static void enchantManually(final ItemStack stack, Enchantment enchantmen ListTag listnbt = stack.getTag().getList("Enchantments", 10); - // Makes sure to remove nbt tag of the existing curse with its previous level + // Makes sure to remove nbt tag of the existing enchantment with its previous level if (level > 1) { + if (Cursery.config.getCommonConfig().debugTries) { + Cursery.LOGGER.info("Removing enchantment: " + enchantment.getDescriptionId() + + ",\n with level: " + (level - 1) + " from item to replace it with level: " + level); + } CompoundTag compoundnbt = new CompoundTag(); compoundnbt.putString("id", String.valueOf((Object) ForgeRegistries.ENCHANTMENTS.getKey(enchantment))); compoundnbt.putShort("lvl", (short) ((byte) level - 1)); listnbt.remove(compoundnbt); } + + if (Cursery.config.getCommonConfig().debugTries) { + Cursery.LOGGER.info("Adding back enchantment: " + enchantment.getDescriptionId() + + ",\n with level: " + level); + } CompoundTag compoundnbt = new CompoundTag(); compoundnbt.putString("id", String.valueOf((Object) ForgeRegistries.ENCHANTMENTS.getKey(enchantment))); compoundnbt.putShort("lvl", (short) ((byte) level)); diff --git a/src/main/java/com/cursery/mixin/KintsugiRemixEnchantmentMenuMixin.java b/src/main/java/com/cursery/mixin/KintsugiRemixEnchantmentMenuMixin.java new file mode 100644 index 0000000..8e31004 --- /dev/null +++ b/src/main/java/com/cursery/mixin/KintsugiRemixEnchantmentMenuMixin.java @@ -0,0 +1,62 @@ +package com.cursery.mixin; + +import com.cursery.Cursery; +import com.cursery.enchant.CurseEnchantmentHelper; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.Enchantment; +import net.infinitelimit.kintsugi.menus.RemixEnchantmentMenu; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.Map; + +@Mixin(RemixEnchantmentMenu.class) +public abstract class KintsugiRemixEnchantmentMenuMixin +{ + private Map previousEnchants; + + @Inject(method = "calculateResultItem", at = @At("HEAD"), remap = false) + private void delayApplyingCurse(final ItemStack itemStack, final ItemStack fuelStack, final CallbackInfo ci) { + CurseEnchantmentHelper.delayNext = true; + CurseEnchantmentHelper.delayItem = itemStack.getItem(); + previousEnchants = itemStack.getAllEnchantments(); + } + + @Inject(method = "onTake", at = @At("HEAD"), remap = false) + private void curseItemOnTake(final Player pPlayer, final ItemStack pStack, final CallbackInfo ci) { + if (Cursery.config.getCommonConfig().debugTries) { + Cursery.LOGGER.info("calculateResultItem: delayed the curse."); + Cursery.LOGGER.info("Previous Enchantments:" + formatEnchantments(previousEnchants)); + Cursery.LOGGER.info("onTake: Retrieving new enchantments."); + } + + Map existingEnchants = pStack.getAllEnchantments(); + + if (Cursery.config.getCommonConfig().debugTries) { + Cursery.LOGGER.info("New Enchantments:" + formatEnchantments(existingEnchants)); + Cursery.LOGGER.info("Checking for random curse for stack: " + pStack); + } + + boolean isCurseApplied = CurseEnchantmentHelper.checkForRandomCurse(pStack, previousEnchants, existingEnchants); + + if (Cursery.config.getCommonConfig().debugTries) { + Cursery.LOGGER.info(isCurseApplied ? "Curse applied!" : "Curse was not applied."); + } + } + + + /** + * Helper method to format enchantments map into a readable string. + */ + private String formatEnchantments(Map enchantments) { + if (enchantments == null || enchantments.isEmpty()) { + return " None"; + } + StringBuilder sb = new StringBuilder(); + enchantments.forEach((enchant, level) -> sb.append("\n - ").append(enchant.getDescriptionId()).append(": Level ").append(level)); + return sb.toString(); + } + +} diff --git a/src/main/resources/cursery.mixins.json b/src/main/resources/cursery.mixins.json index 8cea302..f53f05f 100644 --- a/src/main/resources/cursery.mixins.json +++ b/src/main/resources/cursery.mixins.json @@ -8,6 +8,7 @@ "AttributeModifierManagerMixin", "EnchantmentHelperMixin", "ItemStackMixin", + "KintsugiRemixEnchantmentMenuMixin", "QuarkEnchanterCompat", "QuarkEnchanterTECompat" ],