papermc/Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch
2019-04-23 10:35:52 +01:00

194 lines
8 KiB
Diff

From b62193df23ee54b4b15077fd0ac4939003ac99aa 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 417c015e56..95a51ab745 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -36,7 +36,7 @@ public class Chunk implements IChunkAccess {
private final BiomeBase[] f;
private final boolean[] g;
private final Map<BlockPosition, NBTTagCompound> h;
- private boolean i;
+ private boolean i;public boolean isLoaded() { return i; } // Paper - OBFHELPER
public final World world;
public final Map<HeightMap.Type, HeightMap> heightMap;
public final int locX;
@@ -66,7 +66,30 @@ public class Chunk implements IChunkAccess {
// CraftBukkit start - Neighbor loaded cache for chunk lighting and entity ticking
private int neighbors = 0x1 << 12;
public long chunkKey;
+ // 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 boolean areNeighborsLoaded(final int radius) {
switch (radius) {
case 2:
@@ -97,7 +120,7 @@ public class Chunk implements IChunkAccess {
this.g = new boolean[256];
this.h = Maps.newHashMap();
this.heightMap = Maps.newEnumMap(HeightMap.Type.class);
- this.tileEntities = Maps.newHashMap();
+ this.tileEntities = new TileEntityHashMap(); // Paper
this.p = Maps.newHashMap();
this.q = Maps.newHashMap();
this.r = new ShortList[16];
@@ -653,6 +676,7 @@ public class Chunk implements IChunkAccess {
}
entity.inChunk = true;
+ entity.setCurrentChunk(this); // Paper
entity.chunkX = this.locX;
entity.chunkY = k;
entity.chunkZ = this.locZ;
@@ -663,6 +687,7 @@ public class Chunk implements IChunkAccess {
((HeightMap) this.heightMap.get(heightmap_type)).a(along);
}
+ public void removeEntity(Entity entity) { this.b(entity); } // Paper - OBFHELPER
public void b(Entity entity) {
this.a(entity, entity.chunkY);
}
@@ -675,8 +700,12 @@ public class Chunk implements IChunkAccess {
if (i >= this.entitySlices.length) {
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
}
public boolean c(BlockPosition blockposition) {
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index d9c9748cec..bdb4ca7643 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -132,7 +132,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
private static final DataWatcherObject<Boolean> aF = DataWatcher.a(Entity.class, DataWatcherRegistry.i);
private static final DataWatcherObject<Boolean> aG = DataWatcher.a(Entity.class, DataWatcherRegistry.i);
private static final DataWatcherObject<Boolean> aH = DataWatcher.a(Entity.class, DataWatcherRegistry.i);
- public boolean inChunk;
+ public boolean inChunk; public boolean isAddedToChunk() { return inChunk; } // Paper - OBFHELPER
public int chunkX; public int getChunkX() { return chunkX; } // Paper - OBFHELPER
public int chunkY; public int getChunkY() { return chunkY; } // Paper - OBFHELPER
public int chunkZ; public int getChunkZ() { return chunkZ; } // Paper - OBFHELPER
@@ -1776,6 +1776,39 @@ 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;
+ return chunk != null && chunk.isLoaded() ? chunk : (isAddedToChunk() ? world.getChunkIfLoaded(getChunkX(), getChunkZ()) : null);
+ }
+ /**
+ * Returns the chunk at the location, using the entities local cache if avail
+ * Will only return null if the location specified is not loaded
+ */
+ public Chunk getCurrentChunkAt(int x, int z) {
+ if (getChunkX() == x && getChunkZ() == z) {
+ Chunk chunk = getCurrentChunk();
+ if (chunk != null) {
+ return chunk;
+ }
+ }
+ return world.getChunkIfLoaded(x, z);
+ }
+ /**
+ * Returns the chunk at the entities current location, using the entities local cache if avail
+ * Will only return null if the location specified is not loaded
+ */
+ public Chunk getChunkAtLocation() {
+ return getCurrentChunkAt((int)Math.floor(locX) >> 4, (int)Math.floor(locZ) >> 4);
+ }
+
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 7390061bf0..c69209497b 100644
--- a/src/main/java/net/minecraft/server/TileEntity.java
+++ b/src/main/java/net/minecraft/server/TileEntity.java
@@ -41,6 +41,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.isLoaded() ? 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 9cdd0331f4..7edbbb106b 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -9,6 +9,7 @@ import java.util.UUID;
import net.minecraft.server.*;
+import org.bukkit.Chunk;
import org.bukkit.EntityEffect;
import org.bukkit.Location;
import org.bukkit.Server;
@@ -44,6 +45,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
--
2.21.0