netGhost.cc 35 KB

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