From 17dca0a0fed54727af1f07a01b57557472564fc0 Mon Sep 17 00:00:00 2001 From: Aikar Date: Thu, 2 Aug 2018 23:06:03 -0400 Subject: [PATCH 1/3] Add "Safe Regen" Duplicate UUID resolver and make default After witnessing behavior of the regeneration logs, its clear that Vanilla has had bugs with saving duplicate entities for a while.... Some entities are saved in multiple chunks, and now we are bringing those duplicates out that use to never surface. This mode will analyze if the entity appears to be a duplicate (near the other dupe uuid) and delete the entity instead. This should reduce regenerations to entities that are nowhere near each other, and therefore more likely to be subject to real UUID collisions due to our previous bug, and therefor should survive the chunk load. --- .../0338-Duplicate-UUID-Resolve-Option.patch | 35 +++++++++++++------ ...dd-some-Debug-to-Chunk-Entity-slices.patch | 6 ++-- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/Spigot-Server-Patches/0338-Duplicate-UUID-Resolve-Option.patch b/Spigot-Server-Patches/0338-Duplicate-UUID-Resolve-Option.patch index 963e00bdc..7e2090639 100644 --- a/Spigot-Server-Patches/0338-Duplicate-UUID-Resolve-Option.patch +++ b/Spigot-Server-Patches/0338-Duplicate-UUID-Resolve-Option.patch @@ -1,4 +1,4 @@ -From 40d2133fe00d2b7208a17e36c2b70e07fc3510c6 Mon Sep 17 00:00:00 2001 +From 81b0946c56f4368fb81c2ee241cd3c244e34b689 Mon Sep 17 00:00:00 2001 From: Aikar Date: Sat, 21 Jul 2018 14:27:34 -0400 Subject: [PATCH] Duplicate UUID Resolve Option @@ -33,21 +33,25 @@ But for those who are ok with leaving this inconsistent behavior, you may use WA It is recommended you regenerate the entities, as these were legit entities, and deserve your love. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 14c8edeffc..1f4e438c1f 100644 +index 14c8edeffc..46ec852b6c 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -541,4 +541,40 @@ public class PaperWorldConfig { +@@ -541,4 +541,44 @@ public class PaperWorldConfig { log("Bed Search Radius: " + bedSearchRadius); } } + + public enum DuplicateUUIDMode { -+ REGEN, DELETE, NOTHING, WARN ++ SAFE_REGEN, REGEN, DELETE, NOTHING, WARN + } -+ public DuplicateUUIDMode duplicateUUIDMode = DuplicateUUIDMode.REGEN; ++ public DuplicateUUIDMode duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; + private void repairDuplicateUUID() { -+ String desiredMode = getString("duplicate-uuid-resolver", "regenerate").toLowerCase().trim(); ++ String desiredMode = getString("duplicate-uuid-resolver", "saferegen").toLowerCase().trim(); + switch (desiredMode.toLowerCase()) { ++ case "saferegen": ++ case "saferegenerate": ++ duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; ++ log("Duplicate UUID Resolve: Safer Regenerate New UUID (Delete likely duplicates)"); + case "regen": + case "regenerate": + duplicateUUIDMode = DuplicateUUIDMode.REGEN; @@ -78,7 +82,7 @@ index 14c8edeffc..1f4e438c1f 100644 + } } diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index f1815d3766..74612a3924 100644 +index 4757081090..4018410485 100644 --- a/src/main/java/net/minecraft/server/Chunk.java +++ b/src/main/java/net/minecraft/server/Chunk.java @@ -1,5 +1,10 @@ @@ -108,7 +112,7 @@ index f1815d3766..74612a3924 100644 } int k = MathHelper.floor(entity.locY / 16.0D); -@@ -851,6 +858,39 @@ public class Chunk { +@@ -851,6 +858,50 @@ public class Chunk { for (int j = 0; j < i; ++j) { List entityslice = aentityslice[j]; // Spigot @@ -123,8 +127,19 @@ index f1815d3766..74612a3924 100644 + if (other == null || other.dead || world.getEntityUnloadQueue().contains(other)) { + other = thisChunk.get(entity.uniqueID); + } ++ ++ if (mode == DuplicateUUIDMode.SAFE_REGEN && other != null && !other.dead && ++ !world.getEntityUnloadQueue().contains(other) ++ && java.util.Objects.equals(other.getSaveID(), entity.getSaveID()) ++ && entity.getBukkitEntity().getLocation().distance(other.getBukkitEntity().getLocation()) < 24 ++ ) { ++ logger.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + " because it was near the duplicate and likely an actual duplicate. See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); ++ entity.die(); ++ continue; ++ } + if (other != null && !other.dead) { + switch (mode) { ++ case SAFE_REGEN: + case REGEN: { + entity.setUUID(UUID.randomUUID()); + logger.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", regenerated UUID for " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); @@ -149,7 +164,7 @@ index f1815d3766..74612a3924 100644 this.world.a((Collection) entityslice); } diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 93ab050fa6..fdabb1e369 100644 +index 7b856cad91..eb8904a728 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java @@ -2619,6 +2619,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper @@ -161,7 +176,7 @@ index 93ab050fa6..fdabb1e369 100644 this.uniqueID = uuid; this.ar = this.uniqueID.toString(); diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 52adee8806..b4de3b515a 100644 +index d5cd289c21..57217bec2b 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java @@ -70,7 +70,7 @@ public abstract class World implements IBlockAccess { diff --git a/Spigot-Server-Patches/0340-Add-some-Debug-to-Chunk-Entity-slices.patch b/Spigot-Server-Patches/0340-Add-some-Debug-to-Chunk-Entity-slices.patch index a8a0569b7..1f573d9ca 100644 --- a/Spigot-Server-Patches/0340-Add-some-Debug-to-Chunk-Entity-slices.patch +++ b/Spigot-Server-Patches/0340-Add-some-Debug-to-Chunk-Entity-slices.patch @@ -1,4 +1,4 @@ -From 5e0068199fd5fce71ab1d880e43f090574f87ebc Mon Sep 17 00:00:00 2001 +From 099d9012a80cc417b8b3be962d67942ce3162b0c Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 23 Jul 2018 22:44:23 -0400 Subject: [PATCH] Add some Debug to Chunk Entity slices @@ -9,7 +9,7 @@ This should hopefully avoid duplicate entities ever being created if the entity was to end up in 2 different chunk slices diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index 27b73acdee..be3ac2d940 100644 +index ccb30d5bfd..94b294e87b 100644 --- a/src/main/java/net/minecraft/server/Chunk.java +++ b/src/main/java/net/minecraft/server/Chunk.java @@ -681,8 +681,33 @@ public class Chunk { @@ -60,7 +60,7 @@ index 27b73acdee..be3ac2d940 100644 this.markDirty(); entity.setCurrentChunk(null); entityCounts.decrement(entity.getMinecraftKeyString()); -@@ -943,6 +974,7 @@ public class Chunk { +@@ -954,6 +985,7 @@ public class Chunk { } // Spigot End entity.setCurrentChunk(null); // Paper From 56b92ff216d4ec7a48537a4ee808ba5bcb1d8d62 Mon Sep 17 00:00:00 2001 From: Aikar Date: Fri, 3 Aug 2018 00:06:20 -0400 Subject: [PATCH 2/3] Fix EXP orb merging causing values to go negative - Closes #1169 --- ...-maximum-exp-value-when-merging-orbs.patch | 25 +++++++++++-------- .../0256-ExperienceOrbMergeEvent.patch | 18 ++++++------- ...ups-for-Entity-TileEntity-Current-Ch.patch | 14 +++++------ ...revent-Saving-Bad-entities-to-chunks.patch | 6 ++--- ...rocess-chunk-removal-in-removeEntity.patch | 8 +++--- ...ead-Entities-in-entityList-iteration.patch | 20 +++++++-------- 6 files changed, 47 insertions(+), 44 deletions(-) diff --git a/Spigot-Server-Patches/0246-Option-for-maximum-exp-value-when-merging-orbs.patch b/Spigot-Server-Patches/0246-Option-for-maximum-exp-value-when-merging-orbs.patch index c998118c4..c10aaec3a 100644 --- a/Spigot-Server-Patches/0246-Option-for-maximum-exp-value-when-merging-orbs.patch +++ b/Spigot-Server-Patches/0246-Option-for-maximum-exp-value-when-merging-orbs.patch @@ -1,11 +1,11 @@ -From d3ad905c6a3156cbf9484834eea088efb106b4dd Mon Sep 17 00:00:00 2001 +From 076f4e8c2a78146df199092bb435153a87ceb89c Mon Sep 17 00:00:00 2001 From: BillyGalbreath Date: Fri, 10 Nov 2017 23:03:12 -0500 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 -index 4d30cdbc8..535a8d3ed 100644 +index 4d30cdbc8b..535a8d3ed1 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -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 -index 29dffc3ac..2c69ae748 100644 +index 3561507de1..b6b4d52718 100644 --- a/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; double radius = spigotConfig.expMerge; if (radius > 0) { + // Paper start - Maximum exp value when merging - Whole section has been tweaked, see comments for specifics + 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 + List entities = this.getEntities(entity, entity.getBoundingBox().grow(radius, radius, radius)); @@ -37,16 +37,19 @@ index 29dffc3ac..2c69ae748 100644 if (e instanceof EntityExperienceOrb) { EntityExperienceOrb loopItem = (EntityExperienceOrb) e; - if (!loopItem.dead) { -+ if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) { // Paper - xp.value += loopItem.value; -+ // Paper start -+ if (!mergeUnconditionally && xp.value > maxValue) { +- xp.value += loopItem.value; +- loopItem.die(); ++ // Paper start ++ 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; + xp.value = maxValue; -+ break; ++ } else { ++ xp.value += loopItem.value; ++ loopItem.die(); + } + // Paper end - loopItem.die(); } } } diff --git a/Spigot-Server-Patches/0256-ExperienceOrbMergeEvent.patch b/Spigot-Server-Patches/0256-ExperienceOrbMergeEvent.patch index 080f2acdb..dfdd87695 100644 --- a/Spigot-Server-Patches/0256-ExperienceOrbMergeEvent.patch +++ b/Spigot-Server-Patches/0256-ExperienceOrbMergeEvent.patch @@ -1,4 +1,4 @@ -From 4104f9583f512022acc4fe898d4487df59a1029a Mon Sep 17 00:00:00 2001 +From 2c072e94e1c963916f63e2ff8fb41b0f933b1ccb Mon Sep 17 00:00:00 2001 From: Aikar Date: Tue, 19 Dec 2017 22:57:26 -0500 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. 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 +++ b/src/main/java/net/minecraft/server/World.java -@@ -1153,7 +1153,7 @@ public abstract class World implements IBlockAccess { - for (Entity e : entities) { +@@ -1154,7 +1154,7 @@ public abstract class World implements IBlockAccess { if (e instanceof EntityExperienceOrb) { EntityExperienceOrb loopItem = (EntityExperienceOrb) e; -- if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) { // Paper -+ 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 - xp.value += loopItem.value; - // Paper start - if (!mergeUnconditionally && xp.value > maxValue) { + // Paper start +- if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) { ++ 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()) { + long newTotal = (long)xp.value + (long)loopItem.value; + if (newTotal > (long)maxValue) { + loopItem.value = xp.value - maxValue; -- 2.18.0 diff --git a/Spigot-Server-Patches/0326-Avoid-Chunk-Lookups-for-Entity-TileEntity-Current-Ch.patch b/Spigot-Server-Patches/0326-Avoid-Chunk-Lookups-for-Entity-TileEntity-Current-Ch.patch index 3fcada57a..a74b9ec51 100644 --- a/Spigot-Server-Patches/0326-Avoid-Chunk-Lookups-for-Entity-TileEntity-Current-Ch.patch +++ b/Spigot-Server-Patches/0326-Avoid-Chunk-Lookups-for-Entity-TileEntity-Current-Ch.patch @@ -1,4 +1,4 @@ -From dbe49167504d8c10b0dd8fbd271f186cf752057e Mon Sep 17 00:00:00 2001 +From bc6e2c6add8004c4e8a231cedcf175565100c441 Mon Sep 17 00:00:00 2001 From: Aikar Date: Wed, 4 Jul 2018 03:39:51 -0400 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. 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 +++ b/src/main/java/net/minecraft/server/Chunk.java @@ -702,6 +702,7 @@ public class Chunk { @@ -22,10 +22,10 @@ index 81bf60efa..04adf4e3c 100644 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 -index c0816b9f8..52adee880 100644 +index 986670f689..a01488e985 100644 --- a/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; // Paper start - Set based removal lists for (Entity e : this.f) { @@ -42,7 +42,7 @@ index c0816b9f8..52adee880 100644 } 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.a("remove"); if (entity.dead) { @@ -62,7 +62,7 @@ index c0816b9f8..52adee880 100644 guardEntityList = false; // Spigot 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(); // Paper start - Skip ticking in chunks scheduled for unload @@ -71,7 +71,7 @@ index c0816b9f8..52adee880 100644 boolean shouldTick = chunk != null; if(this.paperConfig.skipEntityTickingInChunksScheduledForUnload) 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--; this.tileEntityListTick.remove(tileTickPosition--); //this.tileEntityList.remove(tileentity); // Paper - remove unused list diff --git a/Spigot-Server-Patches/0341-Prevent-Saving-Bad-entities-to-chunks.patch b/Spigot-Server-Patches/0341-Prevent-Saving-Bad-entities-to-chunks.patch index b3be86190..4e44b88ce 100644 --- a/Spigot-Server-Patches/0341-Prevent-Saving-Bad-entities-to-chunks.patch +++ b/Spigot-Server-Patches/0341-Prevent-Saving-Bad-entities-to-chunks.patch @@ -1,4 +1,4 @@ -From 84507c90ff4af6aa9e32dc69f6d8c64b4d230345 Mon Sep 17 00:00:00 2001 +From df4224f8e69e3eecc619f3832f5660c09eeeecfa Mon Sep 17 00:00:00 2001 From: Aikar Date: Thu, 26 Jul 2018 00:11:12 -0400 Subject: [PATCH] Prevent Saving Bad entities to chunks @@ -57,10 +57,10 @@ index bcce5e8b7e..bad287fca4 100644 nbttagcompound.set("Entities", nbttaglist1); NBTTagList nbttaglist2 = new NBTTagList(); 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 +++ 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); diff --git a/Spigot-Server-Patches/0342-Always-process-chunk-removal-in-removeEntity.patch b/Spigot-Server-Patches/0342-Always-process-chunk-removal-in-removeEntity.patch index c3b52fe62..14b6c020a 100644 --- a/Spigot-Server-Patches/0342-Always-process-chunk-removal-in-removeEntity.patch +++ b/Spigot-Server-Patches/0342-Always-process-chunk-removal-in-removeEntity.patch @@ -1,4 +1,4 @@ -From 529731e4258b21416a555ed6c2d0200b8449f1d7 Mon Sep 17 00:00:00 2001 +From 1102ec474b6e3afd75431427134a4992ee08c5e8 Mon Sep 17 00:00:00 2001 From: Aikar Date: Sat, 28 Jul 2018 12:09:20 -0400 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. 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 +++ 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(); } @@ -20,7 +20,7 @@ index d2d2ab794..df98a4f44 100644 int i = entity.ab; 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); } diff --git a/Spigot-Server-Patches/0343-Ignore-Dead-Entities-in-entityList-iteration.patch b/Spigot-Server-Patches/0343-Ignore-Dead-Entities-in-entityList-iteration.patch index 857c1498a..087d7d198 100644 --- a/Spigot-Server-Patches/0343-Ignore-Dead-Entities-in-entityList-iteration.patch +++ b/Spigot-Server-Patches/0343-Ignore-Dead-Entities-in-entityList-iteration.patch @@ -1,4 +1,4 @@ -From 9b87108547b8a12487adcc4aea181f103a24cf53 Mon Sep 17 00:00:00 2001 +From 485cc40d70fcb82a5538f2dac8713c253c943aed Mon Sep 17 00:00:00 2001 From: Aikar Date: Sat, 28 Jul 2018 12:18:27 -0400 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. 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 +++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java @@ -128,6 +128,7 @@ public class PaperCommand extends Command { @@ -23,7 +23,7 @@ index ecd1c65a9..1898ab897 100644 MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); 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 -index 1e64d5fcd..45e149f4a 100644 +index 1e64d5fcd6..45e149f4a3 100644 --- a/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 @@ -35,10 +35,10 @@ index 1e64d5fcd..45e149f4a 100644 public float length; public float I; 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 +++ 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 @@ -46,7 +46,7 @@ index 0dca11b2c..dadd4b839 100644 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)) { 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 // 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()) { Entity entity = (Entity) iterator.next(); @@ -62,7 +62,7 @@ index 0dca11b2c..dadd4b839 100644 if (oclass.isAssignableFrom(entity.getClass()) && predicate.apply((T) 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()) { Entity entity = (Entity) iterator.next(); @@ -71,7 +71,7 @@ index 0dca11b2c..dadd4b839 100644 if (entity instanceof EntityInsentient) { EntityInsentient entityinsentient = (EntityInsentient) entity; 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 +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -678,6 +678,7 @@ public class CraftWorld implements World { @@ -107,5 +107,5 @@ index 210e3bc4e..e6ecd1796 100644 if (bukkitEntity == null) { -- -2.17.1 +2.18.0 From 38af7610e325f6ddccdbe1e64d2ce8f3a834805d Mon Sep 17 00:00:00 2001 From: Aikar Date: Fri, 3 Aug 2018 00:07:02 -0400 Subject: [PATCH 3/3] MC-135506: Experience should save as Integers A large orb will lose its EXP value if it went over 32k due to short truncation. --- ...6-Experience-should-save-as-Integers.patch | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Spigot-Server-Patches/0347-MC-135506-Experience-should-save-as-Integers.patch diff --git a/Spigot-Server-Patches/0347-MC-135506-Experience-should-save-as-Integers.patch b/Spigot-Server-Patches/0347-MC-135506-Experience-should-save-as-Integers.patch new file mode 100644 index 000000000..c2eea1f08 --- /dev/null +++ b/Spigot-Server-Patches/0347-MC-135506-Experience-should-save-as-Integers.patch @@ -0,0 +1,30 @@ +From 3ee5221ba7dae7751cd0ed9cdfacbf358484ae53 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 3 Aug 2018 00:04:54 -0400 +Subject: [PATCH] MC-135506: Experience should save as Integers + + +diff --git a/src/main/java/net/minecraft/server/EntityExperienceOrb.java b/src/main/java/net/minecraft/server/EntityExperienceOrb.java +index 1c59fd9661..c179fe516e 100644 +--- a/src/main/java/net/minecraft/server/EntityExperienceOrb.java ++++ b/src/main/java/net/minecraft/server/EntityExperienceOrb.java +@@ -193,14 +193,14 @@ public class EntityExperienceOrb extends Entity { + public void b(NBTTagCompound nbttagcompound) { + nbttagcompound.setShort("Health", (short) this.d); + nbttagcompound.setShort("Age", (short) this.b); +- nbttagcompound.setShort("Value", (short) this.value); ++ nbttagcompound.setInt("Value", (short) this.value); // Paper - save as Integer + savePaperNBT(nbttagcompound); // Paper + } + + public void a(NBTTagCompound nbttagcompound) { + this.d = nbttagcompound.getShort("Health"); + this.b = nbttagcompound.getShort("Age"); +- this.value = nbttagcompound.getShort("Value"); ++ this.value = nbttagcompound.getInt("Value"); // Paper - load as Integer + loadPaperNBT(nbttagcompound); // Paper + } + +-- +2.18.0 +