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

📄 netghost.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 3 页
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#ifdef _USE_TGE_NETCONNTION_


#include "platform/platform.h"
#include "core/dnet.h"
#include "console/simBase.h"
#include "sim/netConnection.h"
#include "core/bitStream.h"
#include "sim/netObject.h"
#include "core/resManager.h"
#include "console/console.h"
#include "console/consoleTypes.h"

#define DebugChecksum 0xF00DBAAD

extern U32 gGhostUpdates;

class GhostAlwaysObjectEvent : public NetEvent
{
   SimObjectId objectId;
   U32 ghostIndex;
   NetObject *object;
   bool validObject;
public:
   GhostAlwaysObjectEvent(NetObject *obj = NULL, U32 index = 0)
   {
      if(obj)
      {
         objectId = obj->getId();
         ghostIndex = index;
      }
      object = NULL;
   }
   ~GhostAlwaysObjectEvent()
      { delete object; }

   void pack(NetConnection *ps, BitStream *bstream)
   {
      bstream->writeInt(ghostIndex, GhostConnection::GhostIdBitSize);

      NetObject *obj = (NetObject *) Sim::findObject(objectId);
      if(bstream->writeFlag(obj != NULL))
      {
         S32 classId = obj->getClassId(ps->getNetClassGroup());
         bstream->writeClassId(classId, NetClassTypeObject, ps->getNetClassGroup());
         obj->packUpdate(ps, 0xFFFFFFFF, bstream);
      }
   }
   void write(NetConnection *ps, BitStream *bstream)
   {
      bstream->writeInt(ghostIndex, GhostConnection::GhostIdBitSize);
      if(bstream->writeFlag(validObject))
      {
         S32 classId = object->getClassId(ps->getNetClassGroup());
         bstream->writeClassId(classId, NetClassTypeObject, ps->getNetClassGroup());
         object->packUpdate(ps, 0xFFFFFFFF, bstream);
      }
   }
   void unpack(NetConnection *ps, BitStream *bstream)
   {
      ghostIndex = bstream->readInt(GhostConnection::GhostIdBitSize);

      if(bstream->readFlag())
      {
         S32 classId = bstream->readClassId(NetClassTypeObject, ps->getNetClassGroup());
         if(classId == -1)
         {
            ps->setLastError("Invalid packet.");
            return;
         }
         object = (NetObject *) ConsoleObject::create(ps->getNetClassGroup(), NetClassTypeObject, classId);
         if(!object)
         {
            ps->setLastError("Invalid packet.");
            return;
         }
         object->mNetFlags = NetObject::IsGhost;
         object->mNetIndex = ghostIndex;
         object->unpackUpdate(ps, bstream);
         validObject = true;
      }
      else
      {
         object = new NetObject;
         validObject = false;
      }
   }
   void process(NetConnection *ps)
   {
      Con::executef(1, "onGhostAlwaysObjectReceived");

      ps->setGhostAlwaysObject(object, ghostIndex);
      object = NULL;
   }
   DECLARE_CONOBJECT(GhostAlwaysObjectEvent);
};

IMPLEMENT_CO_NETEVENT_V1(GhostAlwaysObjectEvent);

ConsoleMethod( NetConnection, getGhostsActive, S32, 2, 2, "()"
			  "Returns number of ghosts active.")
{
	return object->getGhostsActive();
}

void NetConnection::setGhostTo(bool ghostTo)
{
   if(mLocalGhosts) // if ghosting to this is already enabled, silently return
      return;

   if(ghostTo)
   {
      mLocalGhosts = new NetObject *[MaxGhostCount];
      for(S32 i = 0; i < MaxGhostCount; i++)
         mLocalGhosts[i] = NULL;
   }
}

void NetConnection::setGhostFrom(bool ghostFrom)
{
   if(mGhostArray)
      return;

   if(ghostFrom)
   {
      mGhostFreeIndex = mGhostZeroUpdateIndex = 0;
      mGhostArray = new GhostInfo *[MaxGhostCount];
      mGhostRefs = new GhostInfo[MaxGhostCount];
      S32 i;
      for(i = 0; i < MaxGhostCount; i++)
      {
         mGhostRefs[i].obj = NULL;
         mGhostRefs[i].index = i;
         mGhostRefs[i].updateMask = 0;
      }
      mGhostLookupTable = new GhostInfo *[GhostLookupTableSize];
      for(i = 0; i < GhostLookupTableSize; i++)
         mGhostLookupTable[i] = 0;
   }
}

void NetConnection::ghostOnRemove()
{
   if(mGhostArray)
      clearGhostInfo();
}

void NetConnection::ghostPacketDropped(PacketNotify *notify)
{
   GhostRef *packRef = notify->ghostList;
   // loop through all the packRefs in the packet

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

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

      // clear out the ref for this object, plus or together all
      // flags from updates after this

      GhostRef **walk = &(packRef->ghost->updateChain);
      while(*walk != packRef)
      {
         orFlags |= (*walk)->mask;
         walk = &((*walk)->nextUpdateChain);
      }
      *walk = 0;

      // for any flags we haven't updated since this (dropped) packet
      // or them into the mask so they'll get updated soon

      orFlags = packRef->mask & ~orFlags;

      if(orFlags)
      {
         if(!packRef->ghost->updateMask)
         {
            packRef->ghost->updateMask = orFlags;
            ghostPushNonZero(packRef->ghost);
         }
         else
            packRef->ghost->updateMask |= orFlags;
      }

      // if this packet was ghosting an object, set it
      // to re ghost at it's earliest convenience

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

      // otherwise, if it was being deleted,
      // set it to re-delete

      else if(packRef->ghostInfoFlags & GhostInfo::KillingGhost)
      {
         packRef->ghost->flags |= GhostInfo::KillGhost;
         packRef->ghost->flags &= ~GhostInfo::KillingGhost;
      }

      delete packRef;
      packRef = temp;
   }
}

void NetConnection::ghostPacketReceived(PacketNotify *notify)
{
   GhostRef *packRef = notify->ghostList;

   // loop through all the notifies in this packet

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

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

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

      GhostRef **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);

      delete packRef;
      packRef = temp;
   }
}

struct UpdateQueueEntry
{
   F32 priority;
   GhostInfo *obj;

   UpdateQueueEntry(F32 in_priority, GhostInfo *in_obj)
      { priority = in_priority; obj = in_obj; }
};

static S32 QSORT_CALLBACK UQECompare(const void *a,const void *b)
{
   GhostInfo *ga = *((GhostInfo **) a);
   GhostInfo *gb = *((GhostInfo **) b);

   F32 ret = ga->priority - gb->priority;
   return (ret < 0) ? -1 : ((ret > 0) ? 1 : 0);
}

void NetConnection::ghostWritePacket(BitStream *bstream, PacketNotify *notify)
{
#ifdef    TORQUE_DEBUG_NET
   bstream->writeInt(DebugChecksum, 32);
#endif

   notify->ghostList = NULL;

   if(!isGhostingFrom())
      return;

   if(!bstream->writeFlag(mGhosting))
      return;

   // 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.
   // 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

   CameraScopeQuery camInfo;

   camInfo.camera = NULL;
   camInfo.pos.set(0,0,0);
   camInfo.orientation.set(0,1,0);
   camInfo.visibleDistance = 1;
   camInfo.fov = (F32)(3.1415f / 4.0f);
   camInfo.sinFov = 0.7071f;
   camInfo.cosFov = 0.7071f;

   GhostInfo *walk;

   // only need to worry about the ghosts that have update masks set...
   S32 maxIndex = 0;
   S32 i;
   for(i = 0; i < mGhostZeroUpdateIndex; i++)
   {
      // increment the updateSkip for everyone... it's all good
      walk = mGhostArray[i];
      walk->updateSkipCount++;
      if(!(walk->flags & (GhostInfo::ScopeAlways | GhostInfo::ScopeLocalAlways)))
         walk->flags &= ~GhostInfo::InScope;
   }

   if(mScopeObject)
      mScopeObject->onCameraScopeQuery(this, &camInfo);

   for(i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
   {
      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--)
   {

⌨️ 快捷键说明

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