Skip to content
Paul Speed edited this page Aug 20, 2016 · 6 revisions

Documentation

For detailed API javadoc see: SimEthereal API Javadoc

Usage

Configuration and Tuning

Components

Overview Diagram

EtherealHost

This is the SpiderMonkey-style HostedService that is registered with the SpiderMonkey Server's service manager. The EtherealHost manages the client-specific connection to the ZoneManager and provides the interface for the application to start/stop hosting for a particular connection. (A player may be connected but not 'in game' and thus not really part of the shared object space.)

Game code calls the EtherealHost service to start hosting on a connection and tells the service which object ID represents that player. This is necessary for managing the zones of interest in the NetworkStateListener.

ZoneManager

The ZoneManager is where the game server will report object updates and these update states are stored in per-frame history blocks. Internally, it separates objects into a grid of zones to keep the state separated for different areas of interest. This history is kept until 'purged' at a later time, meaning several frames worth of data can build up at a time until the StateCollector chooses to purge it.

StateCollector

The StateCollector is a background thread that periodically purges the history from the ZoneManager to send to clients. The frequency with which it collects this data can be set on the EtherealHost at setup time but defaults to 20 times per second. (This means that on average, three frames worth of state will be sent in blocks.)

Each client will register a NetworkStateListener which will indicate which zones it is interested in recieving updates about. At the configured interval, the StateCollector will purge the current history from the ZoneManager and send it to the interested NetworkStateListeners depending on their zones of interest.

NetworkStateListener

Each client connection that is 'in game', will have a NetworkStateListener that is registered with the StateCollector. This NetworkStateListener knows which object represents the player and will use that to determine which 'zone' the player is in.
This also lets the StateCollector know which surrounding zones should have updates forwarded to this listener.

For example, a NetworkStateListener might be listening for changes to their own zone and one zone to all sides (ie: nine zones total). As that player's object moves then the zones of interest will be different.

The StateCollector delivers object state updates to the NetworkStateListener and it uses them to update its internal SharedObjectSpace. Whenever a frame update is comleted, the current state of these objects is pushed to the StateWriter which will bundle them into messages as appropriate. When one message is 'full' it will be sent and a new one started. It is possible for a single message to contain many frames of data.

When the StateCollector indicates that a history block is 'complete', the NetworkStateListener will flush the StateWriter to make sure all existing buffers are on their way to the client.

SharedObjectSpace

The SharedObjectSpace exists on both the client and the server and it keeps track of the current baseline that the client and server have agreed upon for that player. It also keeps track of the deltas against that baseline.

On the server, this is used as per-client resource to keep track of the current baseline and the deltas so that they can be bundled and sent to the client.

On the client, this is used to receive the state updates from the server and apply them to the current baseline. The game client can SharedObjectListeners with this SharedObjectSpace to receive updates whenever an object moves.

EtherealClient

This is the SpiderMonkey-style ClientService that is registered with the SpiderMonkey Client's service manager. This manages the client-side protocol for retrieving the object state messages, replying with the appropriate ACKs, and forwarding the state to the local SharedObjectSpace.

SharedObjectListener

The game client code registers a SharedObjectListener with the EtherealClient (which internally adds it to the SharedObjectSpace) so that it can receive object update events. Each listener is notified about when a frame starts, the object updates/removes in that frame, and when a frame ends. It can use this information to either do interpolated or extrapolated (predictive) positioning depending on the approach the game prefers. The client can even choose to just forward the raw updates to its visualization if it doesn't care about smooth movement.

TimeSource

Time-based object updates aren't much good unless the server and the client can share a reasonably accurate idea of what the current time is. The EtherealHost and EtherealClient internally keep track of the time latency between the server and client and allow the client's TimeSource to drift to accomodate changes in network latency. The game client can use the TimeSource to interpret the frame times of the updates it receives.

For example, this time can be used to interpolate slightly in the past between known good data states. The messages received at 't' and 't' - 'interval', are using a 't' that is based on the value returned from TimeSource. So if the client wants to interpolate 100 ms in the past (a common technique, see Valve networking articles on the Resources page), it merely needs to use an offset. In fact, the RemoteTimeSource supports this internally and defaults to a 100 ms offset.

So, if the client buffers messages then the getTime() from the time source can be used to interpolate into that buffer and the time will be consistent with the update times.