From dcef1d444ba6db79fc693d5e3948417e0ffffc9e Mon Sep 17 00:00:00 2001 From: Zach Brown <1254957+zachbr@users.noreply.github.com> Date: Sat, 19 Sep 2015 09:34:17 -0500 Subject: [PATCH] Remove our own (outdated) TE handling, for one that's closer to vanilla --- ...-handling-out-of-the-chest-tick-loop.patch | 196 -------- .../Optimize-TileEntity-Ticking.patch | 453 +++++++----------- ...event-tile-entity-and-entity-crashes.patch | 3 +- 3 files changed, 172 insertions(+), 480 deletions(-) delete mode 100644 Spigot-Server-Patches/Move-sound-handling-out-of-the-chest-tick-loop.patch diff --git a/Spigot-Server-Patches/Move-sound-handling-out-of-the-chest-tick-loop.patch b/Spigot-Server-Patches/Move-sound-handling-out-of-the-chest-tick-loop.patch deleted file mode 100644 index b620413f9c..0000000000 --- a/Spigot-Server-Patches/Move-sound-handling-out-of-the-chest-tick-loop.patch +++ /dev/null @@ -1,196 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Iceee -Date: Sun, 8 Mar 2015 03:16:39 -0500 -Subject: [PATCH] Move sound handling out of the chest tick loop - - -diff --git a/src/main/java/net/minecraft/server/TileEntityChest.java b/src/main/java/net/minecraft/server/TileEntityChest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/TileEntityChest.java -+++ b/src/main/java/net/minecraft/server/TileEntityChest.java -@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityContainer implements IUpdatePlaye - - private ItemStack[] items = new ItemStack[27]; - public boolean a; -- public TileEntityChest f; -- public TileEntityChest g; -- public TileEntityChest h; -- public TileEntityChest i; -- public float j; -+ public TileEntityChest f; // PaperSpigot - adjacentChestZNeg -+ public TileEntityChest g; // PaperSpigot - adjacentChestXPos -+ public TileEntityChest h; // PaperSpigot - adjacentChestXNeg -+ public TileEntityChest i; // PaperSpigot - adjacentChestZPos -+ public float j; // PaperSpigot - lidAngle - public float k; -- public int l; -+ public int l; // PaperSpigot - numPlayersUsing - private int n; - private int o = -1; - private String p; -@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityContainer implements IUpdatePlaye - } - - public void c() { -+ // PaperSpigot - Move chest sounds out of the tick loop -+ /* - this.m(); - int i = this.position.getX(); - int j = this.position.getY(); -@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityContainer implements IUpdatePlaye - this.j = 0.0F; - } - } -- -+ */ -+ // PaperSpigot end - } - - public boolean c(int i, int j) { -@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityContainer implements IUpdatePlaye - - ++this.l; - if (this.world == null) return; // CraftBukkit -+ -+ // PaperSpigot start - Move chest open sound out of the tick loop -+ this.m(); -+ -+ if (this.l > 0 && this.j == 0.0F && this.f == null && this.h == null) { -+ this.j = 0.7F; -+ -+ double d0 = (double) this.position.getZ() + 0.5D; -+ double d1 = (double) this.position.getX() + 0.5D; -+ -+ if (this.i != null) { -+ d0 += 0.5D; -+ } -+ -+ if (this.g != null) { -+ d1 += 0.5D; -+ } -+ -+ this.world.makeSound(d1, (double) this.position.getY() + 0.5D, d0, "random.chestopen", 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); -+ } -+ // PaperSpigot end -+ - this.world.playBlockAction(this.position, this.w(), 1, this.l); - - // CraftBukkit start - Call redstone event -@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityContainer implements IUpdatePlaye - int oldPower = Math.max(0, Math.min(15, this.l)); // CraftBukkit - Get power before new viewer is added - --this.l; - if (this.world == null) return; // CraftBukkit -+ -+ // PaperSpigot start - Move chest close sound handling out of the tick loop -+ if (this.l == 0 && this.j > 0.0F || this.l > 0 && this.j < 1.0F) { -+ float f = 0.1F; -+ -+ if (this.l > 0) { -+ this.j += f; -+ } else { -+ this.j -= f; -+ } -+ -+ double d0 = (double) this.getPosition().getX() + 0.5D; -+ double d2 = (double) this.getPosition().getZ() + 0.5D; -+ -+ if (this.i != null) { -+ d2 += 0.5D; -+ } -+ -+ if (this.g != null) { -+ d0 += 0.5D; -+ } -+ -+ this.world.makeSound(d0, (double) this.getPosition().getY() + 0.5D, d2, "random.chestclosed", 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); -+ this.j = 0.0F; -+ } -+ // PaperSpigot end -+ - this.world.playBlockAction(this.position, this.w(), 1, this.l); - - // CraftBukkit start - Call redstone event -diff --git a/src/main/java/net/minecraft/server/TileEntityEnderChest.java b/src/main/java/net/minecraft/server/TileEntityEnderChest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/TileEntityEnderChest.java -+++ b/src/main/java/net/minecraft/server/TileEntityEnderChest.java -@@ -0,0 +0,0 @@ package net.minecraft.server; - - public class TileEntityEnderChest extends TileEntity implements IUpdatePlayerListBox { - -- public float a; -+ public float a; // PaperSpigot - lidAngle - public float f; -- public int g; -+ public int g; // PaperSpigot - numPlayersUsing - private int h; - - public TileEntityEnderChest() {} - - public void c() { -+ // PaperSpigot start - Move enderchest sound handling out of the tick loop -+ /* - if (++this.h % 4 == 0) { // PaperSpigot - Reduced (20 * 4) -> 4 interval due to reduced tick rate from improved tick handling - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.g); - } -@@ -0,0 +0,0 @@ public class TileEntityEnderChest extends TileEntity implements IUpdatePlayerLis - this.a = 0.0F; - } - } -- -+ */ -+ // PaperSpigot end - } - - public boolean c(int i, int j) { -@@ -0,0 +0,0 @@ public class TileEntityEnderChest extends TileEntity implements IUpdatePlayerLis - - public void b() { - ++this.g; -+ -+ // PaperSpigot start - Move enderchest open sounds out of the tick loop -+ if (this.g > 0 && this.a == 0.0F) { -+ this.a = 0.7F; -+ -+ double d1 = (double) this.getPosition().getX() + 0.5D; -+ double d0 = (double) this.getPosition().getZ() + 0.5D; -+ -+ this.world.makeSound(d1, (double) this.getPosition().getY() + 0.5D, d0, "random.chestopen", 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); -+ } -+ // PaperSpigot end -+ - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.g); - } - - public void d() { - --this.g; -+ -+ // PaperSpigot start - Move enderchest close sounds out of the tick loop -+ if (this.g == 0 && this.a > 0.0F || this.g > 0 && this.a < 1.0F) { -+ double d0 = (double) this.getPosition().getX() + 0.5D; -+ double d2 = (double) this.getPosition().getZ() + 0.5D; -+ -+ this.world.makeSound(d0, (double) this.getPosition().getY() + 0.5D, d2, "random.chestclosed", 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); -+ this.a = 0.0F; -+ } -+ // PaperSpigot end -+ - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.g); - } - -diff --git a/src/main/java/org/github/paperspigot/WorldTileEntityList.java b/src/main/java/org/github/paperspigot/WorldTileEntityList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/github/paperspigot/WorldTileEntityList.java -+++ b/src/main/java/org/github/paperspigot/WorldTileEntityList.java -@@ -0,0 +0,0 @@ public class WorldTileEntityList extends HashSet { - TileEntityCommand.class, - TileEntitySkull.class, - TileEntityComparator.class, -- TileEntityFlowerPot.class -+ TileEntityFlowerPot.class, -+ TileEntityChest.class, -+ TileEntityEnderChest.class - }) { - put(ignored, -1); - } --- \ No newline at end of file diff --git a/Spigot-Server-Patches/Optimize-TileEntity-Ticking.patch b/Spigot-Server-Patches/Optimize-TileEntity-Ticking.patch index f0d1f5f6d3..ae080d1c33 100644 --- a/Spigot-Server-Patches/Optimize-TileEntity-Ticking.patch +++ b/Spigot-Server-Patches/Optimize-TileEntity-Ticking.patch @@ -4,75 +4,187 @@ Date: Sun, 8 Mar 2015 01:56:22 -0600 Subject: [PATCH] Optimize TileEntity Ticking -diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/TileEntity.java -+++ b/src/main/java/net/minecraft/server/TileEntity.java -@@ -0,0 +0,0 @@ public abstract class TileEntity { - private int h; - protected Block e; - -+ // PaperSpigot start - Optimized TileEntity tick changes -+ private static int tileEntityCounter = 0; -+ public boolean isAdded = false; -+ public int tileId = tileEntityCounter++; -+ // PaperSpigot end -+ - public TileEntity() { - this.position = BlockPosition.ZERO; - this.h = -1; -diff --git a/src/main/java/net/minecraft/server/TileEntityBeacon.java b/src/main/java/net/minecraft/server/TileEntityBeacon.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/TileEntityBeacon.java -+++ b/src/main/java/net/minecraft/server/TileEntityBeacon.java -@@ -0,0 +0,0 @@ public class TileEntityBeacon extends TileEntityContainer implements IUpdatePlay - public TileEntityBeacon() {} - - public void c() { -- if (this.world.getTime() % 80L == 0L) { -+ if (true || this.world.getTime() % 80L == 0L) { // PaperSpigot - Controlled by improved tick handling - this.m(); - } - diff --git a/src/main/java/net/minecraft/server/TileEntityChest.java b/src/main/java/net/minecraft/server/TileEntityChest.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/TileEntityChest.java +++ b/src/main/java/net/minecraft/server/TileEntityChest.java -@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityContainer implements IUpdatePlaye - ++this.n; - float f; +@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.entity.CraftHumanEntity; + import org.bukkit.entity.HumanEntity; + // CraftBukkit end -- if (!this.world.isClientSide && this.l != 0 && (this.n + i + j + k) % 200 == 0) { -+ if (!this.world.isClientSide && this.l != 0 && (this.n + i + j + k) % 10 == 0) { // PaperSpigot - Reduced 200 -> 10 due to reduced interval from improved tick handling - this.l = 0; - f = 5.0F; - List list = this.world.a(EntityHuman.class, new AxisAlignedBB((double) ((float) i - f), (double) ((float) j - f), (double) ((float) k - f), (double) ((float) (i + 1) + f), (double) ((float) (j + 1) + f), (double) ((float) (k + 1) + f))); +-public class TileEntityChest extends TileEntityContainer implements IUpdatePlayerListBox, IInventory { ++public class TileEntityChest extends TileEntityContainer implements IInventory { // PaperSpigot - remove IUpdatePlayerListBox + + private ItemStack[] items = new ItemStack[27]; + public boolean a; +- public TileEntityChest f; +- public TileEntityChest g; +- public TileEntityChest h; +- public TileEntityChest i; +- public float j; ++ public TileEntityChest f; // PaperSpigot - adjacentChestZNeg ++ public TileEntityChest g; // PaperSpigot - adjacentChestXPos ++ public TileEntityChest h; // PaperSpigot - adjacentChestXNeg ++ public TileEntityChest i; // PaperSpigot - adjacentChestZPos ++ public float j; // PaperSpigot - lidAngle + public float k; +- public int l; ++ public int l; // PaperSpigot - numPlayersUsing + private int n; + private int o = -1; + private String p; +@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityContainer implements IUpdatePlaye + } + + public void c() { ++ // PaperSpigot - Move chest sounds out of the tick loop ++ /* + this.m(); + int i = this.position.getX(); + int j = this.position.getY(); +@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityContainer implements IUpdatePlaye + this.j = 0.0F; + } + } +- ++ */ ++ // PaperSpigot end + } + + public boolean c(int i, int j) { +@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityContainer implements IUpdatePlaye + + ++this.l; + if (this.world == null) return; // CraftBukkit ++ ++ // PaperSpigot start - Move chest open sound out of the tick loop ++ this.m(); ++ ++ if (this.l > 0 && this.j == 0.0F && this.f == null && this.h == null) { ++ this.j = 0.7F; ++ ++ double d0 = (double) this.position.getZ() + 0.5D; ++ double d1 = (double) this.position.getX() + 0.5D; ++ ++ if (this.i != null) { ++ d0 += 0.5D; ++ } ++ ++ if (this.g != null) { ++ d1 += 0.5D; ++ } ++ ++ this.world.makeSound(d1, (double) this.position.getY() + 0.5D, d0, "random.chestopen", 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); ++ } ++ // PaperSpigot end ++ + this.world.playBlockAction(this.position, this.w(), 1, this.l); + + // CraftBukkit start - Call redstone event +@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityContainer implements IUpdatePlaye + int oldPower = Math.max(0, Math.min(15, this.l)); // CraftBukkit - Get power before new viewer is added + --this.l; + if (this.world == null) return; // CraftBukkit ++ ++ // PaperSpigot start - Move chest close sound handling out of the tick loop ++ if (this.l == 0 && this.j > 0.0F || this.l > 0 && this.j < 1.0F) { ++ float f = 0.1F; ++ ++ if (this.l > 0) { ++ this.j += f; ++ } else { ++ this.j -= f; ++ } ++ ++ double d0 = (double) this.getPosition().getX() + 0.5D; ++ double d2 = (double) this.getPosition().getZ() + 0.5D; ++ ++ if (this.i != null) { ++ d2 += 0.5D; ++ } ++ ++ if (this.g != null) { ++ d0 += 0.5D; ++ } ++ ++ this.world.makeSound(d0, (double) this.getPosition().getY() + 0.5D, d2, "random.chestclosed", 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); ++ this.j = 0.0F; ++ } ++ // PaperSpigot end ++ + this.world.playBlockAction(this.position, this.w(), 1, this.l); + + // CraftBukkit start - Call redstone event diff --git a/src/main/java/net/minecraft/server/TileEntityEnderChest.java b/src/main/java/net/minecraft/server/TileEntityEnderChest.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/TileEntityEnderChest.java +++ b/src/main/java/net/minecraft/server/TileEntityEnderChest.java -@@ -0,0 +0,0 @@ public class TileEntityEnderChest extends TileEntity implements IUpdatePlayerLis +@@ -0,0 +0,0 @@ + package net.minecraft.server; + +-public class TileEntityEnderChest extends TileEntity implements IUpdatePlayerListBox { ++public class TileEntityEnderChest extends TileEntity { // PaperSpigot - remove IUpdatePlayerListBox + +- public float a; ++ public float a; // PaperSpigot - lidAngle + public float f; +- public int g; ++ public int g; // PaperSpigot - numPlayersUsing + private int h; + public TileEntityEnderChest() {} public void c() { -- if (++this.h % 20 * 4 == 0) { -+ if (++this.h % 4 == 0) { // PaperSpigot - Reduced (20 * 4) -> 4 interval due to reduced tick rate from improved tick handling ++ // PaperSpigot start - Move enderchest sound handling out of the tick loop ++ /* + if (++this.h % 20 * 4 == 0) { this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.g); } +@@ -0,0 +0,0 @@ public class TileEntityEnderChest extends TileEntity implements IUpdatePlayerLis + this.a = 0.0F; + } + } +- ++ */ ++ // PaperSpigot end + } -diff --git a/src/main/java/net/minecraft/server/TileEntityLightDetector.java b/src/main/java/net/minecraft/server/TileEntityLightDetector.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/TileEntityLightDetector.java -+++ b/src/main/java/net/minecraft/server/TileEntityLightDetector.java -@@ -0,0 +0,0 @@ public class TileEntityLightDetector extends TileEntity implements IUpdatePlayer - public TileEntityLightDetector() {} + public boolean c(int i, int j) { +@@ -0,0 +0,0 @@ public class TileEntityEnderChest extends TileEntity implements IUpdatePlayerLis + + public void b() { + ++this.g; ++ ++ // PaperSpigot start - Move enderchest open sounds out of the tick loop ++ if (this.g > 0 && this.a == 0.0F) { ++ this.a = 0.7F; ++ ++ double d1 = (double) this.getPosition().getX() + 0.5D; ++ double d0 = (double) this.getPosition().getZ() + 0.5D; ++ ++ this.world.makeSound(d1, (double) this.getPosition().getY() + 0.5D, d0, "random.chestopen", 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); ++ } ++ // PaperSpigot end ++ + this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.g); + } + + public void d() { + --this.g; ++ ++ // PaperSpigot start - Move enderchest close sounds out of the tick loop ++ if (this.g == 0 && this.a > 0.0F || this.g > 0 && this.a < 1.0F) { ++ double d0 = (double) this.getPosition().getX() + 0.5D; ++ double d2 = (double) this.getPosition().getZ() + 0.5D; ++ ++ this.world.makeSound(d0, (double) this.getPosition().getY() + 0.5D, d2, "random.chestclosed", 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); ++ this.a = 0.0F; ++ } ++ // PaperSpigot end ++ + this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.g); + } - public void c() { -- if (this.world != null && !this.world.isClientSide && this.world.getTime() % 20L == 0L) { -+ if (this.world != null && !this.world.isClientSide /*&& this.world.getTime() % 20L == 0L*/) { // PaperSpigot - interval controlled by improved tick handling - this.e = this.w(); - if (this.e instanceof BlockDaylightDetector) { - ((BlockDaylightDetector) this.e).f(this.world, this.position); diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/World.java @@ -83,8 +195,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 { + // PaperSpigot start - move always activated entities to top of tick list + @Override -+ public boolean add(Entity e) -+ { ++ public boolean add(Entity e) { + if (e.defaultActivationState) { + super.add(0, e); + return true; @@ -97,24 +208,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public Entity remove(int index) { -@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { - // Spigot end - protected final List g = Lists.newArrayList(); - public final List h = Lists.newArrayList(); -- public final List tileEntityList = Lists.newArrayList(); -+ public final Set tileEntityList = new org.github.paperspigot.WorldTileEntityList(this); // PaperSpigot - private final List b = Lists.newArrayList(); - private final List c = Lists.newArrayList(); - public final List players = Lists.newArrayList(); -@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { - this.getServer().addWorld(this.world); - // CraftBukkit end - this.keepSpawnInMemory = this.paperSpigotConfig.keepSpawnInMemory; // PaperSpigot -- timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings -+ timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings - this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); - this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); - } @@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { guardEntityList = true; // Spigot // CraftBukkit start - Use field for loop variable @@ -134,216 +227,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (tickPosition < 0) tickPosition = 0; for (entityLimiter.initTick(); - entitiesThisCycle < entityList.size() && (entitiesThisCycle % 10 == 0 || entityLimiter.shouldContinue()); -+ entitiesThisCycle < entityList.size() && (tickPosition <= minTickIndex || entitiesThisCycle % 10 == 0 || entityLimiter.shouldContinue()); // PaperSpigot - tickPosition++, entitiesThisCycle++) { +- tickPosition++, entitiesThisCycle++) { ++ entitiesThisCycle < entityList.size() && (tickPosition <= minTickIndex || entitiesThisCycle % 10 == 0 || entityLimiter.shouldContinue()); // PaperSpigot ++ tickPosition++, entitiesThisCycle++) { tickPosition = (tickPosition < entityList.size()) ? tickPosition : 0; entity = (Entity) this.entityList.get(this.tickPosition); -@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { - this.c.clear(); - } - // CraftBukkit end -+ Iterator iterator = this.tileEntityList.iterator(); - -- // Spigot start -- int tilesThisCycle = 0; -- for (tileLimiter.initTick(); -- tilesThisCycle < tileEntityList.size() && (tilesThisCycle % 10 == 0 || tileLimiter.shouldContinue()); -- tileTickPosition++, tilesThisCycle++) { -- tileTickPosition = (tileTickPosition < tileEntityList.size()) ? tileTickPosition : 0; -- TileEntity tileentity = (TileEntity) this.tileEntityList.get(tileTickPosition); -- // Spigot start -+ while (iterator.hasNext()) { -+ TileEntity tileentity = (TileEntity) iterator.next(); - if (tileentity == null) { - getServer().getLogger().severe("Spigot has detected a null entity and has removed it, preventing a crash"); -- tilesThisCycle--; -- this.tileEntityList.remove(tileTickPosition--); -+ iterator.remove(); - continue; - } - // Spigot end -@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { - } - - if (tileentity.x()) { -- tilesThisCycle--; -- this.tileEntityList.remove(tileTickPosition--); -+ iterator.remove(); - this.h.remove(tileentity); - if (this.isLoaded(tileentity.getPosition())) { - this.getChunkAtWorldCoords(tileentity.getPosition()).e(tileentity.getPosition()); -diff --git a/src/main/java/org/github/paperspigot/WorldTileEntityList.java b/src/main/java/org/github/paperspigot/WorldTileEntityList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/org/github/paperspigot/WorldTileEntityList.java -@@ -0,0 +0,0 @@ -+package org.github.paperspigot; -+ -+import com.google.common.collect.ArrayListMultimap; -+import com.google.common.collect.Maps; -+import com.google.common.collect.Multimap; -+import net.minecraft.server.*; -+import gnu.trove.map.hash.TObjectIntHashMap; -+ -+import java.util.Collection; -+import java.util.HashSet; -+import java.util.Iterator; -+import java.util.Map; -+ -+public class WorldTileEntityList extends HashSet { -+ private static final TObjectIntHashMap> tileEntityTickIntervals = -+ new TObjectIntHashMap>() {{ -+ // Use -1 for no ticking -+ // These TE's have empty tick methods, doing nothing. Never bother ticking them. -+ for (Class ignored : new Class[]{ -+ BlockJukeBox.TileEntityRecordPlayer.class, -+ TileEntityDispenser.class, -+ TileEntityDropper.class, -+ TileEntitySign.class, -+ TileEntityNote.class, -+ TileEntityEnderPortal.class, -+ TileEntityCommand.class, -+ TileEntitySkull.class, -+ TileEntityComparator.class, -+ TileEntityFlowerPot.class -+ }) { -+ put(ignored, -1); -+ } -+ -+ // does findPlayer lookup, so this helps performance to slow down -+ put(TileEntityEnchantTable.class, 20); -+ -+ // Vanilla controlled values - These are checks already done in vanilla, so don't tick on ticks we know -+ // won't do anything anyways -+ put(TileEntityBeacon.class, 80); -+ put(TileEntityLightDetector.class, 20); -+ }}; -+ -+ private static int getInterval(Class cls) { -+ int tickInterval = tileEntityTickIntervals.get(cls); -+ return tickInterval != 0 ? tickInterval : 1; -+ } -+ -+ private static int getBucketId(TileEntity entity, Integer interval) { -+ return entity.tileId % interval; -+ } -+ -+ private final Map> tickList = Maps.newHashMap(); -+ private final WorldServer world; -+ -+ public WorldTileEntityList(World world) { -+ this.world = (WorldServer) world; -+ } -+ -+ -+ private Multimap getBucket(int interval) { -+ Multimap intervalBucket = tickList.get(interval); -+ if (intervalBucket == null) { -+ intervalBucket = ArrayListMultimap.create(); -+ tickList.put(interval, intervalBucket); -+ } -+ return intervalBucket; -+ } -+ -+ /** -+ * Adds the TileEntity to the tick list only if it is expected to tick -+ */ -+ @Override -+ public boolean add(TileEntity entity) { -+ if (entity.isAdded) { -+ return false; -+ } -+ -+ int interval = getInterval(entity.getClass()); -+ if (interval > 0) { -+ entity.isAdded = true; -+ int bucket = getBucketId(entity, interval); -+ Multimap typeBucket = getBucket(interval); -+ return typeBucket.put(bucket, entity); -+ } -+ return false; -+ } -+ -+ @Override -+ public boolean remove(Object o) { -+ if (!(o instanceof TileEntity)) { -+ return false; -+ } -+ TileEntity entity = (TileEntity) o; -+ if (!entity.isAdded) { -+ return false; -+ } -+ entity.isAdded = false; -+ int interval = getInterval(entity.getClass()); -+ int bucket = getBucketId(entity, interval); -+ Multimap typeBucket = getBucket(interval); -+ return typeBucket.remove(bucket, entity); -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return new WorldTileEntityIterator(); -+ } -+ -+ @Override -+ public boolean contains(Object o) { -+ return o instanceof TileEntity && ((TileEntity) o).isAdded; -+ } -+ -+ private class WorldTileEntityIterator implements Iterator { -+ private final Iterator>> intervalIterator; -+ private Map.Entry> intervalMap = null; -+ private Iterator listIterator = null; -+ -+ protected WorldTileEntityIterator() { -+ intervalIterator = tickList.entrySet().iterator(); -+ nextInterval(); -+ } -+ -+ private boolean nextInterval() { -+ listIterator = null; -+ if (intervalIterator.hasNext()) { -+ intervalMap = intervalIterator.next(); -+ -+ final Integer interval = intervalMap.getKey(); -+ final Multimap buckets = intervalMap.getValue(); -+ -+ int bucket = (int) (world.getTime() % interval); -+ -+ if (!buckets.isEmpty() && buckets.containsKey(bucket)) { -+ final Collection tileList = buckets.get(bucket); -+ -+ if (tileList != null && !tileList.isEmpty()) { -+ listIterator = tileList.iterator(); -+ return true; -+ } -+ } -+ } -+ -+ return false; -+ -+ } -+ -+ @Override -+ public boolean hasNext() { -+ do { -+ if (listIterator != null && listIterator.hasNext()) { -+ return true; -+ } -+ } while (nextInterval()); -+ return false; -+ } -+ -+ @Override -+ public TileEntity next() { -+ return listIterator.next(); -+ } -+ -+ @Override -+ public void remove() { -+ listIterator.remove(); -+ } -+ } -+} + // CraftBukkit end -- \ No newline at end of file diff --git a/Spigot-Server-Patches/Prevent-tile-entity-and-entity-crashes.patch b/Spigot-Server-Patches/Prevent-tile-entity-and-entity-crashes.patch index 0c656539ef..998fce06c1 100644 --- a/Spigot-Server-Patches/Prevent-tile-entity-and-entity-crashes.patch +++ b/Spigot-Server-Patches/Prevent-tile-entity-and-entity-crashes.patch @@ -57,7 +57,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + tileentity.tickTimer.stopTiming(); + System.err.println("TileEntity threw exception at " + tileentity.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ()); + throwable2.printStackTrace(); -+ iterator.remove(); ++ tilesThisCycle--; ++ this.tileEntityList.remove(tileTickPosition--); + continue; + // PaperSpigot end }