diff --git a/src/main/java/com/volmit/iris/engine/data/mca/Section.java b/src/main/java/com/volmit/iris/engine/data/mca/Section.java index 16ab5ea79..dca402198 100644 --- a/src/main/java/com/volmit/iris/engine/data/mca/Section.java +++ b/src/main/java/com/volmit/iris/engine/data/mca/Section.java @@ -25,18 +25,22 @@ import com.volmit.iris.engine.data.nbt.tag.ListTag; import com.volmit.iris.engine.data.nbt.tag.LongArrayTag; import com.volmit.iris.util.collection.KMap; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicLongArray; public class Section { - + private static final Field longArrayStealer = getLongArrayValueField(); private CompoundTag data; private Map> valueIndexedPalette = new KMap<>(); private ListTag palette; private byte[] blockLight; - private long[] blockStates; + private AtomicLongArray blockStates; private byte[] skyLight; private int dataVersion; @@ -65,7 +69,7 @@ public class Section { this.blockLight = blockLight != null ? blockLight.getValue() : null; } if ((loadFlags & LoadFlags.BLOCK_STATES) != 0) { - this.blockStates = blockStates != null ? blockStates.getValue() : null; + this.blockStates = blockStates != null ? new AtomicLongArray(blockStates.getValue()) : null; } if ((loadFlags & LoadFlags.SKY_LIGHT) != 0) { this.skyLight = skyLight != null ? skyLight.getValue() : null; @@ -185,24 +189,24 @@ public class Section { * @return The index of the block data in the palette. */ public int getPaletteIndex(int blockStateIndex) { - int bits = blockStates.length >> 6; + int bits = blockStates.length() >> 6; if (dataVersion < 2527) { - double blockStatesIndex = blockStateIndex / (4096D / blockStates.length); + 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[longIndex], startBit, 64); - long next = bitRange(blockStates[longIndex + 1], 0, 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[longIndex], startBit, startBit + bits); + 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[blockStatesIndex], startBit, startBit + bits); + return (int) bitRange(blockStates.get(blockStatesIndex), startBit, startBit + bits); } } @@ -213,24 +217,24 @@ public class Section { * @param paletteIndex The block state to be set (index of block data in the palette). * @param blockStates The block states to be updated. */ - public void setPaletteIndex(int blockIndex, int paletteIndex, long[] blockStates) { - int bits = blockStates.length >> 6; + public void setPaletteIndex(int blockIndex, int paletteIndex, AtomicLongArray blockStates) { + int bits = blockStates.length() >> 6; if (dataVersion < 2527) { - double blockStatesIndex = blockIndex / (4096D / blockStates.length); + double blockStatesIndex = blockIndex / (4096D / blockStates.length()); int longIndex = (int) blockStatesIndex; int startBit = (int) ((blockStatesIndex - Math.floor(longIndex)) * 64D); if (startBit + bits > 64) { - blockStates[longIndex] = updateBits(blockStates[longIndex], paletteIndex, startBit, 64); - blockStates[longIndex + 1] = updateBits(blockStates[longIndex + 1], paletteIndex, startBit - 64, startBit + bits - 64); + blockStates.set(longIndex, updateBits(blockStates.get(longIndex), paletteIndex, startBit, 64)); + blockStates.set(longIndex + 1, updateBits(blockStates.get(longIndex + 1), paletteIndex, startBit - 64, startBit + bits - 64)); } else { - blockStates[longIndex] = updateBits(blockStates[longIndex], paletteIndex, startBit, startBit + bits); + blockStates.set(longIndex, updateBits(blockStates.get(longIndex), paletteIndex, startBit, startBit + bits)); } } else { int indicesPerLong = (int) (64D / bits); int blockStatesIndex = blockIndex / indicesPerLong; int startBit = (blockIndex % indicesPerLong) * bits; - blockStates[blockStatesIndex] = updateBits(blockStates[blockStatesIndex], paletteIndex, startBit, startBit + bits); + blockStates.set(blockStatesIndex, updateBits(blockStates.get(blockStatesIndex), paletteIndex, startBit, startBit + bits)); } } @@ -304,7 +308,7 @@ public class Section { return allIndices; } - void adjustBlockStateBits(Map oldToNewMapping, long[] blockStates) { + 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(). @@ -312,13 +316,13 @@ public class Section { int newBits = 32 - Integer.numberOfLeadingZeros(palette.size() - 1); newBits = Math.max(newBits, 4); - long[] newBlockStates; + AtomicLongArray newBlockStates; if (dataVersion < 2527) { - newBlockStates = newBits == blockStates.length / 64 ? blockStates : new long[newBits * 64]; + 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 long[newLength]; + newBlockStates = newBits == blockStates.length() / 64 ? blockStates : new AtomicLongArray(newLength); } if (oldToNewMapping != null) { for (int i = 0; i < 4096; i++) { @@ -355,7 +359,7 @@ public class Section { /** * @return The indices of the block states of this Section. */ - public long[] getBlockStates() { + public AtomicLongArray getBlockStates() { return blockStates; } @@ -366,10 +370,10 @@ public class Section { * @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(long[] blockStates) { + 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) { + } 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; @@ -402,7 +406,7 @@ public class Section { */ public static Section newSection() { Section s = new Section(); - s.blockStates = new long[256]; + s.blockStates = new AtomicLongArray(256); s.palette = new ListTag<>(CompoundTag.class); CompoundTag air = new CompoundTag(); air.putString("Name", "minecraft:air"); @@ -428,11 +432,27 @@ public class Section { data.putByteArray("BlockLight", blockLight); } if (blockStates != null) { - data.putLongArray("BlockStates", blockStates); + try { + data.putLongArray("BlockStates", (long[]) longArrayStealer.get(blockStates)); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } } if (skyLight != null) { data.putByteArray("SkyLight", skyLight); } return data; } + + private static Field getLongArrayValueField() { + Field f = null; + try { + f = AtomicLongArray.class.getDeclaredField("array"); + f.setAccessible(true); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } + + return f; + } }