diff options
Diffstat (limited to 'patches/server/0361-ExperienceOrb-merging-stacking-API-and-fixes.patch')
-rw-r--r-- | patches/server/0361-ExperienceOrb-merging-stacking-API-and-fixes.patch | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/patches/server/0361-ExperienceOrb-merging-stacking-API-and-fixes.patch b/patches/server/0361-ExperienceOrb-merging-stacking-API-and-fixes.patch new file mode 100644 index 0000000000..70fb78d164 --- /dev/null +++ b/patches/server/0361-ExperienceOrb-merging-stacking-API-and-fixes.patch @@ -0,0 +1,113 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath <[email protected]> +Date: Fri, 10 Nov 2017 23:03:12 -0500 +Subject: [PATCH] ExperienceOrb merging/stacking API and fixes + +Adds an option for maximum exp value when merging orbs + +Adds ExperienceOrbMergeEvent +Fired when the server is about to merge 2 experience orbs +as entities. Plugins can cancel it if they want to ensure experience orbs do not lose important +metadata such as spawn reason, or conditionally move data from source to target. + +Fixes an issue where the stacked count was not taking into account +for mending repairs and when merging with spigot's merge-on-spawn +logic + +== AT == +public net.minecraft.world.entity.ExperienceOrb count + +Co-authored-by: Aikar <[email protected]> +Co-authored-by: Jake Potrebic <[email protected]> + +diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index 8007d323023655052acd0cf1f3a753101e9ee74a..a933061d4f0c45a34b5678c2b317b670f20b8a45 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -241,6 +241,7 @@ public class ExperienceOrb extends Entity { + } + + private static boolean tryMergeToExisting(ServerLevel world, Vec3 pos, int amount) { ++ // Paper - TODO some other event for this kind of merge + AABB axisalignedbb = AABB.ofSize(pos, 1.0D, 1.0D, 1.0D); + int j = world.getRandom().nextInt(40); + List<ExperienceOrb> list = world.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), axisalignedbb, (entityexperienceorb) -> { +@@ -267,6 +268,11 @@ public class ExperienceOrb extends Entity { + } + + private void merge(ExperienceOrb other) { ++ // Paper start - call orb merge event ++ if (!new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) this.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) other.getBukkitEntity()).callEvent()) { ++ return; ++ } ++ // Paper end - call orb merge event + this.count += other.count; + this.age = Math.min(this.age, other.age); + other.discard(EntityRemoveEvent.Cause.MERGE); // CraftBukkit - add Bukkit remove cause +@@ -353,7 +359,7 @@ public class ExperienceOrb extends Entity { + + itemstack.setDamageValue(itemstack.getDamageValue() - j); + int k = amount - this.durabilityToXp(j); +- this.value = k; // CraftBukkit - update exp value of orb for PlayerItemMendEvent calls ++ // this.value = k; // CraftBukkit - update exp value of orb for PlayerItemMendEvent calls // Paper - the value field should not be mutated here because it doesn't take "count" into account + + return k > 0 ? this.repairPlayerItems(player, k) : 0; + } else { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java +index 5a7d314ec0562e472f5dc45924a7b24841cff126..650e4a01cecc4cc08e7ff9ebcc4c367084351f21 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java +@@ -18,6 +18,18 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { + this.getHandle().value = value; + } + ++ // Paper start - expose count ++ @Override ++ public int getCount() { ++ return this.getHandle().count; ++ } ++ ++ @Override ++ public void setCount(final int count) { ++ this.getHandle().count = count; ++ } ++ // Paper end ++ + // Paper start + public java.util.UUID getTriggerEntityId() { + return getHandle().triggerEntityId; +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index ac4a8c9d4f727f3caa16f6dc5497d69f9db52aab..53f5eb1682c88abf7b09e16f010ebbd8fe2ac059 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -703,15 +703,29 @@ public class CraftEventFactory { + if (entity instanceof net.minecraft.world.entity.ExperienceOrb xp) { + double radius = world.spigotConfig.expMerge; + if (radius > 0) { ++ // Paper start - Maximum exp value when merging; Whole section has been tweaked, see comments for specifics ++ final long maxValue = world.paperConfig().entities.behavior.experienceMergeMaxValue; ++ final boolean mergeUnconditionally = maxValue <= 0; ++ if (mergeUnconditionally || xp.value < maxValue) { // Paper - Skip iteration if unnecessary ++ + List<Entity> entities = world.getEntities(entity, entity.getBoundingBox().inflate(radius, radius, radius)); + for (Entity e : entities) { + if (e instanceof net.minecraft.world.entity.ExperienceOrb loopItem) { +- if (!loopItem.isRemoved()) { ++ // Paper start ++ if (!loopItem.isRemoved() && xp.count == loopItem.count && (mergeUnconditionally || loopItem.value < maxValue) && new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) entity.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) loopItem.getBukkitEntity()).callEvent()) { // Paper - ExperienceOrbMergeEvent ++ long newTotal = (long)xp.value + (long)loopItem.value; ++ if ((int) newTotal < 0) continue; // Overflow ++ if (!mergeUnconditionally && newTotal > maxValue) { ++ loopItem.value = (int) (newTotal - maxValue); ++ xp.value = (int) maxValue; ++ } else { + xp.value += loopItem.value; + loopItem.discard(null); // Add Bukkit remove cause ++ } // Paper end - Maximum exp value when merging + } + } + } ++ } // Paper end - End iteration skip check - All tweaking ends here + } + } + // Spigot end |