Game Development Community

Ghost IDs

by Brian Uptagrafft · in Torque Game Engine · 03/26/2006 (7:03 pm) · 3 replies

I'm having issues with the whole GhostID business. Okay, so one of my player objects I know has the id of 1450 and 1811 (scaled him up to 20 20 20 using both numbers, so I know that they're referencing the same unit). In no context, however, have I been able to connect these numbers in script. I assume that one of them is the server's id and the other is the GhostID. Using the ServerConnection object, I've tried getGhostID(), which returns -1 for 1450 and 2 for 1811. If I try echoing resolveGhostID for the player ids in createPlayer, I just get 0 back (the ids there include the 1450).

Anyway, thanks for any input!

#1
03/26/2006 (10:25 pm)
I'm facing a similar problem, and have not got a response so far (for a previous post)...i need to identify my player at the client end from the ghost ID, and this player is created at the server end during the game start...using the resolveGhost() (at client's end) or resolveObjectsFromGhostIndex() (at server end), always returns null.
also on registering the objects, the player needs to be registered to the client, i did read that somewhere...and if u know anything abt it, do let me know too...unless the ghost gets resolved, i cant proceed, and its a real PITA... [:-p]
do help me in the process of helpng urself too...[:D]

thx...
#3
03/28/2006 (12:42 pm)
I also found this hard to understand due to poorly-named functions.
I wrote a means to read or write a reference to a ghosted netobject right on BitStream where (I felt) it belonged:

I've not done a great deal of testing, but think this cliche deserves treatment on a level just as writeInt()/readInt() does.

// writes a net object reference, returns true on success
// false on error (error may occur if the object is not ghosted, or has not YET been ghosted)
// works whether it is called from client or server
bool
BitStream::writeNetObjectReference(NetObject *forThisObject, NetConnection *conn)
{    
    if (writeFlag(forThisObject != NULL)) { // if it is not NULL
        bool retval;        
        S32 id;
        const char *weAre = "server";
        
        if (conn->isConnectionToServer()) {
            weAre = "client";
            id = forThisObject->getNetIndex(); // get GhostId -- who names these functions?!
            if (writeFlag(id != -1)) {
                writeRangedU32(U32(id), 0, NetConnection::MaxGhostCount);
            }   
        } else {
            id = conn->getGhostIndex(forThisObject); // get ghostId -- who names these functions?!
            
            if (writeFlag(id != -1)) {
                writeRangedU32(U32(id), 0, NetConnection::MaxGhostCount);
            }            
        }   
        
        retval = id != -1;
        
        if (!retval) {
            // for debug breakpoints
            retval = retval;
        }

        return retval;
    }
    return true;
}

// inverse of the above
// failures MAY be transient (i.e.: if the object has just been activated for ghosting, a few calls may return false 
// before one succeeds, presumably after it is ghosted across)
bool
BitStream::readNetObjectReference(NetConnection *fromThisConnection, NetObject **out)
{

    if (readFlag()) {     // is it non-null?
        NetObject *n = NULL;
        bool readAnInt = false;
        S32 index = -1;
        const char *weAre = "server";

        if (fromThisConnection->isConnectionToServer()) { // if we are on the client
            weAre = "client";
            if (readFlag()) {
                index = readRangedU32(0, NetConnection::MaxGhostCount);
                n = dynamic_cast<NetObject *>(fromThisConnection->resolveGhost(index));
                readAnInt = true;
            }
        } else {
            index = readRangedU32(0, NetConnection::MaxGhostCount);
            n = dynamic_cast<NetObject *>(fromThisConnection->resolveObjectFromGhostIndex(index));
            readAnInt = true;
        }

        if (n != NULL)
            *out = n;
        else {
#if 0
            // is this serious?  it was known not to be null, and yet we could not resolve it as such
            if (readAnInt)
                Con::warnf("readNetObjectReference() could not resolve %d on %s", index, weAre);
            else
                Con::errorf("readNetObjectReference() on %s, other guy could not find a good index", weAre);
#endif
        }

        return n != NULL;
    } else { // it was null
        *out = NULL;
        return true;
    }
}