Appearance
Budgets and tick rates
You'll learn: how much CPU, memory and storage you get, how fast your plot ticks, and who owns movement. You'll need this when: your plot does a lot per tick, or needs to feel snappy.
Status: Built (headless): CPU metering, memory caps, the storage quota, tick rates, client-owned movement checks. Buying higher tiers with Nimgots is Planned. Client code's frame budget per device tier is In progress, with client code.
Budgets are about fairness, not content
There are no caps on what you make: entities, blocks, particles. Devices draw what they can, and the engine degrades the rest (LODs, impostors, average colours). Budgets exist so one plot can't stall the world.
| Budget (per plot) | Default | Hard cap | Over it |
|---|---|---|---|
| CPU per tick | 2 ms | 8 ms | the hook is cut off, its writes are discarded |
| CPU per rolling second | 20 ms | 80 ms | sustained: dropped to 10 Hz, then suspended for a while |
| Memory | 32 MB | 128 MB | growth fails: a crash (below) |
| Storage | 1 MB plus your blocks | 16 MB | storage.set refused with storageFull |
| Bandwidth per viewer | 64 / 128 / 256 KB/s by device tier | lower-priority updates wait a frame | |
| Custom channels | 25% of a viewer's bandwidth, 32 messages a tick per channel | unreliable messages dropped, reliable ones queued | |
| Outbound network | none | none | there's no API |
Higher tiers will cost Nimgots (Planned). All of a plot's packages share its budget, each with its own slice.
Crashes: a trap (an exception you didn't catch, running out of memory) discards that hook's writes. A mod that traps sits out alone and restarts after 1 s, 5 s, then 30 s; the runtime and the other mods carry on. A runtime that traps takes the plot down: players inside are released (stashed or tried-out items given back, as on leaving) and the plot restarts after the same delays. Five crashes in ten minutes stop it (a mod until the plot restarts, a runtime's plot until it's started again). Your blocks and entities stay as they were, and your code rebuilds from storage on restart.
Tick rate: 20 Hz by default, up to 60
json
{ "tickRate": 30 }or at run time (runtime only):
ts
time.setTickRate(60); // refused with "overBudget" if it doesn't fit your CPU quotaEvery lobby that isn't suspended gets tickLobby(dt) once per tick (or export tickAllLobbies(dt, ids): one call for all of them, the cheap path when there are many); tickPlot(dt) runs once per tick at plot level. Most games are fine at 20. Shooters and fast platformers want 30 to 60.
Who owns movement
"movement": "server" (default) | "movement": "client" | |
|---|---|---|
| Authority | the room simulates every player; devices predict and reconcile | each device is authoritative for its own player |
| Feel | fair; a little latency on corrections | Roblox-like responsiveness |
| Cheating | hard | the room sanity-checks speed, acceleration, teleports, flying and noclip, corrects violations, and moves repeat offenders back to server authority |
| Use for | competitive games | platformers, exploration, co-op |
Lag compensation (network.pastPositions, network.raycastAtTime: the last 500 ms) works with both. See the shooter guide.
Determinism
Use time.now(), time.tickNumber() and time.random() (seeded per plot, lobby and tick; recorded). In JS packages, Math.random and Date.now() are wired to those for you; for timers use time.startTimer, not setTimeout. Deterministic code replays exactly in tests and in moderation reviews.