octgn / OCTGN4

2 stars 1 forks source link

State Machine Reconciliation #4

Open kellyelton opened 8 years ago

kellyelton commented 8 years ago

Purpose of this task

To lay out the logic behind the state machine reconciliation and discuss it as necessary before it's implemented

Current

Server pings client so that it can see the clients latency

All messages come in and get two date fields, Received and Sent. Received is when we got the message, Sent is when we think it was sent (Received - Average client latency).

Messages are then put into a queue sorted by Sent date

tickCount == max(clientsAverageLatencies) / 2

The server ticks every tickCount and pops items off the queue. It only grabs items that have a Sent date that's <= DateTime.Now - tickCount. So the server will always be processing the past.

After the server processes all of the items it popped off the queue, it'll construct an object to send back that contains the newest state diff, as well as all of the ID's of StateChangeReq's the server processed at that point(the StateChangeReq are what are sent by the client, requesting a specific state change. They include id's that the client generates so the client can know which changes it made were applied to the state it receives back)

The client then gets the bundle and takes it and applys it to it's cached state object in the clients backend(the client has a state object that sits in memory that's immutable from the client side. It's basically a cached version of what's on the server).

After that is applied, it will apply the diff to the browsers state object. If there's a conflict between data: say the server says that the variable A changed to 15 and on the client side, the variable A was changed to 1 since the last dump it got(basically if we change the state but haven't got it reconciled with the server yet) it will keep the change made by the client, otherwise we'll end up with visual jitter. This is only going to happen though if we've made a change locally since the last state diff from the server.

State dumps into the browser should not trigger any new state updates, but can move items around visually. Basically no game logic should happen as a result of receiving the diff from the server, only visual updates to account for changed state.

Now every time the client changes the browser state, it'll send a message to its backend saying "Hey I updated the state"(this WON'T be triggered by server state dumps). The backend then sends the changes off as they happen to the server as quickly as possible.

Gravecorp commented 8 years ago

Seems reasonable to me. Only issue i perceive is when someone has a very high latency think of in the thousands that could basically slow down the responsiveness down to a major crawl.

kellyelton commented 8 years ago

so bill send a state change at 00:00 tim sends one at 00:01 bill has a latency of 0:05 tim has a latency of 0:02 tims message arives at 0:02 bills message arrives at 00:05

so if we didn't do the offset, tims state change would run before bills, even though bill sent his first, we just received them out of order

We add artificial lag to the server so we can account for the slowest connection, and make sure that even if you have a slow connection, your state change should still happen in the right order.

Gravecorp commented 8 years ago

so tldr state changes on the client side get sent to the server. and the server processes them with the tickcount set as the lowest latency and when a tickcount gets hit then sends out a diff to all connected clients. That diff should have compounded the changes making sure the clients recieve the most up to date diff based on queue progress and tickcount.