From ed8c4433bee5bcdc6b33c8664f1d349bcade7794 Mon Sep 17 00:00:00 2001 From: lordlogo2002 Date: Fri, 19 Dec 2025 23:53:30 +0100 Subject: [PATCH] Refactor ProtectionAuraHandler: improve energy calculation and armor damage handling --- .../item/armor/ProtectionAuraHandler.java | 221 ++++++++++-------- 1 file changed, 123 insertions(+), 98 deletions(-) diff --git a/src/main/java/net/Chipperfluff/chipi/item/armor/ProtectionAuraHandler.java b/src/main/java/net/Chipperfluff/chipi/item/armor/ProtectionAuraHandler.java index 4f4ca7c..89be409 100644 --- a/src/main/java/net/Chipperfluff/chipi/item/armor/ProtectionAuraHandler.java +++ b/src/main/java/net/Chipperfluff/chipi/item/armor/ProtectionAuraHandler.java @@ -20,147 +20,149 @@ public final class ProtectionAuraHandler { private static final float BASE_RECHARGE_RATE = 0.0005f; private static final float BASE_DRAIN_RATE = 0.0008f; - private static final float CASCADE_LOSS = 0.30f; // 30% relative - private static final int CRITICAL_PCT = 10; + private static final float CASCADE_LOSS = 0.30f; + private static final int CRITICAL_PCT = 10; private ProtectionAuraHandler() {} /* ========================================================== - ENTRY POINT — SERVER SIDE + ENTRY POINT ========================================================== */ public static void tick(PlayerEntity player) { if (!hasFullChipperArmor(player)) return; - Float value = player.getDataTracker().get(CHIPI_ENERGY); - if (value == null) return; + Float energy = player.getDataTracker().get(CHIPI_ENERGY); + if (energy == null) return; float durabilityFactor = getDurabilityFactor(player); if (durabilityFactor <= 0f) return; - boolean inChipi = isInChipi(player.getWorld()); - boolean protectedAura = isOnProtectedBlock(player); + float nextEnergy = calculateNextEnergy(player, energy, durabilityFactor); + if (nextEnergy == energy) return; - float rechargeRate = BASE_RECHARGE_RATE * durabilityFactor; - float drainRate = BASE_DRAIN_RATE * (1.0f + (1.0f - durabilityFactor)); + applyEnergyDelta(player, energy, nextEnergy); + player.getDataTracker().set(CHIPI_ENERGY, nextEnergy); + } - float next = (!inChipi || protectedAura) - ? Math.min(1.0f, value + rechargeRate) - : Math.max(0.0f, value - drainRate); + /* ========================================================== + ENERGY + ========================================================== */ - if (next == value) return; + private static float calculateNextEnergy(PlayerEntity player, float current, float durabilityFactor) { + boolean recharge = !isInChipi(player.getWorld()) || isOnProtectedBlock(player); - int oldPercent = (int) (value * 100f); - int newPercent = (int) (next * 100f); - int delta = Math.abs(newPercent - oldPercent); + float rate = recharge + ? BASE_RECHARGE_RATE * durabilityFactor + : BASE_DRAIN_RATE * (1.0f + (1.0f - durabilityFactor)); + + return recharge + ? Math.min(1.0f, current + rate) + : Math.max(0.0f, current - rate); + } + + private static void applyEnergyDelta(PlayerEntity player, float before, float after) { + int oldPct = (int) (before * 100f); + int newPct = (int) (after * 100f); + int delta = Math.abs(newPct - oldPct); if (delta > 0) { - damageArmor(player, delta); + applyArmorDamage(player, delta); } - - player.getDataTracker().set(CHIPI_ENERGY, next); } /* ========================================================== - ARMOR CHECK + ARMOR DAMAGE ========================================================== */ - public static boolean hasFullChipperArmor(PlayerEntity player) { - PlayerInventory inv = player.getInventory(); - return inv.getArmorStack(3).isOf(ModItems.CHIPPER_HELMET) - && inv.getArmorStack(2).isOf(ModItems.CHIPPER_CHESTPLATE) - && inv.getArmorStack(1).isOf(ModItems.CHIPPER_LEGGINGS) - && inv.getArmorStack(0).isOf(ModItems.CHIPPER_BOOTS); - } - - /* ========================================================== - DURABILITY LOGIC - ========================================================== */ - - private static float getDurabilityFactor(PlayerEntity player) { - int max = 0, current = 0; - - for (ItemStack stack : player.getArmorItems()) { - if (!stack.isEmpty()) { - max += stack.getMaxDamage(); - current += stack.getMaxDamage() - stack.getDamage(); - } - } - - if (max <= 0) return 0f; - return Math.min(1f, (float) current / max); - } - - private static void damageArmor(PlayerEntity player, int amount) { + private static void applyArmorDamage(PlayerEntity player, int amount) { int[] before = getArmorPercents(player); + boolean broke = damageAllPieces(player, amount); + + if (broke) { + handleCascade(player, before); + } else { + handleWarnings(player, before, getArmorPercents(player)); + } + } + + private static boolean damageAllPieces(PlayerEntity player, int amount) { boolean broke = false; - for (ItemStack stack : player.getArmorItems()) { - if (!stack.isEmpty()) { - stack.damage(amount, player, p -> {}); - if (stack.getDamage() >= stack.getMaxDamage()) { - broke = true; - } - } - } - - if (broke) { - applyCascadeDamage(player, before); - } else { - sendWarningIfNeeded(player, before, getArmorPercents(player)); - } - } - - private static void applyCascadeDamage(PlayerEntity player, int[] before) { for (ItemStack stack : player.getArmorItems()) { if (stack.isEmpty()) continue; - int max = stack.getMaxDamage(); - int current = max - stack.getDamage(); - if (current <= 0) continue; - - int extra = Math.round(current * CASCADE_LOSS); - stack.setDamage(Math.min(max, stack.getDamage() + extra)); + stack.damage(amount, player, p -> {}); + if (stack.getDamage() >= stack.getMaxDamage()) { + broke = true; + } } + return broke; + } + /* ========================================================== + CASCADE + ========================================================== */ + + private static void handleCascade(PlayerEntity player, int[] before) { + applyCascadeLoss(player); player.getDataTracker().set(CHIPI_ENERGY, 0f); sendCollapseMessage(player, before, getArmorPercents(player)); } + private static void applyCascadeLoss(PlayerEntity player) { + for (ItemStack stack : player.getArmorItems()) { + if (stack.isEmpty()) continue; + + int max = stack.getMaxDamage(); + int remaining = max - stack.getDamage(); + if (remaining <= 0) continue; + + int extra = Math.round(remaining * CASCADE_LOSS); + stack.setDamage(Math.min(max, stack.getDamage() + extra)); + } + } + /* ========================================================== - CHAT MESSAGES (PLAYER ONLY) + WARNINGS ========================================================== */ - private static void sendWarningIfNeeded(PlayerEntity player, int[] before, int[] after) { - boolean trigger = false; + private static void handleWarnings(PlayerEntity player, int[] before, int[] after) { + if (!enteredCritical(before, after)) return; + player.sendMessage(Text.literal(buildWarningMessage(after)), false); + } + + private static boolean enteredCritical(int[] before, int[] after) { for (int i = 0; i < 4; i++) { if (before[i] > CRITICAL_PCT && after[i] <= CRITICAL_PCT) { - trigger = true; + return true; } } - if (!trigger) return; + return false; + } - player.sendMessage(Text.literal(buildWarningMessage(after)), false); + /* ========================================================== + CHAT BUILDERS + ========================================================== */ + + private static String buildWarningMessage(int[] pct) { + StringBuilder sb = new StringBuilder("§6[AURA WARNING]\n"); + appendPiece(sb, "Head", pct[3]); + appendPiece(sb, "Body", pct[2]); + appendPiece(sb, "Legs", pct[1]); + appendPiece(sb, "Feet", pct[0]); + return sb.toString(); } private static void sendCollapseMessage(PlayerEntity player, int[] before, int[] after) { StringBuilder sb = new StringBuilder("§c[AURA COLLAPSE]\n"); - appendPiece(sb, "Head", before[3], after[3]); - appendPiece(sb, "Body", before[2], after[2]); - appendPiece(sb, "Legs", before[1], after[1]); - appendPiece(sb, "Feet", before[0], after[0]); + appendPiece(sb, "Head", before[3], after[3]); + appendPiece(sb, "Body", before[2], after[2]); + appendPiece(sb, "Legs", before[1], after[1]); + appendPiece(sb, "Feet", before[0], after[0]); player.sendMessage(Text.literal(sb.toString()), false); } - private static String buildWarningMessage(int[] pct) { - StringBuilder sb = new StringBuilder("§6[AURA WARNING]\n"); - appendPiece(sb, "Head", pct[3]); - appendPiece(sb, "Body", pct[2]); - appendPiece(sb, "Legs", pct[1]); - appendPiece(sb, "Feet", pct[0]); - return sb.toString(); - } - private static void appendPiece(StringBuilder sb, String name, int pct) { sb.append("§7").append(name).append(": ").append(pct).append("%"); if (pct <= CRITICAL_PCT) sb.append(" §c!!!"); @@ -172,9 +174,14 @@ public final class ProtectionAuraHandler { .append(after).append("% (was ").append(before).append("%)\n"); } + /* ========================================================== + UTIL + ========================================================== */ + private static int[] getArmorPercents(PlayerEntity player) { int[] out = new int[4]; int i = 0; + for (ItemStack stack : player.getArmorItems()) { if (stack.isEmpty()) { out[i++] = 0; @@ -187,20 +194,38 @@ public final class ProtectionAuraHandler { return out; } + private static float getDurabilityFactor(PlayerEntity player) { + int max = 0, cur = 0; + + for (ItemStack stack : player.getArmorItems()) { + if (!stack.isEmpty()) { + max += stack.getMaxDamage(); + cur += stack.getMaxDamage() - stack.getDamage(); + } + } + return max <= 0 ? 0f : Math.min(1f, (float) cur / max); + } + /* ========================================================== - AURA CONDITIONS + CONDITIONS ========================================================== */ + public static boolean hasFullChipperArmor(PlayerEntity player) { + PlayerInventory inv = player.getInventory(); + return inv.getArmorStack(3).isOf(ModItems.CHIPPER_HELMET) + && inv.getArmorStack(2).isOf(ModItems.CHIPPER_CHESTPLATE) + && inv.getArmorStack(1).isOf(ModItems.CHIPPER_LEGGINGS) + && inv.getArmorStack(0).isOf(ModItems.CHIPPER_BOOTS); + } + private static boolean isOnProtectedBlock(PlayerEntity player) { BlockPos pos = player.getBlockPos(); BlockState state = player.getWorld().getBlockState(pos); - if (!state.contains(Properties.WATERLOGGED) || !state.get(Properties.WATERLOGGED)) { - return false; - } - - return state.getBlock() instanceof StairsBlock - || state.getBlock() instanceof SlabBlock; + return state.contains(Properties.WATERLOGGED) + && state.get(Properties.WATERLOGGED) + && (state.getBlock() instanceof StairsBlock + || state.getBlock() instanceof SlabBlock); } private static boolean isInChipi(World world) { @@ -209,7 +234,7 @@ public final class ProtectionAuraHandler { public static boolean hasAura(PlayerEntity player) { if (!hasFullChipperArmor(player)) return false; - Float value = player.getDataTracker().get(CHIPI_ENERGY); - return value != null && value > 0f && getDurabilityFactor(player) > 0f; + Float v = player.getDataTracker().get(CHIPI_ENERGY); + return v != null && v > 0f && getDurabilityFactor(player) > 0f; } }