Skip to main content

Choosing Game APIs

Crowded Kingdoms has five complementary implementation tiers. Most production features use more than one:

  1. Platform primitives move identity, permissions and realtime data.
  2. Model containers/functions hold durable truth and atomic rules.
  3. Model automations schedule or fan out simple Model functions.
  4. Compute modules run bounded loops, secrets, simulation and referees.
  5. Client conventions render, interpolate and provide optimistic UX.

The default is Model first. Add compute at an expression ceiling. Use a platform primitive when the problem is transport, spatial storage or identity rather than a game rule. Never make a client authoritative for a competitive result.

Decision flow

flowchart TD
Need[Game feature] --> Primitive{Transport spatial storage identity?}
Primitive -->|Yes| Platform[Platform primitive]
Primitive -->|No| Durable{Durable data or atomic policy-gated mutation?}
Durable -->|Yes| Model[Model container and function]
Durable -->|No| Schedule{Simple scheduled or event fan-out?}
Schedule -->|Yes| Automation[Model automation]
Schedule -->|No| Engine{Loop secret live context or referee?}
Engine -->|Yes| Compute[Compute tick or invoke]
Engine -->|No| Client[Client presentation convention]
Model --> Hybrid[Hybrid when live engine also needed]
Compute --> Hybrid

Ask these in order:

QuestionChoose
Is this actor/voxel/grid/session/team/channel transport or storage?Platform primitive
Must it survive restarts, be queryable, policy-gated or commit atomically?Model
Is it a simple timer/event selector calling a loop-free function?Automation
Does it need loops, graph search, hidden state, server RNG or live poses?Compute
Is it interpolation, animation, local prediction or UI state only?Client

The five tiers

Platform primitives

Use platform primitives for where and how data moves:

NeedSurface
Presence and posesActors + UDP/world sessions
Building/world cellsChunks, voxels and voxel state
Spatial ownershipGrids + permissions
Match membership/turn holderSessions
Parties, guild chat, match notificationsTeams + channels
Cosmetics/save blobsAvatars + user/app state
Legacy low-stakes coordinatorElected host

Host election is useful for targeted delivery and low-stakes co-op coordination. It is not an anti-cheat boundary. Competitive simulation belongs in compute.

Model functions

Use the Model API for durable catalogs/config, owner-indexed state, atomic inventory/economy transactions, permission effects, and notifications. Examples: stacks, recipes, wallets, quest progress, plots, score records.

Prefer one intent-level function (craft, trade, claim_reward) over a client composing several mutations. A denial must leave every referenced container unchanged.

Model automations

Automations are the seconds/minutes-scale server tier:

  • shop/NPC restock;
  • daily quest/season reset;
  • coarse permission/guard sweep;
  • event-triggered progress increment;
  • timestamp maintenance.

Do not use an automation for pathfinding, projectiles, many-agent motion, hidden information or sub-second decisions.

Compute ticks and invokes

Use compute for:

  • A*, flow fields, behavior trees and many-entity loops;
  • smooth shared NPC/mob/world simulation (normally 1–5 Hz);
  • hidden deck order, pity counters and server RNG;
  • combat/movement/action referees using live server-known poses;
  • projectiles/AoE, capture progress, shrinking zones and race timing;
  • server-computed ranking over large/competitive boards.

Ticks simulate; invokes referee a caller's intent. Compute state is a rebuildable cache (256 KiB); durable state remains in Model/platform storage. A trusted engine commits Model transactions with model_invoke instead of reproducing transaction logic through sequential property writes. When a referee action spans the voxel world and the Model ledger (mine and grant, consume and place), use model_invoke_with_world (SDK 0.1.4+) so both commit in one transaction rather than sequencing writes with compensation code.

Client conventions

Clients own presentation: rendering, interpolation, animation, input, prediction and rollback. Optimism must reconcile to a Model/compute result or authoritative event. Client RNG, peer-supplied damage, client-sorted tournament standings and elected-host competitive referees are anti-patterns.

Named pattern: self-reported vitals

Survival stats that only hurt their own reporter — hunger drain, breath, fall damage, self-heal after eating — may be committed by client-called Model functions (owner_of_self policy) instead of a compute referee. Blocks with Friends' PlayerStats functions (consume_hunger, damage_player, heal_player, eat_food) are the reference. This is a deliberate client-trust choice: a hostile client can at most flatter its own vitals. Use it knowingly, with these guardrails:

  1. Clamp every write in the expression (min(20, self.health + $amount)) so no call can exceed caps regardless of params.
  2. Gate restorative calls on consumed resourceseat_food composes owner_of_self with a condition that a food stack was consumed; the consumption itself is an atomic Model transaction.
  3. Never let self-reported state gate a grant or a competitive result. Kill credit, loot, XP from combat, and PvP damage go through the compute referee (is_automation-locked functions); vitals may influence presentation, not rewards.
  4. The expression language has no clock builtin, so true cooldowns cannot be expressed in an invoke policy. If abuse of a self-reported function would matter (PvP healing mid-fight), move that write behind a compute referee invoke — the referee has now_ms() and live poses — rather than approximating a rate limit in Model.

