Question to pspeed about his bit stream class

Ok, I have a few trapped minutes with my laptop and my source code so I will try to explain the ethereal fundamentals.

At a high level, an application needs to do a few things to set sim-ethereal up and make it work:
-run the server-side service
-run the client-side service
-server: send object updates
-client: receive object updates

Setting up the server-side service:

Basically, you need to add the EtherealHost to your SpiderMonkey network services on the server.

In my espace game, I have some things defined as constants to setting up the service looks like this:

        // Create the server-side service that will manage network sync
        EtherealHost ethereal = new EtherealHost(ESpaceConstants.OBJECT_PROTOCOL, 
                                                 ESpaceConstants.ZONE_GRID,
                                                 ESpaceConstants.ZONE_RADIUS);
        server.getServices().addService(ethereal);

Getting those values right can be tricky in that the bit sizes you specify in the protocol need to be big enough to support the resolution of your grid size.

Here are mine at least as an example:

    private static final int gridSize = 64;
    
    public static final ZoneGrid ZONE_GRID = new ZoneGrid(gridSize, gridSize, 0);
    public static final ObjectStateProtocol OBJECT_PROTOCOL 
                = new ObjectStateProtocol(8, 64, new Vec3Bits(-12, gridSize + 12, 16), new QuatBits(12));

Setting up the client-side service:

Similarly, to the server-side, you have to add the EtherealClient to SpiderMonkey’s client-side services.

In ESpace, mine looks like this (ignore the other services I’ve added):

        this.client = Network.connectToServer(ESpaceConstants.GAME_NAME,
                                              ESpaceConstants.PROTOCOL_VERSION,
                                              host, port);
                                              
        client.getServices().addServices(new RpcClientService(),
                                         new RmiClientService(),
                                         new EntityClientService(),
                                         new AccountClientService(),
                                         new ArenaClient(),                   
                                         new ChatClient((short)-2),
                                         new EtherealClient(ESpaceConstants.OBJECT_PROTOCOL,
                                                            ESpaceConstants.ZONE_GRID,
                                                            ESpaceConstants.ZONE_RADIUS));

Note that it uses the same constants… this is important. Both the EtherealHost and EtherealClient must share the same setup or they will get very confused.

It’s possible that in the future I may make client setup automatic.

Sending the object updates:

Once a physics frame, whatever physics engine you are using, you need to call some methods on the ZoneManager (accessible from EtherealHost)
-beginUpdate() with your game time. This locks the frame time of all of the updates you are about to add.
-updateEntity() called once per object to update its position and orientation.
-endUpdate() when all of the updates for that frame are complete.

Handling updates on the client:

Add a SharedObjectListener to the EtherealClient.

This object will be called with beginFrame(), updateObject(), removeObject(), etc. to update its local version of objects. The update is passed a SharedObject with the current state of the object and this can be transferred to your local objects however. I personally use time buffers that auto-interpolate and support lock-free multithreaded access. updateObject() is called from a different thread so you will have to make sure to handle that. I can provide an example of using a time buffer if you are interested.

I think those are all of the important bits. Let me know if you have any specific questions after playing with it and we can drill in further.

…my trapped-with-the-laptop time is just about up. Hope it helps. :slight_smile: