From f2bcb786e5eed44c74b3ebc8573f5735e589cd6d 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..e4fd7fa7 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,40 @@ 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 isInChunkOrNull = (tileEntity) -> { + if (tileEntity == null) { + return true; + } + + 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(isInChunkOrNull); + this.tileEntitiesChunkToBeRemoved.clear(); + } + } + // Paper end } -- 2.14.1