2
0

netGhost.cpp 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "core/dnet.h"
  24. #include "console/simBase.h"
  25. #include "sim/netConnection.h"
  26. #include "core/stream/bitStream.h"
  27. #include "sim/netObject.h"
  28. //#include "core/resManager.h"
  29. #include "console/console.h"
  30. #include "console/consoleTypes.h"
  31. #include "console/engineAPI.h"
  32. #define DebugChecksum 0xF00DBAAD
  33. Signal<void()> NetConnection::smGhostAlwaysDone;
  34. extern U32 gGhostUpdates;
  35. class GhostAlwaysObjectEvent : public NetEvent
  36. {
  37. SimObjectId objectId;
  38. U32 ghostIndex;
  39. NetObject *object;
  40. bool validObject;
  41. public:
  42. typedef NetEvent Parent;
  43. GhostAlwaysObjectEvent(NetObject *obj = NULL, U32 index = 0)
  44. {
  45. if(obj)
  46. {
  47. objectId = obj->getId();
  48. ghostIndex = index;
  49. }
  50. else
  51. {
  52. objectId = 0;
  53. ghostIndex = 0;
  54. }
  55. object = NULL;
  56. validObject = false;
  57. }
  58. ~GhostAlwaysObjectEvent()
  59. { delete object; }
  60. void pack(NetConnection *ps, BitStream *bstream)
  61. {
  62. bstream->writeInt(ghostIndex, NetConnection::GhostIdBitSize);
  63. NetObject *obj = (NetObject *) Sim::findObject(objectId);
  64. if(bstream->writeFlag(obj != NULL))
  65. {
  66. S32 classId = obj->getClassId(ps->getNetClassGroup());
  67. bstream->writeClassId(classId, NetClassTypeObject, ps->getNetClassGroup());
  68. #ifdef TORQUE_NET_STATS
  69. U32 beginSize = bstream->getBitPosition();
  70. #endif
  71. U32 retMask = obj->packUpdate(ps, 0xFFFFFFFF, bstream);
  72. if ( retMask != 0 ) obj->setMaskBits( retMask );
  73. #ifdef TORQUE_NET_STATS
  74. obj->getClassRep()->updateNetStatPack(0xFFFFFFFF, bstream->getBitPosition() - beginSize);
  75. #endif
  76. }
  77. }
  78. void write(NetConnection *ps, BitStream *bstream)
  79. {
  80. bstream->writeInt(ghostIndex, NetConnection::GhostIdBitSize);
  81. if(bstream->writeFlag(validObject))
  82. {
  83. S32 classId = object->getClassId(ps->getNetClassGroup());
  84. bstream->writeClassId(classId, NetClassTypeObject, ps->getNetClassGroup());
  85. #ifdef TORQUE_NET_STATS
  86. U32 beginSize = bstream->getBitPosition();
  87. #endif
  88. U32 retMask = object->packUpdate(ps, 0xFFFFFFFF, bstream);
  89. if ( retMask != 0 ) object->setMaskBits( retMask );
  90. #ifdef TORQUE_NET_STATS
  91. object->getClassRep()->updateNetStatPack(0xFFFFFFFF, bstream->getBitPosition() - beginSize);
  92. #endif
  93. }
  94. }
  95. void unpack(NetConnection *ps, BitStream *bstream)
  96. {
  97. ghostIndex = bstream->readInt(NetConnection::GhostIdBitSize);
  98. if(bstream->readFlag())
  99. {
  100. S32 classId = bstream->readClassId(NetClassTypeObject, ps->getNetClassGroup());
  101. if(classId == -1)
  102. {
  103. ps->setLastError("Invalid packet. (invalid ghost class id)");
  104. return;
  105. }
  106. object = (NetObject *) ConsoleObject::create(ps->getNetClassGroup(), NetClassTypeObject, classId);
  107. if(!object)
  108. {
  109. ps->setLastError("Invalid packet. (failed to created from class id)");
  110. return;
  111. }
  112. object->mNetFlags = NetObject::IsGhost;
  113. object->mNetIndex = ghostIndex;
  114. #ifdef TORQUE_NET_STATS
  115. U32 beginSize = bstream->getBitPosition();
  116. #endif
  117. object->unpackUpdate(ps, bstream);
  118. #ifdef TORQUE_NET_STATS
  119. object->getClassRep()->updateNetStatUnpack(bstream->getBitPosition() - beginSize);
  120. #endif
  121. validObject = true;
  122. }
  123. else
  124. {
  125. object = new NetObject;
  126. validObject = false;
  127. }
  128. }
  129. void process(NetConnection *ps)
  130. {
  131. Con::executef("onGhostAlwaysObjectReceived");
  132. ps->setGhostAlwaysObject(object, ghostIndex);
  133. object = NULL;
  134. }
  135. DECLARE_CONOBJECT(GhostAlwaysObjectEvent);
  136. };
  137. IMPLEMENT_CO_NETEVENT_V1(GhostAlwaysObjectEvent);
  138. ConsoleDocClass( GhostAlwaysObjectEvent,
  139. "@brief Legacy or soon to be locked down object.\n\n"
  140. "Not intended for game development, for editors or internal use only.\n\n "
  141. "@internal");
  142. DefineEngineMethod( NetConnection, getGhostsActive, S32, (),,
  143. "@brief Provides the number of active ghosts on the connection.\n\n"
  144. "@returns The number of active ghosts.\n"
  145. "@see @ref ghosting_scoping for a description of the ghosting system.\n\n")
  146. {
  147. return object->getGhostsActive();
  148. }
  149. void NetConnection::setGhostTo(bool ghostTo)
  150. {
  151. if(mLocalGhosts) // if ghosting to this is already enabled, silently return
  152. return;
  153. if(ghostTo)
  154. {
  155. mLocalGhosts = new NetObject *[MaxGhostCount];
  156. for(S32 i = 0; i < MaxGhostCount; i++)
  157. mLocalGhosts[i] = NULL;
  158. }
  159. }
  160. void NetConnection::setGhostFrom(bool ghostFrom)
  161. {
  162. if(mGhostArray)
  163. return;
  164. if(ghostFrom)
  165. {
  166. mGhostFreeIndex = mGhostZeroUpdateIndex = 0;
  167. mGhostArray = new GhostInfo *[MaxGhostCount];
  168. mGhostRefs = new GhostInfo[MaxGhostCount];
  169. S32 i;
  170. for(i = 0; i < MaxGhostCount; i++)
  171. {
  172. mGhostRefs[i].obj = NULL;
  173. mGhostRefs[i].index = i;
  174. mGhostRefs[i].updateMask = 0;
  175. }
  176. mGhostLookupTable = new GhostInfo *[GhostLookupTableSize];
  177. for(i = 0; i < GhostLookupTableSize; i++)
  178. mGhostLookupTable[i] = 0;
  179. }
  180. }
  181. void NetConnection::ghostOnRemove()
  182. {
  183. if(mGhostArray)
  184. clearGhostInfo();
  185. }
  186. void NetConnection::ghostPacketDropped(PacketNotify *notify)
  187. {
  188. GhostRef *packRef = notify->ghostList;
  189. // loop through all the packRefs in the packet
  190. while(packRef)
  191. {
  192. GhostRef *temp = packRef->nextRef;
  193. U32 orFlags = 0;
  194. AssertFatal(packRef->nextUpdateChain == NULL, "Out of order notify!!");
  195. // clear out the ref for this object, plus or together all
  196. // flags from updates after this
  197. GhostRef **walk = &(packRef->ghost->updateChain);
  198. while(*walk != packRef)
  199. {
  200. orFlags |= (*walk)->mask;
  201. walk = &((*walk)->nextUpdateChain);
  202. }
  203. *walk = 0;
  204. // for any flags we haven't updated since this (dropped) packet
  205. // or them into the mask so they'll get updated soon
  206. orFlags = packRef->mask & ~orFlags;
  207. if(orFlags)
  208. {
  209. if(!packRef->ghost->updateMask)
  210. {
  211. packRef->ghost->updateMask = orFlags;
  212. ghostPushNonZero(packRef->ghost);
  213. }
  214. else
  215. packRef->ghost->updateMask |= orFlags;
  216. }
  217. // if this packet was ghosting an object, set it
  218. // to re ghost at it's earliest convenience
  219. if(packRef->ghostInfoFlags & GhostInfo::Ghosting)
  220. {
  221. packRef->ghost->flags |= GhostInfo::NotYetGhosted;
  222. packRef->ghost->flags &= ~GhostInfo::Ghosting;
  223. }
  224. // otherwise, if it was being deleted,
  225. // set it to re-delete
  226. else if(packRef->ghostInfoFlags & GhostInfo::KillingGhost)
  227. {
  228. packRef->ghost->flags |= GhostInfo::KillGhost;
  229. packRef->ghost->flags &= ~GhostInfo::KillingGhost;
  230. }
  231. delete packRef;
  232. packRef = temp;
  233. }
  234. }
  235. void NetConnection::ghostPacketReceived(PacketNotify *notify)
  236. {
  237. GhostRef *packRef = notify->ghostList;
  238. // loop through all the notifies in this packet
  239. while(packRef)
  240. {
  241. GhostRef *temp = packRef->nextRef;
  242. AssertFatal(packRef->nextUpdateChain == NULL, "Out of order notify!!");
  243. // clear this notify from the end of the object's notify
  244. // chain
  245. GhostRef **walk = &(packRef->ghost->updateChain);
  246. while(*walk != packRef)
  247. walk = &((*walk)->nextUpdateChain);
  248. *walk = 0;
  249. // if this object was ghosting , it is now ghosted
  250. if(packRef->ghostInfoFlags & GhostInfo::Ghosting)
  251. packRef->ghost->flags &= ~GhostInfo::Ghosting;
  252. // otherwise, if it was dieing, free the ghost
  253. else if(packRef->ghostInfoFlags & GhostInfo::KillingGhost)
  254. freeGhostInfo(packRef->ghost);
  255. delete packRef;
  256. packRef = temp;
  257. }
  258. }
  259. struct UpdateQueueEntry
  260. {
  261. F32 priority;
  262. GhostInfo *obj;
  263. UpdateQueueEntry(F32 in_priority, GhostInfo *in_obj)
  264. { priority = in_priority; obj = in_obj; }
  265. };
  266. static S32 QSORT_CALLBACK UQECompare(const void *a,const void *b)
  267. {
  268. GhostInfo *ga = *((GhostInfo **) a);
  269. GhostInfo *gb = *((GhostInfo **) b);
  270. F32 ret = ga->priority - gb->priority;
  271. return (ret < 0) ? -1 : ((ret > 0) ? 1 : 0);
  272. }
  273. void NetConnection::ghostWritePacket(BitStream *bstream, PacketNotify *notify)
  274. {
  275. #ifdef TORQUE_DEBUG_NET
  276. bstream->writeInt(DebugChecksum, 32);
  277. #endif
  278. notify->ghostList = NULL;
  279. if(!isGhostingFrom())
  280. return;
  281. if(!bstream->writeFlag(mGhosting))
  282. return;
  283. // fill a packet (or two) with ghosting data
  284. // first step is to check all our polled ghosts:
  285. // 1. Scope query - find if any new objects have come into
  286. // scope and if any have gone out.
  287. // 2. call scoped objects' priority functions if the flag set is nonzero
  288. // A removed ghost is assumed to have a high priority
  289. // 3. call updates based on sorted priority until the packet is
  290. // full. set flags to zero for all updated objects
  291. CameraScopeQuery camInfo;
  292. camInfo.camera = NULL;
  293. camInfo.pos.set(0,0,0);
  294. camInfo.orientation.set(0,1,0);
  295. camInfo.visibleDistance = 1;
  296. camInfo.fov = (F32)(3.1415f / 4.0f);
  297. camInfo.sinFov = 0.7071f;
  298. camInfo.cosFov = 0.7071f;
  299. GhostInfo *walk;
  300. // only need to worry about the ghosts that have update masks set...
  301. S32 maxIndex = 0;
  302. S32 i;
  303. for(i = 0; i < mGhostZeroUpdateIndex; i++)
  304. {
  305. // increment the updateSkip for everyone... it's all good
  306. walk = mGhostArray[i];
  307. walk->updateSkipCount++;
  308. if(!(walk->flags & (GhostInfo::ScopeAlways | GhostInfo::ScopeLocalAlways)))
  309. walk->flags &= ~GhostInfo::InScope;
  310. }
  311. if( mScopeObject )
  312. mScopeObject->onCameraScopeQuery( this, &camInfo );
  313. doneScopingScene();
  314. for(i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
  315. {
  316. // [rene, 07-Mar-11] Killing ghosts depending on the camera scope queries
  317. // seems like a bad thing to me and something that definitely has the potential
  318. // of causing scoping to eat into bandwidth rather than preserve it. As soon
  319. // as an object comes back into scope, it will have to completely retransmit its
  320. // full server-side state from scratch.
  321. if(!(mGhostArray[i]->flags & GhostInfo::InScope))
  322. detachObject(mGhostArray[i]);
  323. }
  324. for(i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
  325. {
  326. walk = mGhostArray[i];
  327. if(walk->index > maxIndex)
  328. maxIndex = walk->index;
  329. // clear out any kill objects that haven't been ghosted yet
  330. if((walk->flags & GhostInfo::KillGhost) && (walk->flags & GhostInfo::NotYetGhosted))
  331. {
  332. freeGhostInfo(walk);
  333. continue;
  334. }
  335. // don't do any ghost processing on objects that are being killed
  336. // or in the process of ghosting
  337. else if(!(walk->flags & (GhostInfo::KillingGhost | GhostInfo::Ghosting)))
  338. {
  339. if(walk->flags & GhostInfo::KillGhost)
  340. walk->priority = 10000;
  341. else
  342. walk->priority = walk->obj->getUpdatePriority(&camInfo, walk->updateMask, walk->updateSkipCount);
  343. }
  344. else
  345. walk->priority = 0;
  346. }
  347. GhostRef *updateList = NULL;
  348. dQsort(mGhostArray, mGhostZeroUpdateIndex, sizeof(GhostInfo *), UQECompare);
  349. // reset the array indices...
  350. for(i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
  351. mGhostArray[i]->arrayIndex = i;
  352. S32 sendSize = 1;
  353. while(maxIndex >>= 1)
  354. sendSize++;
  355. if(sendSize < 3)
  356. sendSize = 3;
  357. bstream->writeInt(sendSize - 3, GhostIndexBitSize);
  358. U32 count = 0;
  359. //
  360. for(i = mGhostZeroUpdateIndex - 1; i >= 0 && !bstream->isFull(); i--)
  361. {
  362. walk = mGhostArray[i];
  363. if(walk->flags & (GhostInfo::KillingGhost | GhostInfo::Ghosting))
  364. continue;
  365. bstream->writeFlag(true);
  366. bstream->writeInt(walk->index, sendSize);
  367. U32 updateMask = walk->updateMask;
  368. GhostRef *upd = new GhostRef;
  369. upd->nextRef = updateList;
  370. updateList = upd;
  371. upd->nextUpdateChain = walk->updateChain;
  372. walk->updateChain = upd;
  373. upd->ghost = walk;
  374. upd->ghostInfoFlags = 0;
  375. if(walk->flags & GhostInfo::KillGhost)
  376. {
  377. walk->flags &= ~GhostInfo::KillGhost;
  378. walk->flags |= GhostInfo::KillingGhost;
  379. walk->updateMask = 0;
  380. upd->mask = updateMask;
  381. ghostPushToZero(walk);
  382. upd->ghostInfoFlags = GhostInfo::KillingGhost;
  383. bstream->writeFlag(true); // killing ghost
  384. }
  385. else
  386. {
  387. bstream->writeFlag(false);
  388. #ifdef TORQUE_DEBUG_NET
  389. U32 startPos = bstream->getCurPos();
  390. #endif
  391. if(walk->flags & GhostInfo::NotYetGhosted)
  392. {
  393. S32 classId = walk->obj->getClassId(getNetClassGroup());
  394. bstream->writeClassId(classId, NetClassTypeObject, getNetClassGroup());
  395. #ifdef TORQUE_DEBUG_NET
  396. bstream->writeInt(classId ^ DebugChecksum, 32);
  397. #endif
  398. walk->flags &= ~GhostInfo::NotYetGhosted;
  399. walk->flags |= GhostInfo::Ghosting;
  400. upd->ghostInfoFlags = GhostInfo::Ghosting;
  401. }
  402. #ifdef TORQUE_DEBUG_NET
  403. else {
  404. S32 classId = walk->obj->getClassId(getNetClassGroup());
  405. bstream->writeClassId(classId, NetClassTypeObject, getNetClassGroup());
  406. bstream->writeInt(classId ^ DebugChecksum, 32);
  407. }
  408. #endif
  409. // update the object
  410. #ifdef TORQUE_NET_STATS
  411. U32 beginSize = bstream->getBitPosition();
  412. #endif
  413. U32 retMask = walk->obj->packUpdate(this, updateMask, bstream);
  414. #ifdef TORQUE_NET_STATS
  415. walk->obj->getClassRep()->updateNetStatPack(updateMask, bstream->getBitPosition() - beginSize);
  416. #endif
  417. DEBUG_LOG(("PKLOG %d GHOST %d: %s", getId(), bstream->getBitPosition() - 16 - startPos, walk->obj->getClassName()));
  418. AssertFatal((retMask & (~updateMask)) == 0, "Cannot set new bits in packUpdate return");
  419. ghostWriteExtra(walk->obj,bstream);
  420. walk->updateMask = retMask;
  421. if(!retMask)
  422. ghostPushToZero(walk);
  423. upd->mask = updateMask & ~retMask;
  424. //PacketStream::getStats()->addBits(PacketStats::Send, bstream->getCurPos() - startPos, walk->obj->getPersistTag());
  425. #ifdef TORQUE_DEBUG_NET
  426. bstream->writeInt(walk->index ^ DebugChecksum, 32);
  427. #endif
  428. }
  429. walk->updateSkipCount = 0;
  430. count++;
  431. }
  432. //Con::printf("Ghosts updated: %d (%d remain)", count, mGhostZeroUpdateIndex);
  433. // no more objects...
  434. bstream->writeFlag(false);
  435. notify->ghostList = updateList;
  436. }
  437. void NetConnection::ghostReadPacket(BitStream *bstream)
  438. {
  439. #ifdef TORQUE_DEBUG_NET
  440. U32 sum = bstream->readInt(32);
  441. AssertISV(sum == DebugChecksum, "Invalid checksum.");
  442. #endif
  443. if(!isGhostingTo())
  444. return;
  445. if(!bstream->readFlag())
  446. return;
  447. S32 idSize;
  448. idSize = bstream->readInt( GhostIndexBitSize);
  449. idSize += 3;
  450. // while there's an object waiting...
  451. gGhostUpdates = 0;
  452. while(bstream->readFlag())
  453. {
  454. gGhostUpdates++;
  455. U32 index;
  456. //S32 startPos = bstream->getCurPos();
  457. index = (U32) bstream->readInt(idSize);
  458. if(bstream->readFlag()) // is this ghost being deleted?
  459. {
  460. mGhostsActive--;
  461. AssertFatal(mLocalGhosts[index] != NULL, "Error, NULL ghost encountered.");
  462. mLocalGhosts[index]->deleteObject();
  463. mLocalGhosts[index] = NULL;
  464. }
  465. else
  466. {
  467. if(!mLocalGhosts[index]) // it's a new ghost... cool
  468. {
  469. mGhostsActive++;
  470. S32 classId = bstream->readClassId(NetClassTypeObject, getNetClassGroup());
  471. if(classId == -1)
  472. {
  473. setLastError("Invalid packet. (invalid new ghost class id)");
  474. return;
  475. }
  476. NetObject *obj = (NetObject *) ConsoleObject::create(getNetClassGroup(), NetClassTypeObject, classId);
  477. if(!obj)
  478. {
  479. setLastError("Invalid packet. (failed to create new ghost)");
  480. return;
  481. }
  482. // remove all flags associated with netobject
  483. obj->mNetFlags &= ~(BIT(NetObject::MaxNetFlagBit+1)-1);
  484. // we're a ghost...
  485. obj->mNetFlags |= NetObject::IsGhost;
  486. // object gets initial update before adding to the manager
  487. obj->mNetIndex = index;
  488. mLocalGhosts[index] = obj;
  489. #ifdef TORQUE_DEBUG_NET
  490. U32 checksum = bstream->readInt(32);
  491. S32 origId = checksum ^ DebugChecksum;
  492. AssertISV(mLocalGhosts[index] != NULL, "Invalid dest ghost.");
  493. AssertISV(origId == mLocalGhosts[index]->getClassId(getNetClassGroup()),
  494. avar("class id mismatch for dest class %s.",
  495. mLocalGhosts[index]->getClassName()) );
  496. #endif
  497. // give derived classes a chance to prepare ghost for reading
  498. ghostPreRead(mLocalGhosts[index],true);
  499. #ifdef TORQUE_NET_STATS
  500. U32 beginSize = bstream->getBitPosition();
  501. #endif
  502. mLocalGhosts[index]->unpackUpdate(this, bstream);
  503. #ifdef TORQUE_NET_STATS
  504. mLocalGhosts[index]->getClassRep()->updateNetStatUnpack(bstream->getBitPosition() - beginSize);
  505. #endif
  506. // Setup the remote object pointers before
  507. // we register so that it can be used from onAdd.
  508. if( mRemoteConnection )
  509. {
  510. obj->mServerObject = mRemoteConnection->resolveObjectFromGhostIndex(index);
  511. if ( obj->mServerObject )
  512. {
  513. obj->mServerObject->mClientObject = obj;
  514. // Sync selection flag as otherwise the editor will end up setting only
  515. // server-side flags when selecting an object that hasn't been ghosted yet
  516. // (usually the case when creating new objects).
  517. if( obj->mServerObject->isSelected() )
  518. obj->setSelected( true );
  519. }
  520. }
  521. if(!obj->registerObject())
  522. {
  523. if(mErrorBuffer.isEmpty())
  524. setLastError("Invalid packet. (failed to register ghost)");
  525. return;
  526. }
  527. addObject(obj);
  528. ghostReadExtra(mLocalGhosts[index],bstream,true);
  529. }
  530. else
  531. {
  532. #ifdef TORQUE_DEBUG_NET
  533. S32 classId = bstream->readClassId(NetClassTypeObject, getNetClassGroup());
  534. U32 checksum = bstream->readInt(32);
  535. S32 origId = checksum ^ DebugChecksum;
  536. AssertISV(mLocalGhosts[index] != NULL, "Invalid dest ghost.");
  537. AssertISV(origId == mLocalGhosts[index]->getClassId(getNetClassGroup()),
  538. avar("class id mismatch for dest class %s.",
  539. mLocalGhosts[index]->getClassName()) );
  540. #endif
  541. // give derived classes a chance to prepare ghost for reading
  542. ghostPreRead(mLocalGhosts[index],false);
  543. #ifdef TORQUE_NET_STATS
  544. U32 beginSize = bstream->getBitPosition();
  545. #endif
  546. mLocalGhosts[index]->unpackUpdate(this, bstream);
  547. #ifdef TORQUE_NET_STATS
  548. mLocalGhosts[index]->getClassRep()->updateNetStatUnpack(bstream->getBitPosition() - beginSize);
  549. #endif
  550. ghostReadExtra(mLocalGhosts[index],bstream,false);
  551. }
  552. //PacketStream::getStats()->addBits(PacketStats::Receive, bstream->getCurPos() - startPos, ghostRefs[index].localGhost->getPersistTag());
  553. #ifdef TORQUE_DEBUG_NET
  554. U32 checksum = bstream->readInt(32);
  555. S32 origIndex = checksum ^ DebugChecksum;
  556. AssertISV(origIndex == index,
  557. avar("unpackUpdate did not match packUpdate for object of class %s.",
  558. mLocalGhosts[index]->getClassName()) );
  559. #endif
  560. if(mErrorBuffer.isNotEmpty())
  561. return;
  562. }
  563. }
  564. }
  565. //-----------------------------------------------------------------------------
  566. //-----------------------------------------------------------------------------
  567. void NetConnection::setScopeObject(NetObject *obj)
  568. {
  569. if(((NetObject *) mScopeObject) == obj)
  570. return;
  571. mScopeObject = obj;
  572. }
  573. void NetConnection::detachObject(GhostInfo *info)
  574. {
  575. // mark it for ghost killin'
  576. info->flags |= GhostInfo::KillGhost;
  577. // if the mask is in the zero range, we've got to move it up...
  578. if(!info->updateMask)
  579. {
  580. info->updateMask = 0xFFFFFFFF;
  581. ghostPushNonZero(info);
  582. }
  583. if(info->obj)
  584. {
  585. if(info->prevObjectRef)
  586. info->prevObjectRef->nextObjectRef = info->nextObjectRef;
  587. else
  588. info->obj->mFirstObjectRef = info->nextObjectRef;
  589. if(info->nextObjectRef)
  590. info->nextObjectRef->prevObjectRef = info->prevObjectRef;
  591. // remove it from the lookup table
  592. U32 id = info->obj->getId();
  593. for(GhostInfo **walk = &mGhostLookupTable[id & (GhostLookupTableSize - 1)]; *walk; walk = &((*walk)->nextLookupInfo))
  594. {
  595. GhostInfo *temp = *walk;
  596. if(temp == info)
  597. {
  598. *walk = temp->nextLookupInfo;
  599. break;
  600. }
  601. }
  602. info->prevObjectRef = info->nextObjectRef = NULL;
  603. info->obj = NULL;
  604. }
  605. }
  606. void NetConnection::freeGhostInfo(GhostInfo *ghost)
  607. {
  608. AssertFatal(ghost->arrayIndex < mGhostFreeIndex, "Ghost already freed.");
  609. if(ghost->arrayIndex < mGhostZeroUpdateIndex)
  610. {
  611. AssertFatal(ghost->updateMask != 0, "Invalid ghost mask.");
  612. ghost->updateMask = 0;
  613. ghostPushToZero(ghost);
  614. }
  615. ghostPushZeroToFree(ghost);
  616. AssertFatal(ghost->updateChain == NULL, "Ack!");
  617. }
  618. //-----------------------------------------------------------------------------
  619. void NetConnection::objectLocalScopeAlways(NetObject *obj)
  620. {
  621. if(!isGhostingFrom())
  622. return;
  623. objectInScope(obj);
  624. for(GhostInfo *walk = mGhostLookupTable[obj->getId() & (GhostLookupTableSize - 1)]; walk; walk = walk->nextLookupInfo)
  625. {
  626. if(walk->obj != obj)
  627. continue;
  628. walk->flags |= GhostInfo::ScopeLocalAlways;
  629. return;
  630. }
  631. }
  632. void NetConnection::objectLocalClearAlways(NetObject *obj)
  633. {
  634. if(!isGhostingFrom())
  635. return;
  636. for(GhostInfo *walk = mGhostLookupTable[obj->getId() & (GhostLookupTableSize - 1)]; walk; walk = walk->nextLookupInfo)
  637. {
  638. if(walk->obj != obj)
  639. continue;
  640. walk->flags &= ~GhostInfo::ScopeLocalAlways;
  641. return;
  642. }
  643. }
  644. bool NetConnection::validateGhostArray()
  645. {
  646. AssertFatal(mGhostZeroUpdateIndex >= 0 && mGhostZeroUpdateIndex <= mGhostFreeIndex, "Invalid update index range.");
  647. AssertFatal(mGhostFreeIndex <= MaxGhostCount, "Invalid free index range.");
  648. U32 i;
  649. for(i = 0; i < mGhostZeroUpdateIndex; i ++)
  650. {
  651. AssertFatal(mGhostArray[i]->arrayIndex == i, "Invalid array index.");
  652. AssertFatal(mGhostArray[i]->updateMask != 0, "Invalid ghost mask.");
  653. }
  654. for(; i < mGhostFreeIndex; i ++)
  655. {
  656. AssertFatal(mGhostArray[i]->arrayIndex == i, "Invalid array index.");
  657. AssertFatal(mGhostArray[i]->updateMask == 0, "Invalid ghost mask.");
  658. }
  659. for(; i < MaxGhostCount; i++)
  660. {
  661. AssertFatal(mGhostArray[i]->arrayIndex == i, "Invalid array index.");
  662. }
  663. return true;
  664. }
  665. void NetConnection::objectInScope(NetObject *obj)
  666. {
  667. if (!mScoping || !isGhostingFrom())
  668. return;
  669. if (obj->isScopeLocal() && !isLocalConnection())
  670. return;
  671. S32 index = obj->getId() & (GhostLookupTableSize - 1);
  672. // check if it's already in scope
  673. // the object may have been cleared out without the lookupTable being cleared
  674. // so validate that the object pointers are the same.
  675. for(GhostInfo *walk = mGhostLookupTable[index ]; walk; walk = walk->nextLookupInfo)
  676. {
  677. if(walk->obj != obj)
  678. continue;
  679. walk->flags |= GhostInfo::InScope;
  680. // Make sure scope always if reflected on the ghostinfo too
  681. if (obj->mNetFlags.test(NetObject::ScopeAlways))
  682. walk->flags |= GhostInfo::ScopeAlways;
  683. return;
  684. }
  685. if (mGhostFreeIndex == MaxGhostCount)
  686. {
  687. AssertWarn(0,"NetConnection::objectInScope: too many ghosts");
  688. return;
  689. }
  690. GhostInfo *giptr = mGhostArray[mGhostFreeIndex];
  691. ghostPushFreeToZero(giptr);
  692. giptr->updateMask = 0xFFFFFFFF;
  693. ghostPushNonZero(giptr);
  694. giptr->flags = GhostInfo::NotYetGhosted | GhostInfo::InScope;
  695. if(obj->mNetFlags.test(NetObject::ScopeAlways))
  696. giptr->flags |= GhostInfo::ScopeAlways;
  697. giptr->obj = obj;
  698. giptr->updateChain = NULL;
  699. giptr->updateSkipCount = 0;
  700. giptr->connection = this;
  701. giptr->nextObjectRef = obj->mFirstObjectRef;
  702. if(obj->mFirstObjectRef)
  703. obj->mFirstObjectRef->prevObjectRef = giptr;
  704. giptr->prevObjectRef = NULL;
  705. obj->mFirstObjectRef = giptr;
  706. giptr->nextLookupInfo = mGhostLookupTable[index];
  707. mGhostLookupTable[index] = giptr;
  708. //AssertFatal(validateGhostArray(), "Invalid ghost array!");
  709. }
  710. //-----------------------------------------------------------------------------
  711. void NetConnection::handleConnectionMessage(U32 message, U32 sequence, U32 ghostCount)
  712. {
  713. if(( message == SendNextDownloadRequest
  714. || message == FileDownloadSizeMessage
  715. || message == GhostAlwaysStarting
  716. || message == GhostAlwaysDone
  717. || message == EndGhosting) && !isGhostingTo())
  718. {
  719. setLastError("Invalid packet. (not ghosting)");
  720. return;
  721. }
  722. S32 i;
  723. GhostSave sv;
  724. switch(message)
  725. {
  726. case GhostAlwaysDone:
  727. mGhostingSequence = sequence;
  728. NetConnection::smGhostAlwaysDone.trigger();
  729. // ok, all the ghost always objects are now on the client... but!
  730. // it's possible that there were some file load errors...
  731. // if so, we need to indicate to the server to restart ghosting, after
  732. // we download all the files...
  733. sv.ghost = NULL;
  734. sv.index = -1;
  735. mGhostAlwaysSaveList.push_back(sv);
  736. if(mGhostAlwaysSaveList.size() == 1)
  737. loadNextGhostAlwaysObject(true);
  738. break;
  739. case ReadyForNormalGhosts:
  740. if(sequence != mGhostingSequence)
  741. return;
  742. Con::executef(this, "onGhostAlwaysObjectsReceived");
  743. Con::printf("Ghost Always objects received.");
  744. mGhosting = true;
  745. for(i = 0; i < mGhostFreeIndex; i++)
  746. {
  747. if(mGhostArray[i]->flags & GhostInfo::ScopedEvent)
  748. mGhostArray[i]->flags &= ~(GhostInfo::Ghosting | GhostInfo::ScopedEvent);
  749. }
  750. break;
  751. case EndGhosting:
  752. onEndGhosting();
  753. // just delete all the local ghosts,
  754. // and delete all the ghosts in the current save list
  755. for(i = 0; i < MaxGhostCount; i++)
  756. {
  757. if(mLocalGhosts[i])
  758. {
  759. mLocalGhosts[i]->deleteObject();
  760. mLocalGhosts[i] = NULL;
  761. }
  762. }
  763. while(mGhostAlwaysSaveList.size())
  764. {
  765. delete mGhostAlwaysSaveList[0].ghost;
  766. mGhostAlwaysSaveList.pop_front();
  767. }
  768. break;
  769. case GhostAlwaysStarting:
  770. Con::executef("onGhostAlwaysStarted", Con::getIntArg(ghostCount));
  771. break;
  772. case SendNextDownloadRequest:
  773. sendNextFileDownloadRequest();
  774. break;
  775. case FileDownloadSizeMessage:
  776. mCurrentFileBufferSize = sequence;
  777. mCurrentFileBuffer = dRealloc(mCurrentFileBuffer, mCurrentFileBufferSize);
  778. mCurrentFileBufferOffset = 0;
  779. break;
  780. }
  781. }
  782. void NetConnection::activateGhosting()
  783. {
  784. if(!isGhostingFrom())
  785. return;
  786. mGhostingSequence++;
  787. // iterate through the ghost always objects and InScope them...
  788. // also post em all to the other side.
  789. SimSet* ghostAlwaysSet = Sim::getGhostAlwaysSet();
  790. SimSet::iterator i;
  791. AssertFatal((mGhostFreeIndex == 0) && (mGhostZeroUpdateIndex == 0), "Error: ghosts in the ghost list before activate.");
  792. U32 sz = ghostAlwaysSet->size();
  793. S32 j;
  794. for(j = 0; j < sz; j++)
  795. {
  796. U32 idx = MaxGhostCount - sz + j;
  797. mGhostArray[j] = mGhostRefs + idx;
  798. mGhostArray[j]->arrayIndex = j;
  799. }
  800. for(j = sz; j < MaxGhostCount; j++)
  801. {
  802. U32 idx = j - sz;
  803. mGhostArray[j] = mGhostRefs + idx;
  804. mGhostArray[j]->arrayIndex = j;
  805. }
  806. mScoping = true; // so that objectInScope will work
  807. for(i = ghostAlwaysSet->begin(); i != ghostAlwaysSet->end(); i++)
  808. {
  809. AssertFatal(dynamic_cast<NetObject *>(*i) != NULL, avar("Non NetObject in GhostAlwaysSet: %s", (*i)->getClassName()));
  810. NetObject *obj = (NetObject *)(*i);
  811. if(obj->mNetFlags.test(NetObject::Ghostable))
  812. objectInScope(obj);
  813. }
  814. // Send the initial ghosting connection message.
  815. sendConnectionMessage(GhostAlwaysStarting, mGhostingSequence, ghostAlwaysSet->size());
  816. // If this is the connection to the local client...
  817. if (getLocalClientConnection() == this)
  818. {
  819. // Get a pointer to the local client.
  820. NetConnection* pClient = NetConnection::getConnectionToServer();
  821. Con::executef("onGhostAlwaysStarted", Con::getIntArg(mGhostZeroUpdateIndex));
  822. // Set up a buffer for the object send.
  823. U8 iBuffer[4096];
  824. BitStream mStream(iBuffer, 4096);
  825. // Iterate through the scope always objects...
  826. for (j = mGhostZeroUpdateIndex - 1; j >= 0; j--)
  827. {
  828. AssertFatal((mGhostArray[j]->flags & GhostInfo::ScopeAlways) != 0, "NetConnection::activateGhosting: Non-scope always in the scope always list.");
  829. // Clear the ghost update mask and flags appropriately.
  830. mGhostArray[j]->updateMask = 0;
  831. ghostPushToZero(mGhostArray[j]);
  832. mGhostArray[j]->flags &= ~GhostInfo::NotYetGhosted;
  833. mGhostArray[j]->flags |= GhostInfo::ScopedEvent;
  834. // Set up a pointer to the new object.
  835. NetObject* pObject = 0;
  836. // If there's a valid ghost object...
  837. if (mGhostArray[j]->obj)
  838. {
  839. // Pack the server object's update.
  840. mStream.setPosition(0);
  841. mStream.clearCompressionPoint();
  842. U32 retMask = mGhostArray[j]->obj->packUpdate(this, 0xFFFFFFFF, &mStream);
  843. if ( retMask != 0 )
  844. mGhostArray[j]->obj->setMaskBits( retMask );
  845. // Create a new object instance for the client.
  846. pObject = (NetObject*)ConsoleObject::create(pClient->getNetClassGroup(), NetClassTypeObject, mGhostArray[j]->obj->getClassId(getNetClassGroup()));
  847. // Set the client object networking flags.
  848. pObject->mNetFlags = NetObject::IsGhost;
  849. pObject->mNetIndex = mGhostArray[j]->index;
  850. // Unpack the client object's update.
  851. mStream.setPosition(0);
  852. mStream.clearCompressionPoint();
  853. pObject->unpackUpdate(pClient, &mStream);
  854. }
  855. else
  856. {
  857. // Otherwise, create a new dummy netobject.
  858. pObject = new NetObject;
  859. }
  860. // Execute the appropriate console callback.
  861. Con::executef("onGhostAlwaysObjectReceived");
  862. // Set the ghost always object for the client.
  863. pClient->setGhostAlwaysObject(pObject, mGhostArray[j]->index);
  864. }
  865. }
  866. else
  867. {
  868. // Iterate through the scope always objects...
  869. for (j = mGhostZeroUpdateIndex - 1; j >= 0; j--)
  870. {
  871. AssertFatal((mGhostArray[j]->flags & GhostInfo::ScopeAlways) != 0, "NetConnection::activateGhosting: Non-scope always in the scope always list.");
  872. // Clear the ghost update mask and flags appropriately.
  873. mGhostArray[j]->updateMask = 0;
  874. ghostPushToZero(mGhostArray[j]);
  875. mGhostArray[j]->flags &= ~GhostInfo::NotYetGhosted;
  876. mGhostArray[j]->flags |= GhostInfo::ScopedEvent;
  877. // Post a network event to ghost the scope always object.
  878. postNetEvent(new GhostAlwaysObjectEvent(mGhostArray[j]->obj, mGhostArray[j]->index));
  879. }
  880. }
  881. // Send the ghosting always done message.
  882. sendConnectionMessage(GhostAlwaysDone, mGhostingSequence); //AssertFatal(validateGhostArray(), "Invalid ghost array!");
  883. }
  884. void NetConnection::clearGhostInfo()
  885. {
  886. // gotta clear out the ghosts...
  887. for(PacketNotify *walk = mNotifyQueueHead; walk; walk = walk->nextPacket)
  888. {
  889. ghostPacketReceived(walk);
  890. walk->ghostList = NULL;
  891. }
  892. for(S32 i = 0; i < MaxGhostCount; i++)
  893. {
  894. if(mGhostRefs[i].arrayIndex < mGhostFreeIndex)
  895. {
  896. detachObject(&mGhostRefs[i]);
  897. freeGhostInfo(&mGhostRefs[i]);
  898. }
  899. }
  900. AssertFatal((mGhostFreeIndex == 0) && (mGhostZeroUpdateIndex == 0), "Invalid indices.");
  901. }
  902. void NetConnection::resetGhosting()
  903. {
  904. if(!isGhostingFrom())
  905. return;
  906. // stop all ghosting activity
  907. // send a message to the other side notifying of this
  908. mGhosting = false;
  909. mScoping = false;
  910. sendConnectionMessage(EndGhosting, mGhostingSequence);
  911. mGhostingSequence++;
  912. clearGhostInfo();
  913. //AssertFatal(validateGhostArray(), "Invalid ghost array!");
  914. }
  915. void NetConnection::setGhostAlwaysObject(NetObject *object, U32 index)
  916. {
  917. if(!isGhostingTo())
  918. {
  919. object->deleteObject();
  920. setLastError("Invalid packet. (unexpected ghostalways)");
  921. return;
  922. }
  923. object->mNetFlags = NetObject::IsGhost;
  924. object->mNetIndex = index;
  925. // while there's an object waiting...
  926. if ( isLocalConnection() )
  927. {
  928. object->mServerObject = mRemoteConnection->resolveObjectFromGhostIndex(index);
  929. if ( object->mServerObject )
  930. object->mServerObject->mClientObject = object;
  931. }
  932. GhostSave sv;
  933. sv.ghost = object;
  934. sv.index = index;
  935. mGhostAlwaysSaveList.push_back(sv);
  936. // check if we are already downloading files for a previous object:
  937. if(mGhostAlwaysSaveList.size() == 1)
  938. loadNextGhostAlwaysObject(true); // the initial call always has "new" files
  939. }
  940. void NetConnection::fileDownloadSegmentComplete()
  941. {
  942. // this is called when a the file list has finished processing...
  943. // at this point we can try again to add the object
  944. // subclasses can override this to do, for example, datablock redos.
  945. if(mGhostAlwaysSaveList.size())
  946. loadNextGhostAlwaysObject(mNumDownloadedFiles != 0);
  947. }
  948. void NetConnection::loadNextGhostAlwaysObject(bool hadNewFiles)
  949. {
  950. if(!mGhostAlwaysSaveList.size())
  951. return;
  952. while(mGhostAlwaysSaveList.size())
  953. {
  954. if (isLocalConnection()) hadNewFiles = false;
  955. // only check for new files if this is the first load, or if new
  956. // files were downloaded from the server.
  957. // if(hadNewFiles)
  958. // gResourceManager->setMissingFileLogging(true);
  959. //
  960. // gResourceManager->clearMissingFileList();
  961. NetObject *object = mGhostAlwaysSaveList[0].ghost;
  962. U32 index = mGhostAlwaysSaveList[0].index;
  963. if(!object)
  964. {
  965. // a null object is used to signify that the last ghost in the list is down
  966. mGhostAlwaysSaveList.pop_front();
  967. AssertFatal(mGhostAlwaysSaveList.size() == 0, "Error! Ghost save list should be empty!");
  968. sendConnectionMessage(ReadyForNormalGhosts, mGhostingSequence);
  969. // gResourceManager->setMissingFileLogging(false);
  970. return;
  971. }
  972. mFilesWereDownloaded = hadNewFiles;
  973. if(!object->registerObject())
  974. {
  975. mFilesWereDownloaded = false;
  976. // make sure there's an error message if necessary
  977. if(mErrorBuffer.isEmpty())
  978. setLastError("Invalid packet. (failed to register ghost always)");
  979. // if there were no new files, make sure the error message
  980. // is the one from the last time we tried to add this object
  981. if(!hadNewFiles)
  982. {
  983. mErrorBuffer = mLastFileErrorBuffer;
  984. // gResourceManager->setMissingFileLogging(false);
  985. return;
  986. }
  987. // object failed to load, let's see if it had any missing files
  988. // if(!gResourceManager->getMissingFileList(mMissingFileList))
  989. // {
  990. // // no missing files, must be an error
  991. // // connection will automagically delete the ghost always list
  992. // // when this error is reported.
  993. // gResourceManager->setMissingFileLogging(false);
  994. // return;
  995. // }
  996. // ok, copy the error buffer out to a scratch pad for now
  997. mLastFileErrorBuffer = mErrorBuffer;
  998. mErrorBuffer = String();
  999. // request the missing files...
  1000. mNumDownloadedFiles = 0;
  1001. sendNextFileDownloadRequest();
  1002. break;
  1003. }
  1004. mFilesWereDownloaded = false;
  1005. // gResourceManager->setMissingFileLogging(false);
  1006. addObject(object);
  1007. mGhostAlwaysSaveList.pop_front();
  1008. AssertFatal(mLocalGhosts[index] == NULL, "Ghost already in table!");
  1009. mLocalGhosts[index] = object;
  1010. hadNewFiles = true;
  1011. }
  1012. }
  1013. //-----------------------------------------------------------------------------
  1014. NetObject *NetConnection::resolveGhost(S32 id)
  1015. {
  1016. return mLocalGhosts[id];
  1017. }
  1018. NetObject *NetConnection::resolveObjectFromGhostIndex(S32 id)
  1019. {
  1020. return mGhostRefs[id].obj;
  1021. }
  1022. S32 NetConnection::getGhostIndex(NetObject *obj)
  1023. {
  1024. if(!isGhostingFrom())
  1025. return obj->mNetIndex;
  1026. S32 index = obj->getId() & (GhostLookupTableSize - 1);
  1027. for(GhostInfo *gptr = mGhostLookupTable[index]; gptr; gptr = gptr->nextLookupInfo)
  1028. {
  1029. if(gptr->obj == obj && (gptr->flags & (GhostInfo::KillingGhost | GhostInfo::Ghosting | GhostInfo::NotYetGhosted | GhostInfo::KillGhost)) == 0)
  1030. return gptr->index;
  1031. }
  1032. return -1;
  1033. }
  1034. //-----------------------------------------------------------------------------
  1035. //-----------------------------------------------------------------------------
  1036. void NetConnection::ghostWriteStartBlock(ResizeBitStream *stream)
  1037. {
  1038. // Ok, writing the start block for the ghosts:
  1039. // here's how it goes.
  1040. //
  1041. // First we record out all the indices and class ids for all the objects
  1042. // This is so when the objects are read in, all the objects are instantiated
  1043. // before they are unpacked. The unpack code may reference other
  1044. // existing ghosts, so we want to make sure that all the ghosts are in the
  1045. // table with the correct pointers before any of the unpacks are called.
  1046. stream->write(mGhostingSequence);
  1047. // first write out the indices and ids:
  1048. for(U32 i = 0; i < MaxGhostCount; i++)
  1049. {
  1050. if(mLocalGhosts[i])
  1051. {
  1052. stream->writeFlag(true);
  1053. stream->writeInt(i, GhostIdBitSize);
  1054. stream->writeClassId(mLocalGhosts[i]->getClassId(getNetClassGroup()), NetClassTypeObject, getNetClassGroup());
  1055. stream->validate();
  1056. }
  1057. }
  1058. // mark off the end of the ghost list:
  1059. // it would be more space efficient to write out a count of active ghosts followed
  1060. // by index run lengths, but hey, what's a few bits here and there?
  1061. stream->writeFlag(false);
  1062. // then, for each ghost written into the start block, write the full pack update
  1063. // into the start block. For demos to work properly, packUpdate must
  1064. // be callable from client objects.
  1065. for(U32 i = 0; i < MaxGhostCount; i++)
  1066. {
  1067. if(mLocalGhosts[i])
  1068. {
  1069. U32 retMask = mLocalGhosts[i]->packUpdate(this, 0xFFFFFFFF, stream);
  1070. if ( retMask != 0 ) mLocalGhosts[i]->setMaskBits( retMask );
  1071. stream->validate();
  1072. }
  1073. }
  1074. }
  1075. void NetConnection::ghostReadStartBlock(BitStream *stream)
  1076. {
  1077. stream->read(&mGhostingSequence);
  1078. // read em back in.
  1079. // first, read in the index/class id, construct the object, and place it in mLocalGhosts[i]
  1080. while(stream->readFlag())
  1081. {
  1082. U32 index = stream->readInt(GhostIdBitSize);
  1083. S32 tag = stream->readClassId(NetClassTypeObject, getNetClassGroup());
  1084. NetObject *obj = (NetObject *) ConsoleObject::create(getNetClassGroup(), NetClassTypeObject, tag);
  1085. if(!obj)
  1086. {
  1087. setLastError("Invalid packet. (failed to create ghost from demo block)");
  1088. return;
  1089. }
  1090. obj->mNetFlags = NetObject::IsGhost;
  1091. obj->mNetIndex = index;
  1092. mLocalGhosts[index] = obj;
  1093. }
  1094. // now, all the ghosts are in the mLocalGhosts, so we loop
  1095. // through all non-null mLocalGhosts, unpacking the objects
  1096. // as we go:
  1097. for(U32 i = 0; i < MaxGhostCount; i++)
  1098. {
  1099. if(mLocalGhosts[i])
  1100. {
  1101. mLocalGhosts[i]->unpackUpdate(this, stream);
  1102. if(!mLocalGhosts[i]->registerObject())
  1103. {
  1104. if(mErrorBuffer.isEmpty())
  1105. setLastError("Invalid packet. (failed to register ghost from demo block)");
  1106. return;
  1107. }
  1108. addObject(mLocalGhosts[i]);
  1109. }
  1110. }
  1111. // MARKF - TODO - looks like we could have memory leaks here
  1112. // if there are errors.
  1113. }