nengi intro 2: state and structure

Previous: nengi Intro 1: Authoritative Server Model

We’ve talked about our new religion, the authoritative server. Blessed be.

Now let’s talk about networked state and state in general. State is a word like data. It can sound a bit abstract or vague. I have been called “the master of vague,” which I took as a compliment though it certainly was not intended as such. So let’s work on a shared definition for the word state.

State can and often will be the properties and values of a specific object. For example

{
    id: 1,
    x: 50,
    y: 78,
    hitpoints: 100
}

If I refer to the “state of this object,” then I mean the properties (id, x, y, hitpoints) and their values (1, 50, 50, 100). I could also refer to the “state of x,” in this case the value 50. Saying that “one of the pieces of state has changed” means that the value of id, x, y, or hitpoints has now changed to a new value. I may also refer to a whole collection of objects as state.

Why all this talk about state? Games have a lot of state. They’re basically big collections of state and logic that mutates (aka changes) that state. Making a game multiplayer is fundamentally about deciding which pieces of state should be sent to the game clients and when.

So "networked state" is state that is synchronized between a server and clients. As we'll see soon, with nengi we're often making decisions about what this state should be. Much of the rest of the complexity of actually networking the state is handled for us.

How will we know if a piece of state needs networked? The general rule is that if something is *visible* and *changeable* then we will be networking it. Does the object move around? We're probably networking `x` & `y`. Does it have a hitpoint bar? We'll network `hitpoints.` Is the object supposed to look like a kitten on the game client? We'll just display our kitten sprite whenever some `type` of object is created.

That's enough general concepts. Let’s talk nengi specifics!

nengi.js

The core components of a nengi game are simple. We can build complex things out of simple parts.

The `nengi.Instance` is the serverside component of a game. We use this in our server application.

The `nengi.Client` is the clientside component of a game. We use this in the game application the user plays on their computer.

Clients connect to instances, afterwhich data flows between them.

Instances send two types of things to clients: messages and entities.

Clients send commands to instances.

Messages are single deliveries of state (keys and values) to clients. We can make any feature out of this, but it is a manual process.

Entities are stateful objects (keys and values) that stay updated in real time. These are powerful and automatic.

Commands are are just like messages, but these go from ours clients to an instance.

That's everything! So let's think of it all together now. As developers we network all aspects of the game state via creating some combination of entities and messages within a game instance. The game instance sends this state to the clients. We write clientside code that reacts to receiving these and entities by displaying sprites, 3D models, text, etc. The client can also send commands to the server to supply their input.

Revisiting the generic authoritative server model from earlier, we can now fill it out with nengi terms

  1. Client sends command to server
  2. Instance receives command
  3. serverside game logic validates command and changes some piece of game state
  4. Instance sends new game state to connected clients
  5. Client receives updated game state
  6. clientside logic renders the new state

I think we’re ready for some code!

Next: nengi Intro 3: Code & Tour