The WorldChunk class represents a 16x16 column of blocks in a Minecraft world, containing blocks, entities, and block actors (tile entities).
Constructor
The constructor is internal. Chunks are created automatically when loading world data.
// Access chunks through MCWorld
const chunk = world.chunks.get(0)?.get(5)?.get(10); // Dimension 0, chunk (5, 10)
Properties
Chunk X coordinate (multiply by 16 for block coordinates).const blockX = chunk.x * 16; // First block X in this chunk
Chunk Z coordinate (multiply by 16 for block coordinates).const blockZ = chunk.z * 16; // First block Z in this chunk
Minimum Y coordinate of loaded subchunks.console.log(`Chunk ranges from Y ${chunk.minY} to ${chunk.maxY}`);
Maximum Y coordinate of loaded subchunks.
Array of block actors (tile entities) in this chunk.for (const actor of chunk.blockActors) {
if (actor.id === 'Chest') {
console.log(`Found chest at (${actor.x}, ${actor.y}, ${actor.z})`);
}
}
Array of entities stored in this chunk (legacy format, pre-1.18.30).for (const entity of chunk.entities) {
console.log(`Entity: ${entity.identifier}`);
}
Reference to the parent world.
Block Access
getBlock
(x: number, y: number, z: number) => Block | undefined
Gets a block at the given chunk-local coordinates (0-15 for x/z).// Get block at chunk-local position (5, 64, 10)
const block = chunk.getBlock(5, 64, 10);
if (block) {
console.log(block.typeName); // "minecraft:stone"
}
getTopBlock
(x: number, z: number) => Block | undefined
Gets the topmost non-air block at the given x/z coordinates.const topBlock = chunk.getTopBlock(8, 8);
console.log(`Surface block: ${topBlock?.typeName}`);
getTopBlockY
(x: number, z: number) => number
Gets the Y coordinate of the topmost block.const surfaceY = chunk.getTopBlockY(8, 8);
console.log(`Surface height: ${surfaceY}`);
Returns all blocks in the chunk as a flat array.This allocates a Block object for every position and can use significant memory for large chunks. Consider using countBlockTypes() for analysis.
const blocks = chunk.getBlockList();
console.log(`Total blocks: ${blocks.length}`);
countBlockTypes
() => Map<string, number>
Efficiently counts block types without allocating Block objects.const counts = chunk.countBlockTypes();
for (const [type, count] of counts) {
console.log(`${type}: ${count}`);
}
// Output:
// minecraft:stone: 15234
// minecraft:dirt: 8921
// minecraft:air: 40000
Memory Management
Clears parsed chunk data while preserving raw LevelDB data. The chunk can be re-parsed later.// Free memory but allow re-parsing
chunk.clearCachedData();
// Later, accessing blocks will trigger re-parsing
const block = chunk.getBlock(0, 64, 0);
Clears all chunk data including raw bytes. Cannot re-parse after this.After calling this, the chunk data cannot be accessed without reloading the entire world.
chunk.clearAllData();
// Chunk is now empty and cannot be used
Subchunks
Chunks are divided into 16-block-tall subchunks for efficient storage:
getSubChunkCube
(subChunkId: number) => BlockVolume
Gets all blocks in a subchunk as a 16x16x16 volume.// Get subchunk at Y=64-79 (subchunk 4 for worlds with minY=0)
const volume = chunk.getSubChunkCube(4);
fillCube
(cube: BlockVolume, cubeX: number, cubeY: number, cubeZ: number, maxCubeX: number, maxCubeY: number, maxCubeZ: number, internalOffsetX: number, internalOffsetY: number, internalOffsetZ: number) => void
Fills a BlockVolume with chunk data.const volume = new BlockVolume();
volume.maxX = 16;
volume.maxY = 16;
volume.maxZ = 16;
chunk.fillCube(volume, 0, 0, 0, 16, 16, 16, 0, 64, 0);
Example: Analyzing Chunk Contents
import { MCWorld } from '@minecraft/creator-tools';
async function analyzeChunk(world: MCWorld, chunkX: number, chunkZ: number) {
const chunk = world.chunks.get(0)?.get(chunkX)?.get(chunkZ);
if (!chunk) {
console.log('Chunk not loaded');
return;
}
console.log(`Analyzing chunk at (${chunk.x}, ${chunk.z})`);
console.log(`Height range: ${chunk.minY} to ${chunk.maxY}`);
// Count block types efficiently
const blockCounts = chunk.countBlockTypes();
// Find most common blocks
const sorted = [...blockCounts.entries()]
.filter(([type]) => type !== 'minecraft:air')
.sort((a, b) => b[1] - a[1])
.slice(0, 5);
console.log('Top 5 blocks:');
for (const [type, count] of sorted) {
console.log(` ${type}: ${count}`);
}
// Check for interesting block actors
const chests = chunk.blockActors.filter(ba => ba.id === 'Chest');
const spawners = chunk.blockActors.filter(ba => ba.id === 'MobSpawner');
console.log(`Chests: ${chests.length}`);
console.log(`Spawners: ${spawners.length}`);
// Get surface height at center
const centerHeight = chunk.getTopBlockY(8, 8);
console.log(`Surface height at center: ${centerHeight}`);
// Free memory
chunk.clearCachedData();
}
Example: Finding Specific Blocks
interface BlockPosition {
x: number;
y: number;
z: number;
type: string;
}
function findDiamonds(chunk: WorldChunk): BlockPosition[] {
const diamonds: BlockPosition[] = [];
// Iterate through potential diamond Y levels (-64 to 16)
for (let y = -64; y <= 16; y++) {
for (let x = 0; x < 16; x++) {
for (let z = 0; z < 16; z++) {
const block = chunk.getBlock(x, y, z);
if (block?.typeName === 'minecraft:diamond_ore' ||
block?.typeName === 'minecraft:deepslate_diamond_ore') {
diamonds.push({
x: chunk.x * 16 + x,
y: y,
z: chunk.z * 16 + z,
type: block.typeName
});
}
}
}
}
return diamonds;
}
Example: Creating a Height Map
function createHeightMap(chunk: WorldChunk): number[][] {
const heightMap: number[][] = [];
for (let x = 0; x < 16; x++) {
heightMap[x] = [];
for (let z = 0; z < 16; z++) {
heightMap[x][z] = chunk.getTopBlockY(x, z);
}
}
return heightMap;
}
function visualizeHeightMap(heightMap: number[][]): string {
const minY = Math.min(...heightMap.flat());
const maxY = Math.max(...heightMap.flat());
let output = '';
for (let z = 0; z < 16; z++) {
for (let x = 0; x < 16; x++) {
const height = heightMap[x][z];
const normalized = (height - minY) / (maxY - minY);
const chars = ' .:-=+*#%@';
const charIndex = Math.floor(normalized * (chars.length - 1));
output += chars[charIndex];
}
output += '\n';
}
return output;
}
Block Actors (Tile Entities)
Block actors are blocks with additional data (chests, signs, spawners, etc.):
function analyzeBlockActors(chunk: WorldChunk) {
for (const actor of chunk.blockActors) {
console.log(`${actor.id} at (${actor.x}, ${actor.y}, ${actor.z})`);
// Type-specific handling
if (actor.id === 'Sign') {
// Access sign text
const signData = actor as SignBlockActor;
console.log(` Text: ${signData.text}`);
} else if (actor.id === 'Chest') {
// Access chest contents
const chestData = actor as ChestBlockActor;
console.log(` Items: ${chestData.items?.length || 0}`);
}
}
}
Chunk Coordinates
Chunks use a coordinate system where each chunk is 16x16 blocks:
// Convert block coordinates to chunk coordinates
function getChunkCoords(blockX: number, blockZ: number) {
return {
chunkX: Math.floor(blockX / 16),
chunkZ: Math.floor(blockZ / 16),
localX: ((blockX % 16) + 16) % 16,
localZ: ((blockZ % 16) + 16) % 16
};
}
// Example
const coords = getChunkCoords(100, -50);
console.log(coords);
// { chunkX: 6, chunkZ: -4, localX: 4, localZ: 14 }
// Access the chunk
const chunk = world.chunks.get(0)?.get(coords.chunkX)?.get(coords.chunkZ);
if (chunk) {
const block = chunk.getBlock(coords.localX, 64, coords.localZ);
}
- Use
countBlockTypes() instead of getBlockList() when analyzing block distribution
- Call
clearCachedData() after processing to free memory
- Use
forEachChunk() on the world for batch processing with automatic memory management
- Cache frequently accessed data rather than repeatedly parsing chunks
// Good: Memory-efficient counting
const counts = chunk.countBlockTypes();
const stoneCount = counts.get('minecraft:stone') || 0;
// Bad: Allocates thousands of Block objects
const blocks = chunk.getBlockList();
const stoneCount = blocks.filter(b => b.typeName === 'minecraft:stone').length;