⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ghostconnection.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 3 页
字号:
   {
      if(!(mGhostArray[i]->flags & GhostInfo::InScope))
         detachObject(mGhostArray[i]);
   }

   for(i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
   {
      walk = mGhostArray[i];
      if(walk->index > maxIndex)
         maxIndex = walk->index;

      // clear out any kill objects that haven't been ghosted yet
      if((walk->flags & GhostInfo::KillGhost) && (walk->flags & GhostInfo::NotYetGhosted))
      {
         freeGhostInfo(walk);
         continue;
      }
      // 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;
         else
            walk->priority = walk->obj->getUpdatePriority(&camInfo, walk->updateMask, walk->updateSkipCount);
      }
      else
         walk->priority = 0;
   }
   GhostRef *updateList = NULL;
   dQsort(mGhostArray, mGhostZeroUpdateIndex, sizeof(GhostInfo *), UQECompare);

   // reset the array indices...
   for(i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
      mGhostArray[i]->arrayIndex = i;

   S32 sendSize = 1;
   while(maxIndex >>= 1)
      sendSize++;

   if(sendSize < 3)
      sendSize = 3;

   bstream->writeInt(sendSize - 3, GhostIndexBitSize);

   U32 count = 0;
   //
   for(i = mGhostZeroUpdateIndex - 1; i >= 0 && !bstream->isFull(); i--)
   {
      GhostInfo *walk = mGhostArray[i];
		if(walk->flags & (GhostInfo::KillingGhost | GhostInfo::Ghosting))
		   continue;
		
      bstream->writeFlag(true);

      bstream->writeInt(walk->index, sendSize);
      U32 updateMask = walk->updateMask;

      GhostRef *upd = new GhostRef;

      upd->nextRef = updateList;
      updateList = upd;
      upd->nextUpdateChain = walk->updateChain;
      walk->updateChain = upd;

      upd->ghost = walk;
      upd->ghostInfoFlags = 0;

      if(walk->flags & GhostInfo::KillGhost)
      {
         walk->flags &= ~GhostInfo::KillGhost;
         walk->flags |= GhostInfo::KillingGhost;
         walk->updateMask = 0;
         upd->mask = updateMask;
         ghostPushToZero(walk);
         upd->ghostInfoFlags = GhostInfo::KillingGhost;
         bstream->writeFlag(true); // killing ghost
      }
      else
      {
         bstream->writeFlag(false);
         U32 startPos = bstream->getCurPos();
         if(walk->flags & GhostInfo::NotYetGhosted)
         {
            S32 classId = walk->obj->getClassId(getNetClassGroup());
            bstream->writeClassId(classId, NetClassTypeObject, getNetClassGroup());
#ifdef TORQUE_DEBUG_NET
            bstream->writeInt(classId ^ DebugChecksum, 32);
#endif

            walk->flags &= ~GhostInfo::NotYetGhosted;
            walk->flags |= GhostInfo::Ghosting;
            upd->ghostInfoFlags = GhostInfo::Ghosting;
         }
#ifdef TORQUE_DEBUG_NET
         else {
            S32 classId = walk->obj->getClassId(getNetClassGroup());
            bstream->writeClassId(classId, NetClassTypeObject, getNetClassGroup());
            bstream->writeInt(classId ^ DebugChecksum, 32);
         }
#endif
         // update the object
			U32 retMask(0);
//#ifdef _RPG_NOCOMMENT
         retMask = walk->obj->packUpdate(this, updateMask, bstream);
//#endif
         DEBUG_LOG(("PKLOG %d GHOST %d: %s", getId(), bstream->getCurPos() - 16 - startPos, walk->obj->getClassName()));

         AssertFatal((retMask & (~updateMask)) == 0, "Cannot set new bits in packUpdate return");

         walk->updateMask = retMask;
         if(!retMask)
            ghostPushToZero(walk);

         upd->mask = updateMask & ~retMask;

         //PacketStream::getStats()->addBits(PacketStats::Send, bstream->getCurPos() - startPos, walk->obj->getPersistTag());
#ifdef TORQUE_DEBUG_NET
         bstream->writeInt(walk->index ^ DebugChecksum, 32);
#endif
      }
      walk->updateSkipCount = 0;
      count++;
   }
   //Con::printf("Ghosts updated: %d (%d remain)", count, mGhostZeroUpdateIndex);
   // no more objects...
   bstream->writeFlag(false);
   notify->ghostList = updateList;
}

