Implementing a client and a server in Urho3D.
Since I’ve started the project a few days ago, I’ve been trying to get a decent system for handling the game logic for xn in a single package. The vision with the game is that anyone who has the game can start up a server within their game that a friend can connect to directly, or you can set up a separate, dedicated server for things like a tournament.
I tried to learn how to do this using Urho’s scene replication examples, however in those and other network samples, the user is asked whether the game should act as a client or as a server. A global variable is set, and then in the update loop there is a separate section for client tasks and server tasks. This has always felt really inelegant, and makes it extraordinarily difficult to allow for the game to act as either a client, a server, or both at the same time; countless logic branches would have to be designed in the various event handlers.
My ideal solution would allow the server to be hosted from within the same executable, but acting as a separate entity. Then the server handles all of the game logic, and all of the clients, include the local client, just connect to the server, send events with actions, and stream the replicated scene.
After much experimenting, the solution I’ve decided on is essentially creating two separate applications, using Objects. In the main Application class, I parse the command line arguments to determine if the game should run as a normal client or as a headless server. Then it calls the setup of either of the two other “mini-applications.” Note that even if run as a client, the server can be started in the background at any point. The code to actually start the server looks something like this:
SharedPtr<Server> server = context_->CreateObject<Server>(); context_->RegisterSubsystem(server); server->Start();
There is a near-identical block of code for the client. The Server class extends Object, and has a public Start function. When this is called, the server builds the scene, and subscribes to all the events it will need, and begins listening for connections. Likewise, the Client’s Start will setup the window and UI, and prepare a scene with an octree and camera. It then tries to connect to the server. This setup allows for the two aspects of the game to be run in the same executable, but operate independently.
This system could also be used for game states, something I’ll look into when it’s time to expand past developing the gameplay itself.
I figured this out when I was trying to figure out how I could have basically two applications in one. I tried to figure out what the Application class did that was so special, but after I while I realized that other than the Start() and Stop() functions, it didn’t really do all that much. Everything important is achieved through event handlers, which can be added to any object. Thus, any Object can become your main game loop class thing with enough event handlers. It also helps that nearly all logic for units and other things like that is offloaded to components. Really, the only thing the Client class does is handle rendering and input, while the Server only handles the incoming network events. The Server receives a “move this ship here” command, which is just passes off the a component on the ship node itself.
I’m really learning to love this whole event system.
















