First you need to know how to represent your relevant data in a protocol compliant manner. This depends on the data relevant to the game. I will use an RTS game as an example.
For networking purposes, all entities in the game are enumerated (e.g. pickups, units, buildings, natural resources, destructibles).
The players need to have the data relevant to them (for instance all visible units):
- Are they alive or dead?
- What type are they?
- How much health do they have left?
- Current position, rotation, velocity (speed + direction), path in the near future...
- Activity: Attacking, walking, building, fixing, healing, etc...
- buff/debuff status effects
- and possibly other stats like mana, shields and what not?
At first the player must receive the full state before she can enter the game (or alternatively all info relevant to that player).
Each unit has an integer ID. Attributes are enumerated and therefore have integral identifiers too. The units IDs don't have to be 32 bits long (it could be if we aren't frugal). It could very well be 20 bits (leaving 10bits for the attributes).
The units' ID has to be unique, it could very well be assigned by a counter when the unit is instantiated and/or added to the game world (buildings and resources are considered an immobile unit and resources could be assigned an ID when the map is loaded).
The server stores the current global state. Each player's most recent updated state is represented by a pointer to a
list of recent changes (all the changes after the pointer have not been sent to that player yet). Changes are added to the
list when they occur. Once the server is done with sending the last update, it can begin to iterate over the list: the server moves the player's pointer along the list to it's tail, collecting all changes along the way and placing them in a buffer that will be sent to the player(i.e the protocol's format can be something like this: unit_id; attr_id; new_value)
New units are considered changes as well and are sent with all their attribute values to the receiving players.
If you are not using a language with a garbage collector, you will need to setup a lazy pointer that will be lagging behind and then catching up to the most outdated player pointer in the list, freeing objects along the way. You can remember which player is the most outdated inside a priority heap or simply iterate and free until the lazy pointer equals (i.e points to the same item as one of the players pointers).
Some questions you did not raise and I think are interesting are:
- Should the clients receive a snapshot with all the data in the first place? What about items outside their line of vision? What about fog of war in RTS games? If you send all the data, the client could be hacked to display data that should not be available to the player (depending on other security measures you take). If you only send relevant data, the issue is resolved.
- When is it vital to send changes instead of sending all the information? Considering the bandwidth available on modern machines, do we gain anything from sending a "delta" instead of sending all the information, if so when?