ReadonlysceneReadonlycameraReadonlyrendererReadonlylayoutReadonlycontrolsReadonlyhashReadonlychunksReadonlypickerReadonlyoverlaysReadonlysunShadow-casting sun rig when the shadows option was set (and default lights are on); null otherwise.
Called once per frame after chunks/picking update, before rendering.
ReadonlyeventsTyped world events — pointer/cell interaction, the frame tick, chunk
streaming, and (after trackUnits) unit movement. Subscribing beats
wiring raycasts and callbacks by hand, and unlike the single-slot
onFrame / onCellEnter hooks any number of systems can listen.
world.events.on('cellClick', ({ col, row, button }) => {
if (button === 0) select(col, row);
});
const off = world.events.on('cellHover', ({ cell }) => showTooltip(cell));
off(); // unsubscribe
dispose drops every listener before tearing anything down, so no events fire against a half-disposed world.
ReadonlyterrainThe material options used for terrain materials this world builds — reuse for loadHexPack so pack materials match the scene lighting.
Resolved terrain definitions currently in use.
Liquid type descriptors currently in use. Swap with setLiquidDescriptors.
Terrain definitions keyed by terrain index.
Cell under the pointer, updated every frame while the loop runs.
The day/night cycle, if enabled via the dayNight option or setTimeOfDay.
The weather system, once setWeather has been called.
The world's shared wind — the one vector behind cloud drift, rain slant, plant sway, and the ripples marching across open water. Always present, so it can be configured before or after anything that reads it; switch it on with setWind.
world.wind.base is the same THREE.Vector2 as world.weather.wind.
The god-ray pass, if enabled via the godRays option or setGodRays.
The season cycle, if enabled via the seasons option or setSeasons.
Per-cell climate once seasons are on — the same bytes the shaders sample,
so climate.snowDepth(col, row) is exactly what the player can see.
The fog-of-war state this world renders with, if the fogData option was set.
The territory layer, once setFactions has been called.
The resource layer, once setResourceTypes has been called.
True if the terrain index belongs to any liquid type.
StaticcreateBuild a fully wired world. Async because the terrain texture atlas is built from (possibly image-based) terrain descriptors.
Start the render loop (no-op if already running).
Re-emit a UnitManager's events through events, so unit movement arrives alongside cell and chunk events instead of on a second emitter the rest of the game has to know about. Returns an unsubscribe function; dispose also drops every forward this world set up.
HexWorld does not own the manager — construct it as usual and hand it
over:
const units = new UnitManager({ scene: world.scene, map: world.map, layout: world.layout, fogData: world.fog ?? undefined });
world.trackUnits(units);
world.events.on('unitArrived', ({ unit }) => endTurn(unit));
Stop the render loop (state is kept; call start() to resume).
Swap in a different map; chunks rebuild, climate re-derives, camera recenters.
Swap the terrain set at runtime (custom terrain, loaded pack): rebuilds
the texture atlas + terrain material and re-derives all lookups. The
previous terrain material is disposed unless you pass keepOldMaterial.
Optionalregistry: TerrainAssetRegistryAdopt already-resolved terrain state (e.g. from loadHexPack, which
builds its own material). Returns the previous material WITHOUT disposing
it — the caller decides, since it may be shared.
Toggle or restyle the shader hex grid overlay drawn by the terrain
material — crisp anti-aliased cell borders that fade with camera distance.
true/false toggles with current styling; an options object restyles
(and enables unless enabled: false). Survives terrain material swaps.
Toggle or restyle the sedimentary bedding the terrain shader draws on bare
rock — horizontal layers picking out every cliff face, terrace and carved
channel side. On by default; false turns it off, an options object
restyles (and enables unless enabled: false). Survives terrain material
swaps.
Point the sun (day/night hook): updates the shadow rig AND the terrain
material's hand-rolled light direction in one call so shading and shadows
never disagree. dirTowardSun points from the scene toward the sun.
Survives terrain material swaps.
Jump the world clock to a time of day (0 = midnight, 0.5 = noon) and
relight the scene. Creates a paused DayNightCycle on first use if the
dayNight option wasn't set — unpause via world.dayNight.paused = false
to let time flow.
Every material the sky hazes into its horizon color: terrain, roads, each
liquid layer, and the scatter materials (which setSky runs through
attachAtmosphere, since stock three materials have no haze of their own).
Hand it to a SkyDome you build yourself, or to configureAtmosphere for
distance haze without a dome.
Replace the scatter definitions at runtime and rebuild the scatter of every loaded chunk. New materials get the haze, snow, season, and wind bindings the originals were given at construction, so a definition added from an editor's scatter builder looks like one from the start.
Enable, restyle, or (with false) remove the gradient sky dome and its
matching distance haze. Options accumulate across calls, and the dome
immediately picks up the current time of day and weather.
groundTint defaults to the terrain palette's average color so the horizon
haze matches the biome — pass it explicitly to override. Scatter materials
are patched with the same shader haze so they recede with the terrain;
do the same for your own unit and prop materials with attachAtmosphere.
Enable, restyle, or (with false) remove the map skirt — the wall of cut
earth that gives the map a bottom and four sides instead of ending where
its triangles stop.
The geometry options that have to agree with the terrain
(perturbStrength, noiseScale, elevationScale,
elevPerturbStrength) are taken from the world's own geometryOptions
unless you override them — pass them by hand only if you are also building
terrain by hand, since a mismatch tears the seam along the entire edge.
Every material that renders seasonal snow or ice: terrain, each liquid layer, and the scatter materials (which setSeasons runs through attachSnow, since stock three materials have no snow of their own).
Roads are deliberately absent — a road under snow is a road you can't see,
and hiding the network the player routes on is worse than the realism is
worth. Hand your own prop materials to attachSnow if you want them white.
The seasonal foliage tint is not attached here either, and that is the
point: whether a plant turns in autumn is what tells a broadleaf from a
pine. Call attachSeasonalTint on the scatter materials that should turn —
before or after setSeasons, since both effects share one climate binding.
Enable, restyle, or (with false) remove seasons: a year clock, snow that
accumulates and melts, and liquids that freeze at their own
freezePoint. Options accumulate across calls.
Supply climate when the map was generated with a climateData sink —
that field is the one the biomes were assigned from. Without it the base
temperature is rebuilt via ClimateData.fromMap, which matches only
if you pass the same temperature options the generator used.
The cycle advances with the day clock and re-applies every HexWorldSeasonOptions.applyInterval seconds; scrub it directly with setSeason.
Optionalclimate: ClimateData// Generated map: hand over the field the biomes came from.
const climate = new ClimateData(map.width, map.height);
generateMap(map, { climateData: climate }, seed);
world.setSeasons({ daysPerYear: 8 }, climate);
Jump the year clock and repaint immediately — the turn-based entry point
("day 214 of the migration"). Creates a paused cycle if the seasons
option wasn't set, so a game that drives its own calendar never needs the
real-time clock at all.
Set the weather: drifting cloud shadows on the terrain plus a matching rain/snow layer that falls under the denser clouds and follows the camera (world-anchored — panning doesn't drag the rain). Creates the WeatherSystem on first use; returns it for fine-grained control (intensity ramps, wind changes).
'clear' means no precipitation, not an empty sky: it keeps scattered
fair-weather cloud shadows drifting over the ground. Pass
{ clouds: false } for a cloudless one.
Every material the wind can move: each liquid layer, and the scatter materials. Materials that carry none of the wind uniforms are skipped by setMaterialWind, so this can be handed out whole.
The terrain is absent because a hillside does not move, and the road with it. What lives here is water — which drifts and roughens — and whichever plants have been given attachWindSway.
Enable, restyle, or (with false) still the world's wind: one vector that
drifts the cloud deck, slants the rain, bends the plants, and marches the
ripples across open water. Options accumulate across calls; returns the
shared Wind for direct control (world.wind.setPolar(…) mid-storm).
Which plants bend is yours to say. This drives every material that carries attachWindSway and attaches the patch to none of them — the same division as the seasonal foliage tint, and for the same reason: that a hedge answers the wind and a boulder does not is a fact about your scatter, not about the renderer. Water needs no such call; every liquid material already carries the uniforms and sits at zero until this is switched on.
The wind itself exists and advances from the first frame either way, which is why a shower gusts before anything on the ground is wired up to it.
Set the faction roster and start drawing per-cell ownership: translucent faction tints with an outline around each faction's holdings. Creates the TerritoryLayer on first use and returns it for the claim/release calls; later calls just re-colour with the new roster.
Ownership is stored in the map's metadata channel, so it serializes with
the map — no companion file, and world.map round-trips through
serializeMapJSON with the borders intact.
Set the resource types and start drawing per-cell deposits as instanced camera-facing icons — one draw call per type. Creates the ResourceLayer on first use and returns it for placement calls; later calls swap the type set.
The world's fog (the fogData option) is wired in automatically, so icons
hide on unexplored cells and dim on remembered ones along with the ground
beneath them. Placement data lives in the map's metadata channel and
serializes with the map.
Optionalicons: ResourceIconRegistryAttach or detach fog of war at runtime, across every layer that reads it — terrain, liquids, roads, scatter, and resource icons.
Hide unexplored cells (the fog's memory tier boundary), across terrain and resource icons alike. Independent of setDimExplored.
Dim explored-but-not-currently-visible cells — the remembered tier's ghost look — across terrain and resource icons alike.
Swap the liquid types at runtime (edited appearance, new custom liquid). Materials are resolved from the descriptors unless provided; previous liquid materials this world held are disposed unless still referenced by the new set.
Optionalmaterials: Map<string, LiquidMaterialSet>Stop the loop and free everything this world created.
Batteries-included entry point: renderer, camera + RTS controls, lighting, terrain/liquid materials, chunk streaming, per-frame picking, and cell overlays — wired the same way the à-la-carte API would be by hand. Every piece stays reachable (
scene,camera,renderer,chunks,overlays,picker, …), so you can drop to the lower-level API at any point.Example