Skip to main content

World & Blocks

session.levelState is a LevelStateTracker — the world model: blocks, chunks, ray-tracing, collision, and the block-state registry.

LevelStateTracker

Reading & writing blocks

MemberSignatureDescription
getBlock(x, y, z, layer?)BlockStateBlock state at a world position (layer 0 by default).
setBlock(x, y, z, layer, blockState)voidSet a block state client-side only (not sent to the server).
getBlockEntity(x, y, z)BlockEntity | undefinedBlock entity at a world position, if any.
providerBlockStateProviderThe block-state registry (look blocks up by name).
const block = ctx.session.levelState.getBlock(100, 64, 100);
console.log(block.name); // "minecraft:stone"
console.log(block.states); // { ... }
console.log(block.meta.isFullBlock); // true

Ray-tracing & collision

MemberSignatureDescription
rayTrace(position, direction, maxDistance){ block, blockPosition, position, face } | nullRay-trace against world blocks; returns the hit, or null.
checkCollision(position, motion){ verticalCollision, horizontalCollision }Collision flags for a player at position after applying motion.
getCollidingBlocks(aabb)AABB[]World-space collision boxes intersecting the given AABB.
const p = ctx.session.entityState.localPlayer;
const hit = ctx.session.levelState.rayTrace(p.eyePosition, /* dir */ p.motion, 5);
if (hit) console.log("looking at", hit.block.name, "face", hit.face);

Chunks & dimension

MemberSignatureDescription
getChunk(chunkX, chunkZ)Chunk | undefinedA loaded chunk by chunk coordinates.
getSubChunk(chunkX, chunkZ, subChunkY)SubChunk | undefinedA subchunk.
chunkStorageMap<bigint, Chunk>Loaded chunks, keyed by chunk key.
chunkRadiusnumber | nullServer view distance in chunks, if known.
get dimensionDimensionDataThe current dimension's data.
dimensionIdnumberCurrent dimension index.
dimensionListDimensionData[]Known dimensions.
difficultynumber0 = peaceful, 1 = easy, 2 = normal, 3 = hard.
seedbigintWorld seed.

BlockState

The resolved state of a single block. Implements PaletteItem.

MemberTypeDescription
runtimeIdnumberNetwork runtime id of this block state.
hashnumberIdentity hash of this block state.
namestringBlock identifier, e.g. minecraft:stone.
get statesRecord<string, any>Simplified block-state values, e.g. { facing_direction: 2 }.
nbtStatesTags['compound']Raw NBT block-state compound.
tagsSet<string>Block tags.
metaBlockMetaDerived block metadata (see below).

BlockMeta

MemberType
hardnessnumber
frictionnumber
collisionShapeAABB[]
visualShapeAABB
mapColor[number, number, number, number]
requiresCorrectToolForDropsboolean
isFullBlockboolean

BlockStateProvider

levelState.provider — look up any block state by identifier:

const stone = ctx.session.levelState.provider.getBlock("minecraft:stone");
// BlockState | undefined

DimensionData

MemberTypeDescription
handlestringDimension identifier.
min_heightnumberLowest block Y.
max_heightnumberHighest block Y.

Chunks: Chunk, SubChunk, Palette

Chunk and SubChunk are value exports, so you can name them and narrow with instanceof.

Chunk

MemberSignatureDescription
x / znumberChunk coordinates (block coord >> 4).
providerBlockStateProviderResolves runtime IDs in this chunk.
subChunksSubChunk[]Subchunks, index 0 = bottom (see dimension.min_height).
blockEntitiesBlockEntity[]Block entities tracked in this chunk.
key()bigint64-bit storage key (packed X/Z).
getSubChunk(i)SubChunkSubchunk at vertical index i (0 = bottom).

SubChunk

A 16×16×16 section. Block positions inside are packed indices (0–4095).

MemberSignatureDescription
providerBlockStateProviderResolves runtime IDs.
parentChunkThe owning chunk.
defaultLayerPalette<BlockState>Layer 0 (primary block layer).
extraLayersPalette<BlockState>[]Extra layers (e.g. waterlogging); index 0 = layer 1.
index(x, y, z)numberPack local coords (0–15) into a block index.
fromIndex(index){ x, y, z }Unpack a block index into local coords.
getBlock(x, y, z, layer?)BlockStateRead a block at local coords.
setBlock(x, y, z, layer, block)voidWrite a block at local coords.
hasBlock(block, layer?)booleanWhether the block appears on the layer.
getLayer(layer)Palette<BlockState>The palette for a layer (0 = default).

Palette<T>

Backs a subchunk layer — the distinct entries plus per-position lookup.

MemberSignatureDescription
paletteT[]The distinct entries present (e.g. block states).
get(index)TEntry at a block index.
set(index, value)voidSet the entry at a block index.
has(item)booleanWhether the entry is present.
positions(item)Generator<number>Iterate every block index holding item.

Iterating all stone in a subchunk:

const sub = ctx.session.levelState.getSubChunk(0, 0, 4);
if (sub) {
for (const block of sub.defaultLayer.palette) {
if (block.name === "minecraft:stone") {
for (const idx of sub.defaultLayer.positions(block)) {
const { x, y, z } = sub.fromIndex(idx); // local 0-15
}
}
}
}

Tracking blocks: AbstractBlockLocationTracker

To maintain a live set of blocks in the world — kept in sync as chunks load, unload, and blocks update — subclass AbstractBlockLocationTracker<T>. This is the same primitive the built-in Chest ESP / Block ESP modules use.

You implement three methods; the base handles the chunk/block bookkeeping:

MemberSignatureDescription
canTrackBlock(block)booleanYou implement. Return true for blocks to track.
onBlockAdded(entry)voidYou implement. A tracked block appeared.
onBlockRemoved(entry)voidYou implement. A tracked block was removed.
entriesMap<bigint, BlockEntry<T>>All currently tracked blocks, keyed by packed position.
reset()voidRe-scan all loaded chunks.
bindToSession(session)voidAttach and scan already-loaded chunks.
unbindFromSession()voidDetach and clear.

BlockEntry<T> extends IVector3 (x/y/z) and adds block: BlockState and an optional extra?: T.

import { AbstractBlockLocationTracker, type BlockState } from "@protohax/userscript";

class DiamondOreTracker extends AbstractBlockLocationTracker<void> {
canTrackBlock(block: BlockState): boolean {
return block.name === "minecraft:diamond_ore";
}
onBlockAdded(entry) {
console.log("diamond at", entry.x, entry.y, entry.z);
}
onBlockRemoved(entry) {
console.log("gone", entry.x, entry.y, entry.z);
}
}

defineModule({ name: "DiamondFinder", category: ModuleCategory.Utility }, () => (ctx) => {
const tracker = new DiamondOreTracker();
ctx.onEnable(() => tracker.bindToSession(ctx.session));
ctx.onDisable(() => tracker.unbindFromSession());
});

Note — client-side only. setBlock and tracked state are local to your client. They change what your client sees; they do not modify the server's world.