Game Development Community

Passing objects between client and server

by Seth Willits · in Torque Game Builder · 05/14/2008 (12:33 am) · 8 replies

Alright.... it's a little unclear to me what can be passed across a connection via commandToClient and commandToServer.

At first I thought you could only pass strings and numbers, but then I noticed that GameConnection.onConnectionAccepted sends itself as a parameter across the connection via the message*() methods.

So some silly rapid-fire, likely stupid, newb questions:

- Is this passing of an object across the connection "ghosting", or is it simply passing an object?
- I believe I read that ghosted objects only have their static fields sent across the net? And I believe that static fields are those defined in C++ which are manually packed using the pack and unpack C++ methods?

- Assuming that passing the client object across as a parameter *isn't* ghosting, and that ghosting is something much more fancy:
- Does TGB supports ghosting?
- Why marks an object as being ghostable?
- Are fields in an object that is ghosted automatically synced if I update their values?

I have some reading to do on ghosting specifically...

#1
05/14/2008 (4:55 am)
I might get this wrong, but here is my understanding of what is going on.

I would like to get across to people that TGB sports an event driven network model and not a "turn-based" as people like to call it. These events can be generated by either the server or any of the connected clients and can pass information between client and server. Ghosting is a method of transfering information about a specific object between clients.

A "ghost" is a NetObject which is replicated on all clients. There are no objects in TGB are dependent upon a NetObject which makes TGB's implementation of ghost objects almost redundent.

When a server creates a ghost object it is replicated on all ghostable clients (including the server's client) and is able to be referenced easily. A ghostable client is a client that the server acknowledges as being able to accept ghost objects, this property must be set by hand as it is not a default property. It is *very* important to note that ghost objects do not send any information about itself to the server or client. They must be extended to pack and unpack updates.

In the case of TGE, the server is the authorative connection and is the only one that sends information about ghosts. The clients are the ones that receive updates (TGE introduces control objects, but I won't go into any details about those). Fields or properties of ghostable objects are not automatically sent to clients from the server for two major reasons: it would make a really updates between client and server pretty large; and the game doesn't know what type of data is inside dynamic fields (dynamic fields are just strings, which are terribly inefficient when sending over the net). Fields or properties must be flagged as "dirty" by the server before it sends any information to the clients of what to update.

Because nothing is derived from a NetObject, there is no information for one to pack or unpack. I am sure you can appreciate that not all types of objects are going to need to send the same kind of information to each client. This is why in TGE objects pack and unpack vastly different information and at different times. A player might need to pack movement commands, physics information, camera information, etc. Whereas a moving platform might only want to update it's physics information when it reaches certain points.

From what I understand, you would not want to make a t2dSceneObject inherit the properties of a NetObject. Could you imagine the amount of data that would be sent between clients in a fast paced action game with thousands of bullets flying everywhere? I would think that this is one of the main reasons GG hasn't implemented real time networking.

Though this is pretty redundent, I will give you an example of how to create a ghost. To create a netobject in TGB and make it ghostable you can do something like:
%netObj = new NetObject();
%netObj.setScopeAlways();

Provided each client is marked as ghostable the net object should be replicated on each client. This really has no use for you, however.

I have touched on a very complex aspect of the networking layer in TGB. It is complex, yet not fully implemented. If you have access to TGB source you should be able to implement ghostable sceneobjects, as the framework for you to do so is in place.
#2
05/14/2008 (11:52 am)
Philip has done a great job outlining what ghosting means. To answer your other question...

You can pass a simObjectId across the network with a command but that is not in any way passing the entire object and all its data. It is just passing a 4 digit int -- and that simId won't necessarily correspond to any simObject that exists on the other side.
#3
05/14/2008 (12:13 pm)
@James: If all that's going across is an id, what's the point of that? It's not like the other side can use the id alone to get information about what the object is.


@Phillip:

Quote:There are no objects in TGB are dependent upon a NetObject which makes TGB's implementation of ghost objects almost redundent.

So then TGB does have an implementation of ghosting, but it's not the same as TGE's (by using NetObject)?

Or do you mean that since TGB objects are not NetObjects, that for us to be able to ghost anything, we'd have to create little proxy objects that are NetObjects that contains the same data as the TGB objects which makes that work redundant?



Quote:When a server creates a ghost object it is replicated on all ghostable clients (including the server's client) and is able to be referenced easily.

How/When is it replicated and how is referenced?


Quote:From what I understand, you would not want to make a t2dSceneObject inherit the properties of a NetObject. Could you imagine the amount of data that would be sent between clients in a fast paced action game with thousands of bullets flying everywhere?

From that statement, it sounds as if NetObject will send all of its fields, but you said: "Fields or properties of ghostable objects are not automatically sent to clients from the server." By the above did you simply mean, that you wouldn't want ghost a t2dSceneObject because _to make the object useful_ (just dump into a scene graph and go) you'd _need_ to send all properties which would be too much bandwidth, but not that by the simple act of making it ghostable it sends everything?



It seems to me that if you can control which fields get sent over, then you'd be able to use ghosting just fine, but I'm still not perfectly clear on if/how you do that.



Thanks guys.
#4
05/14/2008 (2:49 pm)
I would not use NetObjects at all in TGB. Stephen Zepp has given a far easier method of referencing objects across the network in another post on this branch of the forum.

Ghost objects are replicated when the object is created by the server, or a new client connects. It will only replicate a small amount of information.

Ghost objects do not pack/unpack anything by itself, derived classes must specify what they pack/unpack. What I meant was if you give the average TGB user the ability to create thousands of sprites flying all over the screen as well as the ability to update those object's physics every tick over the net, then you have problems.
#5
10/22/2008 (11:58 am)
Hmm.. I would have loved to see a link to said "Stephen Zepp" post.. as I have the exact same problem. No worries. I will see how well I can track it down.
#7
10/22/2008 (2:42 pm)
Thanks a ton Phillip!
Perusing through the mountain of data now!
-nic
#8
10/22/2008 (11:48 pm)
I looked at the thread by Stephen Zepp, that was recommended. I found it very enlightening, well written, and helpful on a general level. However, my particular question was not answered in the thread.. but almost! The line that hinted at the solution is literally:
"parse %extraData to determine what type of object we need to create, what initial values to give it, etc.

Here is the snippet:
function clientCmdNewObjectFromClient(%networkID, %owningClientID, %extraData)
{
   // parse %extraData to determine what type of object we need to create, what initial values to give it, etc.

   // create a new object locally, and set it's values.
   .....
   // we don't own this object, so mark it as such. This will be important when we get updates, especially
   // so we know how to interpolate, if we should have collision be authoritative or "by courtesy", and other situations
  
  %this.ownedByMe = false;
  %this.networkID = %networkID;
  %this.clientID = %owningClientID;
}

Basically I just need to know what steps I should take to parse the object that's sent to the client. To give a simple concrete example.. if I have the following:


server runs this:
function serverCmdGetNextObject(%client, %object)
{
   echo(%object.time); //works
   commandToClient(%client,'GetNextObject',%object);
}

this is then run on the client as a result of the commandToClient command above:
function clientCmdGetNextObject(%object){  
     echo(%object.time); //doesn't work

}

so basically I don't know how I would go about parsing this.. should I break up the object on the server side, and send the pieces, or is there some way that I can rebuild the object once it gets to the client?