Fix durability wrapping to 1/1 on maxed-out tools (#340)

This commit is contained in:
Aintripin authored and GitHub committed 2026-10-25 09:08:22 +01:00
1 parent 638eb36f00
commit 52f603e4a1
6 files changed
+25 -14

No files matched your search

@@ -23,6 +23,11 @@ import tconstruct.library.util.IToolPart;
public class ToolBuilder {
/** Caps a durability value to what the int NBT tag can hold, instead of letting it wrap around. */
public static int clampDurability(long durability) {
return (int) Math.max(Integer.MIN_VALUE, Math.min(Integer.MAX_VALUE, durability));
}
public static ToolBuilder instance = new ToolBuilder();
public HashMap<String, ToolRecipe> recipeList = new HashMap<>();
@@ -170,7 +175,8 @@ public class ToolBuilder {
if (extra != -1) extraMat = TConstructRegistry.getMaterial(extra);
int durability = headMat.durability();
// long: the head durabilities summed below can exceed Integer.MAX_VALUE
long durability = headMat.durability();
int heads = 1;
int handles = 0;
float modifier = 1f;
@@ -212,7 +218,7 @@ public class ToolBuilder {
modifier /= handles;
}
durability = (int) (durability / heads * (0.5 + heads * 0.5) * modifier * item.getDurabilityModifier());
durability = (long) (durability / heads * (0.5 + heads * 0.5) * modifier * item.getDurabilityModifier());
attack = attack / heads + item.getDamageVsEntity(null);
if (attack % heads != 0) attack++;
@@ -236,8 +242,8 @@ public class ToolBuilder {
}
compound.getCompoundTag("InfiTool").setInteger("Damage", 0); // Damage is damage to the tool
compound.getCompoundTag("InfiTool").setInteger("TotalDurability", durability);
compound.getCompoundTag("InfiTool").setInteger("BaseDurability", durability);
compound.getCompoundTag("InfiTool").setInteger("TotalDurability", clampDurability(durability));
compound.getCompoundTag("InfiTool").setInteger("BaseDurability", clampDurability(durability));
compound.getCompoundTag("InfiTool").setInteger("BonusDurability", 0); // Modifier
compound.getCompoundTag("InfiTool").setFloat("ModDurability", 0f); // Modifier
compound.getCompoundTag("InfiTool").setBoolean("Broken", false);
@@ -376,7 +376,8 @@ public class AbilityHelper {
if (damagedTool) return;
int damage = tags.getCompoundTag("InfiTool").getInteger("Damage");
int damageTrue = damage + dam;
// long: on a tool near max durability, damage + dam can exceed Integer.MAX_VALUE
long damageTrue = (long) damage + dam;
int maxDamage = tags.getCompoundTag("InfiTool").getInteger("TotalDurability");
if (damageTrue <= 0) {
tags.getCompoundTag("InfiTool").setInteger("Damage", 0);
@@ -384,7 +385,7 @@ public class AbilityHelper {
} else if (damageTrue > maxDamage) {
breakTool(stack, tags, entity);
} else {
tags.getCompoundTag("InfiTool").setInteger("Damage", damage + dam);
tags.getCompoundTag("InfiTool").setInteger("Damage", (int) damageTrue);
int toolDamage = (damage * 100 / maxDamage) + 1;
int stackDamage = stack.getItemDamage();
}
@@ -691,7 +691,7 @@ public abstract class ToolCore extends Item implements IEnergyContainerItem, IEq
int energy = tags.getInteger("Energy");
int max = getMaxEnergyStored(stack);
if (energy > 0) {
int damage = ((max - energy) * 100) / max;
int damage = (int) (((long) max - energy) * 100 / max);
if (damage == 0 && max - energy > 0) damage = 1;
super.setDamage(stack, damage);
return damage;
@@ -700,7 +700,8 @@ public abstract class ToolCore extends Item implements IEnergyContainerItem, IEq
int dur = tags.getCompoundTag("InfiTool").getInteger("Damage");
int max = tags.getCompoundTag("InfiTool").getInteger("TotalDurability");
int damage = 0;
if (max > 0) damage = (dur * 100) / max;
// long: a tool with more than ~21M durability wraps dur * 100 once it is worn enough
if (max > 0) damage = (int) ((long) dur * 100 / max);
// rounding.
if (damage == 0 && dur > 0) damage = 1;
@@ -51,7 +51,7 @@ public abstract class AmmoItem extends ToolCore implements IBattlegearWeapon, IA
if (!stack.hasTagCompound()) return toAdd;
NBTTagCompound tags = stack.getTagCompound().getCompoundTag("InfiTool");
int oldCount = tags.getInteger("Ammo");
int newCount = Math.min(oldCount + toAdd, getMaxAmmo(stack));
int newCount = (int) Math.min((long) oldCount + toAdd, getMaxAmmo(stack));
setAmmo(newCount, stack);
return toAdd - (newCount - oldCount);
}
@@ -3,6 +3,7 @@ package tconstruct.modifiers.tools;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import tconstruct.library.crafting.ToolBuilder;
import tconstruct.library.modifier.ItemModifier;
import tconstruct.util.config.PHConstruct;
@@ -37,18 +38,20 @@ public class ModDurability extends ItemModifier {
NBTTagCompound tags = tool.getTagCompound().getCompoundTag("InfiTool");
int base = tags.getInteger("BaseDurability");
int bonus = tags.getInteger("BonusDurability");
long bonus = tags.getInteger("BonusDurability");
float modDur = tags.getFloat("ModDurability");
bonus += durability;
modDur += modifier;
tags.setBoolean("Broken", false);
int total = (int) ((base + bonus) * (modDur + 1f));
// long: base + bonus can exceed Integer.MAX_VALUE, and a wrapped sum would trip the <= 0 check below.
// The multiply is still done in float, so a tool that doesn't overflow gets exactly the value it got before.
long total = (long) ((base + bonus) * (modDur + 1f));
if (total <= 0) total = 1;
tags.setInteger("TotalDurability", total);
tags.setInteger("BonusDurability", bonus);
tags.setInteger("TotalDurability", ToolBuilder.clampDurability(total));
tags.setInteger("BonusDurability", ToolBuilder.clampDurability(bonus));
tags.setFloat("ModDurability", modDur);
if (PHConstruct.miningLevelIncrease) {
@@ -19,7 +19,7 @@ public class WeaponryActiveToolMod extends ActiveToolMod {
int rem = ammo.consumeAmmo(1, stack);
return rem > 0;
} else if (ammo.getAmmoCount(stack) > 0) {
int d = tags.getInteger("Damage") + damage;
long d = (long) tags.getInteger("Damage") + damage;
int max = tags.getInteger("TotalDurability");
if (d > max) {
tags.setInteger("Damage", 0);