I have been working on the server code for my game. It works really well, but 90% of the functions are in 1 class.
Usually I find it pretty easy to know how to divide things up. Either each object is a class or each dialog is a class and handles logic for its children.
In this case, the server receives a request, and then either tells the other players or processes and notifies the appropriate players.
Here is the header file:
class ServerCore : public ServerHost, public NetEventListener,
public ServerEventProvider
{
NetEventDecoder m_dec;
NetEventEncoder m_enc;
LoginManager m_login;
ServerPlayerManager m_playerMan;
ServerTableManager m_tableMan;
void sendToTarget();
void sendToAllActive();
void sendToActiveNotTarget();
void sendToTable(int tableNo);
public:
ServerCore();
virtual void onConnect (Lacewing::Server::Client &client);
virtual void onDisconnect (Lacewing::Server::Client &client);
virtual void onError (Lacewing::Error &error);
virtual void onReceive (Lacewing::Server::Client &client, char * data, int size);
virtual void sendChatMessageC(const std::string& message,ChatAreaEnum area);
virtual void requestTableC(int tableNo, int seatNo);
virtual void playerRequestSitC(int tableNumber, int seatNumber);
virtual void playerStoodUpC();
virtual void hostGameC(const SpadesGameInfo& info);
virtual void gameMessageC(SpadesCSMessageEnum message, const std::vector<int>& params);
virtual void modifyListC(const std::string& player, GroupTypeEnum group, bool add);
virtual void canceledHostingRequestC();
virtual void sendInviteC(int tableNo, const std::string& player);
virtual void loginResult(const std::string& name, ServerPlayer* player,
const std::string& sessionID, bool success, bool newSession);
virtual void readyToReceiveLobbyDataC();
virtual void playerAbandonedGameC();
virtual void watchTableC(int tableNo);
virtual void gameCompleted(int tableId);
virtual void playerWantsPlayAgainC();
virtual ~ServerCore(void);
};
}
I do not really know how I could break this down into smaller classes. The tasks they perform are handed to other objects, such as authentication, and data retrieval from database, but all events are currently processed in this 1 file.
The net event decoder calls the appropriate method after converting it from the string received over the wire.
Doing it this way works very well, but the game is going to get bigger and I want to stay clean and modular.
Is this design a good idea? If not, what type of patterns are usually used in game server development to keep things more object oriented?
Thanks
Looking at your class, the command pattern comes to mind. Indeed, the methods ending in
Clook very much like commands. If you have a command interface:and a separate subclass for each command, then the
NetEventDecodercould decode the received string into a specific command.Also, anytime you find yourself passing the same data to multiple methods, that’s a hint that there’s a class hiding in there. For example, you could pull all the methods taking a
tableNumberinto aTableclass. I would also get rid of theManagerclasses and model the associations more directly.For example:
The
GameServerclass above simply models the game and does not deal with networking at all. TheNetEventDecoderandServerCorecan then coordinate to provide networking functionality and invoke commands on theGameServer. An example command might look like: