From 3e4de1e6288148c59bf07d28759070831c6bc49c Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 5 Jan 2025 19:16:43 -0800 Subject: [PATCH] Mending mends most damages equipment first --- ...g-mends-most-damages-equipment-first.patch | 129 ------------------ .../world/entity/ExperienceOrb.java.patch | 11 ++ .../minecraft/world/item/ItemStack.java.patch | 29 ++++ .../enchantment/EnchantmentHelper.java.patch | 46 ++++++- .../purpurmc/purpur/PurpurWorldConfig.java | 2 + 5 files changed, 87 insertions(+), 130 deletions(-) delete mode 100644 patches/server/0056-Mending-mends-most-damages-equipment-first.patch create mode 100644 purpur-server/minecraft-patches/sources/net/minecraft/world/entity/ExperienceOrb.java.patch create mode 100644 purpur-server/minecraft-patches/sources/net/minecraft/world/item/ItemStack.java.patch diff --git a/patches/server/0056-Mending-mends-most-damages-equipment-first.patch b/patches/server/0056-Mending-mends-most-damages-equipment-first.patch deleted file mode 100644 index 2483b76a4..000000000 --- a/patches/server/0056-Mending-mends-most-damages-equipment-first.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 14 Jul 2019 19:52:47 -0500 -Subject: [PATCH] Mending mends most damages equipment first - - -diff --git a/net/minecraft/world/entity/ExperienceOrb.java b/net/minecraft/world/entity/ExperienceOrb.java -index 23b47d90fd35659d9eaa661e808a7f89b29614cf..f1eb74a43881400f23f3750c909f999b35c2f5ce 100644 ---- a/net/minecraft/world/entity/ExperienceOrb.java -+++ b/net/minecraft/world/entity/ExperienceOrb.java -@@ -353,7 +353,7 @@ public class ExperienceOrb extends Entity { - } - - private int repairPlayerItems(ServerPlayer player, int amount) { -- Optional optional = EnchantmentHelper.getRandomItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player, ItemStack::isDamaged); -+ Optional optional = level().purpurConfig.useBetterMending ? EnchantmentHelper.getMostDamagedItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player) : EnchantmentHelper.getRandomItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player, ItemStack::isDamaged); // Purpur - Add option to mend the most damaged equipment first - - if (optional.isPresent()) { - ItemStack itemstack = ((EnchantedItemInUse) optional.get()).itemStack(); -diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java -index 731d2bf4a5861bfe10496162d367e003f40b2d50..122859ba52e9719f98111a9c543dab27abac39b5 100644 ---- a/net/minecraft/world/item/ItemStack.java -+++ b/net/minecraft/world/item/ItemStack.java -@@ -686,6 +686,26 @@ public final class ItemStack implements DataComponentHolder { - return this.isDamageableItem() && this.getDamageValue() > 0; - } - -+ // Purpur start - Add option to mend the most damaged equipment first -+ public float getDamagePercent() { -+ if (this.has(DataComponents.UNBREAKABLE)) { -+ return 0.0F; -+ } -+ -+ final int maxDamage = this.getOrDefault(DataComponents.MAX_DAMAGE, 0); -+ if (maxDamage == 0) { -+ return 0.0F; -+ } -+ -+ final int damage = this.getOrDefault(DataComponents.DAMAGE, 0); -+ if (damage == 0) { -+ return 0.0F; -+ } -+ -+ return (float) damage / maxDamage; -+ } -+ // Purpur end - Add option to mend the most damaged equipment first -+ - public int getDamageValue() { - return Mth.clamp((Integer) this.getOrDefault(DataComponents.DAMAGE, 0), 0, this.getMaxDamage()); - } -diff --git a/net/minecraft/world/item/enchantment/EnchantmentHelper.java b/net/minecraft/world/item/enchantment/EnchantmentHelper.java -index 64c315372277300e58ce413210f47eed5b6e1d6c..2c1799e8c9009a6ab24c24e7363d5a87e41f0c35 100644 ---- a/net/minecraft/world/item/enchantment/EnchantmentHelper.java -+++ b/net/minecraft/world/item/enchantment/EnchantmentHelper.java -@@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; - import java.util.ArrayList; - import java.util.Collection; - import java.util.List; -+import java.util.Map; - import java.util.Optional; - import java.util.function.BiConsumer; - import java.util.function.Consumer; -@@ -588,4 +589,48 @@ public class EnchantmentHelper { - return getItemEnchantmentLevel(getEnchantmentHolder(enchantment), stack); - } - // Purpur end - Enchantment convenience methods -+ -+ // Purpur start - Add option to mend the most damaged equipment first -+ public static Optional getMostDamagedItemWith(DataComponentType componentType, LivingEntity entity) { -+ ItemStack maxStack = null; -+ EquipmentSlot maxSlot = null; -+ float maxPercent = 0.0F; -+ -+ equipmentSlotLoop: -+ for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) { -+ ItemStack stack = entity.getItemBySlot(equipmentSlot); -+ -+ // do not even check enchantments for item with lower or equal damage percent -+ float percent = stack.getDamagePercent(); -+ if (percent <= maxPercent) { -+ continue; -+ } -+ -+ ItemEnchantments itemEnchantments = stack.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY); -+ -+ for (Entry> entry : itemEnchantments.entrySet()) { -+ Enchantment enchantment = entry.getKey().value(); -+ -+ net.minecraft.core.component.DataComponentMap effects = enchantment.effects(); -+ if (!effects.has(componentType)) { -+ // try with another enchantment -+ continue; -+ } -+ -+ if (enchantment.matchingSlot(equipmentSlot)) { -+ maxStack = stack; -+ maxSlot = equipmentSlot; -+ maxPercent = percent; -+ -+ // check another slot now -+ continue equipmentSlotLoop; -+ } -+ } -+ } -+ -+ return maxStack != null -+ ? Optional.of(new EnchantedItemInUse(maxStack, maxSlot, entity)) -+ : Optional.empty(); -+ } -+ // Purpur end - Add option to mend the most damaged equipment first - } -diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -index 3e78e57f29e98db2dde7d650b65ee23f99238ff7..6b7a6a7889353f9557c6e3bfa8ff8caf66416c1b 100644 ---- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -@@ -96,11 +96,13 @@ public class PurpurWorldConfig { - armorstandStepHeight = (float) getDouble("gameplay-mechanics.armorstand.step-height", armorstandStepHeight); - } - -+ public boolean useBetterMending = false; - public boolean boatEjectPlayersOnLand = false; - public boolean disableDropsOnCrammingDeath = false; - public boolean milkCuresBadOmen = true; - public double tridentLoyaltyVoidReturnHeight = 0.0D; - private void miscGameplayMechanicsSettings() { -+ useBetterMending = getBoolean("gameplay-mechanics.use-better-mending", useBetterMending); - boatEjectPlayersOnLand = getBoolean("gameplay-mechanics.boat.eject-players-on-land", boatEjectPlayersOnLand); - disableDropsOnCrammingDeath = getBoolean("gameplay-mechanics.disable-drops-on-cramming-death", disableDropsOnCrammingDeath); - milkCuresBadOmen = getBoolean("gameplay-mechanics.milk-cures-bad-omen", milkCuresBadOmen); diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/entity/ExperienceOrb.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/entity/ExperienceOrb.java.patch new file mode 100644 index 000000000..d4eddf247 --- /dev/null +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/entity/ExperienceOrb.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/ExperienceOrb.java ++++ b/net/minecraft/world/entity/ExperienceOrb.java +@@ -339,7 +_,7 @@ + } + + private int repairPlayerItems(ServerPlayer player, int value) { +- Optional randomItemWith = EnchantmentHelper.getRandomItemWith( ++ Optional randomItemWith = level().purpurConfig.useBetterMending ? EnchantmentHelper.getMostDamagedItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player) : EnchantmentHelper.getRandomItemWith( // Purpur - Add option to mend the most damaged equipment first + EnchantmentEffectComponents.REPAIR_WITH_XP, player, ItemStack::isDamaged + ); + if (randomItemWith.isPresent()) { diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/item/ItemStack.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/item/ItemStack.java.patch new file mode 100644 index 000000000..65294be60 --- /dev/null +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/item/ItemStack.java.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/item/ItemStack.java ++++ b/net/minecraft/world/item/ItemStack.java +@@ -627,6 +_,26 @@ + return this.isDamageableItem() && this.getDamageValue() > 0; + } + ++ // Purpur start - Add option to mend the most damaged equipment first ++ public float getDamagePercent() { ++ if (this.has(DataComponents.UNBREAKABLE)) { ++ return 0.0F; ++ } ++ ++ final int maxDamage = this.getOrDefault(DataComponents.MAX_DAMAGE, 0); ++ if (maxDamage == 0) { ++ return 0.0F; ++ } ++ ++ final int damage = this.getOrDefault(DataComponents.DAMAGE, 0); ++ if (damage == 0) { ++ return 0.0F; ++ } ++ ++ return (float) damage / maxDamage; ++ } ++ // Purpur end - Add option to mend the most damaged equipment first ++ + public int getDamageValue() { + return Mth.clamp(this.getOrDefault(DataComponents.DAMAGE, Integer.valueOf(0)), 0, this.getMaxDamage()); + } diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/item/enchantment/EnchantmentHelper.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/item/enchantment/EnchantmentHelper.java.patch index 574e85fe9..918c41cec 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/world/item/enchantment/EnchantmentHelper.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/item/enchantment/EnchantmentHelper.java.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/world/item/enchantment/EnchantmentHelper.java +++ b/net/minecraft/world/item/enchantment/EnchantmentHelper.java -@@ -602,4 +_,14 @@ +@@ -602,4 +_,58 @@ interface EnchantmentVisitor { void accept(Holder enchantment, int level); } @@ -14,4 +14,48 @@ + return getItemEnchantmentLevel(getEnchantmentHolder(enchantment), stack); + } + // Purpur end - Enchantment convenience methods ++ ++ // Purpur start - Add option to mend the most damaged equipment first ++ public static Optional getMostDamagedItemWith(DataComponentType componentType, LivingEntity entity) { ++ ItemStack maxStack = null; ++ EquipmentSlot maxSlot = null; ++ float maxPercent = 0.0F; ++ ++ equipmentSlotLoop: ++ for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) { ++ ItemStack stack = entity.getItemBySlot(equipmentSlot); ++ ++ // do not even check enchantments for item with lower or equal damage percent ++ float percent = stack.getDamagePercent(); ++ if (percent <= maxPercent) { ++ continue; ++ } ++ ++ ItemEnchantments itemEnchantments = stack.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY); ++ ++ for (Entry> entry : itemEnchantments.entrySet()) { ++ Enchantment enchantment = entry.getKey().value(); ++ ++ net.minecraft.core.component.DataComponentMap effects = enchantment.effects(); ++ if (!effects.has(componentType)) { ++ // try with another enchantment ++ continue; ++ } ++ ++ if (enchantment.matchingSlot(equipmentSlot)) { ++ maxStack = stack; ++ maxSlot = equipmentSlot; ++ maxPercent = percent; ++ ++ // check another slot now ++ continue equipmentSlotLoop; ++ } ++ } ++ } ++ ++ return maxStack != null ++ ? Optional.of(new EnchantedItemInUse(maxStack, maxSlot, entity)) ++ : Optional.empty(); ++ } ++ // Purpur end - Add option to mend the most damaged equipment first } diff --git a/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java index 259e7f0d2..686f1f083 100644 --- a/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +++ b/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java @@ -84,11 +84,13 @@ public class PurpurWorldConfig { armorstandStepHeight = (float) getDouble("gameplay-mechanics.armorstand.step-height", armorstandStepHeight); } + public boolean useBetterMending = false; public boolean boatEjectPlayersOnLand = false; public boolean disableDropsOnCrammingDeath = false; public boolean milkCuresBadOmen = true; public double tridentLoyaltyVoidReturnHeight = 0.0D; private void miscGameplayMechanicsSettings() { + useBetterMending = getBoolean("gameplay-mechanics.use-better-mending", useBetterMending); boatEjectPlayersOnLand = getBoolean("gameplay-mechanics.boat.eject-players-on-land", boatEjectPlayersOnLand); disableDropsOnCrammingDeath = getBoolean("gameplay-mechanics.disable-drops-on-cramming-death", disableDropsOnCrammingDeath); milkCuresBadOmen = getBoolean("gameplay-mechanics.milk-cures-bad-omen", milkCuresBadOmen);