# Spawning entities from data (spawn.system) ## What it is for `spawn.system` is the one door through which a game puts entities into the world from data. Each spawn entry names a `kind` (a vehicle, an NPC, a prop, a pickup...), a place and some tags; the kit that registered a factory for that kind builds the entity, and a kind without a factory becomes a bare entity. The kit spawns the project `spawns` collection at start, answers `spawn.request` events from triggers and scripts, keeps a cap on how many spawned entities are alive, and brings back those tagged `respawn` after a delay. With `game.engine`, a scene can carry its own spawns that come and go with it. It draws nothing: what a kind looks like belongs to the kit behind the factory. ## Turn it on ```text gripforge_gamekit_install { project_id: "gkp_…", id: "spawn.system" } gripforge_gamekit_configure { project_id: "gkp_…", id: "spawn.system", config: { "respawnSeconds": 5, "maxEntities": 300 } } ``` It requires `game.engine` and provides the service `spawn.entities`. NPC, vehicle and prop kits register their factories with it. ## First example Entries of the `spawns` collection are spawned in document order, so entity ids are the same on every run. An entry without a valid `at` is skipped: ```json { "spawns": [ { "id": "c", "kind": "crate", "at": [1, 0, 1], "tags": ["loot"] }, { "kind": "ghost" }, { "kind": "barrel", "at": [2, 0, 2], "yaw": 0.5, "components": { "hp": 3 } } ] } ``` This spawns a crate and a barrel (the `ghost` entry has no place). `spawn.entities.count()` answers 2, and `spawn.entities.specOf("e1")` returns the first entry. ## A spawn entry `{ kind, at, id?, yaw?, tags?, components?, archetype? }` where `at` is a point `[x, y, z]`, `{ zone }` (a point inside the zone) or `{ entity, offset? }` (next to another entity). `components` sets initial components, `archetype` names one to build from. ## Settings | Setting | Type | Default | Meaning | |---|---|---|---| | `respawnSeconds` | number, 0 to 120 | `3` | seconds before an entity tagged `respawn` comes back at its spawn point | | `maxEntities` | integer, 1 to 2048 | `256` | cap on live spawned entities; a spawn above it is skipped with a warning | ## Services - `spawn.entities` (service), methods: - `spawn(spec)`: spawns an entry and returns the new entity id, or `null` if the entry is malformed (no string `kind` or no `at`), the cap is reached, or a hook cancelled it. - `despawn(id)`: removes an entity on purpose: it is not respawned. - `respawn(id, at?)`: removes the entity and brings it back after the respawn delay, optionally at a new `at`. - `count()`: live spawned entities. - `specOf(id)`: the entry that produced an entity, or `null`. ## Events - `spawn.request` (listened): a spawn entry as payload. A trigger can write `{ "emit": { "topic": "spawn.request", "payload": {...} } }`; invalid payloads are ignored. - `entity.despawned` (listened): an entity this kit spawned was destroyed; if it was not removed on purpose and carries the `respawn` tag, it is queued to come back. - `spawn.spawned` (event): an entity was created, payload `{ entity, kind, tags }`. - `spawn.despawned` (event): a spawned entity is gone, payload `{ entity, id, kind }`; sent before any respawn is planned. ## Hooks and modding A game (a hooks document) or a mod can change these decisions without touching the kit: - `spawn.entity`, payload `{ kind, tags }`: before an entity is spawned, after the cap; `kind` can be changed (another factory), a cancel spawns nothing. Then the kernel hook `engine.spawn` is asked (`archetype` and `tags` can change, a cancel spawns nothing and uses no entity id). - `spawn.respawn`, payload `{ entity, kind, delay }`: before a respawn is queued; `delay` can be changed, a cancel means it does not come back. ```json { "id": "no_respawn", "hook": "spawn.respawn", "match": { "kind": "boss" }, "cancel": true } ``` A mod can override `respawnSeconds` and `maxEntities` and add, patch or remove documents of the `spawns` collection. ## Scenes With `game.engine`, a scene's `data.spawns` (same entries) are spawned on entering the scene and despawned on leaving it, with no respawn; pending respawns of that scene are dropped. The project `spawns` stay global. A load rebuilds each entity's scene. ## Engines The same Rust module runs on the web, the native player and the Godot, Unity and Unreal wrappers. ## When it does not do what you expect - Nothing appears: the entry has no string `kind`, or no valid `at`; or `maxEntities` is reached; or a hook cancelled it. - An entity does not come back: it needs the tag `respawn` and must not have been removed with `despawn` (that means on purpose). - A respawn comes late: check `respawnSeconds` and any `spawn.respawn` hook that raises `delay`. - A kind appears as an empty entity: no kit registered a factory for it; install the kit that provides it. ## Limits - It does not decide what a kind looks like or does; factories belong to other kits. - Respawn brings back the original entry at its spawn point, not the entity's old state. - Scene spawns never respawn. ## Versions Kit version 1.4.0; the service `spawn.entities` is at 1.0.0. Since 1.4.0 an entity is created through the kernel's `engine.spawn` hook after `spawn.entity`.