SimObject Id and client/server connection
by Frank Bignone · in Torque Game Engine · 05/07/2002 (8:19 am) · 15 replies
Here is my question. How can I transmit to the server id of an object i'm inspecting on a client ?
Let's say that on a client, i'm looking at some object. I can get their id by object->getId(); but if I use that id on the server with Sim::findObject(id,toto) I cannot retrieve the object (toto is always NULL) !
So, How can I do it please ?
Let's say that on a client, i'm looking at some object. I can get their id by object->getId(); but if I use that id on the server with Sim::findObject(id,toto) I cannot retrieve the object (toto is always NULL) !
So, How can I do it please ?
About the author
Real programmers don't waste time recompiling; they patch the binary files... ... Real programmers don't waste time patching binary files; they patch memory.
#2
You could try:-
.. which provide mappings for ghosts.
If you search the codebase there should be plenty of examples for their usage.
Hope this helps.
- Melv.
05/07/2002 (2:12 pm)
Although I've not messed with these they seem pretty self explanatory.You could try:-
NetObject *NetConnection::resolveGhostParent(S32 id); NetObject *NetConnection::resolveGhost(S32 id); S32 NetConnection::getGhostIndex(NetObject *obj);
.. which provide mappings for ghosts.
If you search the codebase there should be plenty of examples for their usage.
Hope this helps.
- Melv.
#3
Maybe I used it in a wrong manner
05/07/2002 (2:25 pm)
Melv, I tried it and it did not solve my pbMaybe I used it in a wrong manner
#4
05/07/2002 (4:35 pm)
how bout this one:class NetObject
{
...
U32 getNetIndex() { return mNetIndex; }
#5
What iv done to get by this problem is to just resolved the id on server and passed info u need to ghost through unpackupdate packupdate.
but i dont like the idea of more network transfers
05/07/2002 (8:18 pm)
iv tried this too and would really like to see input(any Employee's out there hint hint..hehe)!!What iv done to get by this problem is to just resolved the id on server and passed info u need to ghost through unpackupdate packupdate.
but i dont like the idea of more network transfers
#6
Dave Myers
21-6 Productions
05/08/2002 (6:07 am)
I posted a resource for object picking some time ago and used the methods Melv is referring to in a way that I think might be useful to you. Take a look, and if you still have questions let me know.Dave Myers
21-6 Productions
#7
05/08/2002 (9:03 am)
I tried using something similar to your resource but it crashed my appli with no chance to debug it. I will give it a second try this week. Thanks
#8
//on server pass ghostindex:
gIndex = getGhostIndex(mSelectedObj);
bstream->writeInt(gIndex,10);
//on client resolve obj from index:
ShapeBase* obj = static_cast(resolveGhost(gIndex));
nice a simple looking..:) thanks David
05/08/2002 (1:17 pm)
ahh i see so://on server pass ghostindex:
gIndex = getGhostIndex(mSelectedObj);
bstream->writeInt(gIndex,10);
//on client resolve obj from index:
ShapeBase* obj = static_cast
nice a simple looking..:) thanks David
#9
Can someone write out how a NetEvent would pass a reference bidirectionally? I am going to solve this once and once only, and create
// does what it says, not caring if run on server or client, thankyouverymuch
void BitStream::writeNetObjectReference(NetObject *forMe, NetConnection *toBeSentOverThisConnection);
// returns false if the object is NOT null but we do not yet have a ghost image of it -- if such an error is possible??
bool BitStream::readNetObjectReference(NetObject **out, NetConnection *receivedOverThisConnection);
This is as common a need as writing or reading an int, and yet I still cannot find an example of this working in the NetEvents shipped with TGE. It should not require an understanding of implementation, or more than a single call. Please help me write this function pair?
tone
11/18/2005 (7:14 am)
This is only half of the story, however. Doesn't passing a reference from client to server require a different sequence of calls?Can someone write out how a NetEvent would pass a reference bidirectionally? I am going to solve this once and once only, and create
// does what it says, not caring if run on server or client, thankyouverymuch
void BitStream::writeNetObjectReference(NetObject *forMe, NetConnection *toBeSentOverThisConnection);
// returns false if the object is NOT null but we do not yet have a ghost image of it -- if such an error is possible??
bool BitStream::readNetObjectReference(NetObject **out, NetConnection *receivedOverThisConnection);
This is as common a need as writing or reading an int, and yet I still cannot find an example of this working in the NetEvents shipped with TGE. It should not require an understanding of implementation, or more than a single call. Please help me write this function pair?
tone
#10
Keep in mind that each client has a unique and non-consistent GhostID for every object that is ghosted for it, and the server (and client) both have script ConsoleMethods, as well as engine methods as part of the NetConnection/GameConnection class for proper resolution of the indexes.
11/18/2005 (10:13 am)
If you mean "ObjectID" when you speak of "reference" above, then the networking code already does this for you--you simply need to resolve in each direction as appropriate.Keep in mind that each client has a unique and non-consistent GhostID for every object that is ghosted for it, and the server (and client) both have script ConsoleMethods, as well as engine methods as part of the NetConnection/GameConnection class for proper resolution of the indexes.
#11
Consider trying to learn what these things are from the documents... it's as though they're trying to make a visible display of showing me how to use the API without actually helping me.
Consider:
This documentation creates more questions than it answers. Why does getNetIndex() return the ghost index? Are they different things, or the same? or something else? Is a ghost simply the version of a NetObject that resides on both server and client? If so, why not tell me what happens if this is run on the server? Is a ghosted object on the server itself called a ghost? Why isn't this done more in the following form:
[code]
U32 getClientObjectID()
Returns the "ghost ID" of the NetObject on the client running the code. A NetObject which is ghosted on clients (from the server) has a different ghostIndex by which each client refers to it. Returns 0 if called on the Server, as a NetObject on the server is not a ghosted copy.
U32 getServerObjectID()
Returns the canonical object index for efficient storage and reference on the server. This returns 0 if called on a client-only object, as the TGE network security model does not permit direct reference to objects on the server -- such reference should be made by the ClientObjectID
bool isServerObject () const
A NetObject, whether or not it is ghosted, will return true if the code is being run on the server.
bool isClientObject () const
If your NetObject is a ghost copy of a NetObject on the server, this will return true. It will also return true if it is a NetObject that only resides on your client. Always false for NetObjects examined from the server's code.
bool isGhost () const
On a client application, returns true only if your view of the NetObject is a ghost projected from the server. Calling this on the server always returns false, but servers can tell if a given object has ghost images on any clients by isGhostedToClients() and whether they are eligible for ghosting via isGhostingActivated()/
[code]
tone
11/20/2005 (11:42 am)
Can you please post code that will do what you're suggesting, as I have no idea what solution you are trying to steer me toward. I have a CS and engineering degree and years of C++ experience, but the vagueness and ambiguity of the TGE code is thwarting me left and right.Consider trying to learn what these things are from the documents... it's as though they're trying to make a visible display of showing me how to use the API without actually helping me.
Consider:
U32 getNetIndex () Get the ghost index of this object. bool isServerObject () const Is this a server object? bool isClientObject () const Is this a client object? bool isGhost () const Is this is a ghost?
This documentation creates more questions than it answers. Why does getNetIndex() return the ghost index? Are they different things, or the same? or something else? Is a ghost simply the version of a NetObject that resides on both server and client? If so, why not tell me what happens if this is run on the server? Is a ghosted object on the server itself called a ghost? Why isn't this done more in the following form:
[code]
U32 getClientObjectID()
Returns the "ghost ID" of the NetObject on the client running the code. A NetObject which is ghosted on clients (from the server) has a different ghostIndex by which each client refers to it. Returns 0 if called on the Server, as a NetObject on the server is not a ghosted copy.
U32 getServerObjectID()
Returns the canonical object index for efficient storage and reference on the server. This returns 0 if called on a client-only object, as the TGE network security model does not permit direct reference to objects on the server -- such reference should be made by the ClientObjectID
bool isServerObject () const
A NetObject, whether or not it is ghosted, will return true if the code is being run on the server.
bool isClientObject () const
If your NetObject is a ghost copy of a NetObject on the server, this will return true. It will also return true if it is a NetObject that only resides on your client. Always false for NetObjects examined from the server's code.
bool isGhost () const
On a client application, returns true only if your view of the NetObject is a ghost projected from the server. Calling this on the server always returns false, but servers can tell if a given object has ghost images on any clients by isGhostedToClients() and whether they are eligible for ghosting via isGhostingActivated()/
[code]
tone
#12
Torque is definitely a "learn by doing" kind of project. Questions I always ask myself are:
1. What am I trying to do?
2. Is there somewhere else in the engine that does a similar thing? If so, steal it and learn from it. If not, find the closest thing and use it as a starting point.
From your original post, it looks like your trying to pass the object id from a client up to the server. Why? I haven't run into this need yet, so maybe there's another way to accomplish your task?
However, you should be able to get the netindex of the client object, push it up to the server, then resolve the object id as you would on a client. The mount code in ShapeBase is a good place to see similar things in action. (Thanks to Josh "The Force" Moore for pointing me at that recently)
11/20/2005 (6:40 pm)
A ghost is a client copy of an object. The index is used to turn a server id into a client id. Each client has unique object client ids. Torque is definitely a "learn by doing" kind of project. Questions I always ask myself are:
1. What am I trying to do?
2. Is there somewhere else in the engine that does a similar thing? If so, steal it and learn from it. If not, find the closest thing and use it as a starting point.
From your original post, it looks like your trying to pass the object id from a client up to the server. Why? I haven't run into this need yet, so maybe there's another way to accomplish your task?
However, you should be able to get the netindex of the client object, push it up to the server, then resolve the object id as you would on a client. The mount code in ShapeBase is a good place to see similar things in action. (Thanks to Josh "The Force" Moore for pointing me at that recently)
#13
The short answer is: send your client's object ID up to the server (normally via a cmdToServer script call, but not always), and then on the server use NetConnection::resolveObjectFromGhostIndex() to return a pointer to the server's authoritative object that is associated with the client's clientID.
11/21/2005 (5:08 am)
You may want to look at the TDN article on Torque Networking, specifically the section on Ghosting.The short answer is: send your client's object ID up to the server (normally via a cmdToServer script call, but not always), and then on the server use NetConnection::resolveObjectFromGhostIndex() to return a pointer to the server's authoritative object that is associated with the client's clientID.
#14
Will this work?
12/02/2005 (11:59 am)
I appreciate your help, but I do not see any clear-cut cases in the code which answer the question, and trying out code when other factors might get in the way is arduous when one has many other open questions. I would love it if you could cast your eye over the following code I have written in an effort to make it easy to simply write a read/write method on BitStream.Will this work?
// write out a reference that the other side should be able to resolve to a pointer
// no matter which side of the connection this code is run from
// so that no pack()/unpack() routines need conditional behaviors based on whether they
// are run on client or on server
void
BitStream::writeNetObjectReference(NetObject *n, NetConnection *conn)
{
if (writeFlag(n != NULL)) {
// if we are on the client
if (conn->isConnectionToServer()) {
writeRangedU32(n->getId(), 0, NetConnection::MaxGhostCount);
} else {
S32 id = conn->getGhostIndex(n);
AssertFatal(id != -1, "writeNetObjectReference() called on
object with no ghost index");
writeRangedU32(U32(id), 0, NetConnection::MaxGhostCount);
}
}
}
// inverse of above function, returns false
// if the object referenced is known to be non-null yet no corresponding object
// on this network node can be found
bool
BitStream::readNetObjectReference(NetConnection *conn, NetObject **out)
{
if (readFlag()) {
// if we are on the client
if (conn->isConnectionToServer()) {
U32 ghostIndex = readRangedU32(0,NetConnection::MaxGhostCount);
*out = dynamic_cast<NetObject*>(conn->resolveGhost(ghostIndex));
} else {
U32 ghostIndex = readRangedU32(0,NetConnection::MaxGhostCount);
*out = dynamic_cast<NetObject *>(conn->resolveObjectFromGhostIndex(ghostIndex));
}
return out != NULL;
} else {
*out = NULL;
return true;
}
}
Torque Owner Daniel Neilsen
Another way would be to output the value to a script function and transfer it to the server using a CommandToServer call in script.
I am sure there would be a better way than this to do it in the engine but I am not that great at C++ sorry :/