It appears to cause visual glitching issues with certain TNT entities fired from cannons. TileEntity tick capping has already been removed for some time, Entity tick capping removal is new to this patch.
267 lines
11 KiB
Diff
267 lines
11 KiB
Diff
From 4104e547b01f6511a1c7a87a5eef7322e4a83878 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
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 c268a40..1971941 100644
|
|
--- a/src/main/java/net/minecraft/server/TileEntity.java
|
|
+++ b/src/main/java/net/minecraft/server/TileEntity.java
|
|
@@ -21,6 +21,12 @@ 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 4f280dd..3ea1b62 100644
|
|
--- a/src/main/java/net/minecraft/server/TileEntityBeacon.java
|
|
+++ b/src/main/java/net/minecraft/server/TileEntityBeacon.java
|
|
@@ -48,7 +48,7 @@ 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 189fa93..07891ec 100644
|
|
--- a/src/main/java/net/minecraft/server/TileEntityChest.java
|
|
+++ b/src/main/java/net/minecraft/server/TileEntityChest.java
|
|
@@ -246,7 +246,7 @@ public class TileEntityChest extends TileEntityContainer implements IUpdatePlaye
|
|
++this.n;
|
|
float f;
|
|
|
|
- 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)));
|
|
diff --git a/src/main/java/net/minecraft/server/TileEntityEnderChest.java b/src/main/java/net/minecraft/server/TileEntityEnderChest.java
|
|
index 794cdc8..f712885 100644
|
|
--- a/src/main/java/net/minecraft/server/TileEntityEnderChest.java
|
|
+++ b/src/main/java/net/minecraft/server/TileEntityEnderChest.java
|
|
@@ -10,7 +10,7 @@ public class TileEntityEnderChest extends TileEntity implements IUpdatePlayerLis
|
|
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
|
|
this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.g);
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/TileEntityLightDetector.java b/src/main/java/net/minecraft/server/TileEntityLightDetector.java
|
|
index f75e2de..7119612 100644
|
|
--- a/src/main/java/net/minecraft/server/TileEntityLightDetector.java
|
|
+++ b/src/main/java/net/minecraft/server/TileEntityLightDetector.java
|
|
@@ -5,7 +5,7 @@ public class TileEntityLightDetector extends TileEntity implements IUpdatePlayer
|
|
public TileEntityLightDetector() {}
|
|
|
|
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 bdf4896..67c739e 100644
|
|
--- a/src/main/java/net/minecraft/server/World.java
|
|
+++ b/src/main/java/net/minecraft/server/World.java
|
|
@@ -53,7 +53,7 @@ public abstract class World implements IBlockAccess {
|
|
// Spigot end
|
|
protected final List<Entity> g = Lists.newArrayList();
|
|
public final List<TileEntity> h = Lists.newArrayList();
|
|
- public final List<TileEntity> tileEntityList = Lists.newArrayList();
|
|
+ public final Set<TileEntity> tileEntityList = new org.github.paperspigot.WorldTileEntityList(this); // PaperSpigot
|
|
private final List<TileEntity> b = Lists.newArrayList();
|
|
private final List<TileEntity> c = Lists.newArrayList();
|
|
public final List<EntityHuman> players = Lists.newArrayList();
|
|
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 0000000..5af5dcc
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/github/paperspigot/WorldTileEntityList.java
|
|
@@ -0,0 +1,168 @@
|
|
+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<TileEntity> {
|
|
+ private static final TObjectIntHashMap<Class<? extends TileEntity>> tileEntityTickIntervals =
|
|
+ new TObjectIntHashMap<Class<? extends TileEntity>>() {{
|
|
+ // Use -1 for no ticking
|
|
+ // These TE's have empty tick methods, doing nothing. Never bother ticking them.
|
|
+ for (Class<? extends TileEntity> 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<? extends TileEntity> 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<Integer, Multimap<Integer, TileEntity>> tickList = Maps.newHashMap();
|
|
+ private final WorldServer world;
|
|
+
|
|
+ public WorldTileEntityList(World world) {
|
|
+ this.world = (WorldServer) world;
|
|
+ }
|
|
+
|
|
+
|
|
+ private Multimap<Integer, TileEntity> getBucket(int interval) {
|
|
+ Multimap<Integer, TileEntity> 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<Integer, TileEntity> 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<Integer, TileEntity> 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<TileEntity> {
|
|
+ private final Iterator<Map.Entry<Integer, Multimap<Integer, TileEntity>>> intervalIterator;
|
|
+ private Map.Entry<Integer, Multimap<Integer, TileEntity>> intervalMap = null;
|
|
+ private Iterator<TileEntity> 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<Integer, TileEntity> buckets = intervalMap.getValue();
|
|
+
|
|
+ int bucket = (int) (world.getTime() % interval);
|
|
+
|
|
+ if (!buckets.isEmpty() && buckets.containsKey(bucket)) {
|
|
+ final Collection<TileEntity> 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();
|
|
+ }
|
|
+ }
|
|
+}
|
|
\ No newline at end of file
|
|
--
|
|
2.4.1.windows.1
|
|
|