From d5da8e4e2b9f23e8ef109eb1a91ae2d97672ec48 Mon Sep 17 00:00:00 2001 From: cyberpwn Date: Tue, 24 Aug 2021 23:16:01 -0400 Subject: [PATCH] Forcefully integrate a mangled DataPalette from NMS into a NBTMCA API --- .../com/volmit/iris/util/nbt/mca/Chunk.java | 10 - .../com/volmit/iris/util/nbt/mca/Section.java | 248 ++---------------- .../util/nbt/mca/palettes/DataPalette.java | 2 + .../nbt/mca/palettes/DataPaletteBlock.java | 69 ++--- .../nbt/mca/palettes/DataPaletteHash.java | 5 + .../nbt/mca/palettes/DataPaletteLinear.java | 11 + 6 files changed, 77 insertions(+), 268 deletions(-) diff --git a/src/main/java/com/volmit/iris/util/nbt/mca/Chunk.java b/src/main/java/com/volmit/iris/util/nbt/mca/Chunk.java index 04125982e..23bf1ac99 100644 --- a/src/main/java/com/volmit/iris/util/nbt/mca/Chunk.java +++ b/src/main/java/com/volmit/iris/util/nbt/mca/Chunk.java @@ -688,14 +688,4 @@ public class Chunk { public int sectionCount() { return sections.length(); } - - public void runLighting() { - for (int s = 15; s >= 0; s--) { - Section section = getSection(s); - - if (section != null) { - section.runLighting(); - } - } - } } diff --git a/src/main/java/com/volmit/iris/util/nbt/mca/Section.java b/src/main/java/com/volmit/iris/util/nbt/mca/Section.java index ec6df11f1..2e95af170 100644 --- a/src/main/java/com/volmit/iris/util/nbt/mca/Section.java +++ b/src/main/java/com/volmit/iris/util/nbt/mca/Section.java @@ -20,12 +20,13 @@ package com.volmit.iris.util.nbt.mca; import com.volmit.iris.Iris; import com.volmit.iris.util.collection.KMap; +import com.volmit.iris.util.nbt.mca.palettes.DataPaletteBlock; import com.volmit.iris.util.nbt.tag.ByteArrayTag; import com.volmit.iris.util.nbt.tag.CompoundTag; import com.volmit.iris.util.nbt.tag.ListTag; import com.volmit.iris.util.nbt.tag.LongArrayTag; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -import net.minecraft.world.level.chunk.DataPaletteGlobal; +import net.minecraft.world.level.chunk.Chunk; import java.util.ArrayList; import java.util.HashMap; @@ -35,10 +36,8 @@ import java.util.concurrent.atomic.AtomicLongArray; public class Section { private CompoundTag data; - private Map> valueIndexedPalette = new KMap<>(); - private ListTag palette; + private DataPaletteBlock palette; private byte[] blockLight; - private AtomicLongArray blockStates; private byte[] skyLight; private int dataVersion; @@ -53,72 +52,18 @@ public class Section { if (rawPalette == null) { return; } - palette = rawPalette.asCompoundTagList(); - for (int i = 0; i < palette.size(); i++) { - CompoundTag data = palette.get(i); - putValueIndexedPalette(data, i); - } - - palette.makeAtomic(); - ByteArrayTag blockLight = sectionRoot.getByteArrayTag("BlockLight"); + palette = new DataPaletteBlock<>(); LongArrayTag blockStates = sectionRoot.getLongArrayTag("BlockStates"); + palette.a((ListTag) rawPalette, blockStates.getValue()); + ByteArrayTag blockLight = sectionRoot.getByteArrayTag("BlockLight"); ByteArrayTag skyLight = sectionRoot.getByteArrayTag("SkyLight"); - - if ((loadFlags & LoadFlags.BLOCK_LIGHTS) != 0) { - this.blockLight = blockLight != null ? blockLight.getValue() : null; - } - if ((loadFlags & LoadFlags.BLOCK_STATES) != 0) { - this.blockStates = blockStates != null ? new AtomicLongArray(blockStates.getValue()) : null; - } - if ((loadFlags & LoadFlags.SKY_LIGHT) != 0) { - this.skyLight = skyLight != null ? skyLight.getValue() : null; - } + this.blockLight = blockLight != null ? blockLight.getValue() : null; + this.skyLight = skyLight != null ? skyLight.getValue() : null; } Section() { } - void putValueIndexedPalette(CompoundTag data, int index) { - PaletteIndex leaf = new PaletteIndex(data, index); - String name = data.getString("Name"); - List leaves = valueIndexedPalette.get(name); - if (leaves == null) { - leaves = new ArrayList<>(1); - leaves.add(leaf); - valueIndexedPalette.put(name, leaves); - } else { - for (PaletteIndex pal : leaves) { - if (pal.data.equals(data)) { - return; - } - } - leaves.add(leaf); - } - } - - PaletteIndex getValueIndexedPalette(CompoundTag data) { - List leaves = valueIndexedPalette.get(data.getString("Name")); - if (leaves == null) { - return null; - } - for (PaletteIndex leaf : leaves) { - if (leaf.data.equals(data)) { - return leaf; - } - } - return null; - } - - public void runLighting() { - for (int x = 1; x < 14; x++) { - for (int z = 1; z < 14; z++) { - for (int y = 0; y < 16; y++) { - - } - } - } - } - @SuppressWarnings("ClassCanBeRecord") private static class PaletteIndex { @@ -150,16 +95,7 @@ public class Section { * @return The block state data of this block. */ public synchronized CompoundTag getBlockStateAt(int blockX, int blockY, int blockZ) { - try { - int index = getBlockIndex(blockX, blockY, blockZ); - int paletteIndex = getPaletteIndex(index); - return palette.get(paletteIndex); - } catch (Throwable ignored) { - Iris.reportError(ignored); - - } - - return null; + return palette.a(blockX, blockY, blockZ); } /** @@ -169,52 +105,17 @@ public class Section { * @param blockY The y-coordinate of the block in this Section * @param blockZ The z-coordinate of the block in this Section * @param state The block state to be set - * @param cleanup When true, it will cleanup the palette of this section. - * This option should only be used moderately to avoid unnecessary recalculation of the palette indices. - * Recalculating the Palette should only be executed once right before saving the Section to file. */ public synchronized void setBlockStateAt(int blockX, int blockY, int blockZ, CompoundTag state, boolean cleanup) { - int paletteIndex = addToPalette(state); - int paletteSizeBefore = palette.size(); - //power of 2 --> bits must increase, but only if the palette size changed - //otherwise we would attempt to update all blockstates and the entire palette - //every time an existing blockstate was added while having 2^x blockstates in the palette - if (paletteSizeBefore != palette.size() && (paletteIndex & (paletteIndex - 1)) == 0) { - adjustBlockStateBits(null, blockStates); - cleanup = true; + + if(cleanup) + { + palette.setBlock(blockX, blockY, blockZ, state); } - setPaletteIndex(getBlockIndex(blockX, blockY, blockZ), paletteIndex, blockStates); - if (cleanup) { - cleanupPaletteAndBlockStates(); - } - } - - /** - * Returns the index of the block data in the palette. - * - * @param blockStateIndex The index of the block in this section, ranging from 0-4095. - * @return The index of the block data in the palette. - */ - public synchronized int getPaletteIndex(int blockStateIndex) { - int bits = blockStates.length() >> 6; - - if (dataVersion < 2527) { - double blockStatesIndex = blockStateIndex / (4096D / blockStates.length()); - int longIndex = (int) blockStatesIndex; - int startBit = (int) ((blockStatesIndex - Math.floor(blockStatesIndex)) * 64D); - if (startBit + bits > 64) { - long prev = bitRange(blockStates.get(longIndex), startBit, 64); - long next = bitRange(blockStates.get(longIndex + 1), 0, startBit + bits - 64); - return (int) ((next << 64 - startBit) + prev); - } else { - return (int) bitRange(blockStates.get(longIndex), startBit, startBit + bits); - } - } else { - int indicesPerLong = (int) (64D / bits); - int blockStatesIndex = blockStateIndex / indicesPerLong; - int startBit = (blockStateIndex % indicesPerLong) * bits; - return (int) bitRange(blockStates.get(blockStatesIndex), startBit, startBit + bits); + else + { + palette.b(blockX, blockY, blockZ, state); } } @@ -246,25 +147,6 @@ public class Section { } } - /** - * Fetches the palette of this Section. - * - * @return The palette of this Section. - */ - public synchronized ListTag getPalette() { - return palette; - } - - synchronized int addToPalette(CompoundTag data) { - PaletteIndex index; - if ((index = getValueIndexedPalette(data)) != null) { - return index.index; - } - palette.add(data); - putValueIndexedPalette(data, palette.size() - 1); - return palette.size() - 1; - } - int getBlockIndex(int blockX, int blockY, int blockZ) { return (blockY & 0xF) * 256 + (blockZ & 0xF) * 16 + (blockX & 0xF); } @@ -285,63 +167,8 @@ public class Section { * This should only be used moderately to avoid unnecessary recalculation of the palette indices. * Recalculating the Palette should only be executed once right before saving the Section to file. */ - public synchronized void cleanupPaletteAndBlockStates() { - Map oldToNewMapping = cleanupPalette(); - adjustBlockStateBits(oldToNewMapping, blockStates); - } + public void cleanupPaletteAndBlockStates() { - private synchronized Map cleanupPalette() { - //create index - palette mapping - Map allIndices = new Int2IntOpenHashMap(); - for (int i = 0; i < 4096; i++) { - int paletteIndex = getPaletteIndex(i); - allIndices.put(paletteIndex, paletteIndex); - } - //delete unused blocks from palette - //start at index 1 because we need to keep minecraft:air - int index = 1; - valueIndexedPalette = new HashMap<>(valueIndexedPalette.size()); - putValueIndexedPalette(palette.get(0), 0); - for (int i = 1; i < palette.size(); i++) { - if (!allIndices.containsKey(index)) { - palette.remove(i); - i--; - } else { - putValueIndexedPalette(palette.get(i), i); - allIndices.put(index, i); - } - index++; - } - - return allIndices; - } - - synchronized void adjustBlockStateBits(Map oldToNewMapping, AtomicLongArray blockStates) { - //increases or decreases the amount of bits used per BlockState - //based on the size of the palette. oldToNewMapping can be used to update indices - //if the palette had been cleaned up before using MCAFile#cleanupPalette(). - - int newBits = 32 - Integer.numberOfLeadingZeros(palette.size() - 1); - newBits = Math.max(newBits, 4); - - AtomicLongArray newBlockStates; - - if (dataVersion < 2527) { - newBlockStates = newBits == blockStates.length() / 64 ? blockStates : new AtomicLongArray(newBits * 64); - } else { - int newLength = (int) Math.ceil(4096D / (64D / newBits)); - newBlockStates = newBits == blockStates.length() / 64 ? blockStates : new AtomicLongArray(newLength); - } - if (oldToNewMapping != null) { - for (int i = 0; i < 4096; i++) { - setPaletteIndex(i, oldToNewMapping.get(getPaletteIndex(i)), newBlockStates); - } - } else { - for (int i = 0; i < 4096; i++) { - setPaletteIndex(i, getPaletteIndex(i), newBlockStates); - } - } - this.blockStates = newBlockStates; } /** @@ -364,29 +191,6 @@ public class Section { this.blockLight = blockLight; } - /** - * @return The indices of the block states of this Section. - */ - public synchronized AtomicLongArray getBlockStates() { - return blockStates; - } - - /** - * Sets the block state indices to a custom value. - * - * @param blockStates The block state indices. - * @throws NullPointerException If blockStates is null - * @throws IllegalArgumentException When blockStates' length is < 256 or > 4096 and is not a multiple of 64 - */ - public void setBlockStates(AtomicLongArray blockStates) { - if (blockStates == null) { - throw new NullPointerException("BlockStates cannot be null"); - } else if (blockStates.length() % 64 != 0 || blockStates.length() < 256 || blockStates.length() > 4096) { - throw new IllegalArgumentException("BlockStates must have a length > 255 and < 4097 and must be divisible by 64"); - } - this.blockStates = blockStates; - } - /** * @return The sky light values of this Section */ @@ -414,11 +218,7 @@ public class Section { */ public static Section newSection() { Section s = new Section(); - s.blockStates = new AtomicLongArray(256); - s.palette = new ListTag<>(CompoundTag.class); - CompoundTag air = new CompoundTag(); - air.putString("Name", "minecraft:air"); - s.palette.add(air); + s.palette = new DataPaletteBlock<>(); s.data = new CompoundTag(); return s; } @@ -434,20 +234,12 @@ public class Section { public synchronized CompoundTag updateHandle(int y) { data.putByte("Y", (byte) y); if (palette != null) { - data.put("Palette", palette); + data.put("Palette", palette.getK().getPalette()); + data.putLongArray("BlockStates", palette.getC().a()); } if (blockLight != null) { data.putByteArray("BlockLight", blockLight); } - if (blockStates != null) { - long[] c = new long[blockStates.length()]; - - for (int i = 0; i < c.length; i++) { - c[i] = blockStates.get(i); - } - - data.putLongArray("BlockStates", c); - } if (skyLight != null) { data.putByteArray("SkyLight", skyLight); } diff --git a/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPalette.java b/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPalette.java index b29da7adc..0b5a07fec 100644 --- a/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPalette.java +++ b/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPalette.java @@ -35,4 +35,6 @@ public interface DataPalette { int b(); void a(ListTag t); + + ListTag getPalette(); } diff --git a/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPaletteBlock.java b/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPaletteBlock.java index bbd43a2e7..65d943fc0 100644 --- a/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPaletteBlock.java +++ b/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPaletteBlock.java @@ -19,16 +19,20 @@ package com.volmit.iris.util.nbt.mca.palettes; import com.volmit.iris.util.math.MathHelper; +import com.volmit.iris.util.nbt.mca.NBTWorld; import com.volmit.iris.util.nbt.tag.CompoundTag; import com.volmit.iris.util.nbt.tag.ListTag; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; +import lombok.Getter; import net.minecraft.network.PacketDataSerializer; +import org.bukkit.Material; import java.util.concurrent.Semaphore; import java.util.function.Function; import java.util.function.Predicate; +@Getter public class DataPaletteBlock implements DataPaletteExpandable { private static final int d = 4096; public static final int a = 9; @@ -41,16 +45,26 @@ public class DataPaletteBlock implements DataPaletteExpandable { private final Function h; private final Function i; private final T j; + private static final RegistryBlockID registry = new RegistryBlockID<>(); + private static final CompoundTag air = NBTWorld.getCompound(Material.AIR.createBlockData()); protected DataBits c; private DataPalette k; - private int l; + private int bits; private final Semaphore m = new Semaphore(1); public void b() { this.m.release(); } - public DataPaletteBlock(DataPalette var0, RegistryBlockID var1, Function var2, Function var3, T var4) { + public DataPaletteBlock() { + this(null, (RegistryBlockID) registry, (i) -> (T) i, (i) -> (CompoundTag) i, (T) air); + } + + public DataPaletteBlock(DataPalette var0, + RegistryBlockID var1, + Function var2, + Function var3, + T var4) { this.e = var0; this.g = var1; this.h = var2; @@ -64,20 +78,20 @@ public class DataPaletteBlock implements DataPaletteExpandable { } private void b(int var0) { - if (var0 != this.l) { - this.l = var0; - if (this.l <= 4) { - this.l = 4; - this.k = new DataPaletteLinear(this.g, this.l, this, this.h); - } else if (this.l < 9) { - this.k = new DataPaletteHash(this.g, this.l, this, this.h, this.i); + if (var0 != this.bits) { + this.bits = var0; + if (this.bits <= 4) { + this.bits = 4; + this.k = new DataPaletteLinear(this.g, this.bits, this, this.h); + } else if (this.bits < 9) { + this.k = new DataPaletteHash(this.g, this.bits, this, this.h, this.i); } else { this.k = this.e; - this.l = MathHelper.e(this.g.a()); + this.bits = MathHelper.e(this.g.a()); } this.k.a(this.j); - this.c = new DataBits(this.l, 4096); + this.c = new DataBits(this.bits, 4096); } } @@ -140,27 +154,27 @@ public class DataPaletteBlock implements DataPaletteExpandable { return var1 == null ? this.j : var1; } - public void a(ListTag var0, long[] var1) { + public void a(ListTag palettedata, long[] databits) { try { - int var2 = Math.max(4, MathHelper.e(var0.size())); - if (var2 != this.l) { + int var2 = Math.max(4, MathHelper.e(palettedata.size())); + if (var2 != this.bits) { this.b(var2); } - this.k.a(var0); - int var3 = var1.length * 64 / 4096; + this.k.a(palettedata); + int var3 = databits.length * 64 / 4096; if (this.k == this.e) { - DataPalette var4 = new DataPaletteHash(this.g, var2, this.f, this.h, this.i); - var4.a(var0); - DataBits var5 = new DataBits(var2, 4096, var1); + DataPalette var4 = new DataPaletteHash(this.g, var2, this.f, this.h, this.i); + var4.a(palettedata); + DataBits var5 = new DataBits(var2, 4096, databits); for (int var6 = 0; var6 < 4096; ++var6) { this.c.b(var6, this.e.a(var4.a(var5.a(var6)))); } - } else if (var3 == this.l) { - System.arraycopy(var1, 0, this.c.a(), 0, var1.length); + } else if (var3 == this.bits) { + System.arraycopy(databits, 0, this.c.a(), 0, databits.length); } else { - DataBits var4 = new DataBits(var3, 4096, var1); + DataBits var4 = new DataBits(var3, 4096, databits); for (int var5 = 0; var5 < 4096; ++var5) { this.c.b(var5, var4.a(var5)); @@ -169,12 +183,11 @@ public class DataPaletteBlock implements DataPaletteExpandable { } finally { this.b(); } - } public void a(CompoundTag var0, String var1, String var2) { try { - DataPaletteHash var3 = new DataPaletteHash(this.g, this.l, this.f, this.h, this.i); + DataPaletteHash var3 = new DataPaletteHash(this.g, this.bits, this.f, this.h, this.i); T var4 = this.j; int var5 = var3.a(this.j); int[] var6 = new int[4096]; @@ -215,12 +228,8 @@ public class DataPaletteBlock implements DataPaletteExpandable { public void a(DataPaletteBlock.a var0) { Int2IntMap var1 = new Int2IntOpenHashMap(); - this.c.a((var1x) -> { - var1.put(var1x, var1.get(var1x) + 1); - }); - var1.int2IntEntrySet().forEach((var1x) -> { - var0.accept(this.k.a(var1x.getIntKey()), var1x.getIntValue()); - }); + this.c.a((var1x) -> var1.put(var1x, var1.get(var1x) + 1)); + var1.int2IntEntrySet().forEach((var1x) -> var0.accept(this.k.a(var1x.getIntKey()), var1x.getIntValue())); } @FunctionalInterface diff --git a/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPaletteHash.java b/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPaletteHash.java index 4b9719527..060646e6e 100644 --- a/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPaletteHash.java +++ b/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPaletteHash.java @@ -110,6 +110,11 @@ public class DataPaletteHash implements DataPalette { } } + @Override + public ListTag getPalette() { + return null; + } + public void b(ListTag var0) { for (int var1 = 0; var1 < this.b(); ++var1) { var0.add(this.e.apply(this.b.fromId(var1))); diff --git a/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPaletteLinear.java b/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPaletteLinear.java index 20cd59d6a..7823d40e7 100644 --- a/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPaletteLinear.java +++ b/src/main/java/com/volmit/iris/util/nbt/mca/palettes/DataPaletteLinear.java @@ -112,4 +112,15 @@ public class DataPaletteLinear implements DataPalette { this.f = var0.size(); } + + @Override + public ListTag getPalette() { + ListTag c = (ListTag) ListTag.createUnchecked(CompoundTag.class); + for(T i : b) + { + c.add((CompoundTag) i); + } + + return c; + } }