mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-23 09:27:45 +01:00
4768e3c4ed
Reduces number of instructions a chunk lookup does when accessing the last chunk cache. This reduces amount of work and opcodes and allows better inlining. In lots of profiling comparisons, this optimization was able to reduce the cost of repeated chunk lookups that hit the cache pretty significantly.
164 lines
6.9 KiB
Diff
164 lines
6.9 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
Date: Wed, 4 Jul 2018 02:10:36 -0400
|
|
Subject: [PATCH] Store reference to current Chunk for Entity and Block
|
|
Entities
|
|
|
|
This enables us a fast reference to the entities current chunk instead
|
|
of having to look it up by hashmap lookups.
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
|
|
index 8d5598fab64ce3ac58121302dca4b528edd26563..402f6ed90132f48d560a21f56cd50121c42fb34a 100644
|
|
--- a/src/main/java/net/minecraft/server/Chunk.java
|
|
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
|
@@ -56,11 +56,36 @@ public class Chunk implements IChunkAccess {
|
|
this(world, chunkcoordintpair, biomestorage, ChunkConverter.a, TickListEmpty.b(), TickListEmpty.b(), 0L, (ChunkSection[]) null, (Consumer) null);
|
|
}
|
|
|
|
+ // Paper start
|
|
+ private class TileEntityHashMap extends java.util.HashMap<BlockPosition, TileEntity> {
|
|
+ @Override
|
|
+ public TileEntity put(BlockPosition key, TileEntity value) {
|
|
+ TileEntity replaced = super.put(key, value);
|
|
+ if (replaced != null) {
|
|
+ replaced.setCurrentChunk(null);
|
|
+ }
|
|
+ if (value != null) {
|
|
+ value.setCurrentChunk(Chunk.this);
|
|
+ }
|
|
+ return replaced;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public TileEntity remove(Object key) {
|
|
+ TileEntity removed = super.remove(key);
|
|
+ if (removed != null) {
|
|
+ removed.setCurrentChunk(null);
|
|
+ }
|
|
+ return removed;
|
|
+ }
|
|
+ }
|
|
+ // Paper end
|
|
+
|
|
public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage, ChunkConverter chunkconverter, TickList<Block> ticklist, TickList<FluidType> ticklist1, long i, @Nullable ChunkSection[] achunksection, @Nullable Consumer<Chunk> consumer) {
|
|
this.sections = new ChunkSection[16];
|
|
this.e = Maps.newHashMap();
|
|
this.heightMap = Maps.newEnumMap(HeightMap.Type.class);
|
|
- this.tileEntities = Maps.newHashMap();
|
|
+ this.tileEntities = new TileEntityHashMap(); // Paper
|
|
this.l = Maps.newHashMap();
|
|
this.m = Maps.newHashMap();
|
|
this.n = new ShortList[16];
|
|
@@ -470,6 +495,7 @@ public class Chunk implements IChunkAccess {
|
|
}
|
|
|
|
entity.inChunk = true;
|
|
+ entity.setCurrentChunk(this); // Paper
|
|
entity.chunkX = this.loc.x;
|
|
entity.chunkY = k;
|
|
entity.chunkZ = this.loc.z;
|
|
@@ -482,6 +508,7 @@ public class Chunk implements IChunkAccess {
|
|
((HeightMap) this.heightMap.get(heightmap_type)).a(along);
|
|
}
|
|
|
|
+ public final void removeEntity(Entity entity) { this.b(entity); } // Paper - OBFHELPER
|
|
public void b(Entity entity) {
|
|
this.a(entity, entity.chunkY);
|
|
}
|
|
@@ -495,7 +522,12 @@ public class Chunk implements IChunkAccess {
|
|
i = this.entitySlices.length - 1;
|
|
}
|
|
|
|
- this.entitySlices[i].remove(entity);
|
|
+ // Paper start
|
|
+ if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null);
|
|
+ if (!this.entitySlices[i].remove(entity)) {
|
|
+ return;
|
|
+ }
|
|
+ // Paper end
|
|
this.entities.remove(entity); // Paper
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
|
|
index f6b97eec33ace01077e6bca58f3c11978422ac47..5e0db989a0f6c7c7041a968550f4068b9a946136 100644
|
|
--- a/src/main/java/net/minecraft/server/Entity.java
|
|
+++ b/src/main/java/net/minecraft/server/Entity.java
|
|
@@ -176,7 +176,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
|
|
}
|
|
|
|
public boolean isChunkLoaded() {
|
|
- return world.isChunkLoaded((int) Math.floor(this.locX()) >> 4, (int) Math.floor(this.locZ()) >> 4);
|
|
+ return getCurrentChunk() != null;
|
|
}
|
|
// CraftBukkit end
|
|
|
|
@@ -1678,6 +1678,23 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
|
|
}
|
|
|
|
// Paper start
|
|
+ java.lang.ref.WeakReference<Chunk> currentChunk = null;
|
|
+
|
|
+ public void setCurrentChunk(Chunk chunk) {
|
|
+ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null;
|
|
+ }
|
|
+ /**
|
|
+ * Returns the entities current registered chunk. If the entity is not added to a chunk yet, it will return null
|
|
+ */
|
|
+ public Chunk getCurrentChunk() {
|
|
+ final Chunk chunk = currentChunk != null ? currentChunk.get() : null;
|
|
+ if (chunk != null && chunk.loaded) {
|
|
+ return chunk;
|
|
+ }
|
|
+
|
|
+ return !inChunk ? null : ((WorldServer)world).getChunkProvider().getChunkAtIfLoadedMainThreadNoCache(chunkX, chunkZ);
|
|
+ }
|
|
+
|
|
private MinecraftKey entityKey;
|
|
private String entityKeyString;
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java
|
|
index b8f0653e3e82824a62dfe64348a33ab6432b4e17..b9ffd000c97111678d45fd55dc9c207ebadc140e 100644
|
|
--- a/src/main/java/net/minecraft/server/TileEntity.java
|
|
+++ b/src/main/java/net/minecraft/server/TileEntity.java
|
|
@@ -51,6 +51,15 @@ public abstract class TileEntity implements KeyedObject { // Paper
|
|
getMinecraftKey(); // Try to load if it doesn't exists.
|
|
return tileEntityKeyString;
|
|
}
|
|
+
|
|
+ private java.lang.ref.WeakReference<Chunk> currentChunk = null;
|
|
+ public Chunk getCurrentChunk() {
|
|
+ final Chunk chunk = currentChunk != null ? currentChunk.get() : null;
|
|
+ return chunk != null && chunk.loaded ? chunk : null;
|
|
+ }
|
|
+ public void setCurrentChunk(Chunk chunk) {
|
|
+ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null;
|
|
+ }
|
|
// Paper end
|
|
|
|
@Nullable
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
|
index 2770441b13cb993b222c6bf31c11711f001b74c0..db7c4011c8b90b6daca2b48a6d9ec447d31f7197 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
|
@@ -145,6 +145,7 @@ import net.minecraft.server.EntityZombieVillager;
|
|
import net.minecraft.server.IChatBaseComponent;
|
|
import net.minecraft.server.NBTBase;
|
|
import net.minecraft.server.NBTTagCompound;
|
|
+import org.bukkit.Chunk; // Paper
|
|
import org.bukkit.EntityEffect;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.Server;
|
|
@@ -186,6 +187,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
|
this.entity = entity;
|
|
}
|
|
|
|
+ @Override
|
|
+ public Chunk getChunk() {
|
|
+ net.minecraft.server.Chunk currentChunk = entity.getCurrentChunk();
|
|
+ return currentChunk != null ? currentChunk.bukkitChunk : getLocation().getChunk();
|
|
+ }
|
|
+
|
|
public static CraftEntity getEntity(CraftServer server, Entity entity) {
|
|
/*
|
|
* Order is *EXTREMELY* important -- keep it right! =D
|