From 60a23a04c83c1561af668351d85323ecb635b906 Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Sat, 15 Aug 2020 19:29:29 -0500 Subject: [PATCH] Handle pre-1.16 chunks in forge 1.16+ --- .../java/org/dynmap/utils/DataBitsPacked.java | 53 +++++++++++++++++++ .../dynmap/forge_1_16_1/ChunkSnapshot.java | 18 +++++-- 2 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 DynmapCore/src/main/java/org/dynmap/utils/DataBitsPacked.java diff --git a/DynmapCore/src/main/java/org/dynmap/utils/DataBitsPacked.java b/DynmapCore/src/main/java/org/dynmap/utils/DataBitsPacked.java new file mode 100644 index 00000000..3f4b62f6 --- /dev/null +++ b/DynmapCore/src/main/java/org/dynmap/utils/DataBitsPacked.java @@ -0,0 +1,53 @@ +package org.dynmap.utils; + +// Pre 1.16 chunk section data array +public class DataBitsPacked { + + private final long[] values; + private final int bitsperrec; + private final long valuemask; + private final int length; + + public static int calcLongCount(int i, int j) { + if (j == 0) { + return 0; + } else if (i == 0) { + return j; + } else { + if (i < 0) { + j *= -1; + } + + int k = i % j; + + return k == 0 ? i : i + j - k; + } + } + + public DataBitsPacked(int bitsperrec, int length, long[] values) { + this.length = length; + this.bitsperrec = bitsperrec; + this.values = values; + this.valuemask = (1L << bitsperrec) - 1L; + int properlength = calcLongCount(length * bitsperrec, 64) / 64; + + if (values.length != properlength) { + throw new IllegalArgumentException("Invalid length given for storage, got: " + values.length + " but expected: " + properlength); + } + } + + public int getAt(int offset) { + int j = offset * this.bitsperrec; + int k = j >> 6; + int l = (offset + 1) * this.bitsperrec - 1 >> 6; + int i1 = j ^ k << 6; + + if (k == l) { + return (int) (this.values[k] >>> i1 & this.valuemask); + } else { + int j1 = 64 - i1; + + return (int) ((this.values[k] >>> i1 | this.values[l] << j1) & this.valuemask); + } + } +} diff --git a/forge-1.16.1/src/main/java/org/dynmap/forge_1_16_1/ChunkSnapshot.java b/forge-1.16.1/src/main/java/org/dynmap/forge_1_16_1/ChunkSnapshot.java index 4332968c..0c95a65a 100644 --- a/forge-1.16.1/src/main/java/org/dynmap/forge_1_16_1/ChunkSnapshot.java +++ b/forge-1.16.1/src/main/java/org/dynmap/forge_1_16_1/ChunkSnapshot.java @@ -4,6 +4,7 @@ import java.util.Arrays; import org.dynmap.Log; import org.dynmap.renderer.DynmapBlockState; +import org.dynmap.utils.DataBitsPacked; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; @@ -178,16 +179,25 @@ public class ChunkSnapshot palette[pi] = DynmapBlockState.AIR; } } - int bitsperblock = (statelist.length * 64) / 4096; - BitArray db = new BitArray(bitsperblock, 4096, statelist); + int recsperblock = (4096 + statelist.length - 1) / statelist.length; + int bitsperblock = 64 / recsperblock; + BitArray db = null; + DataBitsPacked dbp = null; + try { + db = new BitArray(bitsperblock, 4096, statelist); + } catch (Exception x) { // Handle legacy encoded + bitsperblock = (statelist.length * 64) / 4096; + dbp = new DataBitsPacked(bitsperblock, 4096, statelist); + } if (bitsperblock > 8) { // Not palette for (int j = 0; j < 4096; j++) { - states[j] = DynmapBlockState.getStateByGlobalIndex(db.getAt(j)); + int v = (dbp != null) ? dbp.getAt(j) : db.getAt(j); + states[j] = DynmapBlockState.getStateByGlobalIndex(v); } } else { for (int j = 0; j < 4096; j++) { - int v = db.getAt(j); + int v = (dbp != null) ? dbp.getAt(j) : db.getAt(j); states[j] = (v < palette.length) ? palette[v] : DynmapBlockState.AIR; } }