Ask three engineers how to architect a multiplayer game and you’ll get three sprawling diagrams. We wanted something simpler — a single concept flexible enough to model a player, a bullet, a door, a weather system or a quest, while still being predictable to synchronise across the network. That concept is the entity.
Everything is an entity
In our engine there are no special cases for “players” versus “objects” versus “the world.” There are only entities. Each one has a type, a bag of state, and a script that defines how it behaves. A type is the template; an entity is a living instance of it.
- Type — what kind of thing this is (player, tree, projectile).
- State — the data that makes this particular instance unique (position, health, owner).
- Behaviour — the Lua functions that run on the server to update that state.
Behaviour lives in scripts
An entity’s logic is plain Lua in a repository we host for you. The engine calls well-known lifecycle functions — such as an initialiser when the entity is created and an update each tick — and your script does the rest. Because the script runs on the server, it is the single source of truth for that entity’s state.
-- door.lua
function init(self)
self.data.open = false
end
function on_interact(self, actor)
if distance(self, actor) < 2 then
self.data.open = not self.data.open
end
endNotice what isn’t here: no networking code, no serialization, no “if I’m the host” branches. You describe the door’s rules; the platform handles getting that state to every player who can see it.
Server owns state, client renders it
This split is the heart of the design. The server-side entity holds authoritative state. The client — through the SDK — holds a synchronised mirror it uses purely for presentation: meshes, animations, particles, sound. When the server says the door is open, every client shows it open. Clients can’t lie about state they don’t own, which removes a whole class of cheating and desync bugs.
Separating authority from presentation means your game logic exists in exactly one place. There is no “host” copy and “guest” copy to keep reconciled — there is the server’s entity, and everyone else is watching it.
Composition over inheritance
Because behaviour is just code attached to a type, building variety is a matter of composing small, focused scripts rather than wrestling with deep inheritance trees. A flammable crate and a flammable barrel can share the same “catches fire” logic without pretending to be the same kind of object.
Entities and the wider engine
Entity-centric design dovetails with the rest of the platform. Entities live inside chunks, which is how the world scales horizontally across servers. With dimensions, the same entity types populate many independent worlds at once. And the SDKs know how to sync any entity to any client regardless of which engine that client is built in.
The payoff
When everything is an entity and every entity is a script, a multiplayer game stops being a tangle of networking concerns and becomes a collection of small, testable behaviours. You spend your time on what your game does, not on the machinery that keeps it consistent across the wire — which is exactly where an indie team’s time should go.
