Fix EXP orb merging causing values to go negative - Closes #1169

This commit is contained in:
Aikar 2018-08-03 00:06:20 -04:00
parent 17dca0a0fe
commit 56b92ff216
No known key found for this signature in database
GPG Key ID: 401ADFC9891FAAFE
6 changed files with 47 additions and 44 deletions

View File

@ -1,11 +1,11 @@
From d3ad905c6a3156cbf9484834eea088efb106b4dd Mon Sep 17 00:00:00 2001 From 076f4e8c2a78146df199092bb435153a87ceb89c Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com> From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Fri, 10 Nov 2017 23:03:12 -0500 Date: Fri, 10 Nov 2017 23:03:12 -0500
Subject: [PATCH] Option for maximum exp value when merging orbs Subject: [PATCH] Option for maximum exp value when merging orbs
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 4d30cdbc8..535a8d3ed 100644 index 4d30cdbc8b..535a8d3ed1 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -457,4 +457,10 @@ public class PaperWorldConfig { @@ -457,4 +457,10 @@ public class PaperWorldConfig {
@ -20,16 +20,16 @@ index 4d30cdbc8..535a8d3ed 100644
+ } + }
} }
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 29dffc3ac..2c69ae748 100644 index 3561507de1..b6b4d52718 100644
--- a/src/main/java/net/minecraft/server/World.java --- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java
@@ -1143,16 +1143,30 @@ public abstract class World implements IBlockAccess { @@ -1143,16 +1143,31 @@ public abstract class World implements IBlockAccess {
EntityExperienceOrb xp = (EntityExperienceOrb) entity; EntityExperienceOrb xp = (EntityExperienceOrb) entity;
double radius = spigotConfig.expMerge; double radius = spigotConfig.expMerge;
if (radius > 0) { if (radius > 0) {
+ // Paper start - Maximum exp value when merging - Whole section has been tweaked, see comments for specifics + // Paper start - Maximum exp value when merging - Whole section has been tweaked, see comments for specifics
+ final int maxValue = paperConfig.expMergeMaxValue; + final int maxValue = paperConfig.expMergeMaxValue;
+ final boolean mergeUnconditionally = maxValue <= 0; + final boolean mergeUnconditionally = paperConfig.expMergeMaxValue <= 0;
+ if (mergeUnconditionally || xp.value < maxValue) { // Paper - Skip iteration if unnecessary + if (mergeUnconditionally || xp.value < maxValue) { // Paper - Skip iteration if unnecessary
+ +
List<Entity> entities = this.getEntities(entity, entity.getBoundingBox().grow(radius, radius, radius)); List<Entity> entities = this.getEntities(entity, entity.getBoundingBox().grow(radius, radius, radius));
@ -37,16 +37,19 @@ index 29dffc3ac..2c69ae748 100644
if (e instanceof EntityExperienceOrb) { if (e instanceof EntityExperienceOrb) {
EntityExperienceOrb loopItem = (EntityExperienceOrb) e; EntityExperienceOrb loopItem = (EntityExperienceOrb) e;
- if (!loopItem.dead) { - if (!loopItem.dead) {
+ if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) { // Paper - xp.value += loopItem.value;
xp.value += loopItem.value; - loopItem.die();
+ // Paper start + // Paper start
+ if (!mergeUnconditionally && xp.value > maxValue) { + if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) {
+ long newTotal = (long)xp.value + (long)loopItem.value;
+ if (newTotal > (long)maxValue) {
+ loopItem.value = xp.value - maxValue; + loopItem.value = xp.value - maxValue;
+ xp.value = maxValue; + xp.value = maxValue;
+ break; + } else {
+ xp.value += loopItem.value;
+ loopItem.die();
+ } + }
+ // Paper end + // Paper end
loopItem.die();
} }
} }
} }

View File

@ -1,4 +1,4 @@
From 4104f9583f512022acc4fe898d4487df59a1029a Mon Sep 17 00:00:00 2001 From 2c072e94e1c963916f63e2ff8fb41b0f933b1ccb Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co> From: Aikar <aikar@aikar.co>
Date: Tue, 19 Dec 2017 22:57:26 -0500 Date: Tue, 19 Dec 2017 22:57:26 -0500
Subject: [PATCH] ExperienceOrbMergeEvent Subject: [PATCH] ExperienceOrbMergeEvent
@ -8,18 +8,18 @@ Plugins can cancel this if they want to ensure experience orbs do not lose impor
metadata such as spawn reason, or conditionally move data from source to target. metadata such as spawn reason, or conditionally move data from source to target.
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 39b90fb4c..c0816b9f8 100644 index c0e79796bd..986670f689 100644
--- a/src/main/java/net/minecraft/server/World.java --- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java
@@ -1153,7 +1153,7 @@ public abstract class World implements IBlockAccess { @@ -1154,7 +1154,7 @@ public abstract class World implements IBlockAccess {
for (Entity e : entities) {
if (e instanceof EntityExperienceOrb) { if (e instanceof EntityExperienceOrb) {
EntityExperienceOrb loopItem = (EntityExperienceOrb) e; EntityExperienceOrb loopItem = (EntityExperienceOrb) e;
- if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) { // Paper // Paper start
+ if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue) && new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) entity.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) loopItem.getBukkitEntity()).callEvent()) { // Paper - if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) {
xp.value += loopItem.value; + if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue) && new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) entity.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) loopItem.getBukkitEntity()).callEvent()) {
// Paper start long newTotal = (long)xp.value + (long)loopItem.value;
if (!mergeUnconditionally && xp.value > maxValue) { if (newTotal > (long)maxValue) {
loopItem.value = xp.value - maxValue;
-- --
2.18.0 2.18.0

View File

@ -1,4 +1,4 @@
From dbe49167504d8c10b0dd8fbd271f186cf752057e Mon Sep 17 00:00:00 2001 From bc6e2c6add8004c4e8a231cedcf175565100c441 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co> From: Aikar <aikar@aikar.co>
Date: Wed, 4 Jul 2018 03:39:51 -0400 Date: Wed, 4 Jul 2018 03:39:51 -0400
Subject: [PATCH] Avoid Chunk Lookups for Entity/TileEntity Current Chunk Subject: [PATCH] Avoid Chunk Lookups for Entity/TileEntity Current Chunk
@ -10,7 +10,7 @@ to the object directly on the Entity/TileEntity object we can directly grab.
Use that local value instead to reduce lookups in many hot places. Use that local value instead to reduce lookups in many hot places.
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index 81bf60efa..04adf4e3c 100644 index d24d45fdd3..4757081090 100644
--- a/src/main/java/net/minecraft/server/Chunk.java --- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java +++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -702,6 +702,7 @@ public class Chunk { @@ -702,6 +702,7 @@ public class Chunk {
@ -22,10 +22,10 @@ index 81bf60efa..04adf4e3c 100644
this.a(entity, entity.ac); this.a(entity, entity.ac);
} }
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index c0816b9f8..52adee880 100644 index 986670f689..a01488e985 100644
--- a/src/main/java/net/minecraft/server/World.java --- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java
@@ -1511,12 +1511,15 @@ public abstract class World implements IBlockAccess { @@ -1512,12 +1512,15 @@ public abstract class World implements IBlockAccess {
int j; int j;
// Paper start - Set based removal lists // Paper start - Set based removal lists
for (Entity e : this.f) { for (Entity e : this.f) {
@ -42,7 +42,7 @@ index c0816b9f8..52adee880 100644
} }
for (Entity e : this.f) { for (Entity e : this.f) {
@@ -1577,12 +1580,17 @@ public abstract class World implements IBlockAccess { @@ -1578,12 +1581,17 @@ public abstract class World implements IBlockAccess {
this.methodProfiler.b(); this.methodProfiler.b();
this.methodProfiler.a("remove"); this.methodProfiler.a("remove");
if (entity.dead) { if (entity.dead) {
@ -62,7 +62,7 @@ index c0816b9f8..52adee880 100644
guardEntityList = false; // Spigot guardEntityList = false; // Spigot
this.entityList.remove(this.tickPosition--); // CraftBukkit - Use field for loop variable this.entityList.remove(this.tickPosition--); // CraftBukkit - Use field for loop variable
@@ -1627,7 +1635,7 @@ public abstract class World implements IBlockAccess { @@ -1628,7 +1636,7 @@ public abstract class World implements IBlockAccess {
BlockPosition blockposition = tileentity.getPosition(); BlockPosition blockposition = tileentity.getPosition();
// Paper start - Skip ticking in chunks scheduled for unload // Paper start - Skip ticking in chunks scheduled for unload
@ -71,7 +71,7 @@ index c0816b9f8..52adee880 100644
boolean shouldTick = chunk != null; boolean shouldTick = chunk != null;
if(this.paperConfig.skipEntityTickingInChunksScheduledForUnload) if(this.paperConfig.skipEntityTickingInChunksScheduledForUnload)
shouldTick = shouldTick && !chunk.isUnloading() && chunk.scheduledForUnload == null; shouldTick = shouldTick && !chunk.isUnloading() && chunk.scheduledForUnload == null;
@@ -1663,8 +1671,11 @@ public abstract class World implements IBlockAccess { @@ -1664,8 +1672,11 @@ public abstract class World implements IBlockAccess {
tilesThisCycle--; tilesThisCycle--;
this.tileEntityListTick.remove(tileTickPosition--); this.tileEntityListTick.remove(tileTickPosition--);
//this.tileEntityList.remove(tileentity); // Paper - remove unused list //this.tileEntityList.remove(tileentity); // Paper - remove unused list

View File

@ -1,4 +1,4 @@
From 84507c90ff4af6aa9e32dc69f6d8c64b4d230345 Mon Sep 17 00:00:00 2001 From df4224f8e69e3eecc619f3832f5660c09eeeecfa Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co> From: Aikar <aikar@aikar.co>
Date: Thu, 26 Jul 2018 00:11:12 -0400 Date: Thu, 26 Jul 2018 00:11:12 -0400
Subject: [PATCH] Prevent Saving Bad entities to chunks Subject: [PATCH] Prevent Saving Bad entities to chunks
@ -57,10 +57,10 @@ index bcce5e8b7e..bad287fca4 100644
nbttagcompound.set("Entities", nbttaglist1); nbttagcompound.set("Entities", nbttaglist1);
NBTTagList nbttaglist2 = new NBTTagList(); NBTTagList nbttaglist2 = new NBTTagList();
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index b4de3b515a..d2d2ab794b 100644 index 3012768cb9..0aa2f99838 100644
--- a/src/main/java/net/minecraft/server/World.java --- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java
@@ -1202,7 +1202,7 @@ public abstract class World implements IBlockAccess { @@ -1203,7 +1203,7 @@ public abstract class World implements IBlockAccess {
} }
this.getChunkAt(i, j).a(entity); this.getChunkAt(i, j).a(entity);

View File

@ -1,4 +1,4 @@
From 529731e4258b21416a555ed6c2d0200b8449f1d7 Mon Sep 17 00:00:00 2001 From 1102ec474b6e3afd75431427134a4992ee08c5e8 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co> From: Aikar <aikar@aikar.co>
Date: Sat, 28 Jul 2018 12:09:20 -0400 Date: Sat, 28 Jul 2018 12:09:20 -0400
Subject: [PATCH] Always process chunk removal in removeEntity Subject: [PATCH] Always process chunk removal in removeEntity
@ -8,10 +8,10 @@ which can keep them in the chunk when they shouldnt be if done
during entity ticking. during entity ticking.
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index d2d2ab794..df98a4f44 100644 index 0aa2f99838..8822d17745 100644
--- a/src/main/java/net/minecraft/server/World.java --- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java
@@ -1272,7 +1272,7 @@ public abstract class World implements IBlockAccess { @@ -1273,7 +1273,7 @@ public abstract class World implements IBlockAccess {
this.everyoneSleeping(); this.everyoneSleeping();
} }
@ -20,7 +20,7 @@ index d2d2ab794..df98a4f44 100644
int i = entity.ab; int i = entity.ab;
int j = entity.ad; int j = entity.ad;
@@ -1280,6 +1280,7 @@ public abstract class World implements IBlockAccess { @@ -1281,6 +1281,7 @@ public abstract class World implements IBlockAccess {
this.getChunkAt(i, j).b(entity); this.getChunkAt(i, j).b(entity);
} }

View File

@ -1,4 +1,4 @@
From 9b87108547b8a12487adcc4aea181f103a24cf53 Mon Sep 17 00:00:00 2001 From 485cc40d70fcb82a5538f2dac8713c253c943aed Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co> From: Aikar <aikar@aikar.co>
Date: Sat, 28 Jul 2018 12:18:27 -0400 Date: Sat, 28 Jul 2018 12:18:27 -0400
Subject: [PATCH] Ignore Dead Entities in entityList iteration Subject: [PATCH] Ignore Dead Entities in entityList iteration
@ -11,7 +11,7 @@ This will ensure that dead entities are skipped from iteration since
they shouldn't of been in the list in the first place. they shouldn't of been in the list in the first place.
diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java
index ecd1c65a9..1898ab897 100644 index ecd1c65a98..1898ab897c 100644
--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java --- a/src/main/java/com/destroystokyo/paper/PaperCommand.java
+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java
@@ -128,6 +128,7 @@ public class PaperCommand extends Command { @@ -128,6 +128,7 @@ public class PaperCommand extends Command {
@ -23,7 +23,7 @@ index ecd1c65a9..1898ab897 100644
MutablePair<Integer, Map<ChunkCoordIntPair, Integer>> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); MutablePair<Integer, Map<ChunkCoordIntPair, Integer>> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap()));
ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.getChunkX(), e.getChunkZ()); ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.getChunkX(), e.getChunkZ());
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index 1e64d5fcd..45e149f4a 100644 index 1e64d5fcd6..45e149f4a3 100644
--- a/src/main/java/net/minecraft/server/Entity.java --- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java
@@ -124,6 +124,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper @@ -124,6 +124,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper
@ -35,10 +35,10 @@ index 1e64d5fcd..45e149f4a 100644
public float length; public float length;
public float I; public float I;
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 0dca11b2c..dadd4b839 100644 index 8822d17745..3ce6f9778b 100644
--- a/src/main/java/net/minecraft/server/World.java --- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java
@@ -1214,6 +1214,7 @@ public abstract class World implements IBlockAccess { @@ -1215,6 +1215,7 @@ public abstract class World implements IBlockAccess {
} }
entity.valid = true; // CraftBukkit entity.valid = true; // CraftBukkit
@ -46,7 +46,7 @@ index 0dca11b2c..dadd4b839 100644
new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid
} }
@@ -1279,6 +1280,7 @@ public abstract class World implements IBlockAccess { @@ -1280,6 +1281,7 @@ public abstract class World implements IBlockAccess {
if (entity.aa && this.isChunkLoaded(i, j, true)) { if (entity.aa && this.isChunkLoaded(i, j, true)) {
this.getChunkAt(i, j).b(entity); this.getChunkAt(i, j).b(entity);
} }
@ -54,7 +54,7 @@ index 0dca11b2c..dadd4b839 100644
if (!guardEntityList) { // Spigot - It will get removed after the tick if we are ticking // Paper - always remove from current chunk above if (!guardEntityList) { // Spigot - It will get removed after the tick if we are ticking // Paper - always remove from current chunk above
// CraftBukkit start - Decrement loop variable field if we've already ticked this entity // CraftBukkit start - Decrement loop variable field if we've already ticked this entity
@@ -2633,6 +2635,7 @@ public abstract class World implements IBlockAccess { @@ -2634,6 +2636,7 @@ public abstract class World implements IBlockAccess {
while (iterator.hasNext()) { while (iterator.hasNext()) {
Entity entity = (Entity) iterator.next(); Entity entity = (Entity) iterator.next();
@ -62,7 +62,7 @@ index 0dca11b2c..dadd4b839 100644
if (oclass.isAssignableFrom(entity.getClass()) && predicate.apply((T) entity)) { if (oclass.isAssignableFrom(entity.getClass()) && predicate.apply((T) entity)) {
arraylist.add(entity); arraylist.add(entity);
@@ -2719,6 +2722,7 @@ public abstract class World implements IBlockAccess { @@ -2720,6 +2723,7 @@ public abstract class World implements IBlockAccess {
while (iterator.hasNext()) { while (iterator.hasNext()) {
Entity entity = (Entity) iterator.next(); Entity entity = (Entity) iterator.next();
@ -71,7 +71,7 @@ index 0dca11b2c..dadd4b839 100644
if (entity instanceof EntityInsentient) { if (entity instanceof EntityInsentient) {
EntityInsentient entityinsentient = (EntityInsentient) entity; EntityInsentient entityinsentient = (EntityInsentient) entity;
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 210e3bc4e..e6ecd1796 100644 index 210e3bc4e6..e6ecd1796c 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -678,6 +678,7 @@ public class CraftWorld implements World { @@ -678,6 +678,7 @@ public class CraftWorld implements World {
@ -107,5 +107,5 @@ index 210e3bc4e..e6ecd1796 100644
if (bukkitEntity == null) { if (bukkitEntity == null) {
-- --
2.17.1 2.18.0