From 0e3875914cc7683ad8733f1be2f9d8967927ccac Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sun, 19 Apr 2020 06:07:57 -0700 Subject: [PATCH] Improve random ticking behaviour - Fixes #3181 --- ...re-Entity-is-never-double-registered.patch | 4 +- ...ering-entities-from-unloading-chunks.patch | 2 +- .../Optimise-Chunk-getFluid.patch | 4 +- ...imise-entity-hard-collision-checking.patch | 10 +- .../Optimise-random-block-ticking.patch | 150 ++++++------------ ...-PlayerChunkMap-adds-crashing-server.patch | 4 +- 6 files changed, 63 insertions(+), 111 deletions(-) diff --git a/Spigot-Server-Patches/Ensure-Entity-is-never-double-registered.patch b/Spigot-Server-Patches/Ensure-Entity-is-never-double-registered.patch index a5990ab3d2..29fa77a27a 100644 --- a/Spigot-Server-Patches/Ensure-Entity-is-never-double-registered.patch +++ b/Spigot-Server-Patches/Ensure-Entity-is-never-double-registered.patch @@ -11,7 +11,7 @@ Vs behavior of non ticking of just overwriting state. We will now simply log a warning when this happens instead of crashing the server. diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 16f2e32d..9cb4e5a1 100644 +index 16f2e32d23..9cb4e5a1e6 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java @@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke @@ -23,7 +23,7 @@ index 16f2e32d..9cb4e5a1 100644 private boolean locked = false; @Override diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index 9d35d650..d239afea 100644 +index de24b487d2..e198b8c565 100644 --- a/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java @@ -0,0 +0,0 @@ public class WorldServer extends World { diff --git a/Spigot-Server-Patches/Fix-unregistering-entities-from-unloading-chunks.patch b/Spigot-Server-Patches/Fix-unregistering-entities-from-unloading-chunks.patch index 8d40a65670..8168e539f4 100644 --- a/Spigot-Server-Patches/Fix-unregistering-entities-from-unloading-chunks.patch +++ b/Spigot-Server-Patches/Fix-unregistering-entities-from-unloading-chunks.patch @@ -15,7 +15,7 @@ Combine that with a buggy detail of the previous implementation of the Dupe UUID patch, then this was the likely source of the "Ghost entities" diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index d239afea..a9cb5245 100644 +index e198b8c565..b3e1e3686b 100644 --- a/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java @@ -0,0 +0,0 @@ public class WorldServer extends World { diff --git a/Spigot-Server-Patches/Optimise-Chunk-getFluid.patch b/Spigot-Server-Patches/Optimise-Chunk-getFluid.patch index e5efb3bea1..0111d5e21b 100644 --- a/Spigot-Server-Patches/Optimise-Chunk-getFluid.patch +++ b/Spigot-Server-Patches/Optimise-Chunk-getFluid.patch @@ -8,7 +8,7 @@ faster on its own, however removing the try catch makes it easier to inline due to code size diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index 92bb009b..719c6f3e 100644 +index 8fc26aa4b8..8695845445 100644 --- a/src/main/java/net/minecraft/server/Chunk.java +++ b/src/main/java/net/minecraft/server/Chunk.java @@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { @@ -48,7 +48,7 @@ index 92bb009b..719c6f3e 100644 // CraftBukkit start diff --git a/src/main/java/net/minecraft/server/ChunkSection.java b/src/main/java/net/minecraft/server/ChunkSection.java -index 8b28fb5e..426221f7 100644 +index 3eaf893cdf..cda718bba0 100644 --- a/src/main/java/net/minecraft/server/ChunkSection.java +++ b/src/main/java/net/minecraft/server/ChunkSection.java @@ -0,0 +0,0 @@ public class ChunkSection { diff --git a/Spigot-Server-Patches/Optimise-entity-hard-collision-checking.patch b/Spigot-Server-Patches/Optimise-entity-hard-collision-checking.patch index 952df0a799..95c59f4581 100644 --- a/Spigot-Server-Patches/Optimise-entity-hard-collision-checking.patch +++ b/Spigot-Server-Patches/Optimise-entity-hard-collision-checking.patch @@ -11,7 +11,7 @@ Less crammed entities are likely to show significantly less benefit. Effectively, this patch optimises crammed entity situations. diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index 719c6f3e..d745eae4 100644 +index 8695845445..32c342d313 100644 --- a/src/main/java/net/minecraft/server/Chunk.java +++ b/src/main/java/net/minecraft/server/Chunk.java @@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { @@ -88,7 +88,7 @@ index 719c6f3e..d745eae4 100644 } if (entity instanceof EntityItem) { diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 9cb4e5a1..96a47dd1 100644 +index 9cb4e5a1e6..96a47dd1c2 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java @@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke @@ -133,7 +133,7 @@ index 9cb4e5a1..96a47dd1 100644 this.id = Entity.entityCount.incrementAndGet(); this.passengers = Lists.newArrayList(); diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java -index af10fc36..2887cb14 100644 +index af10fc36e0..2887cb14e4 100644 --- a/src/main/java/net/minecraft/server/EntityEnderDragon.java +++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java @@ -0,0 +0,0 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { @@ -145,7 +145,7 @@ index af10fc36..2887cb14 100644 return this.children; } diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java -index 4157e50e..5135308f 100644 +index 4157e50e4d..5135308fb6 100644 --- a/src/main/java/net/minecraft/server/IEntityAccess.java +++ b/src/main/java/net/minecraft/server/IEntityAccess.java @@ -0,0 +0,0 @@ public interface IEntityAccess { @@ -178,7 +178,7 @@ index 4157e50e..5135308f 100644 return stream.filter(axisalignedbb1::c).map(VoxelShapes::a); diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 46e19d91..09b03aff 100644 +index d530508b61..1a3c7c148b 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java @@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { diff --git a/Spigot-Server-Patches/Optimise-random-block-ticking.patch b/Spigot-Server-Patches/Optimise-random-block-ticking.patch index 3647cd9440..276ed146c4 100644 --- a/Spigot-Server-Patches/Optimise-random-block-ticking.patch +++ b/Spigot-Server-Patches/Optimise-random-block-ticking.patch @@ -20,7 +20,7 @@ remains the same. diff --git a/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java new file mode 100644 -index 00000000..3edc8e52 +index 0000000000..3edc8e52e0 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java @@ -0,0 +0,0 @@ @@ -71,7 +71,7 @@ index 00000000..3edc8e52 + } +} diff --git a/src/main/java/net/minecraft/server/Block.java b/src/main/java/net/minecraft/server/Block.java -index e29ec958..e40375b6 100644 +index e29ec958b3..e40375b67a 100644 --- a/src/main/java/net/minecraft/server/Block.java +++ b/src/main/java/net/minecraft/server/Block.java @@ -0,0 +0,0 @@ public class Block implements IMaterial { @@ -86,7 +86,7 @@ index e29ec958..e40375b6 100644 } diff --git a/src/main/java/net/minecraft/server/BlockFluids.java b/src/main/java/net/minecraft/server/BlockFluids.java -index 6d351f09..a44f65f4 100644 +index 6d351f0979..a44f65f40d 100644 --- a/src/main/java/net/minecraft/server/BlockFluids.java +++ b/src/main/java/net/minecraft/server/BlockFluids.java @@ -0,0 +0,0 @@ public class BlockFluids extends Block implements IFluidSource { @@ -99,7 +99,7 @@ index 6d351f09..a44f65f4 100644 @Override diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java -index e76528f1..e650a2e4 100644 +index e76528f199..e650a2e48d 100644 --- a/src/main/java/net/minecraft/server/BlockPosition.java +++ b/src/main/java/net/minecraft/server/BlockPosition.java @@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali @@ -111,37 +111,9 @@ index e76528f1..e650a2e4 100644 return this.d(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); } diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index 03c25eae..92bb009b 100644 +index 29cfef1605..8fc26aa4b8 100644 --- a/src/main/java/net/minecraft/server/Chunk.java +++ b/src/main/java/net/minecraft/server/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - private final ChunkCoordIntPair loc; public final long coordinateKey; // Paper - cache coordinate key - private volatile boolean x; - -+ final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper -+ - public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage) { - this(world, chunkcoordintpair, biomestorage, ChunkConverter.a, TickListEmpty.b(), TickListEmpty.b(), 0L, (ChunkSection[]) null, (Consumer) null); - } -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - this.v = consumer; - if (achunksection != null) { - if (this.sections.length == achunksection.length) { -+ // Paper start - maintain a list of ticking blocks in a chunk -+ for (ChunkSection section : achunksection) { -+ if (section != null) { -+ section.chunk = this; -+ int offset = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationKey(0, section.yPos, 0); -+ for (it.unimi.dsi.fastutil.longs.LongIterator iterator = section.tickingList.getRawIterator(); iterator.hasNext();) { -+ long raw = iterator.nextLong(); -+ this.tickingList.add(com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw) + offset, com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw)); -+ } -+ } -+ } -+ // Paper end - System.arraycopy(achunksection, 0, this.sections, 0, this.sections.length); - } else { - Chunk.LOGGER.warn("Could not set level chunk sections, array length is {} instead of {}", achunksection.length, this.sections.length); @@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { this.entities.remove(entity); // Paper } @@ -154,7 +126,7 @@ index 03c25eae..92bb009b 100644 } diff --git a/src/main/java/net/minecraft/server/ChunkSection.java b/src/main/java/net/minecraft/server/ChunkSection.java -index 4526527a..8b28fb5e 100644 +index 4526527aca..3eaf893cdf 100644 --- a/src/main/java/net/minecraft/server/ChunkSection.java +++ b/src/main/java/net/minecraft/server/ChunkSection.java @@ -0,0 +0,0 @@ import javax.annotation.Nullable; @@ -193,9 +165,6 @@ index 4526527a..8b28fb5e 100644 --this.tickingBlockCount; + // Paper start + this.tickingList.remove(i, j, k); -+ if (this.chunk != null) { -+ this.chunk.tickingList.remove(i, j + this.yPos, k); -+ } + // Paper end } } @@ -206,9 +175,6 @@ index 4526527a..8b28fb5e 100644 ++this.tickingBlockCount; + // Paper start + this.tickingList.add(i, j, k, iblockdata); -+ if (this.chunk != null) { -+ this.chunk.tickingList.add(i, j + this.yPos, k, iblockdata); -+ } + // Paper end } } @@ -218,13 +184,6 @@ index 4526527a..8b28fb5e 100644 public void recalcBlockCounts() { + // Paper start -+ int offset = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationKey(0, this.yPos, 0); -+ if (this.chunk != null) { -+ for (it.unimi.dsi.fastutil.longs.LongIterator iterator = this.tickingList.getRawIterator(); iterator.hasNext();) { -+ long raw = iterator.nextLong(); -+ this.chunk.tickingList.remove(com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw) + offset); -+ } -+ } + this.tickingList.clear(); + // Paper end this.nonEmptyBlockCount = 0; @@ -242,9 +201,6 @@ index 4526527a..8b28fb5e 100644 + this.tickingBlockCount = (short) (this.tickingBlockCount + 1); // Paper + // Paper start + this.tickingList.add(location, iblockdata); -+ if (this.chunk != null) { -+ this.chunk.tickingList.add(location + offset, iblockdata); -+ } + // Paper end } } @@ -259,7 +215,7 @@ index 4526527a..8b28fb5e 100644 } diff --git a/src/main/java/net/minecraft/server/DataBits.java b/src/main/java/net/minecraft/server/DataBits.java -index f9680b68..a61cffa3 100644 +index f9680b6830..a61cffa3f4 100644 --- a/src/main/java/net/minecraft/server/DataBits.java +++ b/src/main/java/net/minecraft/server/DataBits.java @@ -0,0 +0,0 @@ public class DataBits { @@ -310,7 +266,7 @@ index f9680b68..a61cffa3 100644 + // Paper end } diff --git a/src/main/java/net/minecraft/server/DataPaletteBlock.java b/src/main/java/net/minecraft/server/DataPaletteBlock.java -index 44aed672..fa664897 100644 +index 44aed67274..fa664897fb 100644 --- a/src/main/java/net/minecraft/server/DataPaletteBlock.java +++ b/src/main/java/net/minecraft/server/DataPaletteBlock.java @@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { @@ -329,7 +285,7 @@ index 44aed672..fa664897 100644 public interface a { diff --git a/src/main/java/net/minecraft/server/EntityTurtle.java b/src/main/java/net/minecraft/server/EntityTurtle.java -index dd02cb34..b24a5100 100644 +index dd02cb3485..b24a5100b4 100644 --- a/src/main/java/net/minecraft/server/EntityTurtle.java +++ b/src/main/java/net/minecraft/server/EntityTurtle.java @@ -0,0 +0,0 @@ public class EntityTurtle extends EntityAnimal { @@ -342,7 +298,7 @@ index dd02cb34..b24a5100 100644 public final BlockPosition getHome() { return this.es(); } // Paper - OBFHELPER diff --git a/src/main/java/net/minecraft/server/IBlockData.java b/src/main/java/net/minecraft/server/IBlockData.java -index de438816..e821c236 100644 +index de43881653..e821c236b4 100644 --- a/src/main/java/net/minecraft/server/IBlockData.java +++ b/src/main/java/net/minecraft/server/IBlockData.java @@ -0,0 +0,0 @@ public class IBlockData extends BlockDataAbstract implements @@ -395,7 +351,7 @@ index de438816..e821c236 100644 public final SoundEffectType getStepSound() { return this.r(); } // Paper - OBFHELPER diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 28b6c9a0..d554d4cf 100644 +index 5036348abf..5e6481f115 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java @@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { @@ -420,21 +376,23 @@ index 28b6c9a0..d554d4cf 100644 public boolean isSavingDisabled() { diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index 71f5e3ce..ed41c814 100644 +index 62fabb7ad5..9a2b4fa7a2 100644 --- a/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java @@ -0,0 +0,0 @@ public class WorldServer extends World { }); } +- public void a(Chunk chunk, int i) { + // Paper start - optimise random block ticking + private final BlockPosition.MutableBlockPosition chunkTickMutablePosition = new BlockPosition.MutableBlockPosition(); + private final com.destroystokyo.paper.util.math.ThreadUnsafeRandom randomTickRandom = new com.destroystokyo.paper.util.math.ThreadUnsafeRandom(); + // Paper end + - public void a(Chunk chunk, int i) { ++ public void a(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); boolean flag = this.isRaining(); + int j = chunkcoordintpair.d(); @@ -0,0 +0,0 @@ public class WorldServer extends World { GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); @@ -491,75 +449,69 @@ index 71f5e3ce..ed41c814 100644 - gameprofilerfiller.exitEnter("tickBlocks"); - timings.chunkTicksBlocks.startTiming(); // Paper -- if (i > 0) { -- ChunkSection[] achunksection = chunk.getSections(); -- int l = achunksection.length; -- -- for (int i1 = 0; i1 < l; ++i1) { -- ChunkSection chunksection = achunksection[i1]; -- -- if (chunksection != Chunk.a && chunksection.d()) { -- int j1 = chunksection.getYPosition(); + // Paper start - optimise random block ticking + gameprofilerfiller.exit(); -+ int blocks = chunk.tickingList.size(); -+ if (i > 0 && blocks > 0) { -+ if ((this.randomTickRandom.nextInt() & (16 * 16 * 256 - 1)) > blocks) { -+ // we optimise random block ticking by realising that most of the blocks we will try to tick -+ // are not tickable. Instead we only tick tickable blocks, but only if the above -+ // statement is true -+ // Note: The number of blocks that get ticked per tick still REMAIN the same. -+ return; -+ } -+ gameprofilerfiller.enter("tickBlocks"); + if (i > 0) { +- ChunkSection[] achunksection = chunk.getSections(); +- int l = achunksection.length; ++ gameprofilerfiller.enter("randomTick"); + timings.chunkTicksBlocks.startTiming(); // Paper +- for (int i1 = 0; i1 < l; ++i1) { +- ChunkSection chunksection = achunksection[i1]; ++ ChunkSection[] sections = chunk.getSections(); + +- if (chunksection != Chunk.a && chunksection.d()) { +- int j1 = chunksection.getYPosition(); ++ for (int sectionIndex = 0; sectionIndex < 16; ++sectionIndex) { ++ ChunkSection section = sections[sectionIndex]; ++ if (section == null || section.tickingList.size() == 0) { ++ continue; ++ } + - for (int k1 = 0; k1 < i; ++k1) { - BlockPosition blockposition2 = this.a(j, j1, k, 15); -+ int toTick = i << 4; // i * 16 ++ int yPos = sectionIndex << 4; - gameprofilerfiller.enter("randomTick"); - IBlockData iblockdata = chunksection.getType(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k); -+ gameprofilerfiller.enter("randomTick"); -+ for (int tick = 0; tick < toTick; ++tick) { -+ int tickingSize = chunk.tickingList.size(); -+ if (tickingSize == 0) { -+ break; -+ } ++ for (int a = 0; a < randomTickSpeed; ++a) { ++ int tickingBlocks = section.tickingList.size(); ++ int index = this.randomTickRandom.nextInt(16 * 16 * 16); ++ if (index >= tickingBlocks) { ++ continue; ++ } - if (iblockdata.q()) { - iblockdata.getBlock().randomTick = true; // Paper - fix MC-113809 - iblockdata.b(this, blockposition2, this.random); - iblockdata.getBlock().randomTick = false; // Paper - fix MC-113809 - } -+ int index = this.randomTickRandom.nextInt(tickingSize); -+ long raw = chunk.tickingList.getRaw(index); -+ int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw); -+ int randomX = location & 15; -+ int randomY = (location >>> (4 + 4)) & 255; -+ int randomZ = (location >>> 4) & 15; ++ long raw = section.tickingList.getRaw(index); ++ int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw); ++ int randomX = location & 15; ++ int randomY = ((location >>> (4 + 4)) & 255) | yPos; ++ int randomZ = (location >>> 4) & 15; - Fluid fluid = iblockdata.getFluid(); -+ BlockPosition blockposition2 = blockposition.setValues(j + randomX, randomY, k + randomZ); -+ IBlockData iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); ++ BlockPosition blockposition2 = blockposition.setValues(j + randomX, randomY, k + randomZ); ++ IBlockData iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); - if (fluid.h()) { - fluid.b(this, blockposition2, this.random); - } -+ iblockdata.getBlock().randomTick = true; // Paper - fix MC-113809 -+ iblockdata.b(this, blockposition2, this.randomTickRandom); -+ iblockdata.getBlock().randomTick = false; // Paper - fix MC-113809 ++ iblockdata.getBlock().randomTick = true; // Paper - fix MC-113809 ++ iblockdata.b(this, blockposition2, this.randomTickRandom); ++ iblockdata.getBlock().randomTick = false; // Paper - fix MC-113809 - gameprofilerfiller.exit(); - } -- } -+ // We drop the fluid tick since LAVA is ALREADY TICKED by the above method. -+ // TODO CHECK ON UPDATE ++ // We drop the fluid tick since LAVA is ALREADY TICKED by the above method. ++ // TODO CHECK ON UPDATE + } } -+ + gameprofilerfiller.exit(); + timings.chunkTicksBlocks.stopTiming(); // Paper -+ gameprofilerfiller.exit(); + // Paper end } - timings.chunkTicksBlocks.stopTiming(); // Paper diff --git a/Spigot-Server-Patches/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/Spigot-Server-Patches/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch index badc014b87..30cbebe201 100644 --- a/Spigot-Server-Patches/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch +++ b/Spigot-Server-Patches/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch @@ -7,7 +7,7 @@ Suspected case would be around the technique used in .stopRiding Stack will identify any causer of this and warn instead of crashing. diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java -index 0186ab9e..e1e4ea79 100644 +index 0186ab9e40..e1e4ea793a 100644 --- a/src/main/java/net/minecraft/server/PlayerChunkMap.java +++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java @@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -26,7 +26,7 @@ index 0186ab9e..e1e4ea79 100644 if (!(entity instanceof EntityLightning)) { EntityTypes entitytypes = entity.getEntityType(); diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index a9cb5245..969c6aad 100644 +index b3e1e3686b..142770bcd6 100644 --- a/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java @@ -0,0 +0,0 @@ public class WorldServer extends World {