Making ghosting work without ghosting objects
by Anthony Lovell · in Torque Game Engine · 09/06/2006 (4:44 pm) · 0 replies
Edit: I faxed in and mailed in a copy of your contributor rights waiver form around 2-3 weeks ago. So please consider this as being offered to TNL under those conditions.
The problem: I was failing to see my NetObjects ghosted, and it turns out that the reason was that I had no scoping object. There are certainly some worthwhile ways to use ghosting (objectScopeLocalAlways/objectClearLocalAlways) that do not rely on scoping objects, and so I want to propose that my pair of fixes to GhostConnection's ::writePacket() method which fix this be considered a bug fix.
First fix:
And, further down in the same function:
Along with this fix, I'll offer some logging additions whose absence made my problem much more difficult to detect and rectify. Basically, TNL has a nice logging system, but there are a fair number of places in the code where an early return is made from a function owing to some fairly surprising condition, and these really (I felt) merited a log message. The short list follows without much commentary.
further down in GhostConnection::objectInScope:
And one in NetInterface.cc
The problem: I was failing to see my NetObjects ghosted, and it turns out that the reason was that I had no scoping object. There are certainly some worthwhile ways to use ghosting (objectScopeLocalAlways/objectClearLocalAlways) that do not rely on scoping objects, and so I want to propose that my pair of fixes to GhostConnection's ::writePacket() method which fix this be considered a bug fix.
First fix:
void GhostConnection::writePacket(BitStream *bstream, PacketNotify *pnotify)
{
Parent::writePacket(bstream, pnotify);
GhostPacketNotify *notify = static_cast<GhostPacketNotify *>(pnotify);
if(mConnectionParameters.mDebugObjectSizes)
bstream->writeInt(DebugChecksum, 32);
notify->ghostList = NULL;
if(!doesGhostFrom())
return;
#ifdef MY_FIX
if(!bstream->writeFlag(mGhosting))
return;
#else
if(!bstream->writeFlag(mGhosting && mScopeObject.isValid()))
return;
#endifAnd, further down in the same function:
// don't do any ghost processing on objects that are being killed
// or in the process of ghosting
else if(!(walk->flags & (GhostInfo::KillingGhost | GhostInfo::Ghosting)))
{
if(walk->flags & GhostInfo::KillGhost)
walk->priority = 10000;
#ifdef MY_FIX // this code should be made to work without a scoping object, right?
else if (mScopeObject.isNull())
walk->priority = F32(walk->updateSkipCount) * 0.1f; // cribbed from NetObject::getUpdatePriority()
#endif
else
walk->priority = walk->obj->getUpdatePriority(mScopeObject, walk->updateMask, walk->updateSkipCount);
}
else
walk->priority = 0;Along with this fix, I'll offer some logging additions whose absence made my problem much more difficult to detect and rectify. Basically, TNL has a nice logging system, but there are a fair number of places in the code where an early return is made from a function owing to some fairly surprising condition, and these really (I felt) merited a log message. The short list follows without much commentary.
void GhostConnection::objectLocalScopeAlways(NetObject *obj)
{
// TONE added this log msg
if(!doesGhostFrom()) {
TNLLogMessageV(LogGhostConnection, ("WARNING: objectLocalScopeAlways() called, but !doesGhostFrom()"));
return;
}void GhostConnection::objectLocalClearAlways(NetObject *obj)
{
// TONE added this log msg
if(!doesGhostFrom()) {
TNLLogMessageV(LogGhostConnection, ("WARNING: objectLocalClearAlways() called, but !doesGhostFrom()"));
return;
}d GhostConnection::objectInScope(NetObject *obj)
{
// TONE added these log messages
if (!mScoping) {
TNLLogMessageV(LogGhostConnection, ("WARNING: objectInScope() called, but !mScoping"));
return;
}
if (!doesGhostFrom()) {
TNLLogMessageV(LogGhostConnection, ("WARNING: objectInScope() called, but !doesGhostFrom()"));
return;
}
if (!obj->isGhostable()) {
TNLLogMessageV(LogGhostConnection, ("WARNING: objectInScope() called for !%s->isGhostable()", obj->getClassName()));
return;
}
if (obj->isScopeLocal() && !isLocalConnection()) {
TNLLogMessageV(LogGhostConnection, ("WARNING: objectInScope() called for a %s which isScopeLocal() on non-local connection", obj->getClassName()));
return;
}
// end of TONE's alterationsfurther down in GhostConnection::objectInScope:
// TONE added this warning
if (mGhostFreeIndex == MaxGhostCount) {
TNLLogMessageV(LogGhostConnection, ("ERROR: objectInScopeCalled, but maxGhosts=%d has been reached!", MaxGhostCount));
return;
}void GhostConnection::activateGhosting()
{
if(!doesGhostFrom()) {
// TONE added this logging message
TNLLogMessageV(LogGhostConnection, ("ERROR: activateGhosting() called, but !doesGhostFrom()"));
return;
}And one in NetInterface.cc
void NetInterface::handleConnectChallengeRequest(const Address &addr, BitStream *stream)
{
// TONE added logging
if(!mAllowConnections) {
TNLLogMessageV(LogNetInterface, ("WARNING: Received Connect Challenge Request from %s, but !mAllowConnections", addr.toString()));
return;
}