From 0181286eb9cdda705cdd45719f58af3833c1827d Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Wed, 9 Aug 2017 18:11:57 -0500 Subject: [PATCH] Fix MC-117075: TE Unload Lag Spike PaperMC port of https://github.com/MinecraftForge/MinecraftForge/pull/4281 --- ...33-Fix-MC-117075-TE-Unload-Lag-Spike.patch | 101 ++++++++++++++++++ scripts/importmcdev.sh | 1 + 2 files changed, 102 insertions(+) create mode 100644 Spigot-Server-Patches/0233-Fix-MC-117075-TE-Unload-Lag-Spike.patch diff --git a/Spigot-Server-Patches/0233-Fix-MC-117075-TE-Unload-Lag-Spike.patch b/Spigot-Server-Patches/0233-Fix-MC-117075-TE-Unload-Lag-Spike.patch new file mode 100644 index 0000000000..10cbee8689 --- /dev/null +++ b/Spigot-Server-Patches/0233-Fix-MC-117075-TE-Unload-Lag-Spike.patch @@ -0,0 +1,101 @@ +From 3ce3d501a6fc62dc396aaec8eaff30c4a469b405 Mon Sep 17 00:00:00 2001 +From: mezz +Date: Wed, 9 Aug 2017 17:51:22 -0500 +Subject: [PATCH] Fix MC-117075: TE Unload Lag Spike + + +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index ed595955..228792fa 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -823,6 +823,9 @@ public class Chunk { + + public void removeEntities() { + this.j = false; ++ // Paper start - Fix MC-117075: TE Unload Lag Spike ++ this.world.markTileEntitiesForRemoval(this); ++ /* + Iterator iterator = this.tileEntities.values().iterator(); + + while (iterator.hasNext()) { +@@ -842,6 +845,8 @@ public class Chunk { + + this.world.b(tileentity); + } ++ */ ++ // Paper end + + List[] aentityslice = this.entitySlices; // Spigot + int i = aentityslice.length; +diff --git a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java +index 23944088..e8d1a1c6 100644 +--- a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java ++++ b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java +@@ -15,6 +15,7 @@ public class ChunkCoordIntPair { + this.z = blockposition.getZ() >> 4; + } + ++ public static long asLong(int x, int z) { return a(x, z); } // Paper - OBFHELPER + public static long a(int i, int j) { + return (long) i & 4294967295L | ((long) j & 4294967295L) << 32; + } +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 12938b9f..7e0ba4b2 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -147,6 +147,7 @@ public abstract class World implements IBlockAccess { + private org.spigotmc.TickLimiter tileLimiter; + private int tileTickPosition; + public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions ++ private it.unimi.dsi.fastutil.longs.LongCollection tileEntitiesChunkToBeRemoved = new it.unimi.dsi.fastutil.longs.LongOpenHashSet(); // Paper - Fix MC-117075: TE Unload Lag Spike + + public CraftWorld getWorld() { + return this.world; +@@ -1581,6 +1582,7 @@ public abstract class World implements IBlockAccess { + this.tileEntityListUnload.clear(); + } + // CraftBukkit end ++ this.removeTileEntitiesForRemovedChunks(); // Paper - Fix MC-117075: TE Unload Lag Spike + + // Spigot start + // Iterator iterator = this.tileEntityListTick.iterator(); +@@ -3261,4 +3263,36 @@ public abstract class World implements IBlockAccess { + public BlockPosition a(String s, BlockPosition blockposition, boolean flag) { + return null; + } ++ ++ // Paper start - Fix MC-117075: TE Unload Lag Spike ++ public void markTileEntitiesForRemoval(Chunk chunk) { ++ if (!chunk.getTileEntities().isEmpty()) { ++ long pos = net.minecraft.server.ChunkCoordIntPair.asLong(chunk.locX, chunk.locZ); ++ this.tileEntitiesChunkToBeRemoved.add(pos); ++ } ++ } ++ ++ private void removeTileEntitiesForRemovedChunks() { ++ if (!this.tileEntitiesChunkToBeRemoved.isEmpty()) { ++ java.util.function.Predicate isInChunk = (tileEntity) -> { ++ BlockPosition tilePos = tileEntity.getPosition(); ++ long tileChunkPos = net.minecraft.server.ChunkCoordIntPair.asLong(tilePos.getX() >> 4, tilePos.getZ() >> 4); ++ final boolean willRemove = this.tileEntitiesChunkToBeRemoved.contains(tileChunkPos); ++ // Brought over from Chunk#removeEntities ++ if (willRemove && tileEntity instanceof IInventory) { ++ for (org.bukkit.entity.HumanEntity human : Lists.newArrayList(((IInventory) tileEntity).getViewers())) { ++ if (human instanceof org.bukkit.craftbukkit.entity.CraftHumanEntity) { ++ ((org.bukkit.craftbukkit.entity.CraftHumanEntity) human).getHandle().closeInventory(); ++ } ++ } ++ } ++ ++ return willRemove; ++ }; ++ ++ this.tileEntityListTick.removeIf(isInChunk); ++ this.tileEntitiesChunkToBeRemoved.clear(); ++ } ++ } ++ // Paper end + } +-- +2.13.4 + diff --git a/scripts/importmcdev.sh b/scripts/importmcdev.sh index 6685298554..a6f85e4930 100755 --- a/scripts/importmcdev.sh +++ b/scripts/importmcdev.sh @@ -49,6 +49,7 @@ import BlockPosition import BlockSnowBlock import BlockStateEnum import ChunkCache +import ChunkCoordIntPair import ChunkProviderFlat import ChunkProviderGenerate import ChunkProviderHell