When moving a misplaced chunk move tile entities too. Fixes BUKKIT-4092

When a chunk is being loaded the server checks to ensure the chunk's idea
of where it is located matches where it was located in the region file. If
these two values do not match the chunk's idea of its position is updated
and the chunk is reloaded. In vanilla minecraft this loading involves the
chunk's tile entities as well. With the change to loading player chunks
asynchronously we split loading tile entities to a separate step that takes
place after this check. Because of this tile entities are loaded with
invalid locations that result in trying to fetch block data from negative
or too large positions in the chunk's internal block storage arrays.

Because loading the tile entities is not thread safe we cannot return to
vanilla behavior here. Instead when we detect a misplaced chunk we just
edit the NBT data for the chunk to relocate the tile entities. This results
in them moving correctly with the chunk without having to actually load
them first.
This commit is contained in:
Travis Watkins 2013-04-15 15:10:11 -05:00
parent 0ab14dbaad
commit 928e4d9bbb

View file

@ -97,6 +97,20 @@ public class ChunkRegionLoader implements IAsyncChunkSaver, IChunkLoader {
world.getLogger().severe("Chunk file at " + i + "," + j + " is in the wrong location; relocating. (Expected " + i + ", " + j + ", got " + chunk.x + ", " + chunk.z + ")"); world.getLogger().severe("Chunk file at " + i + "," + j + " is in the wrong location; relocating. (Expected " + i + ", " + j + ", got " + chunk.x + ", " + chunk.z + ")");
nbttagcompound.getCompound("Level").setInt("xPos", i); // CraftBukkit - .getCompound("Level") nbttagcompound.getCompound("Level").setInt("xPos", i); // CraftBukkit - .getCompound("Level")
nbttagcompound.getCompound("Level").setInt("zPos", j); // CraftBukkit - .getCompound("Level") nbttagcompound.getCompound("Level").setInt("zPos", j); // CraftBukkit - .getCompound("Level")
// CraftBukkit start - Have to move tile entities since we don't load them at this stage
NBTTagList tileEntities = nbttagcompound.getCompound("Level").getList("TileEntities");
if (tileEntities != null) {
for (int te = 0; te < tileEntities.size(); te++) {
NBTTagCompound tileEntity = (NBTTagCompound) tileEntities.get(te);
int x = tileEntity.getInt("x") - chunk.x * 16;
int z = tileEntity.getInt("z") - chunk.z * 16;
tileEntity.setInt("x", i * 16 + x);
tileEntity.setInt("z", j * 16 + z);
}
}
// CraftBukkit end
chunk = this.a(world, nbttagcompound.getCompound("Level")); chunk = this.a(world, nbttagcompound.getCompound("Level"));
} }