package com.hbm.util; import net.minecraft.block.Block; import net.minecraft.init.Blocks; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * A snapshot of a 16×16×16 sub-chunk. * @author mlbv */ public class SubChunkSnapshot { /** * A sub-chunk that contains only air. */ public static final SubChunkSnapshot EMPTY = new SubChunkSnapshot(new Block[]{Blocks.air}, null); private final Block[] palette; private final short[] data; private SubChunkSnapshot(Block[] p, short[] d) { this.palette = p; this.data = d; } /** * Creates a SubChunkSnapshot. * * @param world * The World instance from which to retrieve the chunk. * @param key * The SubChunkKey identifying the sub-chunk. * @param allowGeneration * Whether to generate chunks. If false, attempting to retrieve a snapshot of a chunk that does not exist will return {@link SubChunkSnapshot#EMPTY}. * @return * A SubChunkSnapshot containing the palette and block data for the sub-chunk, * or {@link SubChunkSnapshot#EMPTY} if the region contains only air. */ public static SubChunkSnapshot getSnapshot(World world, SubChunkKey key, boolean allowGeneration){ if (!world.getChunkProvider().chunkExists(key.getChunkXPos(), key.getChunkZPos()) && !allowGeneration) { return SubChunkSnapshot.EMPTY; } Chunk chunk = world.getChunkProvider().provideChunk(key.getChunkXPos(), key.getChunkZPos()); ExtendedBlockStorage ebs = chunk.getBlockStorageArray()[key.getSubY()]; if (ebs == null || ebs.isEmpty()) return SubChunkSnapshot.EMPTY; short[] data = new short[16 * 16 * 16]; List palette = new ArrayList<>(); palette.add(Blocks.air); Map idxMap = new HashMap<>(); idxMap.put(Blocks.air, (short) 0); boolean allAir = true; for (int ly = 0; ly < 16; ly++) { for (int lz = 0; lz < 16; lz++) { for (int lx = 0; lx < 16; lx++) { Block block = ebs.getBlockByExtId(lx, ly, lz); int idx; if (block == Blocks.air) { idx = 0; } else { allAir = false; Short e = idxMap.get(block); if (e == null) { idxMap.put(block, (short) palette.size()); palette.add(block); idx = palette.size() - 1; } else { idx = e; } } data[(ly << 8) | (lz << 4) | lx] = (short) idx; } } } if (allAir) return SubChunkSnapshot.EMPTY; return new SubChunkSnapshot(palette.toArray(new Block[0]), data); } /** * Retrieves the Block at the specified local coordinates within this sub-chunk snapshot. * * @param x * The local x-coordinate within the sub-chunk (0–15). * @param y * The local y-coordinate within the sub-chunk (0–15). * @param z * The local z-coordinate within the sub-chunk (0–15). * @return * The Block instance at the given position. */ public Block getBlock(int x, int y, int z) { if (this == EMPTY || data == null) return Blocks.air; short idx = data[(y << 8) | (z << 4) | x]; return (idx >= 0 && idx < palette.length) ? palette[idx] : Blocks.air; } }