Client rendering, stage 1 — the lattice mesh, sunken cells, mountains, and people standing in water
ground-types/003 · created 2026-08-17 · updated 2026-08-18
What to do
Replace the one flat green plane (client_main.gd’s _rebuild_area_geometry) with ground that
is built from the cells. This stage uses no shader: transitions are vertex-colour blends, which
work on every renderer and are an honest placeholder. Runs in parallel with 002 — it can
render from a fake payload.
- New
game/world/client/ground_mesh.gd— pure logic, no Node dependencies, testable headless: from(ground, width, height)build an inset lattice (lattice lines at cell offsets 0, 0.25, 0.75, 1) and return{vertices, indices, colours, uvs}PackedArrays. One rule for every vertex: it is sunk (y = −0.25·CELL) iff every cell touching it is sunken — interior vertices touch one cell, edge vertices two, corners four. A one-cell-wide river is then a flat-bottomed trough with quarter-cell banks (a centre fan would give a row of dimples). Vertex colour = the average of the touching cells’ base colours. Alsomountain_instances()(a Mountain cell → instance; peak when all eight neighbours are Mountain, out-of-bounds counting as not-Mountain; variant tint; kw 56 flagged volcano) andpack_data_image()for task 004. 60×60 → 32,761 vertices, 64,800 triangles, one static mesh. - New
game/world/client/area_view.gd—build(grid): the groundMeshInstance3D(SurfaceTool,generate_normals(),StandardMaterial3Dwithvertex_color_use_as_albedo), aMultiMeshInstance3Dof low-poly cones for Mountains (taller scale for a peak; a second small MultiMesh of red crater caps for volcanoes), aBoxMeshonly forCELL_WALL/CELL_SOFT_BLOCK, portal rings at their cell’s surface height.client_main.gd’s_rebuild_area_geometry()becomes a thin call into it. humanoid_node.gd:set_target_cell(cell, y);client_main.gdpasses y = −0.5·CELL on a sunken cell (local and remote bodies) — the existing constant-speed glide interpolates the dip and the surface at −0.25 hides the lower part. Unify the threeCELL_3Dcopies (humanoid_node.gd,client_main.gd,portal_node.gd) into one.client/ui/_shots.gd:LOR_GROUND_FILE→ build anAreaGridfrom a ground content file →g-ground.png. Write a small deterministic fixture file for it; task 005’s real files replace it.
Definition of done
test_runner.gd: the vertex-sunk rule on a single cell, a 1-wide river and a 2-wide river; the peak rule incl. edges; data packing.- A screenshot from
_shots.gdshowing grass variants, a river with banks, mountains with a peak, reviewed by eye; the web export boots. - Committed and pushed in
land-of-lor.
Where the work lands
land-of-lor/game/world/client/.
What was done (2026-08-17, laptop session)
client/world_units.gd— the oneCELL_3D(plusSUNKEN_DEPTH,ENTITY_SINK, mountain sizes);humanoid_node.gd,portal_node.gd,client_main.gduse it.client/ground_mesh.gd(pure): the inset lattice,vertex_sunk/vertex_colour/build,is_peak/mountain_instances,pack_cells(for 004),standing_height/surface_height. 26 newtest_runner.gdchecks (169 total) — single cell, 1-wide and 2-wide rivers, edge of the Area, blends, peaks incl. the corner case, volcano, packing.client/area_view.gd(Node3D): floor mesh via SurfaceTool +vertex_color_use_as_albedo, one MultiMesh of cones (peaks taller, tinted per flavour) + red crater caps for kw 56, walls only forCELL_WALL/SOFT_BLOCK, portal rings on the cell’s surface.client_main.gd _rebuild_area_geometry()builds it; entities getsnap_to_cell(cell, y)/set_target_cell(cell, y)fromstanding_height._shots.gd:g-ground,g-ground-top,g-ground-wadefromLOR_GROUND_FILEor a built-in showcase; reviewed by eye — the river reads as a channel with banks, patches blend, the mountain block has a taller tinted peak, the wading body’s legs are hidden.- The headless Godot client harness (
npm run test-client-godot) still passes every movement/prediction check; its twoCLIENT_REMOTEchecks fail because they still expectentity-<accountId>ids, which 014 replaced — pre-existing, not touched here. - Not done: the web export itself (task 008 does the export and ships it).
View source in repository · also available as raw markdown.