Game Development Community

Server/Client objects and packing problems

by Adam Beaumont · in Torque Game Engine · 10/13/2003 (10:38 am) · 4 replies

I've just been writing something involving an object that exists on the server and is ghosted (always relevant) to the client. I thought I understood that when playing in single player mode its like a full server/client setup but that the 'network' is short circuited so that network calls get sent immediately to the client part of the code.

I had assumed that this meant that u still had to make sure u packed everything correctly else things wouldn't appear on the client and after some previous problems where I hadn't done so I figured I was correct.

But (!) I've been working on a gui control (on the client) that accesses an object that should be ghosted from the server to display some information. The thing is that if I comment out my PackUpdate code in this server object I still seem to be able to read data from the object on the client in single player mode.

Is this right ? Is handling all the cross network packing necessary in single player games ?

Confused !

#1
10/13/2003 (11:04 am)
Depends on what you are trying to pack up.

Eseentially a dedicated server has little to nothing to do with the display of graphics in the game - that is handled client side. Things like special effects and gui elements areessentially only necessary to the client and the server has no need to know much about them at all.

However, if the code you are working with involves something the server does need to know about - client collisions, client movement, bounding boxes then it is the server who makes the final decisions and the client merely reflects the decisions of the server.

The client anticipates a server resposnse in some cases to compentste for lost packets and the like.

Here is a pretty good general rule to follow.

If another player would need to know what is going on in order to be able to react intelligently then the info needs to be arbitrated by the server.

So, for example, a particle effect doesn't effect the other clients - it might not even be displayed on a lower level video card - so it doesn't need to go to the server. A simple trigger to say start the particle effect and where is sufficient and that is all the server should need to echo to the other clients.

A firing a rocket at a player does need to go to the server and in fact the server determines its flight path and keeps the other players who are in view aware of its flight path and determines who it hit and for how much damage.

Hope that helps.
#2
10/13/2003 (11:35 am)
Are you sure your gui control is accessing the ghost and not the server object? Try using 'AssertFatal(obj->isClientObject()...', this will warn you if your control picks up the wrong object.

Btw: working with the client and server in the same app space can be confusing at times.
#3
10/13/2003 (12:16 pm)
Adam,

John is correct. If you're getting the object by searching for it by name, you'll find that you can only do this on the Server. If you do it only the client with the server running in the same process, then it will also find the object but it will indeed by talking directly to the server object and as soon as you run the client elsewhere, it will break.

There are different ways to achieve what you're attempting but it all depends on the data content. Assuming that there is only one instance of the object in question, a neat trick I use is to set a script-variable to point to the object itself. If you do this in the "OnAdd" and set the appropriate variable according to it being a server or client object then you can access it easily.

Use a variable like "$Server::MyCoolObj" for the server and "$Client::MyCoolObj" for the client. In the "OnRemove", set these to -1 or something to invalidate them. I always use the $Server/$Client prefixes to reduce the possibility of namespace collisions.

Here's an example from our game...

bool fxGameBoard::onAdd()
{
if ( isServerObject() )
	Con::setIntVariable("$Server::fxGameBoard", getId());
else
	Con::setIntVariable("$Client::fxGameBoard", getId());
}

The good thing here is that you can use the same method throughout the scripts and easily resolve the object in C++. Note that doesn't work if you've got multiple objects. A good method in this case is to get them to add themselves to a known group which can be iterated.

There are many other methods but it all depends on your usage.

Hope this helps,

- Melv.
#4
10/13/2003 (12:57 pm)
Thanks for the replies guys.

My object is basically an information only object - at the moment (as an experiment) it holds the (compressed) positions of all the player objects so they can be displayed on a minimap, even if the object goes out of scope and no longer exists on the client. I've used this method in an Unreal mod so I was just playing with it here to see if I could get it working.

After stepping through the code in the debugger I think that when I try to get hold of the object in the GUI control (on the 'client'), it's actually getting the server version. Melv, I'll give ur solution a go as it seems like it would do what I need...

I'll let u know how it goes...

[Edit]
Cool that worked. Thanks very much for the help...