Paper/Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch
Aikar e4d10a6d67
Updated Upstream (Bukkit/CraftBukkit)
Upstream has released updates that appears to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
122289ff Add FaceAttachable interface to handle Grindstone facing in common with Switches
a6db750e SPIGOT-5647: ZombieVillager entity should have getVillagerType()

CraftBukkit Changes:
bbe3d58e SPIGOT-5650: Lectern.setPage(int) causes a NullPointerException
3075579f Add FaceAttachable interface to handle Grindstone facing in common with Switches
95bd4238 SPIGOT-5647: ZombieVillager entity should have getVillagerType()
4d975ac3 SPIGOT-5617: setBlockData does not work when NotPlayEvent is called by redstone current
2020-04-02 17:09:17 -04:00

205 lines
8.9 KiB
Diff

From 3cf32449e02bb6944e4ec14734cbc3f96f2e3168 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 af10c18d44..02b142fe8b 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -29,7 +29,7 @@ public class Chunk implements IChunkAccess {
private final ChunkSection[] sections;
private BiomeStorage d;
private final Map<BlockPosition, NBTTagCompound> e;
- public boolean loaded;
+ public boolean loaded; public boolean isLoaded() { return loaded; } // Paper - OBFHELPER
public final World world;
public final Map<HeightMap.Type, HeightMap> heightMap;
private final ChunkConverter i;
@@ -55,11 +55,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];
@@ -366,6 +391,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;
@@ -378,6 +404,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);
}
@@ -391,7 +418,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 7899fd6d88..2890e8121d 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -134,7 +134,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
private static final DataWatcherObject<Boolean> aB = DataWatcher.a(Entity.class, DataWatcherRegistry.i);
private static final DataWatcherObject<Boolean> aC = DataWatcher.a(Entity.class, DataWatcherRegistry.i);
protected static final DataWatcherObject<EntityPose> POSE = DataWatcher.a(Entity.class, DataWatcherRegistry.s);
- 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
@@ -178,7 +178,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
@@ -1708,6 +1708,43 @@ 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.isLoaded()) {
+ return chunk;
+ }
+
+ return !isAddedToChunk() ? null : ((ChunkProviderServer) world.chunkProvider).getChunkAtIfLoadedMainThreadNoCache(getChunkX(), getChunkZ());
+ }
+
+ /**
+ * 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) {
+ Chunk chunk = getCurrentChunk();
+ if (chunk != null && getChunkX() == chunk.getPos().x && getChunkZ() == chunk.getPos().z) {
+ return chunk;
+ }
+ return ((ChunkProviderServer) world.chunkProvider).getChunkAtIfLoadedMainThreadNoCache(getChunkX(), getChunkZ());
+ }
+ /**
+ * Returns the chunk at the entities current location, using the entities local cache if avail
+ * Ideally this is always the same as getCurrentChunk, but only becomes different in registration issues.
+ * 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 9071bb7ece..820180ab3f 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.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 63ecbcd47a..c82c213260 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -138,6 +138,7 @@ import net.minecraft.server.EntityZombieVillager;
import net.minecraft.server.EnumChatFormat;
import net.minecraft.server.IChatBaseComponent;
import net.minecraft.server.NBTTagCompound;
+import org.bukkit.Chunk; // Paper
import org.bukkit.EntityEffect;
import org.bukkit.Location;
import org.bukkit.Server;
@@ -179,6 +180,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.25.1