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.
- ChunkVisibility
- Which faces of each 16-tall section of a chunk its open cells join: a cell is open when its block does not occlude (VoxelBlockTable's opaque flag), so air, liquids and cutouts let sight through. Two faces are joined when one connected group of open cells inside the section touches both.
- 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.
- SectionOcclusion
- The chunks sight can reach from the camera through open cells: a breadth-first search over 16-tall sections, from the camera's section, crossing a section only between faces its ChunkVisibility joins and never stepping against a direction the path has already taken (Checchi's cave culling). A chunk is reached when any of its sections is.
- 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.