netGhost.cc 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 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 "network/connectionProtocol.h"
  24. #include "sim/simBase.h"
  25. #include "network/netConnection.h"
  26. #include "io/bitStream.h"
  27. #include "network/netObject.h"
  28. #include "io/resource/resourceManager.h"
  29. #include "console/console.h"
  30. #include "console/consoleTypes.h"
  31. #define DebugChecksum 0xF00DBAAD
  32. extern U32 gGhostUpdates;
  33. class GhostAlwaysObjectEvent : public NetEvent
  34. {
  35. SimObjectId objectId;
  36. U32 ghostIndex;
  37. NetObject *object;
  38. bool validObject;
  39. public:
  40. GhostAlwaysObjectEvent(NetObject *obj = NULL, U32 index = 0)
  41. {
  42. if(obj)
  43. {
  44. objectId = obj->getId();
  45. ghostIndex = index;
  46. }
  47. object = NULL;
  48. }
  49. ~GhostAlwaysObjectEvent()
  50. { delete object; }
  51. void pack(NetConnection *ps, BitStream *bstream)
  52. {
  53. bstream->writeInt(ghostIndex, NetConnection::GhostIdBitSize);
  54. NetObject *obj = (NetObject *) Sim::findObject(objectId);
  55. if(bstream->writeFlag(obj != NULL))
  56. {
  57. S32 classId = obj->getClassId(ps->getNetClassGroup());
  58. bstream->writeClassId(classId, NetClassTypeObject, ps->getNetClassGroup());
  59. obj->packUpdate(ps, 0xFFFFFFFF, bstream);
  60. }
  61. }
  62. void write(NetConnection *ps, BitStream *bstream)
  63. {
  64. bstream->writeInt(ghostIndex, NetConnection::GhostIdBitSize);
  65. if(bstream->writeFlag(validObject))
  66. {
  67. S32 classId = object->getClassId(ps->getNetClassGroup());
  68. bstream->writeClassId(classId, NetClassTypeObject, ps->getNetClassGroup());
  69. object->packUpdate(ps, 0xFFFFFFFF, bstream);
  70. }
  71. }
  72. void unpack(NetConnection *ps, BitStream *bstream)
  73. {
  74. ghostIndex = bstream->readInt(NetConnection::GhostIdBitSize);
  75. if(bstream->readFlag())
  76. {
  77. S32 classId = bstream->readClassId(NetClassTypeObject, ps->getNetClassGroup());
  78. if(classId == -1)
  79. {
  80. ps->setLastError("Invalid packet.");
  81. return;
  82. }
  83. object = (NetObject *) ConsoleObject::create(ps->getNetClassGroup(), NetClassTypeObject, classId);
  84. if(!object)
  85. {
  86. ps->setLastError("Invalid packet.");
  87. return;
  88. }
  89. object->mNetFlags = NetObject::IsGhost;
  90. object->mNetIndex = ghostIndex;
  91. object->unpackUpdate(ps, bstream);
  92. validObject = true;
  93. }
  94. else
  95. {
  96. object = new NetObject;
  97. validObject = false;
  98. }
  99. }
  100. void process(NetConnection *ps)
  101. {
  102. Con::executef(1, "onGhostAlwaysObjectReceived");
  103. ps->setGhostAlwaysObject(object, ghostIndex);
  104. object = NULL;
  105. }
  106. DECLARE_CONOBJECT(GhostAlwaysObjectEvent);
  107. };
  108. IMPLEMENT_CO_NETEVENT_V1(GhostAlwaysObjectEvent);
  109. void NetConnection::setGhostTo(bool ghostTo)
  110. {
  111. if(mLocalGhosts) // if ghosting to this is already enabled, silently return
  112. return;
  113. if(ghostTo)
  114. {
  115. mLocalGhosts = new NetObject *[MaxGhostCount];
  116. for(S32 i = 0; i < MaxGhostCount; i++)
  117. mLocalGhosts[i] = NULL;
  118. }
  119. }
  120. void NetConnection::setGhostFrom(bool ghostFrom)
  121. {
  122. if(mGhostArray)
  123. return;
  124. if(ghostFrom)
  125. {
  126. mGhostFreeIndex = mGhostZeroUpdateIndex = 0;
  127. mGhostArray = new GhostInfo *[MaxGhostCount];
  128. mGhostRefs = new GhostInfo[MaxGhostCount];
  129. S32 i;
  130. for(i = 0; i < MaxGhostCount; i++)
  131. {
  132. mGhostRefs[i].obj = NULL;
  133. mGhostRefs[i].index = i;
  134. mGhostRefs[i].updateMask = 0;
  135. }
  136. mGhostLookupTable = new GhostInfo *[GhostLookupTableSize];
  137. for(i = 0; i < GhostLookupTableSize; i++)
  138. mGhostLookupTable[i] = 0;
  139. }
  140. }
  141. void NetConnection::ghostOnRemove()
  142. {
  143. if(mGhostArray)
  144. clearGhostInfo();
  145. }
  146. void NetConnection::ghostPacketDropped(PacketNotify *notify)
  147. {
  148. GhostRef *packRef = notify->ghostList;
  149. // loop through all the packRefs in the packet
  150. while(packRef)
  151. {
  152. GhostRef *temp = packRef->nextRef;
  153. U32 orFlags = 0;
  154. AssertFatal(packRef->nextUpdateChain == NULL, "Out of order notify!!");
  155. // clear out the ref for this object, plus or together all
  156. // flags from updates after this
  157. GhostRef **walk = &(packRef->ghost->updateChain);
  158. while(*walk != packRef)
  159. {
  160. orFlags |= (*walk)->mask;
  161. walk = &((*walk)->nextUpdateChain);
  162. }
  163. *walk = 0;
  164. // for any flags we haven't updated since this (dropped) packet
  165. // or them into the mask so they'll get updated soon
  166. orFlags = packRef->mask & ~orFlags;
  167. if(orFlags)
  168. {
  169. if(!packRef->ghost->updateMask)
  170. {
  171. packRef->ghost->updateMask = orFlags;
  172. ghostPushNonZero(packRef->ghost);
  173. }
  174. else
  175. packRef->ghost->updateMask |= orFlags;
  176. }
  177. // if this packet was ghosting an object, set it
  178. // to re ghost at it's earliest convenience
  179. if(packRef->ghostInfoFlags & GhostInfo::Ghosting)
  180. {
  181. packRef->ghost->flags |= GhostInfo::NotYetGhosted;
  182. packRef->ghost->flags &= ~GhostInfo::Ghosting;
  183. }
  184. // otherwise, if it was being deleted,
  185. // set it to re-delete
  186. else if(packRef->ghostInfoFlags & GhostInfo::KillingGhost)
  187. {
  188. packRef->ghost->flags |= GhostInfo::KillGhost;
  189. packRef->ghost->flags &= ~GhostInfo::KillingGhost;
  190. }
  191. delete packRef;
  192. packRef = temp;
  193. }
  194. }
  195. void NetConnection::ghostPacketReceived(PacketNotify *notify)
  196. {
  197. GhostRef *packRef = notify->ghostList;
  198. // loop through all the notifies in this packet
  199. while(packRef)
  200. {
  201. GhostRef *temp = packRef->nextRef;
  202. AssertFatal(packRef->nextUpdateChain == NULL, "Out of order notify!!");
  203. // clear this notify from the end of the object's notify
  204. // chain
  205. GhostRef **walk = &(packRef->ghost->updateChain);
  206. while(*walk != packRef)
  207. walk = &((*walk)->nextUpdateChain);
  208. *walk = 0;
  209. // if this object was ghosting , it is now ghosted
  210. if(packRef->ghostInfoFlags & GhostInfo::Ghosting)
  211. packRef->ghost->flags &= ~GhostInfo::Ghosting;
  212. // otherwise, if it was dieing, free the ghost
  213. else if(packRef->ghostInfoFlags & GhostInfo::KillingGhost)
  214. freeGhostInfo(packRef->ghost);
  215. delete packRef;
  216. packRef = temp;
  217. }
  218. }
  219. struct UpdateQueueEntry
  220. {
  221. F32 priority;
  222. GhostInfo *obj;
  223. UpdateQueueEntry(F32 in_priority, GhostInfo *in_obj)
  224. { priority = in_priority; obj = in_obj; }
  225. };
  226. static S32 QSORT_CALLBACK UQECompare(const void *a,const void *b)
  227. {
  228. GhostInfo *ga = *((GhostInfo **) a);
  229. GhostInfo *gb = *((GhostInfo **) b);
  230. F32 ret = ga->priority - gb->priority;
  231. return (ret < 0) ? -1 : ((ret > 0) ? 1 : 0);
  232. }
  233. void NetConnection::ghostWritePacket(BitStream *bstream, PacketNotify *notify)
  234. {
  235. #ifdef TORQUE_DEBUG_NET
  236. bstream->writeInt(DebugChecksum, 32);
  237. #endif
  238. notify->ghostList = NULL;
  239. if(!isGhostingFrom())
  240. return;
  241. if(!bstream->writeFlag(mGhosting))
  242. return;
  243. // fill a packet (or two) with ghosting data
  244. // first step is to check all our polled ghosts:
  245. // 1. Scope query - find if any new objects have come into
  246. // scope and if any have gone out.
  247. // 2. call scoped objects' priority functions if the flag set is nonzero
  248. // A removed ghost is assumed to have a high priority
  249. // 3. call updates based on sorted priority until the packet is
  250. // full. set flags to zero for all updated objects
  251. CameraScopeQuery camInfo;
  252. camInfo.camera = NULL;
  253. camInfo.pos.set(0,0,0);
  254. camInfo.orientation.set(0,1,0);
  255. camInfo.visibleDistance = 1;
  256. camInfo.fov = (F32)(3.1415f / 4.0f);
  257. camInfo.sinFov = 0.7071f;
  258. camInfo.cosFov = 0.7071f;
  259. GhostInfo *walk;
  260. // only need to worry about the ghosts that have update masks set...
  261. S32 maxIndex = 0;
  262. S32 i;
  263. for(i = 0; i < (S32)mGhostZeroUpdateIndex; i++)
  264. {
  265. // increment the updateSkip for everyone... it's all good
  266. walk = mGhostArray[i];
  267. walk->updateSkipCount++;
  268. if(!(walk->flags & (GhostInfo::ScopeAlways | GhostInfo::ScopeLocalAlways)))
  269. walk->flags &= ~GhostInfo::InScope;
  270. }
  271. if(mScopeObject)
  272. mScopeObject->onCameraScopeQuery(this, &camInfo);
  273. for(i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
  274. {
  275. if(!(mGhostArray[i]->flags & GhostInfo::InScope))
  276. detachObject(mGhostArray[i]);
  277. }
  278. for(i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
  279. {
  280. walk = mGhostArray[i];
  281. if(walk->index > (U32)maxIndex)
  282. maxIndex = walk->index;
  283. // clear out any kill objects that haven't been ghosted yet
  284. if((walk->flags & GhostInfo::KillGhost) && (walk->flags & GhostInfo::NotYetGhosted))
  285. {
  286. freeGhostInfo(walk);
  287. continue;
  288. }
  289. // don't do any ghost processing on objects that are being killed
  290. // or in the process of ghosting
  291. else if(!(walk->flags & (GhostInfo::KillingGhost | GhostInfo::Ghosting)))
  292. {
  293. if(walk->flags & GhostInfo::KillGhost)
  294. walk->priority = 10000;
  295. else
  296. walk->priority = walk->obj->getUpdatePriority(&camInfo, walk->updateMask, walk->updateSkipCount);
  297. }
  298. else
  299. walk->priority = 0;
  300. }
  301. GhostRef *updateList = NULL;
  302. dQsort(mGhostArray, mGhostZeroUpdateIndex, sizeof(GhostInfo *), UQECompare);
  303. // reset the array indices...
  304. for(i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
  305. mGhostArray[i]->arrayIndex = i;
  306. S32 sendSize = 1;
  307. while(maxIndex >>= 1)
  308. sendSize++;
  309. if(sendSize < 3)
  310. sendSize = 3;
  311. bstream->writeInt(sendSize - 3, GhostIndexBitSize);
  312. U32 count = 0;
  313. //
  314. for(i = mGhostZeroUpdateIndex - 1; i >= 0 && !bstream->isFull(); i--)
  315. {
  316. GhostInfo *walk = mGhostArray[i];
  317. if(walk->flags & (GhostInfo::KillingGhost | GhostInfo::Ghosting))
  318. continue;
  319. bstream->writeFlag(true);
  320. bstream->writeInt(walk->index, sendSize);
  321. U32 updateMask = walk->updateMask;
  322. GhostRef *upd = new GhostRef;
  323. upd->nextRef = updateList;
  324. updateList = upd;
  325. upd->nextUpdateChain = walk->updateChain;
  326. walk->updateChain = upd;
  327. upd->ghost = walk;
  328. upd->ghostInfoFlags = 0;
  329. if(walk->flags & GhostInfo::KillGhost)
  330. {
  331. walk->flags &= ~GhostInfo::KillGhost;
  332. walk->flags |= GhostInfo::KillingGhost;
  333. walk->updateMask = 0;
  334. upd->mask = updateMask;
  335. ghostPushToZero(walk);
  336. upd->ghostInfoFlags = GhostInfo::KillingGhost;
  337. bstream->writeFlag(true); // killing ghost
  338. }
  339. else
  340. {
  341. bstream->writeFlag(false);
  342. if(walk->flags & GhostInfo::NotYetGhosted)
  343. {
  344. S32 classId = walk->obj->getClassId(getNetClassGroup());
  345. bstream->writeClassId(classId, NetClassTypeObject, getNetClassGroup());
  346. #ifdef TORQUE_DEBUG_NET
  347. bstream->writeInt(classId ^ DebugChecksum, 32);
  348. #endif
  349. walk->flags &= ~GhostInfo::NotYetGhosted;
  350. walk->flags |= GhostInfo::Ghosting;
  351. upd->ghostInfoFlags = GhostInfo::Ghosting;
  352. }
  353. #ifdef TORQUE_DEBUG_NET
  354. else {
  355. S32 classId = walk->obj->getClassId(getNetClassGroup());
  356. bstream->writeClassId(classId, NetClassTypeObject, getNetClassGroup());
  357. bstream->writeInt(classId ^ DebugChecksum, 32);
  358. }
  359. #endif
  360. // update the object
  361. U32 retMask = walk->obj->packUpdate(this, updateMask, bstream);
  362. DEBUG_LOG(("PKLOG %d GHOST %d: %s", getId(), bstream->getCurPos() - 16 - startPos, walk->obj->getClassName()));
  363. AssertFatal((retMask & (~updateMask)) == 0, "Cannot set new bits in packUpdate return");
  364. walk->updateMask = retMask;
  365. if(!retMask)
  366. ghostPushToZero(walk);
  367. upd->mask = updateMask & ~retMask;
  368. //PacketStream::getStats()->addBits(PacketStats::Send, bstream->getCurPos() - startPos, walk->obj->getPersistTag());
  369. #ifdef TORQUE_DEBUG_NET
  370. bstream->writeInt(walk->index ^ DebugChecksum, 32);
  371. #endif
  372. }
  373. walk->updateSkipCount = 0;
  374. count++;
  375. }
  376. //Con::printf("Ghosts updated: %d (%d remain)", count, mGhostZeroUpdateIndex);
  377. // no more objects...
  378. bstream->writeFlag(false);
  379. notify->ghostList = updateList;
  380. }
  381. void NetConnection::ghostReadPacket(BitStream *bstream)
  382. {
  383. #ifdef TORQUE_DEBUG_NET
  384. U32 sum = bstream->readInt(32);
  385. AssertISV(sum == DebugChecksum, "Invalid checksum.");
  386. #endif
  387. if(!isGhostingTo())
  388. return;
  389. if(!bstream->readFlag())
  390. return;
  391. S32 idSize;
  392. idSize = bstream->readInt( GhostIndexBitSize);
  393. idSize += 3;
  394. // while there's an object waiting...
  395. while(bstream->readFlag())
  396. {
  397. gGhostUpdates++;
  398. U32 index;
  399. //S32 startPos = bstream->getCurPos();
  400. index = (U32) bstream->readInt(idSize);
  401. if(bstream->readFlag()) // is this ghost being deleted?
  402. {
  403. mGhostsActive--;
  404. AssertFatal(mLocalGhosts[index] != NULL, "Error, NULL ghost encountered.");
  405. mLocalGhosts[index]->deleteObject();
  406. mLocalGhosts[index] = NULL;
  407. }
  408. else
  409. {
  410. if(!mLocalGhosts[index]) // it's a new ghost... cool
  411. {
  412. mGhostsActive++;
  413. S32 classId = bstream->readClassId(NetClassTypeObject, getNetClassGroup());
  414. if(classId == -1)
  415. {
  416. setLastError("Invalid packet.");
  417. return;
  418. }
  419. NetObject *obj = (NetObject *) ConsoleObject::create(getNetClassGroup(), NetClassTypeObject, classId);
  420. if(!obj)
  421. {
  422. setLastError("Invalid packet.");
  423. return;
  424. }
  425. obj->mNetFlags = NetObject::IsGhost;
  426. // object gets initial update before adding to the manager
  427. obj->mNetIndex = index;
  428. mLocalGhosts[index] = obj;
  429. #ifdef TORQUE_DEBUG_NET
  430. U32 checksum = bstream->readInt(32);
  431. S32 origId = checksum ^ DebugChecksum;
  432. AssertISV(mLocalGhosts[index] != NULL, "Invalid dest ghost.");
  433. AssertISV(origId == mLocalGhosts[index]->getClassId(getNetClassGroup()),
  434. avar("class id mismatch for dest class %s.",
  435. mLocalGhosts[index]->getClassName()) );
  436. #endif
  437. mLocalGhosts[index]->unpackUpdate(this, bstream);
  438. if(!obj->registerObject())
  439. {
  440. if(!mErrorBuffer[0])
  441. setLastError("Invalid packet.");
  442. return;
  443. }
  444. if(mRemoteConnection)
  445. obj->mServerObject = mRemoteConnection->resolveObjectFromGhostIndex(index);
  446. addObject(obj);
  447. }
  448. else
  449. {
  450. #ifdef TORQUE_DEBUG_NET
  451. S32 classId = bstream->readClassId(NetClassTypeObject, getNetClassGroup());
  452. U32 checksum = bstream->readInt(32);
  453. S32 origId = checksum ^ DebugChecksum;
  454. AssertISV(mLocalGhosts[index] != NULL, "Invalid dest ghost.");
  455. AssertISV(origId == mLocalGhosts[index]->getClassId(getNetClassGroup()),
  456. avar("class id mismatch for dest class %s.",
  457. mLocalGhosts[index]->getClassName()) );
  458. #endif
  459. mLocalGhosts[index]->unpackUpdate(this, bstream);
  460. }
  461. //PacketStream::getStats()->addBits(PacketStats::Receive, bstream->getCurPos() - startPos, ghostRefs[index].localGhost->getPersistTag());
  462. #ifdef TORQUE_DEBUG_NET
  463. U32 checksum = bstream->readInt(32);
  464. S32 origIndex = checksum ^ DebugChecksum;
  465. AssertISV(origIndex == index,
  466. avar("unpackUpdate did not match packUpdate for object of class %s.",
  467. mLocalGhosts[index]->getClassName()) );
  468. #endif
  469. if(mErrorBuffer[0])
  470. return;
  471. }
  472. }
  473. }
  474. //-----------------------------------------------------------------------------
  475. //-----------------------------------------------------------------------------
  476. void NetConnection::setScopeObject(NetObject *obj)
  477. {
  478. if(((NetObject *) mScopeObject) == obj)
  479. return;
  480. mScopeObject = obj;
  481. }
  482. void NetConnection::detachObject(GhostInfo *info)
  483. {
  484. // mark it for ghost killin'
  485. info->flags |= GhostInfo::KillGhost;
  486. // if the mask is in the zero range, we've got to move it up...
  487. if(!info->updateMask)
  488. {
  489. info->updateMask = 0xFFFFFFFF;
  490. ghostPushNonZero(info);
  491. }
  492. if(info->obj)
  493. {
  494. if(info->prevObjectRef)
  495. info->prevObjectRef->nextObjectRef = info->nextObjectRef;
  496. else
  497. info->obj->mFirstObjectRef = info->nextObjectRef;
  498. if(info->nextObjectRef)
  499. info->nextObjectRef->prevObjectRef = info->prevObjectRef;
  500. // remove it from the lookup table
  501. U32 id = info->obj->getId();
  502. for(GhostInfo **walk = &mGhostLookupTable[id & (GhostLookupTableSize - 1)]; *walk; walk = &((*walk)->nextLookupInfo))
  503. {
  504. GhostInfo *temp = *walk;
  505. if(temp == info)
  506. {
  507. *walk = temp->nextLookupInfo;
  508. break;
  509. }
  510. }
  511. info->prevObjectRef = info->nextObjectRef = NULL;
  512. info->obj = NULL;
  513. }
  514. }
  515. void NetConnection::freeGhostInfo(GhostInfo *ghost)
  516. {
  517. AssertFatal(ghost->arrayIndex < mGhostFreeIndex, "Ghost already freed.");
  518. if(ghost->arrayIndex < mGhostZeroUpdateIndex)
  519. {
  520. AssertFatal(ghost->updateMask != 0, "Invalid ghost mask.");
  521. ghost->updateMask = 0;
  522. ghostPushToZero(ghost);
  523. }
  524. ghostPushZeroToFree(ghost);
  525. AssertFatal(ghost->updateChain == NULL, "Ack!");
  526. }
  527. //-----------------------------------------------------------------------------
  528. void NetConnection::objectLocalScopeAlways(NetObject *obj)
  529. {
  530. if(!isGhostingFrom())
  531. return;
  532. objectInScope(obj);
  533. for(GhostInfo *walk = mGhostLookupTable[obj->getId() & (GhostLookupTableSize - 1)]; walk; walk = walk->nextLookupInfo)
  534. {
  535. if(walk->obj != obj)
  536. continue;
  537. walk->flags |= GhostInfo::ScopeLocalAlways;
  538. return;
  539. }
  540. }
  541. void NetConnection::objectLocalClearAlways(NetObject *obj)
  542. {
  543. if(!isGhostingFrom())
  544. return;
  545. for(GhostInfo *walk = mGhostLookupTable[obj->getId() & (GhostLookupTableSize - 1)]; walk; walk = walk->nextLookupInfo)
  546. {
  547. if(walk->obj != obj)
  548. continue;
  549. walk->flags &= ~GhostInfo::ScopeLocalAlways;
  550. return;
  551. }
  552. }
  553. bool NetConnection::validateGhostArray()
  554. {
  555. AssertFatal(mGhostZeroUpdateIndex >= 0 && mGhostZeroUpdateIndex <= mGhostFreeIndex, "Invalid update index range.");
  556. AssertFatal(mGhostFreeIndex <= MaxGhostCount, "Invalid free index range.");
  557. U32 i;
  558. for(i = 0; i < mGhostZeroUpdateIndex; i ++)
  559. {
  560. AssertFatal(mGhostArray[i]->arrayIndex == i, "Invalid array index.");
  561. AssertFatal(mGhostArray[i]->updateMask != 0, "Invalid ghost mask.");
  562. }
  563. for(; i < mGhostFreeIndex; i ++)
  564. {
  565. AssertFatal(mGhostArray[i]->arrayIndex == i, "Invalid array index.");
  566. AssertFatal(mGhostArray[i]->updateMask == 0, "Invalid ghost mask.");
  567. }
  568. for(; i < MaxGhostCount; i++)
  569. {
  570. AssertFatal(mGhostArray[i]->arrayIndex == i, "Invalid array index.");
  571. }
  572. return true;
  573. }
  574. void NetConnection::objectInScope(NetObject *obj)
  575. {
  576. if (!mScoping || !isGhostingFrom())
  577. return;
  578. if (obj->isScopeLocal() && !isLocalConnection())
  579. return;
  580. S32 index = obj->getId() & (GhostLookupTableSize - 1);
  581. // check if it's already in scope
  582. // the object may have been cleared out without the lookupTable being cleared
  583. // so validate that the object pointers are the same.
  584. for(GhostInfo *walk = mGhostLookupTable[index ]; walk; walk = walk->nextLookupInfo)
  585. {
  586. if(walk->obj != obj)
  587. continue;
  588. walk->flags |= GhostInfo::InScope;
  589. return;
  590. }
  591. if (mGhostFreeIndex == MaxGhostCount)
  592. {
  593. AssertWarn(0,"NetConnection::objectInScope: too many ghosts");
  594. return;
  595. }
  596. GhostInfo *giptr = mGhostArray[mGhostFreeIndex];
  597. ghostPushFreeToZero(giptr);
  598. giptr->updateMask = 0xFFFFFFFF;
  599. ghostPushNonZero(giptr);
  600. giptr->flags = GhostInfo::NotYetGhosted | GhostInfo::InScope;
  601. if(obj->mNetFlags.test(NetObject::ScopeAlways))
  602. giptr->flags |= GhostInfo::ScopeAlways;
  603. giptr->obj = obj;
  604. giptr->updateChain = NULL;
  605. giptr->updateSkipCount = 0;
  606. giptr->connection = this;
  607. giptr->nextObjectRef = obj->mFirstObjectRef;
  608. if(obj->mFirstObjectRef)
  609. obj->mFirstObjectRef->prevObjectRef = giptr;
  610. giptr->prevObjectRef = NULL;
  611. obj->mFirstObjectRef = giptr;
  612. giptr->nextLookupInfo = mGhostLookupTable[index];
  613. mGhostLookupTable[index] = giptr;
  614. //AssertFatal(validateGhostArray(), "Invalid ghost array!");
  615. }
  616. //-----------------------------------------------------------------------------
  617. void NetConnection::handleConnectionMessage(U32 message, U32 sequence, U32 ghostCount)
  618. {
  619. if(( message == SendNextDownloadRequest
  620. || message == FileDownloadSizeMessage
  621. || message == GhostAlwaysStarting
  622. || message == GhostAlwaysDone
  623. || message == EndGhosting) && !isGhostingTo())
  624. {
  625. setLastError("Invalid packet.");
  626. return;
  627. }
  628. S32 i;
  629. GhostSave sv;
  630. switch(message)
  631. {
  632. case GhostAlwaysDone:
  633. mGhostingSequence = sequence;
  634. // ok, all the ghost always objects are now on the client... but!
  635. // it's possible that there were some file load errors...
  636. // if so, we need to indicate to the server to restart ghosting, after
  637. // we download all the files...
  638. sv.ghost = NULL;
  639. mGhostAlwaysSaveList.push_back(sv);
  640. if(mGhostAlwaysSaveList.size() == 1)
  641. loadNextGhostAlwaysObject(true);
  642. break;
  643. case ReadyForNormalGhosts:
  644. if(sequence != mGhostingSequence)
  645. return;
  646. Con::executef(this, 1, "onGhostAlwaysObjectsReceived");
  647. Con::printf("Ghost Always objects received.");
  648. mGhosting = true;
  649. for(i = 0; i < (S32)mGhostFreeIndex; i++)
  650. {
  651. if(mGhostArray[i]->flags & GhostInfo::ScopedEvent)
  652. mGhostArray[i]->flags &= ~(GhostInfo::Ghosting | GhostInfo::ScopedEvent);
  653. }
  654. break;
  655. case EndGhosting:
  656. // just delete all the local ghosts,
  657. // and delete all the ghosts in the current save list
  658. for(i = 0; i < MaxGhostCount; i++)
  659. {
  660. if(mLocalGhosts[i])
  661. {
  662. mLocalGhosts[i]->deleteObject();
  663. mLocalGhosts[i] = NULL;
  664. }
  665. }
  666. while(mGhostAlwaysSaveList.size())
  667. {
  668. delete mGhostAlwaysSaveList[0].ghost;
  669. mGhostAlwaysSaveList.pop_front();
  670. }
  671. break;
  672. case GhostAlwaysStarting:
  673. Con::executef(2, "onGhostAlwaysStarted", Con::getIntArg(ghostCount));
  674. break;
  675. case SendNextDownloadRequest:
  676. sendNextFileDownloadRequest();
  677. break;
  678. case FileDownloadSizeMessage:
  679. mCurrentFileBufferSize = sequence;
  680. mCurrentFileBuffer = dRealloc(mCurrentFileBuffer, mCurrentFileBufferSize);
  681. mCurrentFileBufferOffset = 0;
  682. break;
  683. }
  684. }
  685. void NetConnection::activateGhosting()
  686. {
  687. if(!isGhostingFrom())
  688. return;
  689. mGhostingSequence++;
  690. // iterate through the ghost always objects and InScope them...
  691. // also post em all to the other side.
  692. SimSet* ghostAlwaysSet = Sim::getGhostAlwaysSet();
  693. SimSet::iterator i;
  694. AssertFatal((mGhostFreeIndex == 0) && (mGhostZeroUpdateIndex == 0), "Error: ghosts in the ghost list before activate.");
  695. U32 sz = ghostAlwaysSet->size();
  696. S32 j;
  697. for(j = 0; j < (S32)sz; j++)
  698. {
  699. U32 idx = MaxGhostCount - sz + j;
  700. mGhostArray[j] = mGhostRefs + idx;
  701. mGhostArray[j]->arrayIndex = j;
  702. }
  703. for(j = sz; j < MaxGhostCount; j++)
  704. {
  705. U32 idx = j - sz;
  706. mGhostArray[j] = mGhostRefs + idx;
  707. mGhostArray[j]->arrayIndex = j;
  708. }
  709. mScoping = true; // so that objectInScope will work
  710. for(i = ghostAlwaysSet->begin(); i != ghostAlwaysSet->end(); i++)
  711. {
  712. AssertFatal(dynamic_cast<NetObject *>(*i) != NULL, avar("Non NetObject in GhostAlwaysSet: %s", (*i)->getClassName()));
  713. NetObject *obj = (NetObject *)(*i);
  714. if(obj->mNetFlags.test(NetObject::Ghostable))
  715. objectInScope(obj);
  716. }
  717. sendConnectionMessage(GhostAlwaysStarting, mGhostingSequence, ghostAlwaysSet->size());
  718. for(j = mGhostZeroUpdateIndex - 1; j >= 0; j--)
  719. {
  720. AssertFatal((mGhostArray[j]->flags & GhostInfo::ScopeAlways) != 0, "Non-scope always in the scope always list.")
  721. // we may end up resending state here, but at least initial state
  722. // will not be resent.
  723. mGhostArray[j]->updateMask = 0;
  724. ghostPushToZero(mGhostArray[j]);
  725. mGhostArray[j]->flags &= ~GhostInfo::NotYetGhosted;
  726. mGhostArray[j]->flags |= GhostInfo::ScopedEvent;
  727. postNetEvent(new GhostAlwaysObjectEvent(mGhostArray[j]->obj, mGhostArray[j]->index));
  728. }
  729. sendConnectionMessage(GhostAlwaysDone, mGhostingSequence);
  730. //AssertFatal(validateGhostArray(), "Invalid ghost array!");
  731. }
  732. void NetConnection::clearGhostInfo()
  733. {
  734. // gotta clear out the ghosts...
  735. for(PacketNotify *walk = mNotifyQueueHead; walk; walk = walk->nextPacket)
  736. {
  737. ghostPacketReceived(walk);
  738. walk->ghostList = NULL;
  739. }
  740. for(S32 i = 0; i < MaxGhostCount; i++)
  741. {
  742. if(mGhostRefs[i].arrayIndex < mGhostFreeIndex)
  743. {
  744. detachObject(&mGhostRefs[i]);
  745. freeGhostInfo(&mGhostRefs[i]);
  746. }
  747. }
  748. AssertFatal((mGhostFreeIndex == 0) && (mGhostZeroUpdateIndex == 0), "Invalid indices.");
  749. }
  750. void NetConnection::resetGhosting()
  751. {
  752. if(!isGhostingFrom())
  753. return;
  754. // stop all ghosting activity
  755. // send a message to the other side notifying of this
  756. mGhosting = false;
  757. mScoping = false;
  758. sendConnectionMessage(EndGhosting, mGhostingSequence);
  759. mGhostingSequence++;
  760. clearGhostInfo();
  761. //AssertFatal(validateGhostArray(), "Invalid ghost array!");
  762. }
  763. void NetConnection::setGhostAlwaysObject(NetObject *object, U32 index)
  764. {
  765. if(!isGhostingTo())
  766. {
  767. object->deleteObject();
  768. setLastError("Invalid packet.");
  769. return;
  770. }
  771. object->mNetFlags = NetObject::IsGhost;
  772. object->mNetIndex = index;
  773. // while there's an object waiting...
  774. if (isLocalConnection()) {
  775. object->mServerObject = mRemoteConnection->resolveObjectFromGhostIndex(index);
  776. }
  777. GhostSave sv;
  778. sv.ghost = object;
  779. sv.index = index;
  780. mGhostAlwaysSaveList.push_back(sv);
  781. // check if we are already downloading files for a previous object:
  782. if(mGhostAlwaysSaveList.size() == 1)
  783. loadNextGhostAlwaysObject(true); // the initial call always has "new" files
  784. }
  785. void NetConnection::fileDownloadSegmentComplete()
  786. {
  787. // this is called when a the file list has finished processing...
  788. // at this point we can try again to add the object
  789. // subclasses can override this to do, for example, datablock redos.
  790. if(mGhostAlwaysSaveList.size())
  791. loadNextGhostAlwaysObject(mNumDownloadedFiles != 0);
  792. }
  793. void NetConnection::loadNextGhostAlwaysObject(bool hadNewFiles)
  794. {
  795. if(!mGhostAlwaysSaveList.size())
  796. return;
  797. while(mGhostAlwaysSaveList.size())
  798. {
  799. // only check for new files if this is the first load, or if new
  800. // files were downloaded from the server.
  801. if(hadNewFiles)
  802. ResourceManager->setMissingFileLogging(true);
  803. ResourceManager->clearMissingFileList();
  804. NetObject *object = mGhostAlwaysSaveList[0].ghost;
  805. U32 index = mGhostAlwaysSaveList[0].index;
  806. if(!object)
  807. {
  808. // a null object is used to signify that the last ghost in the list is down
  809. mGhostAlwaysSaveList.pop_front();
  810. AssertFatal(mGhostAlwaysSaveList.size() == 0, "Error! Ghost save list should be empty!");
  811. sendConnectionMessage(ReadyForNormalGhosts, mGhostingSequence);
  812. ResourceManager->setMissingFileLogging(false);
  813. return;
  814. }
  815. mFilesWereDownloaded = hadNewFiles;
  816. if(!object->registerObject())
  817. {
  818. mFilesWereDownloaded = false;
  819. // make sure there's an error message if necessary
  820. if(!mErrorBuffer[0])
  821. setLastError("Invalid packet.");
  822. // if there were no new files, make sure the error message
  823. // is the one from the last time we tried to add this object
  824. if(!hadNewFiles)
  825. {
  826. dStrcpy(mErrorBuffer, mLastFileErrorBuffer);
  827. ResourceManager->setMissingFileLogging(false);
  828. return;
  829. }
  830. // object failed to load, let's see if it had any missing files
  831. if(!ResourceManager->getMissingFileList(mMissingFileList))
  832. {
  833. // no missing files, must be an error
  834. // connection will automagically delete the ghost always list
  835. // when this error is reported.
  836. ResourceManager->setMissingFileLogging(false);
  837. return;
  838. }
  839. // ok, copy the error buffer out to a scratch pad for now
  840. dStrcpy(mLastFileErrorBuffer, mErrorBuffer);
  841. mErrorBuffer[0] = 0;
  842. // request the missing files...
  843. mNumDownloadedFiles = 0;
  844. sendNextFileDownloadRequest();
  845. break;
  846. }
  847. mFilesWereDownloaded = false;
  848. ResourceManager->setMissingFileLogging(false);
  849. addObject(object);
  850. mGhostAlwaysSaveList.pop_front();
  851. AssertFatal(mLocalGhosts[index] == NULL, "Ghost already in table!");
  852. mLocalGhosts[index] = object;
  853. hadNewFiles = true;
  854. }
  855. }
  856. //-----------------------------------------------------------------------------
  857. NetObject *NetConnection::resolveGhost(S32 id)
  858. {
  859. return mLocalGhosts[id];
  860. }
  861. NetObject *NetConnection::resolveObjectFromGhostIndex(S32 id)
  862. {
  863. return mGhostRefs[id].obj;
  864. }
  865. S32 NetConnection::getGhostIndex(NetObject *obj)
  866. {
  867. if(!isGhostingFrom())
  868. return obj->mNetIndex;
  869. S32 index = obj->getId() & (GhostLookupTableSize - 1);
  870. for(GhostInfo *gptr = mGhostLookupTable[index]; gptr; gptr = gptr->nextLookupInfo)
  871. {
  872. if(gptr->obj == obj && (gptr->flags & (GhostInfo::KillingGhost | GhostInfo::Ghosting | GhostInfo::NotYetGhosted | GhostInfo::KillGhost)) == 0)
  873. return gptr->index;
  874. }
  875. return -1;
  876. }
  877. //-----------------------------------------------------------------------------
  878. //-----------------------------------------------------------------------------
  879. void NetConnection::ghostWriteStartBlock(ResizeBitStream *stream)
  880. {
  881. // Ok, writing the start block for the ghosts:
  882. // here's how it goes.
  883. //
  884. // First we record out all the indices and class ids for all the objects
  885. // This is so when the objects are read in, all the objects are instantiated
  886. // before they are unpacked. The unpack code may reference other
  887. // existing ghosts, so we want to make sure that all the ghosts are in the
  888. // table with the correct pointers before any of the unpacks are called.
  889. stream->write(mGhostingSequence);
  890. // first write out the indices and ids:
  891. for(U32 i = 0; i < MaxGhostCount; i++)
  892. {
  893. if(mLocalGhosts[i])
  894. {
  895. stream->writeFlag(true);
  896. stream->writeInt(i, GhostIdBitSize);
  897. stream->writeClassId(mLocalGhosts[i]->getClassId(getNetClassGroup()), NetClassTypeObject, getNetClassGroup());
  898. stream->validate();
  899. }
  900. }
  901. // mark off the end of the ghost list:
  902. // it would be more space efficient to write out a count of active ghosts followed
  903. // by index run lengths, but hey, what's a few bits here and there?
  904. stream->writeFlag(false);
  905. // then, for each ghost written into the start block, write the full pack update
  906. // into the start block. For demos to work properly, packUpdate must
  907. // be callable from client objects.
  908. for(U32 i = 0; i < MaxGhostCount; i++)
  909. {
  910. if(mLocalGhosts[i])
  911. {
  912. mLocalGhosts[i]->packUpdate(this, 0xFFFFFFFF, stream);
  913. stream->validate();
  914. }
  915. }
  916. }
  917. void NetConnection::ghostReadStartBlock(BitStream *stream)
  918. {
  919. stream->read(&mGhostingSequence);
  920. // read em back in.
  921. // first, read in the index/class id, construct the object, and place it in mLocalGhosts[i]
  922. while(stream->readFlag())
  923. {
  924. U32 index = stream->readInt(GhostIdBitSize);
  925. S32 tag = stream->readClassId(NetClassTypeObject, getNetClassGroup());
  926. NetObject *obj = (NetObject *) ConsoleObject::create(getNetClassGroup(), NetClassTypeObject, tag);
  927. if(!obj)
  928. {
  929. setLastError("Invalid packet.");
  930. return;
  931. }
  932. obj->mNetFlags = NetObject::IsGhost;
  933. obj->mNetIndex = index;
  934. mLocalGhosts[index] = obj;
  935. }
  936. // now, all the ghosts are in the mLocalGhosts, so we loop
  937. // through all non-null mLocalGhosts, unpacking the objects
  938. // as we go:
  939. for(U32 i = 0; i < MaxGhostCount; i++)
  940. {
  941. if(mLocalGhosts[i])
  942. {
  943. mLocalGhosts[i]->unpackUpdate(this, stream);
  944. if(!mLocalGhosts[i]->registerObject())
  945. {
  946. if(mErrorBuffer[0])
  947. setLastError("Invalid packet.");
  948. return;
  949. }
  950. addObject(mLocalGhosts[i]);
  951. }
  952. }
  953. // MARKF - TODO - looks like we could have memory leaks here
  954. // if there are errors.
  955. }