Handling Client and Server side versions of objects

Started by
7 comments, last by BoReDoM_Inc 14 years, 5 months ago
My game is a simple 2D networked fighting-style game on a tile-based map. The network architecture is Client-Server with an authoritative server. For all our game objects we have two versions: the base object which contains all necessary logic and data, and a client version which inherits from the base object and adds rendering (and other resource handling) functionality. The main motivation for this type of design is so that the server needs absolutely NO rendering or resource handling code (we can leave out all the libraries that the client uses). This design in-of-itself is a bit cumbersome, as every object needs two versions, but the most annoying part is that any kind of class that HAS a game object, needs to exist in two versions as well, so it can properly instantiate the correct version of the game object (client or server), like the Level class or GameArena, etc. My question is, is this standard practice in making networked games? Do you essentially need to two versions of everything? Is there another, more elegant design possible here?
Advertisement
I don't know whether or not what you've implemented is standard practice but it is not how I've done similar things. In my code I separate rendering from data by completely different classes. My rendering classes are created independently on the client and don't exist on the server. For things like Controllers that control model nodes in my 3D scene, the model nodes exist both on the server and the client. However model nodes are not rendered on the server and as such no model or animation resources are loading. Sometimes when it is necessary I use conditional compilation to compile extra code on the server or client however the code remains in the same class. I usually try to minimise conditional compilation although sometimes it is quite logical.

[Edited by - BoReDoM_Inc on October 30, 2009 8:15:49 AM]
If your game is mostly server side, then yeah is common to have two different representations of the same class. For example, NPCs on a client simply wait for orders, update, animate, and get rendered. NPCs on the server make decisions, do not need to be rendered or animated, and have access to a lot of information that clients should not.

It makes sense not to include huge amounts of code on either server or client that will never get used. Additionally, if for no other reason than security, you don't want server code going to the clients.
We actually explored conditional compilation but found it a bit too hacky for our purposes (since we didn't want ANY graphics code or files included that needed our graphics libs), as we would need way too many conditional preprocessor definitions. However your mention of having completely separate classes for rendering sounds interesting.

How do you communicate from your data class to your renderable class? Or does your renderable class 'observe' your data class? How is this relationship represented?
JerP, for example a client might have a bunch of character statistics, health and such. These are obviously stored both on the client and the server. On the client there is an interface that displays the health, the message handling on client will update the interface whenever the client's health changes.

That's probably a more obvious example as that is how people generally think of an interface, however in my game that general line of thinking is also applied to the 3D world. I have a bunch of controllers that exist on both the client and server, these control nodes in my 3D scene. The controllers contain pointers to a bunch of game specific data which will also exist on both the client and server. However, on both the client and server the world nodes are updated but only on the client are the nodes rendered, this actually the functionality of a game engine I'm using.
Can you give me an example of one of your controllers.. and what exactly are your "nodes"? Are they just nodes in a scene graph or something?

Also, does this mean your rendering code exists on the server, it just isn't called? Do you need to link your server against your graphics library when you compile?

Cheers.
Technically the rendering code does exist and server does link against OpenGL. However this is simply because dedicated server functionality has not been completed in the game engine I'm using. Because the model functionality is a part of the engine when the dedicated server is completed the rendering code will not be compiled on the server.

In regards to nodes, yes these are nodes in my scene graph. A controller has an Update() and Travel() method. It does not have a Render() method. The Render() method is included as a part of the nodes that need to be visibly displayed and is called by the engine when a world is loaded on the client. On the server the render methods aren't called and as such could be conditionally compiled. Mind you the code called in the Render() method actually makes no mention to OpenGL as the low level rendering is very well encapsulated, as such even if you did decide to leave this code around it isn't really a problem, what you would want to remove is the low level rendering code. This would be done with conditional compilation.

I know a lot of people dislike conditional compilation, I also don't like it when it is done unnecessarily however in a lot of projects it is sometimes the cleanest (or only) solution, especially when you're developing cross-platform code.
Alright cool, thanks for the musings bro. I suppose I'll just continue along the path I'm on for this project, but consider a change in the next one.
No worries at all. If you're curious the engine that I use is C4. Don't let the ugly textures in the demo throw you off though it's a very powerful reasonably priced engine.

This topic is closed to new replies.

Advertisement