From b94f2b8159418cf8cc2adf2aeb5512264d01c2d1 Mon Sep 17 00:00:00 2001 From: md_5 Date: Tue, 2 Jul 2013 15:12:49 +1000 Subject: [PATCH] Clean nibble arrays patch Packet51 to fix crash bug mentioned by Drumming102 on IRC. --- CraftBukkit-Patches/0002-mc-dev-imports.patch | 194 ++++++++++++++- .../0014-Compressed-Nibble-Arrays.patch | 221 +++--------------- 2 files changed, 231 insertions(+), 184 deletions(-) diff --git a/CraftBukkit-Patches/0002-mc-dev-imports.patch b/CraftBukkit-Patches/0002-mc-dev-imports.patch index 7d24344492..687ff8a2e2 100644 --- a/CraftBukkit-Patches/0002-mc-dev-imports.patch +++ b/CraftBukkit-Patches/0002-mc-dev-imports.patch @@ -1,4 +1,4 @@ -From d4173f0bd000a1152b28e206169701f250ffc058 Mon Sep 17 00:00:00 2001 +From 1817f378de2afb1a34f322d26f9c40e7a9cc31ca Mon Sep 17 00:00:00 2001 From: md_5 Date: Tue, 2 Jul 2013 13:13:29 +1000 Subject: [PATCH] mc-dev imports @@ -376,6 +376,198 @@ index 0000000..9afa795 + return this.a == 0; + } +} +diff --git a/src/main/java/net/minecraft/server/Packet51MapChunk.java b/src/main/java/net/minecraft/server/Packet51MapChunk.java +new file mode 100644 +index 0000000..4e67e27 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/Packet51MapChunk.java +@@ -0,0 +1,186 @@ ++package net.minecraft.server; ++ ++import java.io.DataInput; ++import java.io.DataOutput; ++import java.io.IOException; ++import java.util.zip.DataFormatException; ++import java.util.zip.Deflater; ++import java.util.zip.Inflater; ++ ++public class Packet51MapChunk extends Packet { ++ ++ public int a; ++ public int b; ++ public int c; ++ public int d; ++ private byte[] buffer; ++ private byte[] inflatedBuffer; ++ public boolean e; ++ private int size; ++ private static byte[] buildBuffer = new byte[196864]; ++ ++ public Packet51MapChunk() { ++ this.lowPriority = true; ++ } ++ ++ public Packet51MapChunk(Chunk chunk, boolean flag, int i) { ++ this.lowPriority = true; ++ this.a = chunk.x; ++ this.b = chunk.z; ++ this.e = flag; ++ ChunkMap chunkmap = a(chunk, flag, i); ++ Deflater deflater = new Deflater(-1); ++ ++ this.d = chunkmap.c; ++ this.c = chunkmap.b; ++ ++ try { ++ this.inflatedBuffer = chunkmap.a; ++ deflater.setInput(chunkmap.a, 0, chunkmap.a.length); ++ deflater.finish(); ++ this.buffer = new byte[chunkmap.a.length]; ++ this.size = deflater.deflate(this.buffer); ++ } finally { ++ deflater.end(); ++ } ++ } ++ ++ public void a(DataInput datainput) throws java.io.IOException { // Spigot - throws ++ this.a = datainput.readInt(); ++ this.b = datainput.readInt(); ++ this.e = datainput.readBoolean(); ++ this.c = datainput.readShort(); ++ this.d = datainput.readShort(); ++ this.size = datainput.readInt(); ++ if (buildBuffer.length < this.size) { ++ buildBuffer = new byte[this.size]; ++ } ++ ++ datainput.readFully(buildBuffer, 0, this.size); ++ int i = 0; ++ ++ int j; ++ ++ for (j = 0; j < 16; ++j) { ++ i += this.c >> j & 1; ++ } ++ ++ j = 12288 * i; ++ if (this.e) { ++ j += 256; ++ } ++ ++ this.inflatedBuffer = new byte[j]; ++ Inflater inflater = new Inflater(); ++ ++ inflater.setInput(buildBuffer, 0, this.size); ++ ++ try { ++ inflater.inflate(this.inflatedBuffer); ++ } catch (DataFormatException dataformatexception) { ++ throw new IOException("Bad compressed data format"); ++ } finally { ++ inflater.end(); ++ } ++ } ++ ++ public void a(DataOutput dataoutput) throws java.io.IOException { // Spigot - throws ++ dataoutput.writeInt(this.a); ++ dataoutput.writeInt(this.b); ++ dataoutput.writeBoolean(this.e); ++ dataoutput.writeShort((short) (this.c & '\uffff')); ++ dataoutput.writeShort((short) (this.d & '\uffff')); ++ dataoutput.writeInt(this.size); ++ dataoutput.write(this.buffer, 0, this.size); ++ } ++ ++ public void handle(Connection connection) { ++ connection.a(this); ++ } ++ ++ public int a() { ++ return 17 + this.size; ++ } ++ ++ public static ChunkMap a(Chunk chunk, boolean flag, int i) { ++ int j = 0; ++ ChunkSection[] achunksection = chunk.i(); ++ int k = 0; ++ ChunkMap chunkmap = new ChunkMap(); ++ byte[] abyte = buildBuffer; ++ ++ if (flag) { ++ chunk.seenByPlayer = true; ++ } ++ ++ int l; ++ ++ for (l = 0; l < achunksection.length; ++l) { ++ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { ++ chunkmap.b |= 1 << l; ++ if (achunksection[l].getExtendedIdArray() != null) { ++ chunkmap.c |= 1 << l; ++ ++k; ++ } ++ } ++ } ++ ++ for (l = 0; l < achunksection.length; ++l) { ++ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { ++ byte[] abyte1 = achunksection[l].getIdArray(); ++ ++ System.arraycopy(abyte1, 0, abyte, j, abyte1.length); ++ j += abyte1.length; ++ } ++ } ++ ++ NibbleArray nibblearray; ++ ++ for (l = 0; l < achunksection.length; ++l) { ++ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { ++ nibblearray = achunksection[l].getDataArray(); ++ System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); ++ j += nibblearray.a.length; ++ } ++ } ++ ++ for (l = 0; l < achunksection.length; ++l) { ++ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { ++ nibblearray = achunksection[l].getEmittedLightArray(); ++ System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); ++ j += nibblearray.a.length; ++ } ++ } ++ ++ if (!chunk.world.worldProvider.g) { ++ for (l = 0; l < achunksection.length; ++l) { ++ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { ++ nibblearray = achunksection[l].getSkyLightArray(); ++ System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); ++ j += nibblearray.a.length; ++ } ++ } ++ } ++ ++ if (k > 0) { ++ for (l = 0; l < achunksection.length; ++l) { ++ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && achunksection[l].getExtendedIdArray() != null && (i & 1 << l) != 0) { ++ nibblearray = achunksection[l].getExtendedIdArray(); ++ System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); ++ j += nibblearray.a.length; ++ } ++ } ++ } ++ ++ if (flag) { ++ byte[] abyte2 = chunk.m(); ++ ++ System.arraycopy(abyte2, 0, abyte, j, abyte2.length); ++ j += abyte2.length; ++ } ++ ++ chunkmap.a = new byte[j]; ++ System.arraycopy(abyte, 0, chunkmap.a, 0, j); ++ return chunkmap; ++ } ++} diff --git a/src/main/java/net/minecraft/server/Packet63WorldParticles.java b/src/main/java/net/minecraft/server/Packet63WorldParticles.java new file mode 100644 index 0000000..f036c53 diff --git a/CraftBukkit-Patches/0014-Compressed-Nibble-Arrays.patch b/CraftBukkit-Patches/0014-Compressed-Nibble-Arrays.patch index 11a5b4d9e5..81257da814 100644 --- a/CraftBukkit-Patches/0014-Compressed-Nibble-Arrays.patch +++ b/CraftBukkit-Patches/0014-Compressed-Nibble-Arrays.patch @@ -1,4 +1,4 @@ -From 004bae243fac61ac72370588bbbe248a767f80c7 Mon Sep 17 00:00:00 2001 +From 4a04b15cf84b0ae02d738271808890199f735331 Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Sun, 13 Jan 2013 03:49:07 -0800 Subject: [PATCH] Compressed Nibble Arrays @@ -271,209 +271,64 @@ index 53c1cb5..9a9e20f 100644 } } diff --git a/src/main/java/net/minecraft/server/Packet51MapChunk.java b/src/main/java/net/minecraft/server/Packet51MapChunk.java -new file mode 100644 -index 0000000..b7b4fd6 ---- /dev/null +index 4e67e27..fa10397 100644 +--- a/src/main/java/net/minecraft/server/Packet51MapChunk.java +++ b/src/main/java/net/minecraft/server/Packet51MapChunk.java -@@ -0,0 +1,198 @@ -+package net.minecraft.server; -+ -+import java.io.DataInput; -+import java.io.DataOutput; -+import java.io.IOException; -+import java.util.zip.DataFormatException; -+import java.util.zip.Deflater; -+import java.util.zip.Inflater; -+ -+public class Packet51MapChunk extends Packet { -+ -+ public int a; -+ public int b; -+ public int c; -+ public int d; -+ private byte[] buffer; -+ private byte[] inflatedBuffer; -+ public boolean e; -+ private int size; -+ private static byte[] buildBuffer = new byte[196864]; -+ -+ public Packet51MapChunk() { -+ this.lowPriority = true; -+ } -+ -+ public Packet51MapChunk(Chunk chunk, boolean flag, int i) { -+ this.lowPriority = true; -+ this.a = chunk.x; -+ this.b = chunk.z; -+ this.e = flag; -+ ChunkMap chunkmap = a(chunk, flag, i); -+ Deflater deflater = new Deflater(-1); -+ -+ this.d = chunkmap.c; -+ this.c = chunkmap.b; -+ -+ try { -+ this.inflatedBuffer = chunkmap.a; -+ deflater.setInput(chunkmap.a, 0, chunkmap.a.length); -+ deflater.finish(); -+ this.buffer = new byte[chunkmap.a.length]; -+ this.size = deflater.deflate(this.buffer); -+ } finally { -+ deflater.end(); -+ } -+ } -+ -+ public void a(DataInput datainput) throws IOException { // CraftBukkit - throws IOException -+ this.a = datainput.readInt(); -+ this.b = datainput.readInt(); -+ this.e = datainput.readBoolean(); -+ this.c = datainput.readShort(); -+ this.d = datainput.readShort(); -+ this.size = datainput.readInt(); -+ if (buildBuffer.length < this.size) { -+ buildBuffer = new byte[this.size]; -+ } -+ -+ datainput.readFully(buildBuffer, 0, this.size); -+ int i = 0; -+ -+ int j; -+ -+ for (j = 0; j < 16; ++j) { -+ i += this.c >> j & 1; -+ } -+ -+ j = 12288 * i; -+ if (this.e) { -+ j += 256; -+ } -+ -+ this.inflatedBuffer = new byte[j]; -+ Inflater inflater = new Inflater(); -+ -+ inflater.setInput(buildBuffer, 0, this.size); -+ -+ try { -+ inflater.inflate(this.inflatedBuffer); -+ } catch (DataFormatException dataformatexception) { -+ throw new IOException("Bad compressed data format"); -+ } finally { -+ inflater.end(); -+ } -+ } -+ -+ public void a(DataOutput dataoutput) throws IOException { // CraftBukkit - throws IOException -+ dataoutput.writeInt(this.a); -+ dataoutput.writeInt(this.b); -+ dataoutput.writeBoolean(this.e); -+ dataoutput.writeShort((short) (this.c & '\uffff')); -+ dataoutput.writeShort((short) (this.d & '\uffff')); -+ dataoutput.writeInt(this.size); -+ dataoutput.write(this.buffer, 0, this.size); -+ } -+ -+ public void handle(Connection connection) { -+ connection.a(this); -+ } -+ -+ public int a() { -+ return 17 + this.size; -+ } -+ -+ public static ChunkMap a(Chunk chunk, boolean flag, int i) { -+ int j = 0; -+ ChunkSection[] achunksection = chunk.i(); -+ int k = 0; -+ ChunkMap chunkmap = new ChunkMap(); -+ byte[] abyte = buildBuffer; -+ -+ if (flag) { -+ chunk.seenByPlayer = true; -+ } -+ -+ int l; -+ -+ for (l = 0; l < achunksection.length; ++l) { -+ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { -+ chunkmap.b |= 1 << l; -+ if (achunksection[l].getExtendedIdArray() != null) { -+ chunkmap.c |= 1 << l; -+ ++k; -+ } -+ } -+ } -+ -+ for (l = 0; l < achunksection.length; ++l) { -+ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { -+ byte[] abyte1 = achunksection[l].getIdArray(); -+ -+ System.arraycopy(abyte1, 0, abyte, j, abyte1.length); -+ j += abyte1.length; -+ } -+ } -+ -+ NibbleArray nibblearray; -+ -+ for (l = 0; l < achunksection.length; ++l) { -+ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { -+ nibblearray = achunksection[l].getDataArray(); +@@ -139,16 +139,22 @@ public class Packet51MapChunk extends Packet { + for (l = 0; l < achunksection.length; ++l) { + if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { + nibblearray = achunksection[l].getDataArray(); +- System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); +- j += nibblearray.a.length; + // Spigot start + // System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); + // j += nibblearray.a.length; + j = nibblearray.copyToByteArray(abyte, j); + // Spigot end -+ } -+ } -+ -+ for (l = 0; l < achunksection.length; ++l) { -+ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { -+ nibblearray = achunksection[l].getEmittedLightArray(); + } + } + + for (l = 0; l < achunksection.length; ++l) { + if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { + nibblearray = achunksection[l].getEmittedLightArray(); +- System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); +- j += nibblearray.a.length; + // Spigot start + // System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); + // j += nibblearray.a.length; + j = nibblearray.copyToByteArray(abyte, j); + // Spigot end -+ } -+ } -+ -+ if (!chunk.world.worldProvider.f) { -+ for (l = 0; l < achunksection.length; ++l) { -+ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { -+ nibblearray = achunksection[l].getSkyLightArray(); + } + } + +@@ -156,8 +162,11 @@ public class Packet51MapChunk extends Packet { + for (l = 0; l < achunksection.length; ++l) { + if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && (i & 1 << l) != 0) { + nibblearray = achunksection[l].getSkyLightArray(); +- System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); +- j += nibblearray.a.length; + // Spigot start + // System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); + // j += nibblearray.a.length; + j = nibblearray.copyToByteArray(abyte, j); + // Spigot end -+ } -+ } -+ } -+ -+ if (k > 0) { -+ for (l = 0; l < achunksection.length; ++l) { -+ if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && achunksection[l].getExtendedIdArray() != null && (i & 1 << l) != 0) { -+ nibblearray = achunksection[l].getExtendedIdArray(); + } + } + } +@@ -166,8 +175,11 @@ public class Packet51MapChunk extends Packet { + for (l = 0; l < achunksection.length; ++l) { + if (achunksection[l] != null && (!flag || !achunksection[l].isEmpty()) && achunksection[l].getExtendedIdArray() != null && (i & 1 << l) != 0) { + nibblearray = achunksection[l].getExtendedIdArray(); +- System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); +- j += nibblearray.a.length; + // Spigot start + //System.arraycopy(nibblearray.a, 0, abyte, j, nibblearray.a.length); + //j += nibblearray.a.length; + j = nibblearray.copyToByteArray(abyte, j); + // Spigot end -+ } -+ } -+ } -+ -+ if (flag) { -+ byte[] abyte2 = chunk.m(); -+ -+ System.arraycopy(abyte2, 0, abyte, j, abyte2.length); -+ j += abyte2.length; -+ } -+ -+ chunkmap.a = new byte[j]; -+ System.arraycopy(abyte, 0, chunkmap.a, 0, j); -+ return chunkmap; -+ } -+} + } + } + } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java index 1a21516..6921206 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java