I'm using a traditional Quake-style delta compression system for my state snapshots. The general process is this:
- Server keeps track of the past N world snapshots.
- Server keeps track of the tick-stamp of the last snapshot the client received (sent by the client).
- When the server wants to send a snapshot to a client, it...
- Retrieves the snapshot at the tick last acked by the client (if we can, otherwise send a full snapshot)
- Compares the latest snapshot to that retrieved snapshot
- Sends a delta
This is pretty straightforward, and it's nice because all the client has to send back is the tick of the last snapshot it received. It works because we can assume that, even though we're only sending deltas, that the client has the latest data for all values at the tick it has acknowledged.
...Except with floats. After months of successfully using this system, I've now run into a problem with floats that only change very slightly tick to tick, such as with damping velocities. Because I can't use strict equality with floats, I'm running into the following problem on low-latency connections:
- Client acked at 48, Server send 49. abs(floatValue@48 - floatValue@49) < epsilon, don't send
- Client acked at 49, Server send 50. abs(floatValue@49 - floatValue@50) < epsilon, don't send
- Client acked at 50, Server send 51. abs(floatValue@50 - floatValue@51) < epsilon, don't send
And so on. Because the float changes so little between ticks, the value is never sent, even though after a while of this it can get very out of date due to this kind of epsilon-slipping. At high latency this is much rarer because instead of comparing ticks 49 and 50, I'm comparing something like ticks 32 and 50, and the difference is big enough to overcome the approximation epsilon and be sent.
Anyone have any ideas for how I fix this problem? I'd like to keep it so the client is only sending an ack tick. I've thought about periodically forcing a "keyframe" snapshot with full data, but that could be expensive for many players. Wondering if any of you have encountered this problem before with delta compression.
Thanks!