Skip to content

Entities

Status: Current Last reviewed: 2026-07-07 Source: server/src/game/entities.ts, shared/src/types.ts

Entity Ids

Ids are prefix_base36, minted by makeId(prefix): pl_ players, gob_ goblins, prj_ projectiles, loot_ loot bags, npc_ NPCs. Ids are unique for the life of the process.

Entity Types

The wire-level EntityType values are player, goblin, projectile, loot_bag, village_npc, plus reserved item and spell_effect. Every server entity implements two methods:

  • spawnData() returns the full EntitySpawnData sent once when the entity enters a client's view.
  • snap() returns the small EntitySnap included in each tick's snapshot, or null for static entities (NPCs and loot bags do not move, so they only send spawn data).

Player

PlayerEntity holds the movement state (pos, vel, onGround), aim (yaw, pitch), vitals (hp, stamina, mana), the equipped weapon, and the weapon state machine (wstate, wstateT, drawStartedAt, blockRaisedAt, blocking). It also carries the input queue, the last acknowledged input sequence, inventory, skills, skill-use accumulators, and the quest log. godMode and isAdmin gate editor and playtest behaviour. See Combat for the state machine.

NPC

NpcEntity comes from an npc_spawn zone object. It stores defId (the stable npcId), display name, role, position, yaw, dialogue lines, and the questIds it offers or completes. NPCs are static; they only send spawn data. In the client they face a fixed yaw and idle. See Adding NPCs.

Mob

GoblinEntity is the one mob family. Its variant selects a tuning row from GOBLIN_TUNING:

Variant HP Speed Sight Attack range Cooldown Windup Damage Weight
scrapper 42 5.4 17 2.2 1.7 0.55 7 1.0
slinger 30 4.6 20 17 2.3 0.5 6 0.9
hexer 24 4.3 19 15 3.0 0.7 11 0.85
champion 240 5.0 24 3.0 2.4 0.75 18 2.4

Runtime AI fields cover state (idle/aggro/return), current target, timers, a pending telegraphed attack, stagger, and animation. weight scales knockback resistance, hit-capsule size, and model scale. See Adding Mobs and the AI section of Combat.

Projectile

ProjectileEntity covers arrow, fireball, rift_burst, goblin_rock, and hex_bolt. Each pulls a ProjectileDef (speed, gravity, radius, damage, splash radius, ttl, knockback). Arrows carry a per-instance damage and draw set by the bow draw model. Projectiles integrate with gravity and use swept sub-step collision (advancing in short steps sized to the projectile radius) so fast arrows do not tunnel through goblin-sized targets.

Loot Bag

LootBagEntity drops on goblin death with rolled loot (rollGoblinLoot) and lives for LOOT_BAG_TTL (120 s). Interacting within INTERACT_RANGE grants the items and fires quest loot_item events. Full-loot player corpses reuse the same class and are a marked TODO.

Quest Trigger

Not an entity but a derived volume. buildZoneRuntime turns each quest_trigger object into a QuestTriggerDef (triggerId, position, radius). Twice a second the server checks players against triggers and fires reach_area quest events. See Quest System.

Resource Node

The resource_node prefab exists as a placeable, colliding prop with a nodeType property. Gathering is not implemented yet; the prefab and its ember hooks are in place so the gathering milestone can build on them.

Ember Relay

The ember_relay prefab (the cracked shrine) is the anchor of the Emberwake system. buildZoneRuntime collects relays into emberRelays, and EmberSystem.bind picks the first one as the pressure source. See The Emberwake System.

Admin-Placed Object

Everything in a zone is a ZoneObjectInstance: id, prefab, x, z, optional y height offset, yaw, scale, and an optional props blob. Colliders, spawns, NPCs, triggers, safe zones, and relays are all derived from these instances by buildZoneRuntime, so the editor only ever manipulates this one shape. See Level Editor.