Mystical Agriculture

Mystical Agriculture

86M Downloads

XP Orb Pickup will cause Player Crash when Mending Enchant and Experience Capsule are being used together

MikeMatrix opened this issue ยท 5 comments

commented

Describe the bug
Player will crash repeatedly out of the server while an experience is nearby, while in the possession of a mending enchanted armor piece and an experience capsule.

To Reproduce
Steps to reproduce the behavior:

  • Wear an Armor piece with the mending Enchantment
  • Keep an Experience Capsule in the Inventory
  • Being in Range of an experience orb that would normally pick up.

Expected behavior
Either handle it correctly so that it will both apply the mending effect and fill the capsule or prioritize one over the other.

Screenshots / Scripts / Logs
Please add your logs and scripts (if applicable).
Server sided error appearing when the issue appears for the player: https://gist.github.com/MikeMatrix/2f6cd336773b967185007078c40dcbab

Versions (please complete the following information):

  • Minecraft: 1.18.1
  • Forge: 39.0.36
  • Cucumber: 5.0.2
  • Mystical Agriculture: 5.0.1
commented

Is there any way I can get out of this loop? I've been locked out completely from the server I've spent multiple months on as well as a creative testing world due to this bug.

commented

Is there any way I can get out of this loop? I've been locked out completely from the server I've spent multiple months on as well as a creative testing world due to this bug.

If you can NBTedit your player file to move yourself off of the experience, you can then delete the experience capsules.

commented

I can't reproduce this with only MA installed. Perhaps there's another mod involved?

commented

It's consistently reproducing for me in All The Mods 7 version 0.2.34, as long as the equipment is damaged and the experience capsule are somewhere in my inventory. The equipment being fully repaired or not having experience capsules on me avoids the bug.

commented

It's getting stuck in a recursive loop trying to mend all the mendable items, from the mapped ExperienceOrb.java:

   private int repairPlayerItems(Player p_147093_, int p_147094_) {
      Entry<EquipmentSlot, ItemStack> entry = EnchantmentHelper.getRandomItemWith(Enchantments.MENDING, p_147093_, ItemStack::isDamaged);
      if (entry != null) {
         ItemStack itemstack = entry.getValue();
         int i = Math.min((int) (this.value * itemstack.getXpRepairRatio()), itemstack.getDamageValue());
         itemstack.setDamageValue(itemstack.getDamageValue() - i);
         int j = p_147094_ - this.durabilityToXp(i);
         return j > 0 ? this.repairPlayerItems(p_147093_, j) : 0;
      } else {
         return p_147094_;
      }
   }

If there are no damaged items on the player with mending, the method exits. Otherwise the problem lies with:

  1. this.value (The XP value of the orb) has somehow been set to 0
  2. This leads to i evaluating to 0
  3. this.durabilityToXp(i) in turn evaluates to 0
  4. j ends up with the same value as the input XP value (p_147094_)
  5. If j is greater than zero, the method is called recursively with the same input values

MA sets this value to zero in the onPlayerPickupXp event:

if (!capsules.isEmpty()) {
for (var stack : capsules) {
int remaining = ExperienceCapsuleUtils.addExperienceToCapsule(stack, orb.getValue());
if (remaining == 0) {
orb.value = 0;
return;
}
orb.value = remaining;
}
}

The Clumps mod calls repairPlayerItems if it has clumpedMap data stored on the XP Orb, it doesn't check the value field.

This means that an XP Orb that has a value of 0 can get stuck in this loop if it also has entries in its clumpedMap and the player that picks it up has a damaged item with Mending.

Note: There may also be other mods that call repairPlayerItems without checking the value field.