If you have any questions about the networking code or any other part of it, let me know. The design is maybe not immediately obvious.
I have a big NetEventListener with all the game's clientC events and serverS events.
These events are encoded / decodes via a NetEventEncoder/Decoder. The decoder propogates the decoded events (as functions) to the listeners. The listener on the server side is ServerCore. The listeners on the client side are LobbyNetHandler and GameNetHandler. Their job is to do any preconditioning, and then to dispatch the event through the game's main event system. For game events this is GameEventListener and for Lobby/Login events this is LobbyEventListener.
So there is an abstraction between networking events and the event model for module communication within the game.
Within the game, every module (GameEventProvider,LobbyEventProvider) gets hooked up to every other module in the scene (a many-to-many version of the observer pattern)
This way any module can talk to any other module without ever knowing about it.
You just put out an event and if a module is interested in it they just need to implement the virtual function.
This whole system makes it very easy to plug in new functionality into the game. So when the Chat module receives the event saying someone is typing, that actually came from the server, then the LobbyNetHandler received it and propagated it into the main event system...
So if all a sudden I want to make it so muting a player is persistent, I just have the NetHandler bubble the mute message to the server, then have the response come from the server and into the system from LobbyNetHandler or GameNetHandler instead of my local client cache. Without having to change the muting code itself.
It's a fairly object oriented design. Over the years I have thought about how it could be improved but I'm pretty happy with it anyways