core library
The engine core: chunk grid, meshing with light and ambient occlusion, chunk streaming on isolates, voxel physics and rays. Renderer-agnostic. Every other subject of this package is written on it.
Classes
- ChunkGenerator
-
Fills one chunk volume (ChunkSize.volume bytes of block ids) for chunk
(
cx,cz) ofdimension. Runs on a worker isolate: it must be pure in (seed, position) and touch nothing outside itself. - ChunkJobs
- Where generation and meshing jobs run. ChunkWorkerPool is the isolate implementation; a test can answer synchronously.
- ChunkMesher
- Face-culling, greedy mesher with baked ambient occlusion, sky + block light, liquids (lowered surface, own transparent surface), cross plants, torches, and the sub-block solids (slab, fence, stairs) built from axis-aligned boxes lit like cube faces. Works on a volume padded on every horizontal side, filled from the eight neighbour chunks, so a border face and its AO corners never guess.
- ChunkMeshResult
- Everything a mesh job produces for one chunk: four surfaces, one per way they draw, and the chunk's light volumes.
- ChunkMeshSink
- What the streamer hands finished meshes to: a renderer, or a test.
- ChunkSize
- The one chunk geometry: 16 × 16 columns, 128 cells tall. A chunk volume is a byte per cell, indexed x-first within z within y.
- ChunkStreamer
- Chunk streaming around a centre, without a renderer: the load window, the generation and mesh jobs, edits and their remesh rule, per-dimension edit deltas and the light volumes each mesh job returns. Finished meshes go to sink within a per-frame budget.
- ChunkWorkerConfig
- Everything a worker isolate needs to build its own generator and mesher.
- ChunkWorkerPool
- A fixed pool of isolates running chunk generation and meshing. Requests are answered by futures; each goes to the least busy worker.
- CollisionBox
- An axis-aligned box as min / max corners: a test reads a face without adding a size to a position.
- EditDeltaCodec
- The binary form of a world's edits: what a generated world needs on top of its seed to be the world the player left. Little-endian throughout:
- FenceJoin
- The sides of a fence that reach toward a neighbour, as bits of a mask.
- IVec3
- An integer cell position. Value-equal, so it keys maps and sets.
- LiquidFlow
- Cellular liquid flow over a VoxelEditor, driven by edits alone so an idle world costs nothing: a generated lake is sources resting on solid and never enters the queue until something next to it changes.
- LiquidRule
- How one liquid kind flows.
- MeshSurface
- One vertex-coloured, indexed triangle list, in chunk-local coordinates (x and z 0..16, y 0..128). Every face is a quad of four vertices and six indices. Triangles wind clockwise seen from the side the normal points to, so a renderer whose front faces are counter-clockwise must mirror the handedness at its camera or cull the other side.
- PathCosts
- What a path may cross and what each cell costs, the game's say in Pathfinder. The engine knows solids, liquids and fences from the block table; which liquid burns and which floor is slow is the game's.
- Pathfinder
-
A* on the block grid for walking creatures. A node is a feet cell (air, air
above, something to stand on below, never a fence top); the moves are the
four horizontal steps, a step up of one (with head room) and a drop of up
to maxDrop onto a landing. The heuristic is the Manhattan distance. At
most
maxNodesexpansions per call; when the goal is not reached the best partial path toward it is returned (the node closest by heuristic, ties on the lower cost). Below y 0 counts as solid. - RayHit
- A voxel raycast hit: the cell, the face normal it was entered through, and the distance travelled to that face.
- Reach
- Reach: the one rule every swing, every use and every bite obeys.
- VoxelBlockDef
- What the engine needs to know about one block id: how it is drawn, whether it stops a body or light, the light it gives, and whether it is a liquid. Names, drops, tools and every other gameplay fact stay with the game.
- VoxelBlockTable
- The block ids of one game, indexed by the byte a chunk stores. Id 0 is air. Built once from the game's definitions; the typed arrays are what a mesher on a worker isolate is handed.
- VoxelBody
- An AABB anchored at the feet, swept against the block volume one axis at a time. Knows nothing of rendering: a game moves its visuals from position.
- VoxelEditor
- A world the flow can change as well as read.
- VoxelModel
- A small voxel model: a map from voxel to linear rgb colour, the way creatures, held items and drops are drawn (coloured cubes, no textures). These are the tools that paint one; a renderer turns it into a mesh through VoxelModel.arrays.
- VoxelModelArrays
- A voxel model's faces as flat arrays, four vertices and six indices a face.
- VoxelQuery
- What a body or a ray needs to read from a world: the block at a cell and what that block is.
- VoxelRaycast
- Grid traversal (Amanatides & Woo) through a VoxelQuery.
Enums
- BlockShape
-
How a block is drawn and what it collides with. The declaration order is a
contract: the mesher reads a shape as its
indexfrom a byte table.
Constants
- fenceBarrierHeight → const double
- How tall a fence stands to a body with VoxelBody.fenceBarrier: above any jump an animal makes (8 m/s rises 1.23 m), so a pen holds it while the player, who meets the drawn block, jumps onto the rail.
- ladderDepth → const double
- How far a ladder's rungs stand off its wall, and where its rails run across it.
- ladderRail0 → const double
- How far a ladder's rungs stand off its wall, and where its rails run across it.
- ladderRail1 → const double
- How far a ladder's rungs stand off its wall, and where its rails run across it.
Functions
-
collisionBoxesAt(
VoxelQuery q, int x, int y, int z, {bool fenceBarrier = false}) → List< CollisionBox> -
The boxes a body collides with at the world cell (
x,y,z), in the block's own 0..1 space. Most blocks answer from their shape alone (VoxelBlockTable.collisionBoxes); a fence and a ladder also read their neighbours.fenceBarrierraises a fence to fenceBarrierHeight. -
collisionBoxesOf(
BlockShape shape, {required bool solid}) → List< CollisionBox> - The boxes a body collides with, in the block's own 0..1 space. Empty for a block that stops no body. Stairs: the bottom slab plus the high step at the back, the same halves the mesher draws (N = high step at z 0..0.5, E = at x 0.5..1). A fence is its lone post here and a ladder nothing: the arms and the ladder's wall depend on the neighbours, which collisionBoxesAt reads. The lists are constants: never mutate one.
-
eulerYXZ(
double x, double y, double z) → Quaternion - The rotation of Euler angles applied Y, then X, then Z (yaw, pitch, roll): the order an animated part is posed in.
-
eulerYXZInto(
Quaternion out, double x, double y, double z) → Quaternion -
eulerYXZ written into
out, which it returns: the product of the three axis rotations worked out by hand, so posing a part every step allocates nothing. -
fenceBoxesOf(
int joins, {bool barrier = false}) → List< CollisionBox> -
The boxes a fence with
joinsstops a body with, in the block's own 0..1 space: the post, stretched along each axis to the sides it joins. Every piece is as tall as the post, one block, or fenceBarrierHeight whenbarrieris set. Shared: never mutate. -
fenceJoinsAt(
VoxelQuery q, int x, int y, int z) → int -
The sides of the fence at (
x,y,z) that join a neighbour: a fence or an opaque block beside it. The mesher draws its rails by the same rule, and the outline and the collider read it here, so the three cannot disagree. -
ladderBoxAt(
VoxelQuery q, int x, int y, int z) → CollisionBox -
The box a ladder at (
x,y,z) fills, in the block's own 0..1 space: its rails and rungs, lying on the wall it hangs from. The wall is the first opaque neighbour of -x, +x, +z, else -z — the mesher's order. A body in the ladder's cell still stands in it (0.12 deep), so it keeps climbing. -
lerpAngle(
double from, double to, double t) → double -
frommoved towardtobytalong the shorter way round the circle, in radians. -
lerpd(
double a, double b, double t) → double -
amoved towardbbyt. -
selectionBoxAt(
VoxelQuery q, int x, int y, int z) → CollisionBox - The box an aimed block's outline is drawn around, in world space: the bounds of what the chunk mesher actually draws in the cell, not the cell. A torch gets a thin post, a slab half a cube, a door a panel, a plant the sheet it grows. Shapes that lean on a neighbour (a wall torch, a ladder) or join one (a fence) read the same neighbours, in the same order, as the mesher does, so the box and the mesh cannot disagree.
Typedefs
- CellLight = ({int block, int sky})
- (sky, block) light of a cell, 0..15 each.
- ChunkGeneratorFactory = ChunkGenerator Function()
-
Builds a ChunkGenerator inside a worker isolate. It is sent to the
isolate, so it must capture only sendable values: make it in a static or
top-level function, never in an instance method whose
thisholds scene objects. - ChunkPos = ({int x, int z})
- A chunk column position, in chunks.
-
EditsByDimension
= Map<
int, Map< ChunkPos, Map< >int, int> > - Every dimension's edit delta: dimension -> chunk -> (cell index -> id).
- LiquidContact = int? Function(int kind, bool source, int touching)
-
What a liquid cell of
kind(a source whensource) becomes when it touches a liquid oftouchingkind, or null when the two ignore each other. Lava meeting water hardens this way.
Exceptions / Errors
- ChunkJobCancelled
- What a ChunkJobs fails a job with when it drops the job on purpose (a disposed pool). The streamer ignores it; any other job error is a bug and ChunkStreamer.update rethrows it.