Setting an objects position on the server from a client
by Steve Lamperti · in Torque Game Engine · 12/02/2004 (10:19 am) · 17 replies
Anyone have a suggestion for some code to set the position of an object on the server from a client?
Just to clarify, I'm making a single machine project, and I have some stuff that is just happening on the client, that I want to propagate back to the server.
Just to clarify, I'm making a single machine project, and I have some stuff that is just happening on the client, that I want to propagate back to the server.
#2
look at :
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=2173
then pass that to a function like the one ted posted above
12/02/2004 (11:04 am)
Yah thats the way we are doing it.. for object selectionlook at :
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=2173
then pass that to a function like the one ted posted above
#3
1) I'm doing this in C++, in the engine, not in scripting.
2) The object on the client is trying to communicate with the object on the server that represents itself. I.e. I'm just trying to reverse the normal process, and make the client the master for the location of the object for a limited period of time.
Now that I think about it, I think I know what I need to do in my situation. I just need to
do a sim::findObject(id) on the id from the client, and that should find the object pointer for the server object. I guess the ID for the object on the client and on the server are the same.
Running on a single machine, my client and server are both accessible at the same time.
12/02/2004 (11:41 am)
A couple of things I didn't clarify in my original question:1) I'm doing this in C++, in the engine, not in scripting.
2) The object on the client is trying to communicate with the object on the server that represents itself. I.e. I'm just trying to reverse the normal process, and make the client the master for the location of the object for a limited period of time.
Now that I think about it, I think I know what I need to do in my situation. I just need to
do a sim::findObject(id) on the id from the client, and that should find the object pointer for the server object. I guess the ID for the object on the client and on the server are the same.
Running on a single machine, my client and server are both accessible at the same time.
#4
12/02/2004 (12:17 pm)
Clearly, as anyone who understands the engine a little better then I do would know, the ID of the server and the client are not the same. I'm currently struggling with trying to make the client know the id of it's server object.
#5
We have a situation where the client can place/position objects on the server. We do this with scripts but if you have a consolecommand that has the same logic i dont see why it woudnt werk.
heres what we do.
client wants to drop an item, client asks server to create the object and put in into the world. Server creates the object and sends back to the client the object's server id. The client can then place/position the object wherever he wants.
maybe you could create a console command that takes the object's serverid as a param. Then use a combination of commandtoserver/commandto client to get the id to pass into your consolecommand..
hope that helps some..
12/02/2004 (12:43 pm)
You might could do this with a little combination of script and engine code..We have a situation where the client can place/position objects on the server. We do this with scripts but if you have a consolecommand that has the same logic i dont see why it woudnt werk.
heres what we do.
client wants to drop an item, client asks server to create the object and put in into the world. Server creates the object and sends back to the client the object's server id. The client can then place/position the object wherever he wants.
maybe you could create a console command that takes the object's serverid as a param. Then use a combination of commandtoserver/commandto client to get the id to pass into your consolecommand..
hope that helps some..
#6
I have this working. What I did was to create an instance variable in my C++ object for the ID of the object on the server, and then I do the settransform directly on the server object when the client has the information.
Seems to be working pretty well.
Thanks again for the suggestions.
12/02/2004 (12:57 pm)
Thanks for all the suggestions.I have this working. What I did was to create an instance variable in my C++ object for the ID of the object on the server, and then I do the settransform directly on the server object when the client has the information.
Seems to be working pretty well.
Thanks again for the suggestions.
#7
Now, my take: I understand that you may have specific reasons for doing what you are doing in the way you are doing it, but the base engine has methods and techniques for handling -all- of what you are trying to do, for very valid reasons.
It is very simple to make assumptions that really weren't intended in a single computer, single player type scenario (like having access to both the server's instantiation of an object and the client's instantiation, or "ghost" of the server's object), but that is going to lead you down a path that even very experienced TGE developers can get caught up in: in any form of remote client environment, those assumptions go right out the window and you have to start all over again.
I know that right now, you don't really care about that, which is fine--but you may always in the future want to implement a remote client (multiplayer) type of game, and if you go back and say "oh, I did it this way before, and it worked", and proceed to use your old code/scripts, you'll be in for a world of confusion.
The basic plan for doing what you wanted to do here using the "built in" functionality of TGE would be similar to:
real object is created on server, and scoped to the client
--client now has a ghost id of the object, plus all the data it needs
client wants to make a change to the object (position in this case)
--client issues a commandToServer script call passing the ghost id of the object, along with the change
--server catches the command with a serverCmd , resolves the ghost id to the true object id, performs the change
--all clients (assuming what was changed is a data value that is part of the ghosting to clients) are automatically updated with the changes as appropriate (if the object is in scope to them, they receive the packets, etc.)
Sorry I didn't get a chance to bring this up when you first needed a solution.
P.S.: What you did to fix the issue (created an instance variable, etc.) is already done by the code--you just needed to look at resolveObjectFromGhostIndex for the server and client(s) to be properly aware of the object.
12/02/2004 (1:07 pm)
Glad that you got it working!Now, my take: I understand that you may have specific reasons for doing what you are doing in the way you are doing it, but the base engine has methods and techniques for handling -all- of what you are trying to do, for very valid reasons.
It is very simple to make assumptions that really weren't intended in a single computer, single player type scenario (like having access to both the server's instantiation of an object and the client's instantiation, or "ghost" of the server's object), but that is going to lead you down a path that even very experienced TGE developers can get caught up in: in any form of remote client environment, those assumptions go right out the window and you have to start all over again.
I know that right now, you don't really care about that, which is fine--but you may always in the future want to implement a remote client (multiplayer) type of game, and if you go back and say "oh, I did it this way before, and it worked", and proceed to use your old code/scripts, you'll be in for a world of confusion.
The basic plan for doing what you wanted to do here using the "built in" functionality of TGE would be similar to:
real object is created on server, and scoped to the client
--client now has a ghost id of the object, plus all the data it needs
client wants to make a change to the object (position in this case)
--client issues a commandToServer script call passing the ghost id of the object, along with the change
--server catches the command with a serverCmd , resolves the ghost id to the true object id, performs the change
--all clients (assuming what was changed is a data value that is part of the ghosting to clients) are automatically updated with the changes as appropriate (if the object is in scope to them, they receive the packets, etc.)
Sorry I didn't get a chance to bring this up when you first needed a solution.
P.S.: What you did to fix the issue (created an instance variable, etc.) is already done by the code--you just needed to look at resolveObjectFromGhostIndex for the server and client(s) to be properly aware of the object.
#8
Thanks for your input. What I was initially asking for was methods to do what I was trying to do with the existing engine functionality, and it sounds like much, if not all of it was already there. (Perhaps I should have waited before going ahead with my implementation.)
You are correct that my code will not work well if I try to do anything with a traditional client/server setup over a network.
Thanks also for mentioning resolveObjectFromGhostIndex, that sounds like an important piece of what I was looking for.
I will read through your suggestions carefully, and rethink the code I just wrote.
12/02/2004 (1:36 pm)
Stephen,Thanks for your input. What I was initially asking for was methods to do what I was trying to do with the existing engine functionality, and it sounds like much, if not all of it was already there. (Perhaps I should have waited before going ahead with my implementation.)
You are correct that my code will not work well if I try to do anything with a traditional client/server setup over a network.
Thanks also for mentioning resolveObjectFromGhostIndex, that sounds like an important piece of what I was looking for.
I will read through your suggestions carefully, and rethink the code I just wrote.
#9
12/02/2004 (2:19 pm)
I'm trying to use resolveObjectFromGhostIndex, and I can't for the life of me figure out what connection to use. It's a method of netConnection, so I need to have a connection to use to communicate with it. I've tried getLocalClientConnection, and getServerConnection from GameConnection, and they aren't working. Again, I'm probably missing something obvious here.
#10
..prep my object's changes..
%newTransform = "10 10 10 0 0 0 0";
commandToServer('ChangeMyObjectSomeHow', %myObject.getGhostID(), %newTransform );
and it's caught with:
function serverCmdChangeMyObjectSomeHow(%client, %object, %transform)
{
%realServerObject = %client.resolveObjectFromGhostIndex(%object);
%realServerObject.setTransform( %transform );
}
NOTE: the %client parameter is automatically added to the parameter list as part of the handling of commandToServer coming from the client. You don't actually send it in your client side commandToServer method call.
Now, the underlying assumption here is that %realServerObject was created on the server properly, and was scoped to the client properly.
12/02/2004 (2:38 pm)
In your client side scripting, where your object is a ghosted object of one on the server, you do something like..prep my object's changes..
%newTransform = "10 10 10 0 0 0 0";
commandToServer('ChangeMyObjectSomeHow', %myObject.getGhostID(), %newTransform );
and it's caught with:
function serverCmdChangeMyObjectSomeHow(%client, %object, %transform)
{
%realServerObject = %client.resolveObjectFromGhostIndex(%object);
%realServerObject.setTransform( %transform );
}
NOTE: the %client parameter is automatically added to the parameter list as part of the handling of commandToServer coming from the client. You don't actually send it in your client side commandToServer method call.
Now, the underlying assumption here is that %realServerObject was created on the server properly, and was scoped to the client properly.
#12
I've tried:
%client.getGhostId(%obj)
and
%obj.getGhostId()
Both returns -1
So again, any idea why?
Edit: A little more context: Im trying to do that during the mission start. Actually, there isnt finished the prior loads, but nevertheless I have a valid %client and %obj values.
Edit 2: Are the ghostIds created on the server at the time the unit is created or only at the moment of inform the client? How I know in which moment the client is advised of the GhostIds? Maybe the problem is the ghostId does not exist yet, or the client is not informed of it.
09/09/2007 (7:09 pm)
Sorry for revive this old thread, but Im having exactly the same problem, with getGhostId returning -1I've tried:
%client.getGhostId(%obj)
and
%obj.getGhostId()
Both returns -1
So again, any idea why?
Edit: A little more context: Im trying to do that during the mission start. Actually, there isnt finished the prior loads, but nevertheless I have a valid %client and %obj values.
Edit 2: Are the ghostIds created on the server at the time the unit is created or only at the moment of inform the client? How I know in which moment the client is advised of the GhostIds? Maybe the problem is the ghostId does not exist yet, or the client is not informed of it.
#13
09/11/2007 (2:33 pm)
Anyone?
#14
the critical part there is which has been ghosted to the client.
couple reasons this might not be the case:
1. ghosting does not start until after mission load.
2. an object may or may not be ghosted to any given client, depending on the network scope.
ie, you cannot rely on the client having an instance of the object.
other stuff:
the ghostID is assigned *per client* when the object is first ghosted to the client.
this has a couple implications:
1. the ghostID for the same object can/will be different for different clients.
2. if the object leaves network scope for a given client and then later comes back in to network scope, a new ghostID will be assigned, probably a different one than before.
So:
* you can't rely on the object being present on the client. if this is absolutely required, consider making the object ScopeAlways.
* don't store ghostIDs; get em, use em, forget em.
09/11/2007 (2:43 pm)
GetGhostID() is used to match up the server and client-side instances of an object which has been ghosted to the client.the critical part there is which has been ghosted to the client.
couple reasons this might not be the case:
1. ghosting does not start until after mission load.
2. an object may or may not be ghosted to any given client, depending on the network scope.
ie, you cannot rely on the client having an instance of the object.
other stuff:
the ghostID is assigned *per client* when the object is first ghosted to the client.
this has a couple implications:
1. the ghostID for the same object can/will be different for different clients.
2. if the object leaves network scope for a given client and then later comes back in to network scope, a new ghostID will be assigned, probably a different one than before.
So:
* you can't rely on the object being present on the client. if this is absolutely required, consider making the object ScopeAlways.
* don't store ghostIDs; get em, use em, forget em.
#15
Is strange that you answer because of my actual problem: I wanna do the attachment of your Gui3DProjectionCtrl to my units during unit creation and squad assignment, thats prior to mission load.
As you make clear, this cannot be done, because I cannot reference the unit on the client at that point. That should not be a problem with units created after the mission start, but how do I do this with units that I actually wanna appear with the control attached?
Edit: mhhh onMissionDownloadComplete sounds like a good place to start for me :) Yes Im that dumb sometimes, but it passes after some minutes...
09/11/2007 (2:54 pm)
Clarifying Orion, thank you very much!Is strange that you answer because of my actual problem: I wanna do the attachment of your Gui3DProjectionCtrl to my units during unit creation and squad assignment, thats prior to mission load.
As you make clear, this cannot be done, because I cannot reference the unit on the client at that point. That should not be a problem with units created after the mission start, but how do I do this with units that I actually wanna appear with the control attached?
Edit: mhhh onMissionDownloadComplete sounds like a good place to start for me :) Yes Im that dumb sometimes, but it passes after some minutes...
#16
how about attaching the controls to the units when they are first received via ghosting on each client ?
- that would circumvent the whole need to get involved in ghostIDs.
there may be a client-side onAdd() call into script which you could hook into,
and if there isn't, you could easily create one.
09/11/2007 (8:52 pm)
Hah, funny!Quote:I wanna do the attachment of your Gui3DProjectionCtrl to my units during unit creation and squad assignment, thats prior to mission load.i'm not sure that makes sense. all GUI elements are client-side, not server-side.
how about attaching the controls to the units when they are first received via ghosting on each client ?
- that would circumvent the whole need to get involved in ghostIDs.
there may be a client-side onAdd() call into script which you could hook into,
and if there isn't, you could easily create one.
#17
What I was trying is, during that process, make a callback to the client to create and attach the control to the unit (that is why I needed the ghostId initially).
If I make the process later, I have to have a of list of squads, iterate, take a unit of each one and assing the control. My idea was to use the creation phase to not have to do that, but I dont think its posibly now that you help me with the ghostId concepts.
Edit: Orion, it works great when I did it on the appropriate place, thank you very much for your help on the concepts (and your help on the practice too :) )
09/11/2007 (9:27 pm)
Im playing with a squad/platoon concept for the rts kit. I create the squad (squad=simset with units+simobject with squad properties) and then fill it with units during the unit creation phase. My plan is to then add the Gui3DProjectionCtrl to each squad, but right now, I add it to one of the units of each squad.What I was trying is, during that process, make a callback to the client to create and attach the control to the unit (that is why I needed the ghostId initially).
If I make the process later, I have to have a of list of squads, iterate, take a unit of each one and assing the control. My idea was to use the creation phase to not have to do that, but I dont think its posibly now that you help me with the ghostId concepts.
Edit: Orion, it works great when I did it on the appropriate place, thank you very much for your help on the concepts (and your help on the practice too :) )
Torque 3D Owner Ted Southard
From the client... commandToServer('moveObject', 100, 100, 100); Which calls, on the server... function serverCmdMoveObject(%client, %x, %y, %z) { %object = %client.getSelectedObj(); %object.setPosition(%x SPC %y SPC %z); }