PaperMC/nms-patches/ChunkRegionLoader.patch
Thinkofdeath fdfadd23d0 Fix a vanilla issue which causes invalid data values on blocks to turn to air
Worlds already loaded in 1.8 can still be saved by this but tile entities will
be lost
2014-11-29 17:31:40 +00:00

157 lines
6.5 KiB
Diff

--- ../work/decompile-8eb82bde//net/minecraft/server/ChunkRegionLoader.java 2014-11-29 17:31:14.897318138 +0000
+++ src/main/java/net/minecraft/server/ChunkRegionLoader.java 2014-11-29 17:31:08.453318281 +0000
@@ -23,8 +23,40 @@
public ChunkRegionLoader(File file) {
this.e = file;
}
+
+ // CraftBukkit start
+ public boolean chunkExists(World world, int i, int j) {
+ ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i, j);
+ synchronized (this.d) {
+ if (this.c.contains(chunkcoordintpair)) {
+ for (int k = 0; k < this.b.size(); ++k) {
+ if (((PendingChunkToSave) this.b.get(k)).a.equals(chunkcoordintpair)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return RegionFileCache.a(this.e, i, j).chunkExists(i & 31, j & 31);
+ }
+ // CraftBukkit end
+
+ // CraftBukkit start - Add async variant, provide compatibility
public Chunk a(World world, int i, int j) {
+ Object[] data = loadChunk(world, i, j);
+ if (data != null) {
+ Chunk chunk = (Chunk) data[0];
+ NBTTagCompound nbttagcompound = (NBTTagCompound) data[1];
+ loadEntities(chunk, nbttagcompound.getCompound("Level"), world);
+ return chunk;
+ }
+
+ return null;
+ }
+
+ public Object[] loadChunk(World world, int i, int j) {
+ // CraftBukkit end
NBTTagCompound nbttagcompound = null;
ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i, j);
Object object = this.d;
@@ -53,7 +85,7 @@
return this.a(world, i, j, nbttagcompound);
}
- protected Chunk a(World world, int i, int j, NBTTagCompound nbttagcompound) {
+ protected Object[] a(World world, int i, int j, NBTTagCompound nbttagcompound) { // CraftBukkit - return Chunk -> Object[]
if (!nbttagcompound.hasKeyOfType("Level", 10)) {
ChunkRegionLoader.a.error("Chunk file at " + i + "," + j + " is missing level data, skipping");
return null;
@@ -64,18 +96,42 @@
Chunk chunk = this.a(world, nbttagcompound.getCompound("Level"));
if (!chunk.a(i, j)) {
- ChunkRegionLoader.a.error("Chunk file at " + i + "," + j + " is in the wrong location; relocating. (Expected " + i + ", " + j + ", got " + chunk.locX + ", " + chunk.locZ + ")");
- nbttagcompound.setInt("xPos", i);
- nbttagcompound.setInt("zPos", j);
+ a.error("Chunk file at " + i + "," + j + " is in the wrong location; relocating. (Expected " + i + ", " + j + ", got " + chunk.locX + ", " + chunk.locZ + ")");
+ nbttagcompound.getCompound("Level").setInt("xPos", i);
+ nbttagcompound.getCompound("Level").setInt("zPos", j);
+
+ // CraftBukkit start - Have to move tile entities since we don't load them at this stage
+ NBTTagList tileEntities = nbttagcompound.getCompound("Level").getList("TileEntities", 10);
+ if (tileEntities != null) {
+ for (int te = 0; te < tileEntities.size(); te++) {
+ NBTTagCompound tileEntity = (NBTTagCompound) tileEntities.get(te);
+ int x = tileEntity.getInt("x") - chunk.locX * 16;
+ int z = tileEntity.getInt("z") - chunk.locZ * 16;
+ tileEntity.setInt("x", i * 16 + x);
+ tileEntity.setInt("z", j * 16 + z);
+ }
+ }
+ // CraftBukkit end
chunk = this.a(world, nbttagcompound.getCompound("Level"));
}
- return chunk;
+ // CraftBukkit start
+ Object[] data = new Object[2];
+ data[0] = chunk;
+ data[1] = nbttagcompound;
+ return data;
+ // CraftBukkit end
}
}
public void a(World world, Chunk chunk) {
- world.checkSession();
+ // CraftBukkit start - "handle" exception
+ try {
+ world.checkSession();
+ } catch (ExceptionWorldConflict ex) {
+ ex.printStackTrace();
+ }
+ // CraftBukkit end
try {
NBTTagCompound nbttagcompound = new NBTTagCompound();
@@ -133,7 +189,7 @@
return true;
}
- public void a(PendingChunkToSave pendingchunktosave) {
+ public void a(PendingChunkToSave pendingchunktosave) throws java.io.IOException { // CraftBukkit - added throws
DataOutputStream dataoutputstream = RegionFileCache.d(this.e, pendingchunktosave.a.x, pendingchunktosave.a.z);
NBTCompressedStreamTools.a(pendingchunktosave.b, (DataOutput) dataoutputstream);
@@ -302,8 +358,23 @@
int j1 = l >> 8 & 15;
int k1 = l >> 4 & 15;
int l1 = nibblearray1 != null ? nibblearray1.a(i1, j1, k1) : 0;
-
- achar[l] = (char) (l1 << 12 | (abyte[l] & 255) << 4 | nibblearray.a(i1, j1, k1));
+
+ // CraftBukkit start - fix broken blocks
+ // achar[l] = (char) (l1 << 12 | (abyte[l] & 255) << 4 | nibblearray.a(i1, j1, k1));
+
+ int ex = l1;
+ int id = (abyte[l] & 255);
+ int data = nibblearray.a(i1, j1, k1);
+ int packed = ex << 12 | id << 4 | data;
+ if (Block.d.a(packed) == null) {
+ Block block = Block.getById(ex << 8 | id);
+ if (block != null) {
+ data = block.toLegacyData(block.fromLegacyData(data));
+ packed = ex << 12 | id << 4 | data;
+ }
+ }
+ achar[l] = (char) packed;
+ // CraftBukkit end
}
chunksection.a(achar);
@@ -320,7 +391,13 @@
if (nbttagcompound.hasKeyOfType("Biomes", 7)) {
chunk.a(nbttagcompound.getByteArray("Biomes"));
}
+
+ // CraftBukkit start - End this method here and split off entity loading to another method
+ return chunk;
+ }
+ public void loadEntities(Chunk chunk, NBTTagCompound nbttagcompound, World world) {
+ // CraftBukkit end
NBTTagList nbttaglist1 = nbttagcompound.getList("Entities", 10);
if (nbttaglist1 != null) {
@@ -379,6 +456,6 @@
}
}
- return chunk;
+ // return chunk; // CraftBukkit
}
}