I have interest in exploring real-time multiplayer client-server game development and related algorithms. A lot of famous multiplayer games such as Quake 3 or Half-Life 2 use delta compression techniques to save bandwidth.
The server has to constantly send the latest game state snapshot to all clients. It would be very expensive to always send the full snapshot, so the server just sends the differences between the last snapshot and the current one.
...easy, right? Well, the part that I find very difficult to think about is how to actually calculate the differences between two game states.
Game states can be very complex and have entities allocated on the heap referring to each other via pointers, can have numeric values whose representation varies from an architecture to another, and much more.
I find it hard to believe that every single game object type has an hand-written serialization/deserialization/diff-calculation function.
Let's go back to the basics. Let's say I have two states, represented by bits, and I want to calculate their difference:
state0: 00001000100 // state at time=0
state1: 10000000101 // state at time=1
-----------
added: 10000000001 // bits that were 0 in state0 and are 1 in state1
removed: 00001000000 // bits that were 1 in state0 and are 1 in state1
Great, I now have the added
and removed
diff bitsets - but...
...the size of a diff is still exactly the same to the size of a state. And I actually have to send two diffs over the network!
Is a valid strategy actually building some sort of sparse data structure from those diff bitsets? Example:
// (bit index, added/removed)
// added = 0
// removed 1
(0,0)(4,1)(10,0)
// ^
// bit 0 was added, bit 4 was removed, bit 10 was added
Is this a possible valid approach?
Let's say that I managed to write serialization/deserialization functions for all my game object types from/to JSON.
Can I, somehow, having two JSON values, compute the difference between them automagically, in terms of bits?
Example:
// state0
{
"hp": 10,
"atk": 5
}
// state1
{
"hp": 4,
"atk": 5
}
// diff
{
"hp": -6
}
// state0 as bits (example, random bits)
010001000110001
// state1 as bits (example, random bits)
000001011110000
// desired diff bits (example, random bits)
100101
If something like that was possible, then it would be reasonably easy to avoid architecture-dependent issues and handwriting difference calculation functions.
Given two strings A and B similar to each other, is it possible to calculate a string C which is smaller in size than A and B, that represents the difference between A and B and that can be applied to A to get B in result?