diff --git a/src/main/java/studio/magemonkey/divinity/manager/listener/object/ItemDurabilityListener.java b/src/main/java/studio/magemonkey/divinity/manager/listener/object/ItemDurabilityListener.java index 42c3ee8d..e9637e4d 100644 --- a/src/main/java/studio/magemonkey/divinity/manager/listener/object/ItemDurabilityListener.java +++ b/src/main/java/studio/magemonkey/divinity/manager/listener/object/ItemDurabilityListener.java @@ -10,8 +10,10 @@ import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerItemDamageEvent; +import org.bukkit.event.player.PlayerItemMendEvent; import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; import org.jetbrains.annotations.NotNull; import studio.magemonkey.codex.manager.IListener; import studio.magemonkey.codex.util.ItemUT; @@ -113,4 +115,48 @@ public void onDuraHoe(PlayerInteractEvent e) { } } } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onMend(PlayerItemMendEvent e) { + ItemStack item = e.getItem(); + + if (!ItemStats.hasStat(item, null, TypedStat.Type.DURABILITY)) return; + + double[] durability = duraStat.getRaw(item); + if (durability == null || duraStat.isUnbreakable(item)) return; + + double current = durability[0]; + double max = durability[1]; + int vanillaMax = item.getType().getMaxDurability(); + + if (vanillaMax <= 0) return; + + int repair = e.getRepairAmount(); + // Scale the repair amount to the durability max, so we can + // properly update the custom durability amount. + double customRepair = ((double) repair / vanillaMax) * max; + double newValue = current + customRepair; + + // Cap the durability at the max + if (newValue > max) { + newValue = max; + } + + newValue = Math.round(newValue * 100.0) / 100.0; + + duraStat.add(item, new double[]{newValue, max}, -1); + duraStat.syncVanillaBar(item, newValue, max); + + e.setCancelled(true); + + Damageable damageable = (Damageable) item.getItemMeta(); + if (damageable != null) { + int vanillaDamage = damageable.getDamage(); + if (vanillaDamage == 0) { + duraStat.add(item, new double[]{max, max}, -1); + duraStat.syncVanillaBar(item, max, max); + e.setCancelled(true); + } + } + } } diff --git a/src/main/java/studio/magemonkey/divinity/stats/items/attributes/stats/DurabilityStat.java b/src/main/java/studio/magemonkey/divinity/stats/items/attributes/stats/DurabilityStat.java index 347a1e7c..3093139b 100644 --- a/src/main/java/studio/magemonkey/divinity/stats/items/attributes/stats/DurabilityStat.java +++ b/src/main/java/studio/magemonkey/divinity/stats/items/attributes/stats/DurabilityStat.java @@ -6,6 +6,7 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,12 +24,8 @@ public class DurabilityStat extends ItemLoreStat implements TypedStat { private double cap; - public DurabilityStat( - @NotNull String name, - @NotNull String format, - double cap) { - super( - TypedStat.Type.DURABILITY.name(), + public DurabilityStat(@NotNull String name, @NotNull String format, double cap) { + super(TypedStat.Type.DURABILITY.name(), name, format, "%ITEM_STAT_" + TypedStat.Type.DURABILITY.name() + "%", @@ -114,9 +111,7 @@ public boolean isBroken(@NotNull ItemStack item) { return durability != null && durability[0] == 0 && !EngineCfg.ATTRIBUTES_DURABILITY_BREAK_ITEMS; } - public boolean reduceDurability( - @NotNull LivingEntity li, @NotNull ItemStack item, int amount) { - + public boolean reduceDurability(@NotNull LivingEntity li, @NotNull ItemStack item, int amount) { if (!(li instanceof Player) && !EngineCfg.ATTRIBUTES_DURABILITY_REDUCE_FOR_MOBS) return false; if (this.isUnbreakable(item)) return false; @@ -155,7 +150,14 @@ public boolean reduceDurability( } } - return this.add(item, new double[]{lose, max}, -1); + boolean result = this.add(item, new double[]{lose, max}, -1); + + if (result) { + syncVanillaBar(item, lose, max); + } + + return result; + } @Override @@ -163,4 +165,30 @@ public boolean reduceDurability( public String formatValue(@NotNull ItemStack item, double[] values) { return EngineCfg.getDurabilityFormat((int) values[0], (int) values[1]); } -} + + /** + * Syncs the durability stat with the vanilla durability bar. Should be called after any change to the durability stat. + * Note: This method assumes that the durability stat is already updated with the new values before calling it. + * + * @param item the item that needs updating + * @param current the current durability value on the item + * @param maxCustom the max value possible to be set for the item + */ + public void syncVanillaBar(@NotNull ItemStack item, double current, double maxCustom) { + ItemMeta meta = item.getItemMeta(); + if (!(meta instanceof Damageable)) return; + + Damageable damageable = (Damageable) meta; + + int maxVanilla = item.getType().getMaxDurability(); + if (maxVanilla <= 0) return; + + double percent = current / maxCustom; + // Scale the vanilla value to the custom percentage + int vanillaDamage = (int) ((1.0 - percent) * maxVanilla); + + damageable.setDamage(vanillaDamage); + item.setItemMeta(damageable); + } + +} \ No newline at end of file