Hbm-s-Nuclear-Tech-GIT/src/main/java/com/hbm/util/SubChunkSnapshot.java
2025-06-12 16:48:37 +08:00

103 lines
3.2 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<Block> palette = new ArrayList<>();
palette.add(Blocks.air);
Map<Block, Short> 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 (015).
* @param y
* The local y-coordinate within the sub-chunk (015).
* @param z
* The local z-coordinate within the sub-chunk (015).
* @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;
}
}