I have tried to code it but not yet very successfully. The idea is that almost all packets sent to a player go to a chronological queue accompanied with a stamp of the turn and the time; packets not logged are ones sent just because the player has connected or requested some information not changing anything, also, just playing with unit activities and city occupance may be overwritten until the final state that actually has influenced the game. The rear of the queue is dropped due to a server setting but for any object visible at the time of the first packet present there is a packet describing its state at that moment.
How does it works: when a player connects, a message shows up "When you were offline, some events happened. Type "/replay missed" in the console to see the replay". This command in general should have some other arguments to filter the packets (by time, turn, area or team of objects involved etc.) and maybe can be written so that will do in some steps but at least it should just send the packets in a bunch (but they can mix order in the nets...) and then regenerate the actual situation. The algorithm:
- Put all visible object ids in a hash.
- Scan the queue backwards. If a packet describes an object from the hash, check it for sending and clear it from the hash. If the packet matches a criterium, check it for sending and put id(s) of its object(s) onto the hash. Continue until the hash is empty and the packets are definitely out of filtered range, or the queue is done (sanity check: in the latter case the hash is empty).
- Send the checked packets to the client. (Lags, setting player into a special mode to interact with the replay?) Packets can be added to the queue during the replay but not removed (but we remember the point).
- When the replay has ended, restore the game vision if the player is still connected. Scan the checked packets backwards. For each next one, check if its object id (or all ids for multiobject packets) is in the (initially empty) hash. If so, just uncheck. If not, send the actual game state of the object and put the object id onto the hash.
- Clear the hash.
- Send the packets the player missed during the replay.
- Update the queue if something from its start should be already forgotten.