コード例 #1
0
void GhostConnection::packetReceived(PacketNotify *pnotify)
{
   Parent::packetReceived(pnotify);
   GhostPacketNotify *notify = static_cast<GhostPacketNotify *>(pnotify);

   GhostRef *packRef = notify->ghostList;

   // loop through all the notifies in this packet

   while(packRef)
   {
      // make sure this packRef isn't the last one on the GhostInfo
      if(packRef->ghost->lastUpdateChain == packRef)
         packRef->ghost->lastUpdateChain = NULL;

      GhostRef *temp = packRef->nextRef;      
      // if this object was ghosting , it is now ghosted

      if(packRef->ghostInfoFlags & GhostInfo::Ghosting)
      {
         packRef->ghost->flags &= ~GhostInfo::Ghosting;
         if(packRef->ghost->obj)
            packRef->ghost->obj->onGhostAvailable(this);
      }
      // otherwise, if it was dieing, free the ghost

      else if(packRef->ghostInfoFlags & GhostInfo::KillingGhost)
         freeGhostInfo(packRef->ghost);

      delete packRef;
      packRef = temp;
   }
}
コード例 #2
0
void GhostManager::packetReceived(DWORD key) 
{
   PacketObjectRef *packRef = (PacketObjectRef *) key;

   // loop through all the notifies in this packet

   while(packRef)
   {
      PacketObjectRef *temp = packRef->nextRef;

      AssertFatal(packRef->nextUpdateChain == NULL, "Out of order notify!!");

      // clear this notify from the end of the object's notify
      // chain

      PacketObjectRef **walk = &(packRef->ghost->updateChain);
      while(*walk != packRef)
      {
         walk = &((*walk)->nextUpdateChain);
      }
      *walk = 0;
      
      // if this object was ghosting , it is now ghosted

      if(packRef->ghostInfoFlags & GhostInfo::Ghosting)
         packRef->ghost->flags &= ~GhostInfo::Ghosting;

      // otherwise, if it was dieing, free the ghost

      else if(packRef->ghostInfoFlags & GhostInfo::KillingGhost)
         freeGhostInfo(packRef->ghost);

      // add the ref to the free list

      packRef->nextRef = freePackRefList;
      freePackRefList = packRef;

      packRef = temp;
   }
}
コード例 #3
0
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;
   
   if(!bstream->writeFlag(mGhosting && mScopeObject.isValid()))
      return;
      
   // fill a packet (or two) with ghosting data

   // 2. call scoped objects' priority functions if the flag set is nonzero
   //    A removed ghost is assumed to have a high priority
   // 3. call updates based on sorted priority until the packet is
   //    full.  set flags to zero for all updated objects

   GhostInfo *walk;

   for(S32 i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
   {
      if(!(mGhostArray[i]->flags & GhostInfo::InScope))
         detachObject(mGhostArray[i]);
   }

   U32 maxIndex = 0;
   for(S32 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(mScopeObject, walk->updateMask, walk->updateSkipCount);
      }
      else
         walk->priority = 0;
   }
   GhostRef *updateList = NULL;
   qsort(mGhostArray, mGhostZeroUpdateIndex, sizeof(GhostInfo *), UQECompare);
   // reset the array indices...
   for(S32 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, 3); // 0-7 3 bit number

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

      size_t updateStart = bstream->getBitPosition();
      U32 updateMask = walk->updateMask;
      U32 retMask = 0;
		   
      bstream->writeFlag(true);
      bstream->writeInt(walk->index, sendSize);
      if(!bstream->writeFlag(walk->flags & GhostInfo::KillGhost))
      {
         // this is an update of some kind:
         if(mConnectionParameters.mDebugObjectSizes)
            bstream->advanceBitPosition(BitStreamPosBitSize);

         size_t startPos = bstream->getBitPosition();

         if(walk->flags & GhostInfo::NotYetGhosted)
         {
            S32 classId = walk->obj->getClassId(getNetClassGroup());
            bstream->writeClassId(classId, NetClassTypeObject, getNetClassGroup());
            NetObject::mIsInitialUpdate = true;
         }

         // update the object
         retMask = walk->obj->packUpdate(this, updateMask, bstream);

         if(NetObject::mIsInitialUpdate)
         {
            NetObject::mIsInitialUpdate = false;
            walk->obj->getClassRep()->addInitialUpdate(bstream->getBitPosition() - startPos);
         }
         else
            walk->obj->getClassRep()->addPartialUpdate(bstream->getBitPosition() - startPos);

		  if(mConnectionParameters.mDebugObjectSizes){
			  size_t bpL = bstream->getBitPosition();
			  U32 bp = static_cast<U32>(bpL);
			  TNLAssert(bp == bpL, "This stream position is too long");
			bstream->writeIntAt(bp, BitStreamPosBitSize, startPos - BitStreamPosBitSize);
		  }
		  

         TNLLogMessageV(LogGhostConnection, ("GhostConnection %s GHOST %d", walk->obj->getClassName(), bstream->getBitPosition() - 16 - startPos));

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

      // check for packet overrun, and rewind this update if there
      // was one:
      if(bstream->getBitSpaceAvailable() < MinimumPaddingBits)
      {
         bstream->setBitPosition(updateStart);
         bstream->clearError();
         break;
      }

      // otherwise, create a record of this ghost update and
      // attach it to the packet.
      GhostRef *upd = new GhostRef;

      upd->nextRef = updateList;
      updateList = upd;

      if(walk->lastUpdateChain)
         walk->lastUpdateChain->updateChain = upd;
      walk->lastUpdateChain = upd;

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

      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;
      }
      else
      {
         if(walk->flags & GhostInfo::NotYetGhosted)
         {
            walk->flags &= ~GhostInfo::NotYetGhosted;
            walk->flags |= GhostInfo::Ghosting;
            upd->ghostInfoFlags = GhostInfo::Ghosting;
         }
         walk->updateMask = retMask;
         if(!retMask)
            ghostPushToZero(walk);
         upd->mask = updateMask & ~retMask;
         walk->updateSkipCount = 0;
         count++;
      }
   }
   // count # of ghosts have been updated,
   // mGhostZeroUpdateIndex # of ghosts remain to be updated.
   // no more objects...
   bstream->writeFlag(false);
   notify->ghostList = updateList;
}
コード例 #4
0
bool GhostManager::writePacket(BitStream *bstream, DWORD &key)
{
   if(curMode != GhostScopeAlwaysMode && curMode != GhostNormalMode &&
      !(curMode == InactiveMode && ghostList) )
      return false;

   // fill a packet (or two) with ghosting data

   // first step is to check all our polled ghosts:

   // 1. Scope query - find if any new objects have come into
   //    scope and if any have gone out.
   //    While the client rep is sending out the ghost always packets
   //    the scope query is not called... just ghost always objects are in the list
   // 2. call scoped objects' priority functions if the flag set is nonzero
   //    A removed ghost is assumed to have a high priority
   //    If the client rep is sending out ghost always objects
   //    then instead of the priority function, the instantiation
   //    time is used for priority. No objects are updated until
   //    all are ghosted during this phase.
   // 3. call updates based on sorted priority until the packet is
   //    full.  set flags to zero for all updated objects

   camInfo.camera = NULL;
   camInfo.pos.set(0,0,0);
   camInfo.orientation.set(0,1,0);
   camInfo.visibleDistance = 1;
   camInfo.fov = (float)(M_PI / 4.0f);
   camInfo.sinFov = 0.5;
   camInfo.cosFov = 0.5;

   GhostInfo *walk = ghostList;
   bstream->writeFlag(curMode == GhostScopeAlwaysMode);
   
   if(curMode == GhostNormalMode || curMode == InactiveMode)
   {
      if(curMode == GhostNormalMode)
      {
         while(walk)
         {
            if(!(walk->flags & GhostInfo::ScopeAlways))
               walk->flags &= ~GhostInfo::InScope;
            walk = walk->nextRef;
         }
         if(scopeObject)
            scopeObject->buildScopeAndCameraInfo(this, &camInfo);
      }
      walk = ghostList;
      while(walk)
      {
         if(!(walk->flags & GhostInfo::InScope))
         {
            walk->flags |= GhostInfo::KillGhost;
            // remove this ghostManager from the object's ghostRefs
            if(walk->obj)
            {
               Vector<GhostRef>::iterator i;
               for(i = walk->obj->ghosts.begin(); i != walk->obj->ghosts.end(); i++)
               {
                  if(i->ghostManager == this)
                  {
                     walk->obj->ghosts.erase(i);
                     break;
                  }
               }
               walk->obj = NULL;
            }
         }
         walk = walk->nextRef;
      }
   }

   static Vector<UpdateQueueEntry> qPriority;
   static Vector<UpdateQueueEntry> qDelete;

   qPriority.clear();
   qDelete.clear();

   walk = ghostList;
   
   while(walk)
   {
      // clear out any kill objects that haven't been ghosted yet
      if((walk->flags & GhostInfo::KillGhost) && (walk->flags & GhostInfo::NotYetGhosted))
      {
         GhostInfo *temp = walk->nextRef;
         freeGhostInfo(walk);
         walk = temp;
         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)
            qDelete.push_back(UpdateQueueEntry(0, walk));
         else if((walk->flags & GhostInfo::NotYetGhosted) && (curMode == GhostScopeAlwaysMode))
            qPriority.push_back(UpdateQueueEntry(-walk->obj->getNumber(), walk));
         else if(walk->updateMask && (curMode == GhostNormalMode))
         {
            float priority;
               if(scopeObject)
                  priority = walk->obj->getUpdatePriority(&camInfo, walk->updateMask, walk->updateSkipCount);
               else
                  priority = 1;
            qPriority.push_back(UpdateQueueEntry(priority, walk));
         }
      }
      walk = walk->nextRef;
   }
   PacketObjectRef *updateList = NULL;
   m_qsort((void *) &qPriority[0], qPriority.size(), sizeof(UpdateQueueEntry), UQECompare);

   Vector<UpdateQueueEntry>::iterator i = qDelete.begin();

   int packedIdSize = sendIdSize - 3; // 0-7 3 bit number
   bstream->writeInt(packedIdSize, 3);

   for(;;i++)
   {
      if(i == qDelete.end())
         i = qPriority.begin();
      if(i == qPriority.end())
         break;

      if(bstream->isFull())
      {
         (*i).obj->updateSkipCount++;
      }
      else
      {
         walk = (*i).obj;

		   if(walk->flags & (GhostInfo::KillGhost | GhostInfo::Ghosting) == (GhostInfo::KillGhost | GhostInfo::Ghosting))
		   	continue;
		   	
         int startPos = bstream->getCurPos();
         bstream->writeFlag(true);

         bstream->writeInt(walk->ghostIndex, sendIdSize);

         DWORD updateMask = walk->updateMask;
      
         PacketObjectRef *upd = freePackRefList;
         if(upd)
            freePackRefList = freePackRefList->nextRef;
         else
            upd = new PacketObjectRef;

         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;
            upd->ghostInfoFlags = GhostInfo::KillingGhost;
            bstream->writeFlag(true); // killing ghost
         }
         else 
         {
            bstream->writeFlag(false);
            if(walk->flags & GhostInfo::NotYetGhosted)
            {
               if(curMode == GhostScopeAlwaysMode)
                  bstream->writeInt(walk->obj->getNumber(), 32);

#ifdef    DEBUG_NET
               if(!walk->obj->getClass())
               {
                  AssertFatal(0, avar("%s is not a persist declared class.", 
                     walk->obj->getClassName()));
               }
#endif
               DWORD tag = walk->obj->getGhostTag();

               AssertFatal(tag > 0 && tag < 1024, "Bad ghost tag.");

               walk->flags &= ~GhostInfo::NotYetGhosted;
               walk->flags |= GhostInfo::Ghosting;
               upd->ghostInfoFlags = GhostInfo::Ghosting;
               bstream->writeInt(tag, 10);
            }

            // update the object
            DWORD retMask = walk->obj->packUpdate(this, updateMask, bstream);

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

            walk->updateMask = retMask;
            upd->mask = updateMask & ~retMask;

            PacketStream::getStats()->addBits(PacketStats::Send, bstream->getCurPos() - startPos, walk->obj->getPersistTag());
#ifdef    DEBUG_NET
            // write out a checksum...
            // we'll check this on the other side for validation
            // later we can put in stuff to check sizes and such

            bstream->writeInt(walk->ghostIndex ^ DebugChecksum, 32);
#endif
         }
         walk->updateSkipCount = 0;
      }
   }
   // no more objects...
   bstream->writeFlag(false);

   key = (DWORD) updateList;

   if(curMode == GhostScopeAlwaysMode)
   {
      // if this is our mode,
      // loop through all the objects
      // if they all have been ghosted, (ie, flags NotYetGhosted and 
      // Ghosting are NOT set), then tag this packet as the ghost always
      // done packet
      // just a bit of advanced warning to the other side to add all its
      // objects.  (if this packet is dropped - no big deal, read will
      // figure it out when it gets a normal ghost packet)

      walk = ghostList;
      bool allGhosted = true;
      while(walk)
      {
         if(walk->flags & (GhostInfo::NotYetGhosted | GhostInfo::Ghosting))
         {
            allGhosted = false;
            break;
         }
         walk = walk->nextRef;
      }
      bstream->writeFlag(allGhosted);
      if(allGhosted)
      {
         curMode = GhostNormalMode;
         CSDelegate *delegate = (CSDelegate *) manager->findObject(SimCSDelegateId);
         if(delegate)
            delegate->onGhostAlwaysDone(getOwner());
      }
   }
   return true;
}