Skip to content

Adding Props

Status: Current Last reviewed: 2026-07-07

A prop is a prefab: a gameplay definition in shared/src/prefabs.ts and a visual in client/src/render/prefabs.ts. Once both exist it appears in the /admin palette automatically.

The Two Halves

Gameplay definition (shared/src/prefabs.ts). Add a PrefabDef:

P('lamp_tall', 'Tall Lamp', 'lights', { kind: 'circle', r: 0.25 }, 0)

Fields: id, name, category, collider (null, circle, or aabb at scale 1), blockHeight (projectile block height; 0 lets shots pass over). Options: instanced (batch into one mesh), marker (gameplay-only, invisible in play), defaults (starting props for new instances).

Visual (client/src/render/prefabs.ts). Either:

  • Add a case to buildPrefabVisual that returns a THREE.Group, for a one-off prop, or
  • Add an entry to INSTANCED_PREFABS (a list of InstancePart geometry/material/offset), for a prop that will appear many times.

The server derives colliders from the shared def; the client renders from the visual. They agree because both read the same ZoneObjectInstance.

Instanced versus Unique

Use instanced parts for anything placed in bulk (trees, rocks, crates, barrels, fences, mushrooms, hay, bone piles). The client batches all instances of that prefab into a single InstancedMesh, which is one draw call. Use buildPrefabVisual for structures and one-offs (houses, the smithy, the ember relay, the cave gate).

Placing

Restart the client so the new prefab is bundled, open /admin, find it in its palette category, click to place, adjust in the inspector, and Save Zone.

Markers

Marker prefabs (player_spawn, mob_spawn, quest_trigger, safe_zone, audio_emitter) return null from buildPrefabVisual, so they are invisible in the game client. The editor draws its own coloured gizmo for them. Use markers for anything that is data rather than scenery.

Performance

Prefer instanced props for repeated scenery and keep unique-mesh props for things that genuinely need custom geometry. Draw calls, triangles, and active entities are all visible in the in-game performance overlay (F3), so you can check the cost of a new prop directly.