Four simulation cadences

TierTypical cadenceGood for
Replication/client render20–60 Hzinput, interpolation, visual prediction
Compute engine1–5 Hzauthoritative agents, referees, world systems
Automationseconds–minutesrestock, dailies, coarse selectors
Model invokeon demandatomic player/admin transactions

A model-only deployment may expose a documented low-stakes host fallback. When an engine is required for competitive integrity, capability detection must fail closed rather than silently downgrade authority.

flowchart LR
Defs[Model definition containers] --> Engine[Compute engine]
Player[Client intent] --> Engine
Engine -->|model_invoke| Tx[Atomic Model transaction]
Engine -->|actor and event lanes| Clients[Clients]
Tx --> Durable[Durable Model state]
Durable --> Clients
Clients -->|optimistic presentation only| Player

Examples: MobDef + mob-engine, MatchMeta + match-engine, AbilityDef + abilities-engine, ControlPoint + territory. Model data is designer-editable; compute owns live decisions; clients consume lanes.

Mechanic → API map

World and agents

FeatureRecommended stackKit/engine/example
Buildingvoxels + grids; compute only for server edits/refereeBWF
Claims/plots/doors/locksModel + grid permission effectskit.plots, kit.objects
World generationdeterministic client/platform, or compute for authoritative generationcustom
Resource nodes/farmingModel timestamps for simple growth; world-engine for spatial loopskit.worldsim, world-engine
Weather/timeModel defs + world-engine transitionsworld-engine
Instances/dungeonssessions/grids + Model run record + computeinstance-engine, dungeon-run
Territory/control pointsModel defs/ownership + compute captureterritory
NPCs/petsModel defs + npc-engine actor lanenpc-engine
Hostile mobsModel pools/defs + mob-engine/refereemob-engine, BWF
Pathfinding/BT/turn AIcompute library inside an enginekit-ai, TMS
Directors/wavesModel encounter defs + computedirector, tower-defense

Conflict and sessions

FeatureRecommended stackKit/engine/example
HP/statusModel durable HP + compute referee/tickskit.combat
Melee/ranged hitcompute invoke using live poses; Model commitcombat referee
Abilities/projectiles/AoEModel AbilityDef + computeabilities-engine, arena-blitz
Movement anti-cheatactor lane + compute observe/flagmovement-warden
Score/win conditionsModel result + match-engine authoritykit.matches
Turns/lobbiessessions + Model MatchMeta + match-enginematch-engine
Hidden cards/decksModel public zones + module-held secretsdeck-engine, card-duel
Matchmakingcompute queues → compute-event handoff → matchmatchmaking
Racing/ghostsactor poses + compute timing + board-engineracing
Ball possessioncompute authority + actor lanepossession
Minigamesinvoke-only compute when secrets/referee matterminigame scaffold

Economy, progression and platform

FeatureRecommended stackKit/engine/example
Inventory/stack transferatomic Model functionskit.inventory
Crafting/bartergenerated atomic Model transaction; optional compute proximity/refereeinventory/economy kits
Wallets/shops/escrowModelkit.economy
Order-book marketModel wallets + compute matchingmarket-engine
LootModel weighted roll for small tables; compute pity/secret roll for large tableskit.loot
XP/achievements/quests/FTUEModelprogression + quests
Idle productionelapsed-time compute catch-up + Model resultidle-factory
LeaderboardsModel small board; board-engine for competitive rankingboard-engine
Liveops/battle passModel season/windows + progression/features; scheduler only for world modifierskit.liveops
Moderation/telemetryModel/clientmoderation + telemetry
Presence/chat/partiesplatform actors/teams/channelskit.social

Genre starter bundles

GenreStart with
MMO/survivalinventory, plots, quests, world + npc/mob/combat engines
Social/cozyplots, social, economy, quests; automations for restock/dailies
RPG/roguelikeprogression, inventory, quests, combat, instances, director, loot
Tacticssessions + Model units + match/tactics compute referee
Card gamematches + deck-engine
Arcade/FPS-liteabilities + movement-warden + combat/match referee
Party/minigamematches + minigame + board-engine
Tower defense/MOBA-litedirector + mobs + flow fields + abilities/territory
BR-liteinstances + shrinking zones + director + movement warden
Racing/sportsracing + possession + board-engine

Cost and operations

Model functions bill through GraphQL/model usage. Compute bills wasm_compute_units plus egress. One unit is approximately one reference CPU millisecond:

GREATEST(CEIL(cpu_us/1000), CEIL(fuel/22,000,000)).

Reference measurements: ~1.4 ms/db-op, 0.4 ms/radius scan and 0.5 ms/spatial emit. Batch reads, amortize scans and emit only changed state. Compute is bounded by fuel, watchdog, memory, host-call, egress, circuit and spend-cap gates; disable module → app → environment in that order.

Deployment choices

  1. Parameterize a platform engine with Model definition containers (preferred): computeDeployTemplate or kit.deploy({ engines: [...] }).
  2. Fork a template when the rule genuinely differs.
  3. Write a custom module only when no catalog engine fits.

Next: Model API · Automations · Compute Modules · Compute Engines · Grids & permissions