void GhostConnection::ghostReadPacket(BitStream *bstream)
{
#ifdef    TORQUE_DEBUG_NET
   U32 sum = bstream->readInt(32);
   AssertISV(sum == DebugChecksum, "Invalid checksum.");
#endif

   if(!isGhostingTo())
      return;
   if(!bstream->readFlag())
      return;

   S32 idSize;
   idSize = bstream->readInt( GhostIndexBitSize);
   idSize += 3;

   // while there's an object waiting...

   while(bstream->readFlag())
   {

	  gGhostUpdates++;

      U32 index;
      //S32 startPos = bstream->getCurPos();
      index = (U32) bstream->readInt(idSize);
      if(bstream->readFlag()) // is this ghost being deleted?
      {
		 mGhostsActive--;
         AssertFatal(mLocalGhosts[index] != NULL, "Error, NULL ghost encountered.");
         mLocalGhosts[index]->deleteObject();
         mLocalGhosts[index] = NULL;
      }
      else
      {
         if(!mLocalGhosts[index]) // it's a new ghost... cool
         {
			mGhostsActive++;
            S32 classId = bstream->readClassId(NetClassTypeObject, getNetClassGroup());
            if(classId == -1)
            {
               setLastError("Invalid packet.");
               return;
            }

            NetObject *obj = (NetObject *) ConsoleObject::create(getNetClassGroup(), NetClassTypeObject, classId);
            if(!obj)
            {
               setLastError("Invalid packet.");
               return;
            }
            obj->mNetFlags = NetObject::IsGhost;

            // object gets initial update before adding to the manager

            obj->mNetIndex = index;
            mLocalGhosts[index] = obj;
#ifdef TORQUE_DEBUG_NET
            U32 checksum = bstream->readInt(32);
            S32 origId = checksum ^ DebugChecksum;
            AssertISV(mLocalGhosts[index] != NULL, "Invalid dest ghost.");
            AssertISV(origId == mLocalGhosts[index]->getClassId(getNetClassGroup()),
               avar("class id mismatch for dest class %s.",
                  mLocalGhosts[index]->getClassName()) );
#endif
//#ifdef _RPG_NOCOMMENT
            mLocalGhosts[index]->unpackUpdate(this, bstream);
//#endif
            if(!obj->registerObject())
            {
               if(!mErrorBuffer[0])
                  setLastError("Invalid packet.");
               return;
            }
//#ifdef _RPG_NOCOMMENT
            if(mRemoteConnection)
               obj->mServerObject = mRemoteConnection->resolveObjectFromGhostIndex(index);
//#endif

            addObject(obj);
         }
         else
         {
#ifdef TORQUE_DEBUG_NET
            S32 classId = bstream->readClassId(NetClassTypeObject, getNetClassGroup());
            U32 checksum = bstream->readInt(32);
            S32 origId = checksum ^ DebugChecksum;
            AssertISV(mLocalGhosts[index] != NULL, "Invalid dest ghost.");
            AssertISV(origId == mLocalGhosts[index]->getClassId(getNetClassGroup()),
               avar("class id mismatch for dest class %s.",
                  mLocalGhosts[index]->getClassName()) );
#endif
//#ifdef _RPG_NOCOMMENT
            mLocalGhosts[index]->unpackUpdate(this, bstream);
//#endif
         }
         //PacketStream::getStats()->addBits(PacketStats::Receive, bstream->getCurPos() - startPos, ghostRefs[index].localGhost->getPersistTag());
#ifdef TORQUE_DEBUG_NET
         U32 checksum = bstream->readInt(32);
         S32 origIndex = checksum ^ DebugChecksum;
         AssertISV(origIndex == index,
            avar("unpackUpdate did not match packUpdate for object of class %s.",
               mLocalGhosts[index]->getClassName()) );
#endif
         if(mErrorBuffer[0])
            return;
      }
   }
}

//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------

void GhostConnection::setScopeObject(NetObject *obj)
{
   if(((NetObject *) mScopeObject) == obj)
      return;
   mScopeObject = obj;
}

void GhostConnection::detachObject(GhostInfo *info)
{
   // mark it for ghost killin'
   info->flags |= GhostInfo::KillGhost;

   // if the mask is in the zero range, we've got to move it up...
   if(!info->updateMask)
   {
      info->updateMask = 0xFFFFFFFF;
      ghostPushNonZero(info);
   }
   if(info->obj)
   {
      if(info->prevObjectRef)
         info->prevObjectRef->nextObjectRef = info->nextObjectRef;
      else
         info->obj->mFirstObjectRef = info->nextObjectRef;
      if(info->nextObjectRef)
         info->nextObjectRef->prevObjectRef = info->prevObjectRef;

      // remove it from the lookup table
      U32 id = info->obj->getId();
      for(GhostInfo **walk = &mGhostLookupTable[id & (GhostLookupTableSize - 1)]; *walk; walk = &((*walk)->nextLookupInfo))
      {
         GhostInfo *temp = *walk;
         if(temp == info)
         {
            *walk = temp->nextLookupInfo;
            break;
         }
      }
      info->prevObjectRef = info->nextObjectRef = NULL;
      info->obj = NULL;
   }
}

