diff --git a/src/main/java/me/jellysquid/mods/sodium/client/world/PaletteStorageExtended.java b/src/main/java/me/jellysquid/mods/sodium/client/world/PaletteStorageExtended.java new file mode 100644 index 0000000000..45a260fc46 --- /dev/null +++ b/src/main/java/me/jellysquid/mods/sodium/client/world/PaletteStorageExtended.java @@ -0,0 +1,7 @@ +package me.jellysquid.mods.sodium.client.world; + +import net.minecraft.world.chunk.Palette; + +public interface PaletteStorageExtended { + void sodium$unpack(T[] out, Palette palette); +} diff --git a/src/main/java/me/jellysquid/mods/sodium/client/world/ReadableContainerExtended.java b/src/main/java/me/jellysquid/mods/sodium/client/world/ReadableContainerExtended.java new file mode 100644 index 0000000000..71746d4cb0 --- /dev/null +++ b/src/main/java/me/jellysquid/mods/sodium/client/world/ReadableContainerExtended.java @@ -0,0 +1,23 @@ +package me.jellysquid.mods.sodium.client.world; + +import net.minecraft.world.chunk.ReadableContainer; + +public interface ReadableContainerExtended { + @SuppressWarnings("unchecked") + static ReadableContainerExtended of(ReadableContainer container) { + return (ReadableContainerExtended) container; + } + + static ReadableContainer clone(ReadableContainer container) { + if (container == null) { + return null; + } + + return of(container).sodium$copy(); + } + + void sodium$unpack(T[] values); + void sodium$unpack(T[] values, int minX, int minY, int minZ, int maxX, int maxY, int maxZ); + + ReadableContainer sodium$copy(); +} diff --git a/src/main/java/me/jellysquid/mods/sodium/client/world/WorldSlice.java b/src/main/java/me/jellysquid/mods/sodium/client/world/WorldSlice.java index 33336cccbb..74fcf85fdc 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/world/WorldSlice.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/world/WorldSlice.java @@ -8,8 +8,6 @@ import me.jellysquid.mods.sodium.client.world.cloned.ChunkRenderContext; import me.jellysquid.mods.sodium.client.world.cloned.ClonedChunkSection; import me.jellysquid.mods.sodium.client.world.cloned.ClonedChunkSectionCache; -import me.jellysquid.mods.sodium.client.world.cloned.PackedIntegerArrayExtended; -import me.jellysquid.mods.sodium.client.world.cloned.palette.ClonedPalette; import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -17,7 +15,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.world.ClientWorld; import net.minecraft.fluid.FluidState; -import net.minecraft.util.collection.PackedIntegerArray; import net.minecraft.util.math.*; import net.minecraft.world.BlockRenderView; import net.minecraft.world.LightType; @@ -27,7 +24,6 @@ import net.minecraft.world.chunk.ChunkSection; import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.chunk.light.LightingProvider; -import org.apache.commons.lang3.Validate; import org.jetbrains.annotations.Nullable; import java.util.Arrays; @@ -176,59 +172,34 @@ private void copySectionData(ChunkRenderContext context, int sectionIndex) { private void unpackBlockData(BlockState[] blockArray, ChunkRenderContext context, ClonedChunkSection section) { if (section.getBlockData() == null) { - this.unpackBlockDataEmpty(blockArray); - } else if (context.getOrigin().equals(section.getPosition())) { - this.unpackBlockDataWhole(blockArray, section); - } else { - this.unpackBlockDataPartial(blockArray, section, context.getVolume()); + Arrays.fill(blockArray, Blocks.AIR.getDefaultState()); + return; } - } - - private void unpackBlockDataEmpty(BlockState[] blockArray) { - Arrays.fill(blockArray, Blocks.AIR.getDefaultState()); - } - - private void unpackBlockDataPartial(BlockState[] states, ClonedChunkSection section, BlockBox box) { - PackedIntegerArray array = section.getBlockData(); - Objects.requireNonNull(array); - ClonedPalette palette = section.getBlockPalette(); - Objects.requireNonNull(palette); + var container = ReadableContainerExtended.of(section.getBlockData()); + ChunkSectionPos origin = context.getOrigin(); ChunkSectionPos pos = section.getPosition(); - int minBlockX = Math.max(box.getMinX(), pos.getMinX()); - int maxBlockX = Math.min(box.getMaxX(), pos.getMaxX()); - - int minBlockY = Math.max(box.getMinY(), pos.getMinY()); - int maxBlockY = Math.min(box.getMaxY(), pos.getMaxY()); - - int minBlockZ = Math.max(box.getMinZ(), pos.getMinZ()); - int maxBlockZ = Math.min(box.getMaxZ(), pos.getMaxZ()); + if (origin.equals(pos)) { + container.sodium$unpack(blockArray); + } else { + var bounds = context.getVolume(); - for (int y = minBlockY; y <= maxBlockY; y++) { - for (int z = minBlockZ; z <= maxBlockZ; z++) { - for (int x = minBlockX; x <= maxBlockX; x++) { - int localBlockIndex = getLocalBlockIndex(x & 15, y & 15, z & 15); + int minBlockX = Math.max(bounds.getMinX(), pos.getMinX()); + int maxBlockX = Math.min(bounds.getMaxX(), pos.getMaxX()); - int paletteIndex = array.get(localBlockIndex); - var paletteValue = palette.get(paletteIndex); + int minBlockY = Math.max(bounds.getMinY(), pos.getMinY()); + int maxBlockY = Math.min(bounds.getMaxY(), pos.getMaxY()); - if (paletteValue == null) { - throw new IllegalStateException("Palette does not contain entry: " + paletteIndex); - } + int minBlockZ = Math.max(bounds.getMinZ(), pos.getMinZ()); + int maxBlockZ = Math.min(bounds.getMaxZ(), pos.getMaxZ()); - states[localBlockIndex] = paletteValue; - } - } + container.sodium$unpack(blockArray, minBlockX & 15, minBlockY & 15, minBlockZ & 15, + maxBlockX & 15, maxBlockY & 15, maxBlockZ & 15); } } - private void unpackBlockDataWhole(BlockState[] states, ClonedChunkSection section) { - ((PackedIntegerArrayExtended) section.getBlockData()) - .sodium$unpack(states, section.getBlockPalette()); - } - public void reset() { // erase any pointers to resources we no longer need // no point in cleaning the pre-allocated arrays (such as block state storage) since we hold the diff --git a/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/ClonedChunkSection.java b/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/ClonedChunkSection.java index 944f080b9a..b0ec3ef338 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/ClonedChunkSection.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/ClonedChunkSection.java @@ -3,24 +3,23 @@ import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; import it.unimi.dsi.fastutil.ints.Int2ReferenceMaps; import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; +import me.jellysquid.mods.sodium.client.world.ReadableContainerExtended; import me.jellysquid.mods.sodium.client.world.WorldSlice; -import me.jellysquid.mods.sodium.client.world.cloned.palette.ClonedPalette; -import me.jellysquid.mods.sodium.client.world.cloned.palette.ClonedPaletteFallback; -import me.jellysquid.mods.sodium.client.world.cloned.palette.ClonedPalleteArray; -import me.jellysquid.mods.sodium.mixin.core.world.chunk.PalettedContainerAccessor; import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachmentBlockEntity; -import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.util.collection.PackedIntegerArray; import net.minecraft.util.math.BlockBox; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkSectionPos; import net.minecraft.world.LightType; import net.minecraft.world.World; import net.minecraft.world.biome.Biome; -import net.minecraft.world.chunk.*; +import net.minecraft.world.chunk.ChunkNibbleArray; +import net.minecraft.world.chunk.ChunkSection; +import net.minecraft.world.chunk.ReadableContainer; +import net.minecraft.world.chunk.WorldChunk; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Map; @@ -31,52 +30,66 @@ public class ClonedChunkSection { private final ChunkSectionPos pos; - private @Nullable Int2ReferenceMap blockEntities; - private @Nullable Int2ReferenceMap blockEntityAttachments; + private final @Nullable Int2ReferenceMap blockEntityMap; + private final @Nullable Int2ReferenceMap blockEntityAttachmentMap; - private final @Nullable ChunkNibbleArray[] lightDataArrays = new ChunkNibbleArray[LightType.values().length]; + private final @Nullable ChunkNibbleArray[] lightDataArrays; - private @Nullable PackedIntegerArray blockStateData; - private @Nullable ClonedPalette blockStatePalette; + private final @Nullable ReadableContainer blockData; - private @Nullable ReadableContainer> biomeData; + private final @Nullable ReadableContainer> biomeData; private long lastUsedTimestamp = Long.MAX_VALUE; public ClonedChunkSection(World world, WorldChunk chunk, @Nullable ChunkSection section, ChunkSectionPos pos) { this.pos = pos; + ReadableContainer blockData = null; + ReadableContainer> biomeData = null; + + Int2ReferenceMap blockEntityMap = null; + Int2ReferenceMap blockEntityAttachmentMap = null; + if (section != null) { if (!section.isEmpty()) { - this.copyBlockData(section); - this.copyBlockEntities(chunk, pos); + blockData = ReadableContainerExtended.clone(section.getBlockStateContainer()); + blockEntityMap = copyBlockEntities(chunk, pos); + + if (blockEntityMap != null) { + blockEntityAttachmentMap = copyBlockEntityAttachments(blockEntityMap); + } } - this.copyBiomeData(section); + + biomeData = ReadableContainerExtended.clone(section.getBiomeContainer()); } - this.copyLightData(world); - } + this.blockData = blockData; + this.biomeData = biomeData; - private void copyBlockData(ChunkSection section) { - PalettedContainer.Data container = ((PalettedContainerAccessor) section.getBlockStateContainer()).getData(); + this.blockEntityMap = blockEntityMap; + this.blockEntityAttachmentMap = blockEntityAttachmentMap; - this.blockStateData = copyBlockData(container); - this.blockStatePalette = copyPalette(container); + this.lightDataArrays = copyLightData(world, pos); } - private void copyLightData(World world) { - this.lightDataArrays[LightType.BLOCK.ordinal()] = copyLightArray(world, LightType.BLOCK, this.pos); + @NotNull + private static ChunkNibbleArray[] copyLightData(World world, ChunkSectionPos pos) { + var arrays = new ChunkNibbleArray[2]; + arrays[LightType.BLOCK.ordinal()] = copyLightArray(world, LightType.BLOCK, pos); // Dimensions without sky-light should not have a default-initialized array if (world.getDimension().hasSkyLight()) { - this.lightDataArrays[LightType.SKY.ordinal()] = copyLightArray(world, LightType.SKY, this.pos); + arrays[LightType.SKY.ordinal()] = copyLightArray(world, LightType.SKY, pos); } + + return arrays; } /** * Copies the light data array for the given light type for this chunk, or returns a default-initialized value if * the light array is not loaded. */ + @NotNull private static ChunkNibbleArray copyLightArray(World world, LightType type, ChunkSectionPos pos) { var array = world.getLightingProvider() .get(type) @@ -92,11 +105,8 @@ private static ChunkNibbleArray copyLightArray(World world, LightType type, Chun return array; } - private void copyBiomeData(ChunkSection section) { - this.biomeData = section.getBiomeContainer(); - } - - private void copyBlockEntities(WorldChunk chunk, ChunkSectionPos chunkCoord) { + @Nullable + private static Int2ReferenceMap copyBlockEntities(WorldChunk chunk, ChunkSectionPos chunkCoord) { BlockBox box = new BlockBox(chunkCoord.getMinX(), chunkCoord.getMinY(), chunkCoord.getMinZ(), chunkCoord.getMaxX(), chunkCoord.getMaxY(), chunkCoord.getMaxZ()); @@ -116,15 +126,18 @@ private void copyBlockEntities(WorldChunk chunk, ChunkSectionPos chunkCoord) { } } - this.blockEntities = blockEntities != null ? blockEntities : Int2ReferenceMaps.emptyMap(); + return blockEntities; + } + @Nullable + private static Int2ReferenceMap copyBlockEntityAttachments(Int2ReferenceMap blockEntities) { Int2ReferenceOpenHashMap blockEntityAttachments = null; // Retrieve any render attachments after we have copied all block entities, as this will call into the code of // other mods. This could potentially result in the chunk being modified, which would cause problems if we // were iterating over any data in that chunk. // See https://github.com/CaffeineMC/sodium-fabric/issues/942 for more info. - for (var entry : Int2ReferenceMaps.fastIterable(this.blockEntities)) { + for (var entry : Int2ReferenceMaps.fastIterable(blockEntities)) { if (entry.getValue() instanceof RenderAttachmentBlockEntity holder) { if (blockEntityAttachments == null) { blockEntityAttachments = new Int2ReferenceOpenHashMap<>(); @@ -134,51 +147,31 @@ private void copyBlockEntities(WorldChunk chunk, ChunkSectionPos chunkCoord) { } } - this.blockEntityAttachments = blockEntityAttachments != null ? blockEntityAttachments : Int2ReferenceMaps.emptyMap(); + return blockEntityAttachments; } - public @Nullable ReadableContainer> getBiomeData() { - return this.biomeData; + public ChunkSectionPos getPosition() { + return this.pos; } - public @Nullable PackedIntegerArray getBlockData() { - return this.blockStateData; + public @Nullable ReadableContainer getBlockData() { + return this.blockData; } - public @Nullable ClonedPalette getBlockPalette() { - return this.blockStatePalette; + public @Nullable ReadableContainer> getBiomeData() { + return this.biomeData; } - public ChunkSectionPos getPosition() { - return this.pos; + public @Nullable Int2ReferenceMap getBlockEntityMap() { + return this.blockEntityMap; } - private static ClonedPalette copyPalette(PalettedContainer.Data container) { - Palette palette = container.palette(); - - if (palette instanceof IdListPalette) { - return new ClonedPaletteFallback<>(Block.STATE_IDS); - } - - BlockState[] array = new BlockState[container.palette().getSize()]; - - for (int i = 0; i < array.length; i++) { - array[i] = palette.get(i); - } - - return new ClonedPalleteArray<>(array); + public @Nullable Int2ReferenceMap getBlockEntityAttachmentMap() { + return this.blockEntityAttachmentMap; } - private static PackedIntegerArray copyBlockData(PalettedContainer.Data container) { - var storage = container.storage(); - var data = storage.getData(); - var bits = container.configuration().bits(); - - if (bits == 0) { - return null; - } - - return new PackedIntegerArray(bits, storage.getSize(), data.clone()); + public @Nullable ChunkNibbleArray getLightArray(LightType lightType) { + return this.lightDataArrays[lightType.ordinal()]; } public long getLastUsedTimestamp() { @@ -188,16 +181,4 @@ public long getLastUsedTimestamp() { public void setLastUsedTimestamp(long timestamp) { this.lastUsedTimestamp = timestamp; } - - public @Nullable Int2ReferenceMap getBlockEntityMap() { - return this.blockEntities; - } - - public @Nullable Int2ReferenceMap getBlockEntityAttachmentMap() { - return this.blockEntityAttachments; - } - - public @Nullable ChunkNibbleArray getLightArray(LightType lightType) { - return this.lightDataArrays[lightType.ordinal()]; - } } diff --git a/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/PackedIntegerArrayExtended.java b/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/PackedIntegerArrayExtended.java deleted file mode 100644 index eaaa33df3d..0000000000 --- a/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/PackedIntegerArrayExtended.java +++ /dev/null @@ -1,7 +0,0 @@ -package me.jellysquid.mods.sodium.client.world.cloned; - -import me.jellysquid.mods.sodium.client.world.cloned.palette.ClonedPalette; - -public interface PackedIntegerArrayExtended { - void sodium$unpack(T[] out, ClonedPalette palette); -} diff --git a/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/palette/ClonedPalette.java b/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/palette/ClonedPalette.java deleted file mode 100644 index 8944da9889..0000000000 --- a/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/palette/ClonedPalette.java +++ /dev/null @@ -1,5 +0,0 @@ -package me.jellysquid.mods.sodium.client.world.cloned.palette; - -public interface ClonedPalette { - K get(int id); -} diff --git a/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/palette/ClonedPaletteFallback.java b/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/palette/ClonedPaletteFallback.java deleted file mode 100644 index c8ed02f4a4..0000000000 --- a/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/palette/ClonedPaletteFallback.java +++ /dev/null @@ -1,16 +0,0 @@ -package me.jellysquid.mods.sodium.client.world.cloned.palette; - -import net.minecraft.util.collection.IdList; - -public class ClonedPaletteFallback implements ClonedPalette { - private final IdList idList; - - public ClonedPaletteFallback(IdList idList) { - this.idList = idList; - } - - @Override - public K get(int id) { - return this.idList.get(id); - } -} diff --git a/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/palette/ClonedPalleteArray.java b/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/palette/ClonedPalleteArray.java deleted file mode 100644 index d5f3a69147..0000000000 --- a/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/palette/ClonedPalleteArray.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.jellysquid.mods.sodium.client.world.cloned.palette; - -import org.apache.commons.lang3.Validate; - -public class ClonedPalleteArray implements ClonedPalette { - private final K[] array; - - public ClonedPalleteArray(K[] array) { - this.array = array; - } - - @Override - public K get(int id) { - // TODO: Remove this check? - return Validate.notNull(this.array[id]); - } -} diff --git a/src/main/java/me/jellysquid/mods/sodium/mixin/core/world/chunk/EmptyPaletteStorageMixin.java b/src/main/java/me/jellysquid/mods/sodium/mixin/core/world/chunk/EmptyPaletteStorageMixin.java new file mode 100644 index 0000000000..e82e6c1c4a --- /dev/null +++ b/src/main/java/me/jellysquid/mods/sodium/mixin/core/world/chunk/EmptyPaletteStorageMixin.java @@ -0,0 +1,28 @@ +package me.jellysquid.mods.sodium.mixin.core.world.chunk; + +import me.jellysquid.mods.sodium.client.world.PaletteStorageExtended; +import net.minecraft.util.collection.EmptyPaletteStorage; +import net.minecraft.world.chunk.Palette; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Arrays; +import java.util.Objects; + +@Mixin(EmptyPaletteStorage.class) +public class EmptyPaletteStorageMixin implements PaletteStorageExtended { + @Shadow + @Final + private int size; + + @Override + public void sodium$unpack(T[] out, Palette palette) { + if (this.size != out.length) { + throw new IllegalArgumentException("Array has mismatched size"); + } + + var defaultEntry = Objects.requireNonNull(palette.get(0), "Palette must have default entry"); + Arrays.fill(out, defaultEntry); + } +} diff --git a/src/main/java/me/jellysquid/mods/sodium/mixin/core/world/chunk/PackedIntegerArrayMixin.java b/src/main/java/me/jellysquid/mods/sodium/mixin/core/world/chunk/PackedIntegerArrayMixin.java index fd193e6898..193a5d6fb2 100644 --- a/src/main/java/me/jellysquid/mods/sodium/mixin/core/world/chunk/PackedIntegerArrayMixin.java +++ b/src/main/java/me/jellysquid/mods/sodium/mixin/core/world/chunk/PackedIntegerArrayMixin.java @@ -1,14 +1,16 @@ package me.jellysquid.mods.sodium.mixin.core.world.chunk; -import me.jellysquid.mods.sodium.client.world.cloned.PackedIntegerArrayExtended; -import me.jellysquid.mods.sodium.client.world.cloned.palette.ClonedPalette; +import me.jellysquid.mods.sodium.client.world.PaletteStorageExtended; import net.minecraft.util.collection.PackedIntegerArray; +import net.minecraft.world.chunk.Palette; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import java.util.Objects; + @Mixin(PackedIntegerArray.class) -public class PackedIntegerArrayMixin implements PackedIntegerArrayExtended { +public class PackedIntegerArrayMixin implements PaletteStorageExtended { @Shadow @Final private long[] data; @@ -30,14 +32,15 @@ public class PackedIntegerArrayMixin implements PackedIntegerArrayExtended { private int size; @Override - public void sodium$unpack(T[] out, ClonedPalette palette) { + public void sodium$unpack(T[] out, Palette palette) { int idx = 0; for (long word : this.data) { long l = word; for (int j = 0; j < this.elementsPerLong; ++j) { - out[idx] = palette.get((int) (l & this.maxValue)); + out[idx] = Objects.requireNonNull(palette.get((int) (l & this.maxValue)), + "Palette does not contain entry for value in storage"); l >>= this.elementBits; if (++idx >= this.size) { diff --git a/src/main/java/me/jellysquid/mods/sodium/mixin/core/world/chunk/PalettedContainerAccessor.java b/src/main/java/me/jellysquid/mods/sodium/mixin/core/world/chunk/PalettedContainerAccessor.java deleted file mode 100644 index a408128816..0000000000 --- a/src/main/java/me/jellysquid/mods/sodium/mixin/core/world/chunk/PalettedContainerAccessor.java +++ /dev/null @@ -1,11 +0,0 @@ -package me.jellysquid.mods.sodium.mixin.core.world.chunk; - -import net.minecraft.world.chunk.PalettedContainer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(PalettedContainer.class) -public interface PalettedContainerAccessor { - @Accessor - PalettedContainer.Data getData(); -} diff --git a/src/main/java/me/jellysquid/mods/sodium/mixin/core/world/chunk/PalettedContainerMixin.java b/src/main/java/me/jellysquid/mods/sodium/mixin/core/world/chunk/PalettedContainerMixin.java new file mode 100644 index 0000000000..d805caeba4 --- /dev/null +++ b/src/main/java/me/jellysquid/mods/sodium/mixin/core/world/chunk/PalettedContainerMixin.java @@ -0,0 +1,71 @@ +package me.jellysquid.mods.sodium.mixin.core.world.chunk; + +import me.jellysquid.mods.sodium.client.world.PaletteStorageExtended; +import me.jellysquid.mods.sodium.client.world.ReadableContainerExtended; +import net.minecraft.world.chunk.PalettedContainer; +import net.minecraft.world.chunk.ReadableContainer; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Objects; + +@Mixin(PalettedContainer.class) +public abstract class PalettedContainerMixin implements ReadableContainerExtended { + + @Shadow + private volatile PalettedContainer.Data data; + + @Shadow + @Final + private PalettedContainer.PaletteProvider paletteProvider; + + @Shadow + public abstract PalettedContainer copy(); + + @Override + public void sodium$unpack(T[] values) { + var indexer = Objects.requireNonNull(this.paletteProvider); + + if (values.length != indexer.getContainerSize()) { + throw new IllegalArgumentException("Array is wrong size"); + } + + var data = Objects.requireNonNull(this.data, "PalettedContainer must have data"); + + var storage = (PaletteStorageExtended) data.storage(); + storage.sodium$unpack(values, data.palette()); + } + + @Override + public void sodium$unpack(T[] values, int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { + var indexer = Objects.requireNonNull(this.paletteProvider); + + if (values.length != indexer.getContainerSize()) { + throw new IllegalArgumentException("Array is wrong size"); + } + + var data = Objects.requireNonNull(this.data, "PalettedContainer must have data"); + + var storage = data.storage(); + var palette = data.palette(); + + for (int y = minY; y <= maxY; y++) { + for (int z = minZ; z <= maxZ; z++) { + for (int x = minX; x <= maxX; x++) { + int localBlockIndex = indexer.computeIndex(x, y, z); + + int paletteIndex = storage.get(localBlockIndex); + var paletteValue = palette.get(paletteIndex); + + values[localBlockIndex] = paletteValue; + } + } + } + } + + @Override + public ReadableContainer sodium$copy() { + return this.copy(); + } +} diff --git a/src/main/resources/sodium.mixins.json b/src/main/resources/sodium.mixins.json index 705f88575a..16466fad53 100644 --- a/src/main/resources/sodium.mixins.json +++ b/src/main/resources/sodium.mixins.json @@ -26,8 +26,9 @@ "core.render.world.ChunkBuilderMixin", "core.render.world.WorldRendererMixin", "core.world.biome.ClientWorldMixin", + "core.world.chunk.EmptyPaletteStorageMixin", "core.world.chunk.PackedIntegerArrayMixin", - "core.world.chunk.PalettedContainerAccessor", + "core.world.chunk.PalettedContainerMixin", "core.world.map.ClientChunkManagerMixin", "core.world.map.ClientPlayNetworkHandlerMixin", "core.world.map.ClientWorldMixin",