A thing what I thought about is the following:
Everythings happens like in normal glests multiplayer implementation but with the following differences:
- hits / death / birth are "actions" distributed by the server and are not calulated by the client!
- the server constantly sends some kind of "corrections" to the clients. With every command cycle it sends the corrections for some units to the clients. So after a while all units are updated und the updates start with the first units again...
This will ( hopefully ) fix the sync problems.
This is exactly what GAE is doing right now. I've been fine tuning and tweaking the updates that the server sends, but most of the problems has been internal client consistency (making sure everybody is "in the cells" they are supposed to be in and not in the cells they aren't). I also have some lag problems because of errors in the way I dealt with some messages, but I haven't started digging into it seriously since my last revamp. At current, I have 4 unit updates:
- unit created
- unit morphed
- minor update
- major update
The 1st two and the last contain all of the unit's data, but the minor update contains just the hit points, current skill and some other bare data. I leveraged the existing code for processing XML and "serializing" units to XML, so all data is being sent as XML documents, but getting zlib compressed 1st. This isn't ideal. However, I can squeeze the data transmitted down to perhaps 20% of the current just by implementing a static dictionary for the zlib compression (a set of common words in a file that both the client and server has) and perhaps compression can come down even more than 20% (perhaps 5 or 10%). Just FYI, this is (mostly) how this works right now. Some of these aren't ideal because I ran into problems:
- worker drops off resources - client predicts (normal Glest behavior), server sends major update
- a worker begins to build a building - client puts unit in "wait for server" skill (which causes it to literally wait until the server overwrites it's skill with another) and server sends "unit created" for new building and major update to builder (I think)
- a unit is damaged - client predicts, server sends minor update
- a unit dies - client predicts, server sends major update
- a dead unit on the client receives a notice from the server that it's still alive - client brings it back to life! (hope you aren't lagging that bad, it looks funny)
- a unit morphs - client enters "wait for server", sever sends "unit morphed"
there are more, but that's the raw concept.
However, the ideal solution (IMO) is
- Alter the messaging protocol to only send the exact fields that are needed in each update (hit points, position, etc.)
- Create a binary message protocol to replace the XML messaging
In practice, using XML for network messaging and using a binary protocol each have their merits; XML messages are very quick to implement, easy to test and are highly maintainable, while binary-based protocols are simply the most efficient. By being more fine-grained and deciding on an event-by-event basis which fields are needed and which aren't, we can eliminate sending information that isn't needed (instead of having only "minor update" and "major update" to choose from).
But I'm not worried about any of that right now at all. I've done so many bit/nibble/byte protocols that I'm comfortable with that. The main problems I've been facing is knowing the right places to "interrupt" (if you will) the process flow Glest and interject this client/server model. Doing so has caused a good number of upsets, so that's been my challenge. Once I get this actually
working, I'll worry more about optimizing it.
If everything is calculated by the server then:
- Every client sends all their information to server
- Server sends only what is needed to each client
I think this will be roughly the same amount of information as sent by the client because the client only needs to know about the areas where their units actually are. For example, player 3 doesn't need to know about a battle occurring between player 1 and 2 unless they are allied and/or can view that part of the field.
Another setup could be to have it like a thin client, where commands are executed on the server and only the immediate viewing area information is sent to the client.
Actually, the client only sends the commands, the server dictates the rest. The problem with not sending data related to units not on screen is that the client may think that one of those units is invading their camp, when the server knows that it's doing something else. This makes things confusing and I think I may need to implement some AI synchronization.