void GhostConnection::freeGhostInfo(GhostInfo *ghost)
{
   AssertFatal(ghost->arrayIndex < mGhostFreeIndex, "Ghost already freed.");
   if(ghost->arrayIndex < mGhostZeroUpdateIndex)
   {
      AssertFatal(ghost->updateMask != 0, "Invalid ghost mask.");
      ghost->updateMask = 0;
      ghostPushToZero(ghost);
   }
   ghostPushZeroToFree(ghost);
   AssertFatal(ghost->updateChain == NULL, "Ack!");
}

//-----------------------------------------------------------------------------

void GhostConnection::objectLocalScopeAlways(NetObject *obj)
{
   if(!isGhostingFrom())
      return;
   objectInScope(obj);
   for(GhostInfo *walk = mGhostLookupTable[obj->getId() & (GhostLookupTableSize - 1)]; walk; walk = walk->nextLookupInfo)
   {
      if(walk->obj != obj)
         continue;
      walk->flags |= GhostInfo::ScopeLocalAlways;
      return;
   }
}

void GhostConnection::objectLocalClearAlways(NetObject *obj)
{
   if(!isGhostingFrom())
      return;
   for(GhostInfo *walk = mGhostLookupTable[obj->getId() & (GhostLookupTableSize - 1)]; walk; walk = walk->nextLookupInfo)
   {
      if(walk->obj != obj)
         continue;
      walk->flags &= ~GhostInfo::ScopeLocalAlways;
      return;
   }
}

bool GhostConnection::validateGhostArray()
{
   AssertFatal(mGhostZeroUpdateIndex >= 0 && mGhostZeroUpdateIndex <= mGhostFreeIndex, "Invalid update index range.");
   AssertFatal(mGhostFreeIndex <= MaxGhostCount, "Invalid free index range.");
   U32 i;
   for(i = 0; i < mGhostZeroUpdateIndex; i ++)
   {
      AssertFatal(mGhostArray[i]->arrayIndex == i, "Invalid array index.");
      AssertFatal(mGhostArray[i]->updateMask != 0, "Invalid ghost mask.");
   }
   for(; i < mGhostFreeIndex; i ++)
   {
      AssertFatal(mGhostArray[i]->arrayIndex == i, "Invalid array index.");
      AssertFatal(mGhostArray[i]->updateMask == 0, "Invalid ghost mask.");
   }
   for(; i < MaxGhostCount; i++)
   {
      AssertFatal(mGhostArray[i]->arrayIndex == i, "Invalid array index.");
   }
   return true;
}

void GhostConnection::objectInScope(NetObject *obj)
{
   if (!mScoping || !isGhostingFrom())
      return;
	if (obj->isScopeLocal() && !isLocalConnection())
		return;

   S32 index = obj->getId() & (GhostLookupTableSize - 1);

   // check if it's already in scope
   // the object may have been cleared out without the lookupTable being cleared
   // so validate that the object pointers are the same.

   for(GhostInfo *walk = mGhostLookupTable[index ]; walk; walk = walk->nextLookupInfo)
   {
      if(walk->obj != obj)
         continue;
      walk->flags |= GhostInfo::InScope;
      return;
   }

   if (mGhostFreeIndex == MaxGhostCount)
   {
      AssertWarn(0,"GhostConnection::objectInScope: too many ghosts");
      return;
   }

   GhostInfo *giptr = mGhostArray[mGhostFreeIndex];
   ghostPushFreeToZero(giptr);
   giptr->updateMask = 0xFFFFFFFF;
   ghostPushNonZero(giptr);

   giptr->flags = GhostInfo::NotYetGhosted | GhostInfo::InScope;

   if(obj->mNetFlags.test(NetObject::ScopeAlways))
      giptr->flags |= GhostInfo::ScopeAlways;

   giptr->obj = obj;
   giptr->updateChain = NULL;
   giptr->updateSkipCount = 0;

   giptr->connection = this;

   giptr->nextObjectRef = obj->mFirstObjectRef;
   if(obj->mFirstObjectRef)
      obj->mFirstObjectRef->prevObjectRef = giptr;
   giptr->prevObjectRef = NULL;
   obj->mFirstObjectRef = giptr;

   giptr->nextLookupInfo = mGhostLookupTable[index];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -