Thanks Duke, it's good to know about that project.
Making a large number of changes creates a large number of bugs, so there's a lot to clean up and straighten out.
In some ways, I haven't modified Glest's networking architecture too greatly, this is a breakdown.
- Util::Platform::Socket layer - This is Glest's low level socket manager (in the shared lib). It is implemented using TCP and issues related to timouts and such are embedded in other layers, so it's not that easily transported to a UDP implementation should we want to do that at some point. Although I don't think it would be too many changes to get it there.
- Glest::Game::NetworkInterface - This is Glest's base class (an abstract class) for all network interfaces in the game. Primarily, it dictates that a network interface should be able to get a Socket object and it has a transmit and receive buffer. I have modified this to add a NetworkMessage queue and to use my NetworkDataBuffer class instead of a char array (will explain that later).
- Glest::Game::GameNetworkInterface derives from NetworkInterface and implements more game-specific functionality, like an update(), updateKeyFrame() and functions to manage chat and command transmission and reception. I haven't made any significant modifications to this class.
- Next are ServerInterface and ClientInterface which I have modified quite a bit. Some of the mods are a bit hacky still, but not too bad. ServerInterface has a function to send a file (compressed or uncompressed) and it basically breaks it down into chunks friendly for UDP protocols and ClientInterface has a private inner class that it uses to receive and reassemble the files. I have also added mechanisms for the server to send updates (to objects in the game) to the client and for the client to receive them, as well as a mechanism for the client to explicitly request updates for specific game objects when it knows that they are out of sync, and the server has a mechanism to respond to those requests.
- NetworkMessage is the base class for all messages transmitted in Glest and GAE. I have added to this library a NetworkMessageFileHeader and NetworkMessageFileFragment for transferring files, NetworkMessageXmlDoc, a base class for transmitting xml document fragments in compressed form, and then NetworkMessageUpdate and NetworkMessageUpdateRequest to handle the previously explained messages. Each of these last two derive from NetworkMessageXmlDoc, so I can reuse most of the same code that we use for saving games as xml files. The NetworkMessageXmlDoc class can still benefit from some tweaking by assembling a good dictionary for the zlib algorithm, that can reduce message sizes significantly, but they aren't very big right now anyway.
So an important feature of this is keeping the game logic out of the network layer. These classes (for the most part) only facilitate the interface for the real game logic classes (Game, World, UnitUpdater, etc.) to run the game. There is room for improvement, but it's not too shabby in it's current form. Also, the NetworkDataBuffer class is the platform neutrality device. The way it works is that you pass it values and it writes them to it's internal buffer using network endianness (htons, e.t., a.l.). The buffer objects are actually owned by NetworkInterface and when you are done adding messages for that particular go around you just call NetworkInterface::flush() and the data is transmitted -- specifically, whatever data can be transmitted without blocking the main thread is sent and the remainders are transmitted when it's update() method is called.
NetworkDataBuffer derives from a class I wrote called SimpleDataBuffer which is in essence a data queue that allows constant time insertion of data at the end of the buffer and constant time retrieval/removal of data at the beginning and almost never has to memcpy it's internal data buffer around. Of course, it supports auto-expansion if you fill it past it's originally allocated point, but you usually won't run into that problem. NetworkDataBuffer extends from it by adding peek(), read() and write() methods for each supported data type (basically, 8, 16 and 32 bit data types).
Throughout the network layer, runtime_error is thrown when things go wrong and I haven't exactly improved upon that yet either (I've added to the mess
Unit production, and building is working better than it ever has. Morphing seems to be working flawlessly (thus far), I haven't tested combat again in a few builds (should be working well now, with minimal amounts of jumping around) and there's still an odd issue every now and again with buildings getting built but still being unfinished.
Anyway, I'll keep you guys posted. I considered back porting some of the bug fixes to the 0.1 branch, but decided against it since we still have a small user base. But after these changes, I'm going to try to keep some stable builds around.