Mending suffers
TheNormMan opened this issue ยท 8 comments
Normally Mending does:
"Experience in the orb is deducted by one point for every two durability points repaired. For example, one durability point repaired doesn't take any experience away from the orb." (https://minecraft.fandom.com/wiki/Mending)
but with this mod Mending doesn't work like it should, some times it repairs, but not with every Orb, just with some.
Normally my Pickaxe in the offhand must have full durability until the player levels, but now he get the XP much more often.
Sry for this missarble english, tried my best; hope you understand what I mean.
Nevertheless nice mod, thank you very much; but could you please fix this?
So, vanilla mending works as follows:
Entry<EquipmentSlotType, ItemStack> entry = EnchantmentHelper.getRandomEquippedWithEnchantment(Enchantments.MENDING, entityIn, ItemStack::isDamaged);
if (entry != null) {
ItemStack itemstack = entry.getValue();
if (!itemstack.isEmpty() && itemstack.isDamaged()) {
int i = Math.min((int)(this.xpValue * itemstack.getXpRepairRatio()), itemstack.getDamage());
this.xpValue -= this.durabilityToXp(i);
itemstack.setDamage(itemstack.getDamage() - i);
}
}
if (this.xpValue > 0) {
entityIn.giveExperiencePoints(this.xpValue);
}
So it gets a random equipped item with mending, if it finds one it repairs it with the current orb's value * a repair value (which is defined by the ItemStack it is repairing).
now clumps code does the following:
for(int j = 0; j < clumpedOrbs; j++) {
int workingXPValue = this.xpValue / Math.max(1, clumpedOrbs);
Map.Entry<EquipmentSlotType, ItemStack> entry = EnchantmentHelper.getRandomItemWithEnchantment(Enchantments.MENDING, entityIn);
if(entry != null) {
ItemStack itemstack = entry.getValue();
if(!itemstack.isEmpty() && itemstack.isDamaged()) {
int i = Math.min((int) (workingXPValue * itemstack.getXpRepairRatio()), itemstack.getDamage());
this.xpValue -= this.durabilityToXp(i);
itemstack.setDamage(itemstack.getDamage() - i);
}
}
}
if(this.xpValue > 0) {
entityIn.giveExperiencePoints(this.xpValue);
}
So clumpedOrbs
is a field that we increment every time we clump orbs together, it keeps track of how many times it should apply the mending effect.
So what we do is apply nearly the same mending effect that vanilla does for as many times as orbs have been clumped together.
we get the xp value that it should work with by taking the average value of the experience and dividing it by how many orbs have been clumped together, so if 2 orbs have been clumped together, and the first orb had a value of 5
and the second a value of 15
, it will apply twice giving each (random) item it finds 10
experience each.
I hope that makes sense.
So sure the formula isn't exactly the same, it would be incredibly resource intensive if I did have to keep track of the exact xp value of each orb that has been clumped.
Imagine a mob farm where new xp orbs are constantly being created, lets say 1 new xp orb per second is being created (which is probably an understatement on most mob farms with something like soul shards or similar mods).
In a single day, if the orbs are never cleared, it would require a list with at least 86400 values per orb, then iterating that list when applying mending is 86400 iterations and array get calls to get the value it should apply.
You shouldn't notice any perceivable difference in how mending works between this mod and how vanilla handles it.
You are 100% correct, I'm not sure how I didn't notice that before.
This is fixed in the next version.
Thanks for fighting against me on it, since I honestly thought my initial calculation was correct
No problem, love Bug Fixing, even if I wasn't able to write something like that.
Thank you for writing this mod.
//
Although I see: it isn't 100% perfect yet.
Cause now, if you combine a 1xp orb with a 2xp orb, 2xp will go to minding and 1xp to lvl, while on vanilla all 3 xp goes to minding. But i can deal with it, it's no hard loss.
//ingame it's a bit better but still not good :/ sry
Thank you for the reply,
i'm not that close in the mechanics, but I see a problem in follwing:
this.xpValue is decrement every time, but the int clumpedOrbs stays the same, so workingXPValue is at some point zero, so nothing repairs the tool anymore and after constant loop-passes the player gets all remaining XP.
So maybe you could calculate the workingXPValue before the Loop, this could work.
The very next line after my code snippet is:
The entity is removed, so it doesn't need to touch its stored orbs because it just won't exist after the method is finished.
Year sure, makes sense.
But that's the step after our problem. If you wouldn't do that the player would get infinity xp.
The problem I see, is in the use of the Orb.
I repeat: workingXPValue gets at some Iteration the Value 0, because clumpedOrbs isn't decreased, but this.xpValue is.
So from this point on the tool get's repaired with 0 xp in every following iteration. So in my eyes, you should set the workingXPValue before the for-loop.
I know my english isn't the best, hope you understand nevertheless.