Fetch tile entities from chunks instead of world. Fixes BUKKIT-4055

When looking up tile entities for a chunk to send to a player we currently
loop through every tile entity in the world checking if it is within the
bounds of the relevant chunk. Instead of doing this we can just use the
tile entities list stored in the chunk to avoid this costly searching.

As a further optimization, we also modify the generic range-based lookup
to use chunks as well. For most lookups this will give a smaller search
pool which will result in faster lookups.

Thanks to @mikeprimm for the idea and most of the implementation.
This commit is contained in:
Travis Watkins 2013-04-11 18:08:44 -05:00 committed by Wesley Wolfe
parent 70a778f475
commit ce5b97ea83
2 changed files with 19 additions and 9 deletions

View File

@ -173,8 +173,11 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
iterator1.remove(); iterator1.remove();
if (chunkcoordintpair != null && this.world.isLoaded(chunkcoordintpair.x << 4, 0, chunkcoordintpair.z << 4)) { if (chunkcoordintpair != null && this.world.isLoaded(chunkcoordintpair.x << 4, 0, chunkcoordintpair.z << 4)) {
arraylist.add(this.world.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z)); // CraftBukkit start - Get tile entities directly from the chunk instead of the world
arraylist1.addAll(((WorldServer) this.world).getTileEntities(chunkcoordintpair.x * 16, 0, chunkcoordintpair.z * 16, chunkcoordintpair.x * 16 + 16, 256, chunkcoordintpair.z * 16 + 16)); Chunk chunk = this.world.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z);
arraylist.add(chunk);
arraylist1.addAll(chunk.tileEntities.values());
// CraftBukkit end
} }
} }

View File

@ -643,17 +643,24 @@ public class WorldServer extends World implements org.bukkit.BlockChangeDelegate
public List getTileEntities(int i, int j, int k, int l, int i1, int j1) { public List getTileEntities(int i, int j, int k, int l, int i1, int j1) {
ArrayList arraylist = new ArrayList(); ArrayList arraylist = new ArrayList();
// CraftBukkit start - Use iterator
Iterator iterator = this.tileEntityList.iterator();
while (iterator.hasNext()) { // CraftBukkit start - Get tile entities from chunks instead of world
TileEntity tileentity = (TileEntity) iterator.next(); for (int chunkX = (i >> 4); chunkX <= ((l - 1) >> 4); chunkX++) {
// CraftBukkit end for (int chunkZ = (k >> 4); chunkZ <= ((j1 - 1) >> 4); chunkZ++) {
Chunk chunk = getChunkAt(chunkX, chunkZ);
if (chunk == null) {
continue;
}
if (tileentity.x >= i && tileentity.y >= j && tileentity.z >= k && tileentity.x < l && tileentity.y < i1 && tileentity.z < j1) { for (Object te : chunk.tileEntities.values()) {
TileEntity tileentity = (TileEntity) te;
if ((tileentity.x >= i) && (tileentity.y >= j) && (tileentity.z >= k) && (tileentity.x < l) && (tileentity.y < i1) && (tileentity.z < j1)) {
arraylist.add(tileentity); arraylist.add(tileentity);
} }
} }
}
}
// CraftBukkit end
return arraylist; return arraylist;
} }