From 457607720da6bbcd7840fd6a0501bac2a7880b87 Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Thu, 6 Sep 2018 17:56:21 -0500 Subject: [PATCH] Fix handling of JEIDS, shift to 1.13 style state for chunk ss --- .../dynmap/forge_1_10_2/ChunkSnapshot.java | 153 +++++++------- .../dynmap/forge_1_11_2/ChunkSnapshot.java | 76 ++++--- .../dynmap/forge_1_12_2/ChunkSnapshot.java | 76 ++++--- .../org/dynmap/forge_1_8_9/ChunkSnapshot.java | 198 +++++++----------- .../org/dynmap/forge_1_9_4/ChunkSnapshot.java | 153 +++++++------- 5 files changed, 320 insertions(+), 336 deletions(-) diff --git a/forge-1.10.2/src/main/java/org/dynmap/forge_1_10_2/ChunkSnapshot.java b/forge-1.10.2/src/main/java/org/dynmap/forge_1_10_2/ChunkSnapshot.java index e1779f6e..50960202 100644 --- a/forge-1.10.2/src/main/java/org/dynmap/forge_1_10_2/ChunkSnapshot.java +++ b/forge-1.10.2/src/main/java/org/dynmap/forge_1_10_2/ChunkSnapshot.java @@ -18,8 +18,7 @@ import scala.actors.threadpool.Arrays; public class ChunkSnapshot { private final int x, z; - private final short[][] blockids; /* Block IDs, by section */ - private final byte[][] blockdata; + private final int[][] blockidx; /* Block state index, by section */ private final byte[][] skylight; private final byte[][] emitlight; private final boolean[] empty; @@ -31,10 +30,9 @@ public class ChunkSnapshot private static final int BLOCKS_PER_SECTION = 16 * 16 * 16; private static final int COLUMNS_PER_CHUNK = 16 * 16; - private static final short[] emptyIDs = new short[BLOCKS_PER_SECTION]; + private static final int[] emptyIdx = new int[BLOCKS_PER_SECTION]; private static final byte[] emptyData = new byte[BLOCKS_PER_SECTION / 2]; private static final byte[] fullData = new byte[BLOCKS_PER_SECTION / 2]; - private static Method getvalarray = null; static { @@ -42,16 +40,6 @@ public class ChunkSnapshot { fullData[i] = (byte)0xFF; } - try { - Method[] m = NibbleArray.class.getDeclaredMethods(); - for (Method mm : m) { - if (mm.getName().equals("getValueArray")) { - getvalarray = mm; - break; - } - } - } catch (Exception x) { - } } /** @@ -68,8 +56,7 @@ public class ChunkSnapshot this.biome = new int[COLUMNS_PER_CHUNK]; this.sectionCnt = worldheight / 16; /* Allocate arrays indexed by section */ - this.blockids = new short[this.sectionCnt][]; - this.blockdata = new byte[this.sectionCnt][]; + this.blockidx = new int[this.sectionCnt][]; this.skylight = new byte[this.sectionCnt][]; this.emitlight = new byte[this.sectionCnt][]; this.empty = new boolean[this.sectionCnt]; @@ -78,8 +65,7 @@ public class ChunkSnapshot for (int i = 0; i < this.sectionCnt; i++) { this.empty[i] = true; - this.blockids[i] = emptyIDs; - this.blockdata[i] = emptyData; + this.blockidx[i] = emptyIdx; this.emitlight[i] = emptyData; this.skylight[i] = fullData; } @@ -103,16 +89,14 @@ public class ChunkSnapshot this.inhabitedTicks = 0; } /* Allocate arrays indexed by section */ - this.blockids = new short[this.sectionCnt][]; - this.blockdata = new byte[this.sectionCnt][]; + this.blockidx = new int[this.sectionCnt][]; this.skylight = new byte[this.sectionCnt][]; this.emitlight = new byte[this.sectionCnt][]; this.empty = new boolean[this.sectionCnt]; /* Fill with empty data */ for (int i = 0; i < this.sectionCnt; i++) { this.empty[i] = true; - this.blockids[i] = emptyIDs; - this.blockdata[i] = emptyData; + this.blockidx[i] = emptyIdx; this.emitlight[i] = emptyData; this.skylight[i] = fullData; } @@ -125,41 +109,73 @@ public class ChunkSnapshot Log.info("Section " + (int) secnum + " above world height " + worldheight); continue; } - byte[] lsb_bytes = sec.getByteArray("Blocks"); - short[] blkids = new short[BLOCKS_PER_SECTION]; - this.blockids[secnum] = blkids; - int len = BLOCKS_PER_SECTION; - if(len > lsb_bytes.length) len = lsb_bytes.length; - for(int j = 0; j < len; j++) { - blkids[j] = (short)(0xFF & lsb_bytes[j]); - } - if (sec.hasKey("Add")) { /* If additional data, add it */ - byte[] msb = sec.getByteArray("Add"); - len = BLOCKS_PER_SECTION / 2; - if(len > msb.length) len = msb.length; - for (int j = 0; j < len; j++) { - short b = (short)(msb[j] & 0xFF); - if (b == 0) { - continue; - } - blkids[j << 1] |= (b & 0x0F) << 8; - blkids[(j << 1) + 1] |= (b & 0xF0) << 4; + int[] blkidxs = new int[BLOCKS_PER_SECTION]; + this.blockidx[secnum] = blkidxs; + // JEI format + if (sec.hasKey("Palette", 11)) { + int[] p = sec.getIntArray("Palette"); + // Palette is list of state values, where Blocks=bit 11-4 of index, Data=bit 3-0 + byte[] msb_bytes = sec.getByteArray("Blocks"); + int mlen = msb_bytes.length / 2; + byte[] lsb_bytes = sec.getByteArray("Data"); + int llen = BLOCKS_PER_SECTION / 2; + if (llen > lsb_bytes.length) llen = lsb_bytes.length; + for(int j = 0; j < llen; j++) { + int idx = lsb_bytes[j] & 0xF; + int idx2 = (lsb_bytes[j] & 0xF0) >>> 4; + if (j < mlen) { + idx += (255 & msb_bytes[2*j]) << 4; + idx2 += (255 & msb_bytes[2*j+1]) << 4; + } + // Get even block id + blkidxs[2*j] = (idx < p.length) ? p[idx] : 0; + // Get odd block id + blkidxs[2*j+1] = (idx2 < p.length) ? p[idx2] : 0; } } - if (sec.hasKey("Add2")) { /* If additional data (NEID), add it */ - byte[] msb = sec.getByteArray("Add2"); - len = BLOCKS_PER_SECTION / 2; - if(len > msb.length) len = msb.length; - for (int j = 0; j < len; j++) { - short b = (short)(msb[j] & 0xFF); - if (b == 0) { - continue; - } - blkids[j << 1] |= (b & 0x0F) << 12; - blkids[(j << 1) + 1] |= (b & 0xF0) << 8; - } + else { + byte[] lsb_bytes = sec.getByteArray("Blocks"); + int len = BLOCKS_PER_SECTION; + if(len > lsb_bytes.length) len = lsb_bytes.length; + for(int j = 0; j < len; j++) { + blkidxs[j] = (0xFF & lsb_bytes[j]) << 4; + } + if (sec.hasKey("Add", 7)) { /* If additional data, add it */ + byte[] msb = sec.getByteArray("Add"); + len = BLOCKS_PER_SECTION / 2; + if(len > msb.length) len = msb.length; + for (int j = 0; j < len; j++) { + short b = (short)(msb[j] & 0xFF); + if (b == 0) { + continue; + } + blkidxs[j << 1] |= (b & 0x0F) << 12; + blkidxs[(j << 1) + 1] |= (b & 0xF0) << 8; + } + } + if (sec.hasKey("Add2", 7)) { /* If additional data (NEID), add it */ + byte[] msb = sec.getByteArray("Add2"); + len = BLOCKS_PER_SECTION / 2; + if(len > msb.length) len = msb.length; + for (int j = 0; j < len; j++) { + short b = (short)(msb[j] & 0xFF); + if (b == 0) { + continue; + } + blkidxs[j << 1] |= (b & 0x0F) << 16; + blkidxs[(j << 1) + 1] |= (b & 0xF0) << 12; + } + } + byte[] bd = sec.getByteArray("Data"); + for (int j = 0; j < bd.length; j++) { + int b = bd[j] & 0xFF; + if (b == 0) { + continue; + } + blkidxs[j << 1] |= b & 0x0F; + blkidxs[(j << 1) + 1] |= (b & 0xF0) >> 4; + } } - this.blockdata[secnum] = sec.getByteArray("Data"); this.emitlight[secnum] = sec.getByteArray("BlockLight"); if (sec.hasKey("SkyLight")) { this.skylight[secnum] = sec.getByteArray("SkyLight"); @@ -172,32 +188,22 @@ public class ChunkSnapshot byte[] b = nbt.getByteArray("Biomes"); if (b != null) { for (int i = 0; i < b.length; i++) { - this.biome[i] = 255 & b[i]; + int bv = 255 & b[i]; + this.biome[i] = (bv == 255) ? 0 : bv; } } else { // Check JEI biomes int[] bb = nbt.getIntArray("Biomes"); if (bb != null) { for (int i = 0; i < bb.length; i++) { - this.biome[i] = bb[i]; + int bv = bb[i]; + this.biome[i] = (bv < 0) ? 0 : bv; } } } } } - private static byte[] getValueArray(NibbleArray na) { - if(getvalarray != null) { - try { - return (byte[])getvalarray.invoke(na); - } catch (IllegalArgumentException e) { - } catch (IllegalAccessException e) { - } catch (InvocationTargetException e) { - } - } - return na.getData(); - } - public int getX() { return x; @@ -210,21 +216,18 @@ public class ChunkSnapshot public int getBlockTypeId(int x, int y, int z) { - return blockids[y >> 4][((y & 0xF) << 8) | (z << 4) | x]; + return blockidx[y >> 4][((y & 0xF) << 8) | (z << 4) | x] >> 4; } public int getBlockData(int x, int y, int z) { - int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1); - return (blockdata[y >> 4][off] >> ((x & 1) << 2)) & 0xF; + return blockidx[y >> 4][((y & 0xF) << 8) | (z << 4) | x] & 0xF; } public DynmapBlockState getBlockType(int x, int y, int z) { - int id = blockids[y >> 4][((y & 0xF) << 8) | (z << 4) | x]; - int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1); - int dat = (blockdata[y >> 4][off] >> ((x & 1) << 2)) & 0xF; - return DynmapPlugin.stateByID[(id << 4) + dat]; + int id = blockidx[y >> 4][((y & 0xF) << 8) | (z << 4) | x]; + return DynmapPlugin.stateByID[id]; } public int getBlockSkyLight(int x, int y, int z) diff --git a/forge-1.11.2/src/main/java/org/dynmap/forge_1_11_2/ChunkSnapshot.java b/forge-1.11.2/src/main/java/org/dynmap/forge_1_11_2/ChunkSnapshot.java index 185c6104..ebbbe602 100644 --- a/forge-1.11.2/src/main/java/org/dynmap/forge_1_11_2/ChunkSnapshot.java +++ b/forge-1.11.2/src/main/java/org/dynmap/forge_1_11_2/ChunkSnapshot.java @@ -13,8 +13,7 @@ import net.minecraft.nbt.NBTTagList; public class ChunkSnapshot { private final int x, z; - private final short[][] blockids; /* Block IDs, by section */ - private final byte[][] blockdata; + private final int[][] blockidx; /* Block state index, by section */ private final byte[][] skylight; private final byte[][] emitlight; private final boolean[] empty; @@ -26,7 +25,7 @@ public class ChunkSnapshot private static final int BLOCKS_PER_SECTION = 16 * 16 * 16; private static final int COLUMNS_PER_CHUNK = 16 * 16; - private static final short[] emptyIDs = new short[BLOCKS_PER_SECTION]; + private static final int[] emptyIdx = new int[BLOCKS_PER_SECTION]; private static final byte[] emptyData = new byte[BLOCKS_PER_SECTION / 2]; private static final byte[] fullData = new byte[BLOCKS_PER_SECTION / 2]; @@ -52,8 +51,7 @@ public class ChunkSnapshot this.biome = new int[COLUMNS_PER_CHUNK]; this.sectionCnt = worldheight / 16; /* Allocate arrays indexed by section */ - this.blockids = new short[this.sectionCnt][]; - this.blockdata = new byte[this.sectionCnt][]; + this.blockidx = new int[this.sectionCnt][]; this.skylight = new byte[this.sectionCnt][]; this.emitlight = new byte[this.sectionCnt][]; this.empty = new boolean[this.sectionCnt]; @@ -62,8 +60,7 @@ public class ChunkSnapshot for (int i = 0; i < this.sectionCnt; i++) { this.empty[i] = true; - this.blockids[i] = emptyIDs; - this.blockdata[i] = emptyData; + this.blockidx[i] = emptyIdx; this.emitlight[i] = emptyData; this.skylight[i] = fullData; } @@ -87,16 +84,14 @@ public class ChunkSnapshot this.inhabitedTicks = 0; } /* Allocate arrays indexed by section */ - this.blockids = new short[this.sectionCnt][]; - this.blockdata = new byte[this.sectionCnt][]; + this.blockidx = new int[this.sectionCnt][]; this.skylight = new byte[this.sectionCnt][]; this.emitlight = new byte[this.sectionCnt][]; this.empty = new boolean[this.sectionCnt]; /* Fill with empty data */ for (int i = 0; i < this.sectionCnt; i++) { this.empty[i] = true; - this.blockids[i] = emptyIDs; - this.blockdata[i] = emptyData; + this.blockidx[i] = emptyIdx; this.emitlight[i] = emptyData; this.skylight[i] = fullData; } @@ -109,18 +104,28 @@ public class ChunkSnapshot Log.info("Section " + (int) secnum + " above world height " + worldheight); continue; } - short[] blkids = new short[BLOCKS_PER_SECTION]; - this.blockids[secnum] = blkids; + int[] blkidxs = new int[BLOCKS_PER_SECTION]; + this.blockidx[secnum] = blkidxs; // JEI format if (sec.hasKey("Palette", 11)) { - byte[] bd = new byte[BLOCKS_PER_SECTION / 2]; int[] p = sec.getIntArray("Palette"); - this.blockdata[secnum] = bd; - int len = BLOCKS_PER_SECTION; - if(len > p.length) len = p.length; - for(int j = 0; j < len; j++) { - blkids[j] = (short)((p[j] >> 4) & 0xFFFF); - bd[j / 2] |= (p[j] & 0xF) << (4 * (j&1)); + // Palette is list of state values, where Blocks=bit 11-4 of index, Data=bit 3-0 + byte[] msb_bytes = sec.getByteArray("Blocks"); + int mlen = msb_bytes.length / 2; + byte[] lsb_bytes = sec.getByteArray("Data"); + int llen = BLOCKS_PER_SECTION / 2; + if (llen > lsb_bytes.length) llen = lsb_bytes.length; + for(int j = 0; j < llen; j++) { + int idx = lsb_bytes[j] & 0xF; + int idx2 = (lsb_bytes[j] & 0xF0) >>> 4; + if (j < mlen) { + idx += (255 & msb_bytes[2*j]) << 4; + idx2 += (255 & msb_bytes[2*j+1]) << 4; + } + // Get even block id + blkidxs[2*j] = (idx < p.length) ? p[idx] : 0; + // Get odd block id + blkidxs[2*j+1] = (idx2 < p.length) ? p[idx2] : 0; } } else { @@ -128,7 +133,7 @@ public class ChunkSnapshot int len = BLOCKS_PER_SECTION; if(len > lsb_bytes.length) len = lsb_bytes.length; for(int j = 0; j < len; j++) { - blkids[j] = (short)(0xFF & lsb_bytes[j]); + blkidxs[j] = (0xFF & lsb_bytes[j]) << 4; } if (sec.hasKey("Add", 7)) { /* If additional data, add it */ byte[] msb = sec.getByteArray("Add"); @@ -139,8 +144,8 @@ public class ChunkSnapshot if (b == 0) { continue; } - blkids[j << 1] |= (b & 0x0F) << 8; - blkids[(j << 1) + 1] |= (b & 0xF0) << 4; + blkidxs[j << 1] |= (b & 0x0F) << 12; + blkidxs[(j << 1) + 1] |= (b & 0xF0) << 8; } } if (sec.hasKey("Add2", 7)) { /* If additional data (NEID), add it */ @@ -152,11 +157,19 @@ public class ChunkSnapshot if (b == 0) { continue; } - blkids[j << 1] |= (b & 0x0F) << 12; - blkids[(j << 1) + 1] |= (b & 0xF0) << 8; + blkidxs[j << 1] |= (b & 0x0F) << 16; + blkidxs[(j << 1) + 1] |= (b & 0xF0) << 12; } } - this.blockdata[secnum] = sec.getByteArray("Data"); + byte[] bd = sec.getByteArray("Data"); + for (int j = 0; j < bd.length; j++) { + int b = bd[j] & 0xFF; + if (b == 0) { + continue; + } + blkidxs[j << 1] |= b & 0x0F; + blkidxs[(j << 1) + 1] |= (b & 0xF0) >> 4; + } } this.emitlight[secnum] = sec.getByteArray("BlockLight"); if (sec.hasKey("SkyLight")) { @@ -198,21 +211,18 @@ public class ChunkSnapshot public int getBlockTypeId(int x, int y, int z) { - return blockids[y >> 4][((y & 0xF) << 8) | (z << 4) | x]; + return blockidx[y >> 4][((y & 0xF) << 8) | (z << 4) | x] >> 4; } public int getBlockData(int x, int y, int z) { - int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1); - return (blockdata[y >> 4][off] >> ((x & 1) << 2)) & 0xF; + return blockidx[y >> 4][((y & 0xF) << 8) | (z << 4) | x] & 0xF; } public DynmapBlockState getBlockType(int x, int y, int z) { - int id = blockids[y >> 4][((y & 0xF) << 8) | (z << 4) | x]; - int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1); - int dat = (blockdata[y >> 4][off] >> ((x & 1) << 2)) & 0xF; - return DynmapPlugin.stateByID[(id << 4) + dat]; + int id = blockidx[y >> 4][((y & 0xF) << 8) | (z << 4) | x]; + return DynmapPlugin.stateByID[id]; } public int getBlockSkyLight(int x, int y, int z) diff --git a/forge-1.12.2/src/main/java/org/dynmap/forge_1_12_2/ChunkSnapshot.java b/forge-1.12.2/src/main/java/org/dynmap/forge_1_12_2/ChunkSnapshot.java index ff98942c..c6037222 100644 --- a/forge-1.12.2/src/main/java/org/dynmap/forge_1_12_2/ChunkSnapshot.java +++ b/forge-1.12.2/src/main/java/org/dynmap/forge_1_12_2/ChunkSnapshot.java @@ -13,8 +13,7 @@ import net.minecraft.nbt.NBTTagList; public class ChunkSnapshot { private final int x, z; - private final short[][] blockids; /* Block IDs, by section */ - private final byte[][] blockdata; + private final int[][] blockidx; /* Block state index, by section */ private final byte[][] skylight; private final byte[][] emitlight; private final boolean[] empty; @@ -26,7 +25,7 @@ public class ChunkSnapshot private static final int BLOCKS_PER_SECTION = 16 * 16 * 16; private static final int COLUMNS_PER_CHUNK = 16 * 16; - private static final short[] emptyIDs = new short[BLOCKS_PER_SECTION]; + private static final int[] emptyIdx = new int[BLOCKS_PER_SECTION]; private static final byte[] emptyData = new byte[BLOCKS_PER_SECTION / 2]; private static final byte[] fullData = new byte[BLOCKS_PER_SECTION / 2]; @@ -52,8 +51,7 @@ public class ChunkSnapshot this.biome = new int[COLUMNS_PER_CHUNK]; this.sectionCnt = worldheight / 16; /* Allocate arrays indexed by section */ - this.blockids = new short[this.sectionCnt][]; - this.blockdata = new byte[this.sectionCnt][]; + this.blockidx = new int[this.sectionCnt][]; this.skylight = new byte[this.sectionCnt][]; this.emitlight = new byte[this.sectionCnt][]; this.empty = new boolean[this.sectionCnt]; @@ -62,8 +60,7 @@ public class ChunkSnapshot for (int i = 0; i < this.sectionCnt; i++) { this.empty[i] = true; - this.blockids[i] = emptyIDs; - this.blockdata[i] = emptyData; + this.blockidx[i] = emptyIdx; this.emitlight[i] = emptyData; this.skylight[i] = fullData; } @@ -87,16 +84,14 @@ public class ChunkSnapshot this.inhabitedTicks = 0; } /* Allocate arrays indexed by section */ - this.blockids = new short[this.sectionCnt][]; - this.blockdata = new byte[this.sectionCnt][]; + this.blockidx = new int[this.sectionCnt][]; this.skylight = new byte[this.sectionCnt][]; this.emitlight = new byte[this.sectionCnt][]; this.empty = new boolean[this.sectionCnt]; /* Fill with empty data */ for (int i = 0; i < this.sectionCnt; i++) { this.empty[i] = true; - this.blockids[i] = emptyIDs; - this.blockdata[i] = emptyData; + this.blockidx[i] = emptyIdx; this.emitlight[i] = emptyData; this.skylight[i] = fullData; } @@ -109,18 +104,28 @@ public class ChunkSnapshot Log.info("Section " + (int) secnum + " above world height " + worldheight); continue; } - short[] blkids = new short[BLOCKS_PER_SECTION]; - this.blockids[secnum] = blkids; + int[] blkidxs = new int[BLOCKS_PER_SECTION]; + this.blockidx[secnum] = blkidxs; // JEI format if (sec.hasKey("Palette", 11)) { - byte[] bd = new byte[BLOCKS_PER_SECTION / 2]; int[] p = sec.getIntArray("Palette"); - this.blockdata[secnum] = bd; - int len = BLOCKS_PER_SECTION; - if(len > p.length) len = p.length; - for(int j = 0; j < len; j++) { - blkids[j] = (short)((p[j] >> 4) & 0xFFFF); - bd[j / 2] |= (p[j] & 0xF) << (4 * (j&1)); + // Palette is list of state values, where Blocks=bit 11-4 of index, Data=bit 3-0 + byte[] msb_bytes = sec.getByteArray("Blocks"); + int mlen = msb_bytes.length / 2; + byte[] lsb_bytes = sec.getByteArray("Data"); + int llen = BLOCKS_PER_SECTION / 2; + if (llen > lsb_bytes.length) llen = lsb_bytes.length; + for(int j = 0; j < llen; j++) { + int idx = lsb_bytes[j] & 0xF; + int idx2 = (lsb_bytes[j] & 0xF0) >>> 4; + if (j < mlen) { + idx += (255 & msb_bytes[2*j]) << 4; + idx2 += (255 & msb_bytes[2*j+1]) << 4; + } + // Get even block id + blkidxs[2*j] = (idx < p.length) ? p[idx] : 0; + // Get odd block id + blkidxs[2*j+1] = (idx2 < p.length) ? p[idx2] : 0; } } else { @@ -128,7 +133,7 @@ public class ChunkSnapshot int len = BLOCKS_PER_SECTION; if(len > lsb_bytes.length) len = lsb_bytes.length; for(int j = 0; j < len; j++) { - blkids[j] = (short)(0xFF & lsb_bytes[j]); + blkidxs[j] = (0xFF & lsb_bytes[j]) << 4; } if (sec.hasKey("Add", 7)) { /* If additional data, add it */ byte[] msb = sec.getByteArray("Add"); @@ -139,8 +144,8 @@ public class ChunkSnapshot if (b == 0) { continue; } - blkids[j << 1] |= (b & 0x0F) << 8; - blkids[(j << 1) + 1] |= (b & 0xF0) << 4; + blkidxs[j << 1] |= (b & 0x0F) << 12; + blkidxs[(j << 1) + 1] |= (b & 0xF0) << 8; } } if (sec.hasKey("Add2", 7)) { /* If additional data (NEID), add it */ @@ -152,11 +157,19 @@ public class ChunkSnapshot if (b == 0) { continue; } - blkids[j << 1] |= (b & 0x0F) << 12; - blkids[(j << 1) + 1] |= (b & 0xF0) << 8; + blkidxs[j << 1] |= (b & 0x0F) << 16; + blkidxs[(j << 1) + 1] |= (b & 0xF0) << 12; } } - this.blockdata[secnum] = sec.getByteArray("Data"); + byte[] bd = sec.getByteArray("Data"); + for (int j = 0; j < bd.length; j++) { + int b = bd[j] & 0xFF; + if (b == 0) { + continue; + } + blkidxs[j << 1] |= b & 0x0F; + blkidxs[(j << 1) + 1] |= (b & 0xF0) >> 4; + } } this.emitlight[secnum] = sec.getByteArray("BlockLight"); if (sec.hasKey("SkyLight")) { @@ -198,21 +211,18 @@ public class ChunkSnapshot public int getBlockTypeId(int x, int y, int z) { - return blockids[y >> 4][((y & 0xF) << 8) | (z << 4) | x]; + return blockidx[y >> 4][((y & 0xF) << 8) | (z << 4) | x] >> 4; } public int getBlockData(int x, int y, int z) { - int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1); - return (blockdata[y >> 4][off] >> ((x & 1) << 2)) & 0xF; + return blockidx[y >> 4][((y & 0xF) << 8) | (z << 4) | x] & 0xF; } public DynmapBlockState getBlockType(int x, int y, int z) { - int id = blockids[y >> 4][((y & 0xF) << 8) | (z << 4) | x]; - int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1); - int dat = (blockdata[y >> 4][off] >> ((x & 1) << 2)) & 0xF; - return DynmapPlugin.stateByID[(id << 4) + dat]; + int id = blockidx[y >> 4][((y & 0xF) << 8) | (z << 4) | x]; + return DynmapPlugin.stateByID[id]; } public int getBlockSkyLight(int x, int y, int z) diff --git a/forge-1.8.9/src/main/java/org/dynmap/forge_1_8_9/ChunkSnapshot.java b/forge-1.8.9/src/main/java/org/dynmap/forge_1_8_9/ChunkSnapshot.java index 2a2040a0..ba17f56a 100644 --- a/forge-1.8.9/src/main/java/org/dynmap/forge_1_8_9/ChunkSnapshot.java +++ b/forge-1.8.9/src/main/java/org/dynmap/forge_1_8_9/ChunkSnapshot.java @@ -20,8 +20,7 @@ import scala.actors.threadpool.Arrays; public class ChunkSnapshot { private final int x, z; - private final short[][] blockids; /* Block IDs, by section */ - private final byte[][] blockdata; + private final int[][] blockidx; /* Block state index, by section */ private final byte[][] skylight; private final byte[][] emitlight; private final boolean[] empty; @@ -33,10 +32,9 @@ public class ChunkSnapshot private static final int BLOCKS_PER_SECTION = 16 * 16 * 16; private static final int COLUMNS_PER_CHUNK = 16 * 16; - private static final short[] emptyIDs = new short[BLOCKS_PER_SECTION]; + private static final int[] emptyIdx = new int[BLOCKS_PER_SECTION]; private static final byte[] emptyData = new byte[BLOCKS_PER_SECTION / 2]; private static final byte[] fullData = new byte[BLOCKS_PER_SECTION / 2]; - private static Method getvalarray = null; static { @@ -44,16 +42,6 @@ public class ChunkSnapshot { fullData[i] = (byte)0xFF; } - try { - Method[] m = NibbleArray.class.getDeclaredMethods(); - for (Method mm : m) { - if (mm.getName().equals("getValueArray")) { - getvalarray = mm; - break; - } - } - } catch (Exception x) { - } } /** @@ -70,8 +58,7 @@ public class ChunkSnapshot this.biome = new int[COLUMNS_PER_CHUNK]; this.sectionCnt = worldheight / 16; /* Allocate arrays indexed by section */ - this.blockids = new short[this.sectionCnt][]; - this.blockdata = new byte[this.sectionCnt][]; + this.blockidx = new int[this.sectionCnt][]; this.skylight = new byte[this.sectionCnt][]; this.emitlight = new byte[this.sectionCnt][]; this.empty = new boolean[this.sectionCnt]; @@ -80,8 +67,7 @@ public class ChunkSnapshot for (int i = 0; i < this.sectionCnt; i++) { this.empty[i] = true; - this.blockids[i] = emptyIDs; - this.blockdata[i] = emptyData; + this.blockidx[i] = emptyIdx; this.emitlight[i] = emptyData; this.skylight[i] = fullData; } @@ -105,16 +91,14 @@ public class ChunkSnapshot this.inhabitedTicks = 0; } /* Allocate arrays indexed by section */ - this.blockids = new short[this.sectionCnt][]; - this.blockdata = new byte[this.sectionCnt][]; + this.blockidx = new int[this.sectionCnt][]; this.skylight = new byte[this.sectionCnt][]; this.emitlight = new byte[this.sectionCnt][]; this.empty = new boolean[this.sectionCnt]; /* Fill with empty data */ for (int i = 0; i < this.sectionCnt; i++) { this.empty[i] = true; - this.blockids[i] = emptyIDs; - this.blockdata[i] = emptyData; + this.blockidx[i] = emptyIdx; this.emitlight[i] = emptyData; this.skylight[i] = fullData; } @@ -127,41 +111,73 @@ public class ChunkSnapshot Log.info("Section " + (int) secnum + " above world height " + worldheight); continue; } - byte[] lsb_bytes = sec.getByteArray("Blocks"); - short[] blkids = new short[BLOCKS_PER_SECTION]; - this.blockids[secnum] = blkids; - int len = BLOCKS_PER_SECTION; - if(len > lsb_bytes.length) len = lsb_bytes.length; - for(int j = 0; j < len; j++) { - blkids[j] = (short)(0xFF & lsb_bytes[j]); - } - if (sec.hasKey("Add")) { /* If additional data, add it */ - byte[] msb = sec.getByteArray("Add"); - len = BLOCKS_PER_SECTION / 2; - if(len > msb.length) len = msb.length; - for (int j = 0; j < len; j++) { - short b = (short)(msb[j] & 0xFF); - if (b == 0) { - continue; - } - blkids[j << 1] |= (b & 0x0F) << 8; - blkids[(j << 1) + 1] |= (b & 0xF0) << 4; + int[] blkidxs = new int[BLOCKS_PER_SECTION]; + this.blockidx[secnum] = blkidxs; + // JEI format + if (sec.hasKey("Palette", 11)) { + int[] p = sec.getIntArray("Palette"); + // Palette is list of state values, where Blocks=bit 11-4 of index, Data=bit 3-0 + byte[] msb_bytes = sec.getByteArray("Blocks"); + int mlen = msb_bytes.length / 2; + byte[] lsb_bytes = sec.getByteArray("Data"); + int llen = BLOCKS_PER_SECTION / 2; + if (llen > lsb_bytes.length) llen = lsb_bytes.length; + for(int j = 0; j < llen; j++) { + int idx = lsb_bytes[j] & 0xF; + int idx2 = (lsb_bytes[j] & 0xF0) >>> 4; + if (j < mlen) { + idx += (255 & msb_bytes[2*j]) << 4; + idx2 += (255 & msb_bytes[2*j+1]) << 4; + } + // Get even block id + blkidxs[2*j] = (idx < p.length) ? p[idx] : 0; + // Get odd block id + blkidxs[2*j+1] = (idx2 < p.length) ? p[idx2] : 0; } } - if (sec.hasKey("Add2")) { /* If additional data (NEID), add it */ - byte[] msb = sec.getByteArray("Add2"); - len = BLOCKS_PER_SECTION / 2; - if(len > msb.length) len = msb.length; - for (int j = 0; j < len; j++) { - short b = (short)(msb[j] & 0xFF); - if (b == 0) { - continue; - } - blkids[j << 1] |= (b & 0x0F) << 12; - blkids[(j << 1) + 1] |= (b & 0xF0) << 8; - } + else { + byte[] lsb_bytes = sec.getByteArray("Blocks"); + int len = BLOCKS_PER_SECTION; + if(len > lsb_bytes.length) len = lsb_bytes.length; + for(int j = 0; j < len; j++) { + blkidxs[j] = (0xFF & lsb_bytes[j]) << 4; + } + if (sec.hasKey("Add", 7)) { /* If additional data, add it */ + byte[] msb = sec.getByteArray("Add"); + len = BLOCKS_PER_SECTION / 2; + if(len > msb.length) len = msb.length; + for (int j = 0; j < len; j++) { + short b = (short)(msb[j] & 0xFF); + if (b == 0) { + continue; + } + blkidxs[j << 1] |= (b & 0x0F) << 12; + blkidxs[(j << 1) + 1] |= (b & 0xF0) << 8; + } + } + if (sec.hasKey("Add2", 7)) { /* If additional data (NEID), add it */ + byte[] msb = sec.getByteArray("Add2"); + len = BLOCKS_PER_SECTION / 2; + if(len > msb.length) len = msb.length; + for (int j = 0; j < len; j++) { + short b = (short)(msb[j] & 0xFF); + if (b == 0) { + continue; + } + blkidxs[j << 1] |= (b & 0x0F) << 16; + blkidxs[(j << 1) + 1] |= (b & 0xF0) << 12; + } + } + byte[] bd = sec.getByteArray("Data"); + for (int j = 0; j < bd.length; j++) { + int b = bd[j] & 0xFF; + if (b == 0) { + continue; + } + blkidxs[j << 1] |= b & 0x0F; + blkidxs[(j << 1) + 1] |= (b & 0xF0) >> 4; + } } - this.blockdata[secnum] = sec.getByteArray("Data"); this.emitlight[secnum] = sec.getByteArray("BlockLight"); if (sec.hasKey("SkyLight")) { this.skylight[secnum] = sec.getByteArray("SkyLight"); @@ -174,77 +190,22 @@ public class ChunkSnapshot byte[] b = nbt.getByteArray("Biomes"); if (b != null) { for (int i = 0; i < b.length; i++) { - this.biome[i] = 255 & b[i]; + int bv = 255 & b[i]; + this.biome[i] = (bv == 255) ? 0 : bv; } } else { // Check JEI biomes int[] bb = nbt.getIntArray("Biomes"); if (bb != null) { for (int i = 0; i < bb.length; i++) { - this.biome[i] = bb[i]; + int bv = bb[i]; + this.biome[i] = (bv < 0) ? 0 : bv; } } } } } - private static byte[] getValueArray(NibbleArray na) { - if(getvalarray != null) { - try { - return (byte[])getvalarray.invoke(na); - } catch (IllegalArgumentException e) { - } catch (IllegalAccessException e) { - } catch (InvocationTargetException e) { - } - } - return na.getData(); - } - public ChunkSnapshot(Chunk chunk, int worldheight) - { - this(worldheight, chunk.xPosition, chunk.zPosition, chunk.getWorld().getWorldTime(), chunk.getInhabitedTime()); - /* Copy biome data */ - System.arraycopy(chunk.getBiomeArray(), 0, biome, 0, COLUMNS_PER_CHUNK); - ExtendedBlockStorage[] ebs = chunk.getBlockStorageArray(); - - /* Copy sections */ - for (int i = 0; i < this.sectionCnt; i++) - { - ExtendedBlockStorage eb = (i < ebs.length) ? ebs[i] : null; - - if ((eb != null) && (eb.isEmpty() == false)) - { - this.empty[i] = false; - /* Copy base IDs */ - /* Copy block data */ - byte[] blockd = new byte[BLOCKS_PER_SECTION / 2]; - short blockids[] = new short[BLOCKS_PER_SECTION]; - char[] blkd = eb.getData(); - - for (int j = 0; j < BLOCKS_PER_SECTION; j++) - { - blockids[j] = (short) (blkd[j] & 0xFFF); - blockd[j / 2] = (byte)(blockd[j / 2] | ((0xF & (blkd[j] >> 12)) << (4 * (j & 1)))); - } - this.blockids[i] = blockids; - this.blockdata[i] = blockd; - /* Copy block lighting data */ - this.emitlight[i] = new byte[BLOCKS_PER_SECTION / 2]; - System.arraycopy(getValueArray(eb.getBlocklightArray()), 0, this.emitlight[i], 0, BLOCKS_PER_SECTION / 2); - /* Copy sky lighting data */ - if(eb.getSkylightArray() != null) { - this.skylight[i] = new byte[BLOCKS_PER_SECTION / 2]; - System.arraycopy(getValueArray(eb.getSkylightArray()), 0, this.skylight[i], 0, BLOCKS_PER_SECTION / 2); - } - else { - this.skylight[i] = ChunkSnapshot.emptyData; - } - } - } - - /* Save height map */ - System.arraycopy(chunk.getHeightMap(), 0, this.hmap, 0, hmap.length); - } - public int getX() { return x; @@ -257,21 +218,18 @@ public class ChunkSnapshot public int getBlockTypeId(int x, int y, int z) { - return blockids[y >> 4][((y & 0xF) << 8) | (z << 4) | x]; + return blockidx[y >> 4][((y & 0xF) << 8) | (z << 4) | x] >> 4; } public int getBlockData(int x, int y, int z) { - int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1); - return (blockdata[y >> 4][off] >> ((x & 1) << 2)) & 0xF; + return blockidx[y >> 4][((y & 0xF) << 8) | (z << 4) | x] & 0xF; } public DynmapBlockState getBlockType(int x, int y, int z) { - int id = blockids[y >> 4][((y & 0xF) << 8) | (z << 4) | x]; - int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1); - int dat = (blockdata[y >> 4][off] >> ((x & 1) << 2)) & 0xF; - return DynmapPlugin.stateByID[(id << 4) + dat]; + int id = blockidx[y >> 4][((y & 0xF) << 8) | (z << 4) | x]; + return DynmapPlugin.stateByID[id]; } public int getBlockSkyLight(int x, int y, int z) diff --git a/forge-1.9.4/src/main/java/org/dynmap/forge_1_9_4/ChunkSnapshot.java b/forge-1.9.4/src/main/java/org/dynmap/forge_1_9_4/ChunkSnapshot.java index 73d6a01d..f1863a91 100644 --- a/forge-1.9.4/src/main/java/org/dynmap/forge_1_9_4/ChunkSnapshot.java +++ b/forge-1.9.4/src/main/java/org/dynmap/forge_1_9_4/ChunkSnapshot.java @@ -18,8 +18,7 @@ import scala.actors.threadpool.Arrays; public class ChunkSnapshot { private final int x, z; - private final short[][] blockids; /* Block IDs, by section */ - private final byte[][] blockdata; + private final int[][] blockidx; /* Block state index, by section */ private final byte[][] skylight; private final byte[][] emitlight; private final boolean[] empty; @@ -31,10 +30,9 @@ public class ChunkSnapshot private static final int BLOCKS_PER_SECTION = 16 * 16 * 16; private static final int COLUMNS_PER_CHUNK = 16 * 16; - private static final short[] emptyIDs = new short[BLOCKS_PER_SECTION]; + private static final int[] emptyIdx = new int[BLOCKS_PER_SECTION]; private static final byte[] emptyData = new byte[BLOCKS_PER_SECTION / 2]; private static final byte[] fullData = new byte[BLOCKS_PER_SECTION / 2]; - private static Method getvalarray = null; static { @@ -42,16 +40,6 @@ public class ChunkSnapshot { fullData[i] = (byte)0xFF; } - try { - Method[] m = NibbleArray.class.getDeclaredMethods(); - for (Method mm : m) { - if (mm.getName().equals("getValueArray")) { - getvalarray = mm; - break; - } - } - } catch (Exception x) { - } } /** @@ -68,8 +56,7 @@ public class ChunkSnapshot this.biome = new int[COLUMNS_PER_CHUNK]; this.sectionCnt = worldheight / 16; /* Allocate arrays indexed by section */ - this.blockids = new short[this.sectionCnt][]; - this.blockdata = new byte[this.sectionCnt][]; + this.blockidx = new int[this.sectionCnt][]; this.skylight = new byte[this.sectionCnt][]; this.emitlight = new byte[this.sectionCnt][]; this.empty = new boolean[this.sectionCnt]; @@ -78,8 +65,7 @@ public class ChunkSnapshot for (int i = 0; i < this.sectionCnt; i++) { this.empty[i] = true; - this.blockids[i] = emptyIDs; - this.blockdata[i] = emptyData; + this.blockidx[i] = emptyIdx; this.emitlight[i] = emptyData; this.skylight[i] = fullData; } @@ -103,16 +89,14 @@ public class ChunkSnapshot this.inhabitedTicks = 0; } /* Allocate arrays indexed by section */ - this.blockids = new short[this.sectionCnt][]; - this.blockdata = new byte[this.sectionCnt][]; + this.blockidx = new int[this.sectionCnt][]; this.skylight = new byte[this.sectionCnt][]; this.emitlight = new byte[this.sectionCnt][]; this.empty = new boolean[this.sectionCnt]; /* Fill with empty data */ for (int i = 0; i < this.sectionCnt; i++) { this.empty[i] = true; - this.blockids[i] = emptyIDs; - this.blockdata[i] = emptyData; + this.blockidx[i] = emptyIdx; this.emitlight[i] = emptyData; this.skylight[i] = fullData; } @@ -125,41 +109,73 @@ public class ChunkSnapshot Log.info("Section " + (int) secnum + " above world height " + worldheight); continue; } - byte[] lsb_bytes = sec.getByteArray("Blocks"); - short[] blkids = new short[BLOCKS_PER_SECTION]; - this.blockids[secnum] = blkids; - int len = BLOCKS_PER_SECTION; - if(len > lsb_bytes.length) len = lsb_bytes.length; - for(int j = 0; j < len; j++) { - blkids[j] = (short)(0xFF & lsb_bytes[j]); - } - if (sec.hasKey("Add")) { /* If additional data, add it */ - byte[] msb = sec.getByteArray("Add"); - len = BLOCKS_PER_SECTION / 2; - if(len > msb.length) len = msb.length; - for (int j = 0; j < len; j++) { - short b = (short)(msb[j] & 0xFF); - if (b == 0) { - continue; - } - blkids[j << 1] |= (b & 0x0F) << 8; - blkids[(j << 1) + 1] |= (b & 0xF0) << 4; + int[] blkidxs = new int[BLOCKS_PER_SECTION]; + this.blockidx[secnum] = blkidxs; + // JEI format + if (sec.hasKey("Palette", 11)) { + int[] p = sec.getIntArray("Palette"); + // Palette is list of state values, where Blocks=bit 11-4 of index, Data=bit 3-0 + byte[] msb_bytes = sec.getByteArray("Blocks"); + int mlen = msb_bytes.length / 2; + byte[] lsb_bytes = sec.getByteArray("Data"); + int llen = BLOCKS_PER_SECTION / 2; + if (llen > lsb_bytes.length) llen = lsb_bytes.length; + for(int j = 0; j < llen; j++) { + int idx = lsb_bytes[j] & 0xF; + int idx2 = (lsb_bytes[j] & 0xF0) >>> 4; + if (j < mlen) { + idx += (255 & msb_bytes[2*j]) << 4; + idx2 += (255 & msb_bytes[2*j+1]) << 4; + } + // Get even block id + blkidxs[2*j] = (idx < p.length) ? p[idx] : 0; + // Get odd block id + blkidxs[2*j+1] = (idx2 < p.length) ? p[idx2] : 0; } } - if (sec.hasKey("Add2")) { /* If additional data (NEID), add it */ - byte[] msb = sec.getByteArray("Add2"); - len = BLOCKS_PER_SECTION / 2; - if(len > msb.length) len = msb.length; - for (int j = 0; j < len; j++) { - short b = (short)(msb[j] & 0xFF); - if (b == 0) { - continue; - } - blkids[j << 1] |= (b & 0x0F) << 12; - blkids[(j << 1) + 1] |= (b & 0xF0) << 8; - } + else { + byte[] lsb_bytes = sec.getByteArray("Blocks"); + int len = BLOCKS_PER_SECTION; + if(len > lsb_bytes.length) len = lsb_bytes.length; + for(int j = 0; j < len; j++) { + blkidxs[j] = (0xFF & lsb_bytes[j]) << 4; + } + if (sec.hasKey("Add", 7)) { /* If additional data, add it */ + byte[] msb = sec.getByteArray("Add"); + len = BLOCKS_PER_SECTION / 2; + if(len > msb.length) len = msb.length; + for (int j = 0; j < len; j++) { + short b = (short)(msb[j] & 0xFF); + if (b == 0) { + continue; + } + blkidxs[j << 1] |= (b & 0x0F) << 12; + blkidxs[(j << 1) + 1] |= (b & 0xF0) << 8; + } + } + if (sec.hasKey("Add2", 7)) { /* If additional data (NEID), add it */ + byte[] msb = sec.getByteArray("Add2"); + len = BLOCKS_PER_SECTION / 2; + if(len > msb.length) len = msb.length; + for (int j = 0; j < len; j++) { + short b = (short)(msb[j] & 0xFF); + if (b == 0) { + continue; + } + blkidxs[j << 1] |= (b & 0x0F) << 16; + blkidxs[(j << 1) + 1] |= (b & 0xF0) << 12; + } + } + byte[] bd = sec.getByteArray("Data"); + for (int j = 0; j < bd.length; j++) { + int b = bd[j] & 0xFF; + if (b == 0) { + continue; + } + blkidxs[j << 1] |= b & 0x0F; + blkidxs[(j << 1) + 1] |= (b & 0xF0) >> 4; + } } - this.blockdata[secnum] = sec.getByteArray("Data"); this.emitlight[secnum] = sec.getByteArray("BlockLight"); if (sec.hasKey("SkyLight")) { this.skylight[secnum] = sec.getByteArray("SkyLight"); @@ -172,32 +188,22 @@ public class ChunkSnapshot byte[] b = nbt.getByteArray("Biomes"); if (b != null) { for (int i = 0; i < b.length; i++) { - this.biome[i] = 255 & b[i]; + int bv = 255 & b[i]; + this.biome[i] = (bv == 255) ? 0 : bv; } } else { // Check JEI biomes int[] bb = nbt.getIntArray("Biomes"); if (bb != null) { for (int i = 0; i < bb.length; i++) { - this.biome[i] = bb[i]; + int bv = bb[i]; + this.biome[i] = (bv < 0) ? 0 : bv; } } } } } - private static byte[] getValueArray(NibbleArray na) { - if(getvalarray != null) { - try { - return (byte[])getvalarray.invoke(na); - } catch (IllegalArgumentException e) { - } catch (IllegalAccessException e) { - } catch (InvocationTargetException e) { - } - } - return na.getData(); - } - public int getX() { return x; @@ -210,21 +216,18 @@ public class ChunkSnapshot public int getBlockTypeId(int x, int y, int z) { - return blockids[y >> 4][((y & 0xF) << 8) | (z << 4) | x]; + return blockidx[y >> 4][((y & 0xF) << 8) | (z << 4) | x] >> 4; } public int getBlockData(int x, int y, int z) { - int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1); - return (blockdata[y >> 4][off] >> ((x & 1) << 2)) & 0xF; + return blockidx[y >> 4][((y & 0xF) << 8) | (z << 4) | x] & 0xF; } public DynmapBlockState getBlockType(int x, int y, int z) { - int id = blockids[y >> 4][((y & 0xF) << 8) | (z << 4) | x]; - int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1); - int dat = (blockdata[y >> 4][off] >> ((x & 1) << 2)) & 0xF; - return DynmapPlugin.stateByID[(id << 4) + dat]; + int id = blockidx[y >> 4][((y & 0xF) << 8) | (z << 4) | x]; + return DynmapPlugin.stateByID[id]; } public int getBlockSkyLight(int x, int y, int z)