The mental model
- Shared game state lives in a room on our servers; every entity has an owner — a client or the server — and only the owner writes it.
- Write to what you own exactly like local state; the SDK streams your changes up and everyone else’s down, and the server can veto or correct any write.
- Put anything cheat-sensitive or game-logic-shaped in server-owned entities (driven by typed RPCs if needed), deploy the room file with one command, and run simulated players to prove it works.
The ladder
Each rung is a local change, never a rewrite. Start at whichever rung your game needs today and climb when it gets more serious.
| Rung | What | Change |
|---|---|---|
| 0 | Relay (nothing deployed) | joinRoom(id) |
| 1 | Owner-write sync | assign owners in onJoin |
| 2 | Validators | add a validate per entity |
| 3 | Server-owned + RPCs | mark serverOwned: true |
| 4 | Server tick loop | add a tick(state, dt) |
Why ownership
Ownership is the whole trick. It turns “who is allowed to change this?” — the hardest question in multiplayer — into a property of your data, checked in one place. A cosmetic position can be client-owned and cheap. A score, a card deck, or a hit result is server-owned and safe. You choose per entity.
What the server can always do
Even for client-owned entities, the server sees every write before it’s broadcast and can reject or clamp it. That’s how you add anti-cheat without moving your whole game server-side.
Next steps
Placeholder content.