Connection.cpp 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402
  1. //
  2. // Copyright (c) 2008-2014 the Urho3D project.
  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 deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // 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 FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "Precompiled.h"
  23. #include "Component.h"
  24. #include "Connection.h"
  25. #include "File.h"
  26. #include "FileSystem.h"
  27. #include "Log.h"
  28. #include "MemoryBuffer.h"
  29. #include "Network.h"
  30. #include "NetworkEvents.h"
  31. #include "NetworkPriority.h"
  32. #include "PackageFile.h"
  33. #include "Profiler.h"
  34. #include "Protocol.h"
  35. #include "ResourceCache.h"
  36. #include "Scene.h"
  37. #include "SceneEvents.h"
  38. #include "SmoothedTransform.h"
  39. #include <kNet.h>
  40. #include "DebugNew.h"
  41. namespace Urho3D
  42. {
  43. static const int STATS_INTERVAL_MSEC = 2000;
  44. PackageDownload::PackageDownload() :
  45. totalFragments_(0),
  46. checksum_(0),
  47. initiated_(false)
  48. {
  49. }
  50. PackageUpload::PackageUpload() :
  51. fragment_(0),
  52. totalFragments_(0)
  53. {
  54. }
  55. Connection::Connection(Context* context, bool isClient, kNet::SharedPtr<kNet::MessageConnection> connection) :
  56. Object(context),
  57. position_(Vector3::ZERO),
  58. connection_(connection),
  59. isClient_(isClient),
  60. connectPending_(false),
  61. sceneLoaded_(false),
  62. logStatistics_(false)
  63. {
  64. sceneState_.connection_ = this;
  65. // Store address and port now for accurate logging (kNet may already have destroyed the socket on disconnection,
  66. // in which case we would log a zero address:port on disconnect)
  67. kNet::EndPoint endPoint = connection_->RemoteEndPoint();
  68. ///\todo Not IPv6-capable.
  69. address_ = Urho3D::ToString("%d.%d.%d.%d", endPoint.ip[0], endPoint.ip[1], endPoint.ip[2], endPoint.ip[3]);
  70. port_ = endPoint.port;
  71. }
  72. Connection::~Connection()
  73. {
  74. // Reset scene (remove possible owner references), as this connection is about to be destroyed
  75. SetScene(0);
  76. }
  77. void Connection::SendMessage(int msgID, bool reliable, bool inOrder, const VectorBuffer& msg, unsigned contentID)
  78. {
  79. SendMessage(msgID, reliable, inOrder, msg.GetData(), msg.GetSize(), contentID);
  80. }
  81. void Connection::SendMessage(int msgID, bool reliable, bool inOrder, const unsigned char* data, unsigned numBytes,
  82. unsigned contentID)
  83. {
  84. // Make sure not to use kNet internal message ID's
  85. if (msgID <= 0x4 || msgID >= 0x3ffffffe)
  86. {
  87. LOGERROR("Can not send message with reserved ID");
  88. return;
  89. }
  90. connection_->SendMessage(msgID, reliable, inOrder, 0, contentID, (const char*)data, numBytes);
  91. }
  92. void Connection::SendRemoteEvent(StringHash eventType, bool inOrder, const VariantMap& eventData)
  93. {
  94. if (!GetSubsystem<Network>()->CheckRemoteEvent(eventType))
  95. {
  96. LOGWARNING("Discarding not allowed remote event " + eventType.ToString());
  97. return;
  98. }
  99. RemoteEvent queuedEvent;
  100. queuedEvent.senderID_ = 0;
  101. queuedEvent.eventType_ = eventType;
  102. queuedEvent.eventData_ = eventData;
  103. queuedEvent.inOrder_ = inOrder;
  104. remoteEvents_.Push(queuedEvent);
  105. }
  106. void Connection::SendRemoteEvent(Node* node, StringHash eventType, bool inOrder, const VariantMap& eventData)
  107. {
  108. if (!GetSubsystem<Network>()->CheckRemoteEvent(eventType))
  109. {
  110. LOGWARNING("Discarding not allowed remote event " + eventType.ToString());
  111. return;
  112. }
  113. if (!node)
  114. {
  115. LOGERROR("Null sender node for remote node event");
  116. return;
  117. }
  118. if (node->GetScene() != scene_)
  119. {
  120. LOGERROR("Sender node is not in the connection's scene, can not send remote node event");
  121. return;
  122. }
  123. if (node->GetID() >= FIRST_LOCAL_ID)
  124. {
  125. LOGERROR("Sender node has a local ID, can not send remote node event");
  126. return;
  127. }
  128. RemoteEvent queuedEvent;
  129. queuedEvent.senderID_ = node->GetID();
  130. queuedEvent.eventType_ = eventType;
  131. queuedEvent.eventData_ = eventData;
  132. queuedEvent.inOrder_ = inOrder;
  133. remoteEvents_.Push(queuedEvent);
  134. }
  135. void Connection::SetScene(Scene* newScene)
  136. {
  137. if (scene_)
  138. {
  139. // Remove replication states and owner references from the previous scene
  140. scene_->CleanupConnection(this);
  141. }
  142. scene_ = newScene;
  143. sceneLoaded_ = false;
  144. UnsubscribeFromEvent(E_ASYNCLOADFINISHED);
  145. if (!scene_)
  146. return;
  147. if (isClient_)
  148. {
  149. sceneState_.Clear();
  150. // When scene is assigned on the server, instruct the client to load it. This may require downloading packages
  151. const Vector<SharedPtr<PackageFile> >& packages = scene_->GetRequiredPackageFiles();
  152. unsigned numPackages = packages.Size();
  153. msg_.Clear();
  154. msg_.WriteString(scene_->GetFileName());
  155. msg_.WriteVLE(numPackages);
  156. for (unsigned i = 0; i < numPackages; ++i)
  157. {
  158. PackageFile* package = packages[i];
  159. msg_.WriteString(GetFileNameAndExtension(package->GetName()));
  160. msg_.WriteUInt(package->GetTotalSize());
  161. msg_.WriteUInt(package->GetChecksum());
  162. }
  163. SendMessage(MSG_LOADSCENE, true, true, msg_);
  164. }
  165. else
  166. {
  167. // Make sure there is no existing async loading
  168. scene_->StopAsyncLoading();
  169. SubscribeToEvent(scene_, E_ASYNCLOADFINISHED, HANDLER(Connection, HandleAsyncLoadFinished));
  170. }
  171. }
  172. void Connection::SetIdentity(const VariantMap& identity)
  173. {
  174. identity_ = identity;
  175. }
  176. void Connection::SetControls(const Controls& newControls)
  177. {
  178. controls_ = newControls;
  179. }
  180. void Connection::SetPosition(const Vector3& position)
  181. {
  182. position_ = position;
  183. }
  184. void Connection::SetConnectPending(bool connectPending)
  185. {
  186. connectPending_ = connectPending;
  187. }
  188. void Connection::SetLogStatistics(bool enable)
  189. {
  190. logStatistics_ = enable;
  191. }
  192. void Connection::Disconnect(int waitMSec)
  193. {
  194. connection_->Disconnect(waitMSec);
  195. }
  196. void Connection::SendServerUpdate()
  197. {
  198. if (!scene_ || !sceneLoaded_)
  199. return;
  200. // Always check the root node (scene) first so that the scene-wide components get sent first,
  201. // and all other replicated nodes get added to the dirty set for sending the initial state
  202. unsigned sceneID = scene_->GetID();
  203. nodesToProcess_.Insert(sceneID);
  204. ProcessNode(sceneID);
  205. // Then go through all dirtied nodes
  206. nodesToProcess_.Insert(sceneState_.dirtyNodes_);
  207. nodesToProcess_.Erase(sceneID); // Do not process the root node twice
  208. while (nodesToProcess_.Size())
  209. {
  210. unsigned nodeID = nodesToProcess_.Front();
  211. ProcessNode(nodeID);
  212. }
  213. }
  214. void Connection::SendClientUpdate()
  215. {
  216. if (!scene_ || !sceneLoaded_)
  217. return;
  218. msg_.Clear();
  219. msg_.WriteUInt(controls_.buttons_);
  220. msg_.WriteFloat(controls_.yaw_);
  221. msg_.WriteFloat(controls_.pitch_);
  222. msg_.WriteVariantMap(controls_.extraData_);
  223. msg_.WriteVector3(position_);
  224. SendMessage(MSG_CONTROLS, false, false, msg_, CONTROLS_CONTENT_ID);
  225. }
  226. void Connection::SendRemoteEvents()
  227. {
  228. #ifdef URHO3D_LOGGING
  229. if (logStatistics_ && statsTimer_.GetMSec(false) > STATS_INTERVAL_MSEC)
  230. {
  231. statsTimer_.Reset();
  232. char statsBuffer[256];
  233. sprintf(statsBuffer, "RTT %.3f ms Pkt in %d Pkt out %d Data in %.3f KB/s Data out %.3f KB/s", connection_->RoundTripTime(), (int)connection_->PacketsInPerSec(),
  234. (int)connection_->PacketsOutPerSec(), connection_->BytesInPerSec() / 1000.0f, connection_->BytesOutPerSec() / 1000.0f);
  235. LOGINFO(statsBuffer);
  236. }
  237. #endif
  238. if (remoteEvents_.Empty())
  239. return;
  240. PROFILE(SendRemoteEvents);
  241. for (Vector<RemoteEvent>::ConstIterator i = remoteEvents_.Begin(); i != remoteEvents_.End(); ++i)
  242. {
  243. msg_.Clear();
  244. if (!i->senderID_)
  245. {
  246. msg_.WriteStringHash(i->eventType_);
  247. msg_.WriteVariantMap(i->eventData_);
  248. SendMessage(MSG_REMOTEEVENT, true, i->inOrder_, msg_);
  249. }
  250. else
  251. {
  252. msg_.WriteNetID(i->senderID_);
  253. msg_.WriteStringHash(i->eventType_);
  254. msg_.WriteVariantMap(i->eventData_);
  255. SendMessage(MSG_REMOTENODEEVENT, true, i->inOrder_, msg_);
  256. }
  257. }
  258. remoteEvents_.Clear();
  259. }
  260. void Connection::SendPackages()
  261. {
  262. while (!uploads_.Empty() && connection_->NumOutboundMessagesPending() < 1000)
  263. {
  264. unsigned char buffer[PACKAGE_FRAGMENT_SIZE];
  265. for (HashMap<StringHash, PackageUpload>::Iterator i = uploads_.Begin(); i != uploads_.End();)
  266. {
  267. HashMap<StringHash, PackageUpload>::Iterator current = i++;
  268. PackageUpload& upload = current->second_;
  269. unsigned fragmentSize = Min((int)(upload.file_->GetSize() - upload.file_->GetPosition()), (int)PACKAGE_FRAGMENT_SIZE);
  270. upload.file_->Read(buffer, fragmentSize);
  271. msg_.Clear();
  272. msg_.WriteStringHash(current->first_);
  273. msg_.WriteUInt(upload.fragment_++);
  274. msg_.Write(buffer, fragmentSize);
  275. SendMessage(MSG_PACKAGEDATA, true, false, msg_);
  276. // Check if upload finished
  277. if (upload.fragment_ == upload.totalFragments_)
  278. uploads_.Erase(current);
  279. }
  280. }
  281. }
  282. void Connection::ProcessPendingLatestData()
  283. {
  284. if (!scene_ || !sceneLoaded_)
  285. return;
  286. // Iterate through pending node data and see if we can find the nodes now
  287. for (HashMap<unsigned, PODVector<unsigned char> >::Iterator i = nodeLatestData_.Begin(); i != nodeLatestData_.End();)
  288. {
  289. HashMap<unsigned, PODVector<unsigned char> >::Iterator current = i++;
  290. Node* node = scene_->GetNode(current->first_);
  291. if (node)
  292. {
  293. MemoryBuffer msg(current->second_);
  294. msg.ReadNetID(); // Skip the node ID
  295. node->ReadLatestDataUpdate(msg);
  296. // ApplyAttributes() is deliberately skipped, as Node has no attributes that require late applying.
  297. // Furthermore it would propagate to components and child nodes, which is not desired in this case
  298. nodeLatestData_.Erase(current);
  299. }
  300. }
  301. // Iterate through pending component data and see if we can find the components now
  302. for (HashMap<unsigned, PODVector<unsigned char> >::Iterator i = componentLatestData_.Begin(); i != componentLatestData_.End();)
  303. {
  304. HashMap<unsigned, PODVector<unsigned char> >::Iterator current = i++;
  305. Component* component = scene_->GetComponent(current->first_);
  306. if (component)
  307. {
  308. MemoryBuffer msg(current->second_);
  309. msg.ReadNetID(); // Skip the component ID
  310. component->ReadLatestDataUpdate(msg);
  311. component->ApplyAttributes();
  312. componentLatestData_.Erase(current);
  313. }
  314. }
  315. }
  316. bool Connection::ProcessMessage(int msgID, MemoryBuffer &msg)
  317. {
  318. bool processed = true;
  319. switch (msgID)
  320. {
  321. case MSG_IDENTITY:
  322. ProcessIdentity(msgID, msg);
  323. break;
  324. case MSG_CONTROLS:
  325. ProcessControls(msgID, msg);
  326. break;
  327. case MSG_SCENELOADED:
  328. ProcessSceneLoaded(msgID, msg);
  329. break;
  330. case MSG_REQUESTPACKAGE:
  331. case MSG_PACKAGEDATA:
  332. ProcessPackageDownload(msgID, msg);
  333. break;
  334. case MSG_LOADSCENE:
  335. ProcessLoadScene(msgID, msg);
  336. break;
  337. case MSG_SCENECHECKSUMERROR:
  338. ProcessSceneChecksumError(msgID, msg);
  339. break;
  340. case MSG_CREATENODE:
  341. case MSG_NODEDELTAUPDATE:
  342. case MSG_NODELATESTDATA:
  343. case MSG_REMOVENODE:
  344. case MSG_CREATECOMPONENT:
  345. case MSG_COMPONENTDELTAUPDATE:
  346. case MSG_COMPONENTLATESTDATA:
  347. case MSG_REMOVECOMPONENT:
  348. ProcessSceneUpdate(msgID, msg);
  349. break;
  350. case MSG_REMOTEEVENT:
  351. case MSG_REMOTENODEEVENT:
  352. ProcessRemoteEvent(msgID, msg);
  353. break;
  354. default:
  355. processed = false;
  356. break;
  357. }
  358. return processed;
  359. }
  360. void Connection::ProcessLoadScene(int msgID, MemoryBuffer& msg)
  361. {
  362. if (IsClient())
  363. {
  364. LOGWARNING("Received unexpected LoadScene message from client " + ToString());
  365. return;
  366. }
  367. if (!scene_)
  368. {
  369. LOGERROR("Can not handle LoadScene message without an assigned scene");
  370. return;
  371. }
  372. // Store the scene file name we need to eventually load
  373. sceneFileName_ = msg.ReadString();
  374. // Clear previous pending latest data and package downloads if any
  375. nodeLatestData_.Clear();
  376. componentLatestData_.Clear();
  377. downloads_.Clear();
  378. // In case we have joined other scenes in this session, remove first all downloaded package files from the resource system
  379. // to prevent resource conflicts
  380. const String& packageCacheDir = GetSubsystem<Network>()->GetPackageCacheDir();
  381. ResourceCache* cache = GetSubsystem<ResourceCache>();
  382. Vector<SharedPtr<PackageFile> > packages = cache->GetPackageFiles();
  383. for (unsigned i = 0; i < packages.Size(); ++i)
  384. {
  385. PackageFile* package = packages[i];
  386. if (!package->GetName().Find(packageCacheDir))
  387. cache->RemovePackageFile(package, true);
  388. }
  389. // Now check which packages we have in the resource cache or in the download cache, and which we need to download
  390. unsigned numPackages = msg.ReadVLE();
  391. packages = cache->GetPackageFiles(); // Refresh resource cache's package list after possible removals
  392. Vector<String> downloadedPackages;
  393. if (!packageCacheDir.Empty())
  394. GetSubsystem<FileSystem>()->ScanDir(downloadedPackages, packageCacheDir, "*.*", SCAN_FILES, false);
  395. for (unsigned i = 0; i < numPackages; ++i)
  396. {
  397. String name = msg.ReadString();
  398. unsigned fileSize = msg.ReadUInt();
  399. unsigned checksum = msg.ReadUInt();
  400. String checksumString = ToStringHex(checksum);
  401. bool found = false;
  402. // Check first the resource cache
  403. for (unsigned j = 0; j < packages.Size(); ++j)
  404. {
  405. PackageFile* package = packages[j];
  406. if (!GetFileNameAndExtension(package->GetName()).Compare(name, false) && package->GetTotalSize() == fileSize &&
  407. package->GetChecksum() == checksum)
  408. {
  409. found = true;
  410. break;
  411. }
  412. }
  413. // Then the download cache
  414. for (unsigned j = 0; j < downloadedPackages.Size(); ++j)
  415. {
  416. const String& fileName = downloadedPackages[j];
  417. if (!fileName.Find(checksumString) && !fileName.Substring(9).Compare(name, false))
  418. {
  419. // Name matches. Check filesize and actual checksum to be sure
  420. SharedPtr<PackageFile> newPackage(new PackageFile(context_, packageCacheDir + fileName));
  421. if (newPackage->GetTotalSize() == fileSize && newPackage->GetChecksum() == checksum)
  422. {
  423. // Add the package to the resource system now, as we will need it to load the scene
  424. cache->AddPackageFile(newPackage, true);
  425. found = true;
  426. break;
  427. }
  428. }
  429. }
  430. // Package not found, need to request a download
  431. if (!found)
  432. {
  433. if (!packageCacheDir.Empty())
  434. RequestPackage(name, fileSize, checksum);
  435. else
  436. {
  437. LOGERROR("Can not download required packages, as package cache directory is not set");
  438. OnSceneLoadFailed();
  439. return;
  440. }
  441. }
  442. }
  443. // If no downloads were queued, can load the scene directly
  444. if (downloads_.Empty())
  445. OnPackagesReady();
  446. }
  447. void Connection::ProcessSceneChecksumError(int msgID, MemoryBuffer& msg)
  448. {
  449. if (IsClient())
  450. {
  451. LOGWARNING("Received unexpected SceneChecksumError message from client " + ToString());
  452. return;
  453. }
  454. LOGERROR("Scene checksum error");
  455. OnSceneLoadFailed();
  456. }
  457. void Connection::ProcessSceneUpdate(int msgID, MemoryBuffer& msg)
  458. {
  459. /// \todo On mobile devices processing this message may potentially cause a crash if it attempts to load new GPU resources
  460. /// while the application is minimized
  461. if (IsClient())
  462. {
  463. LOGWARNING("Received unexpected SceneUpdate message from client " + ToString());
  464. return;
  465. }
  466. if (!scene_)
  467. return;
  468. switch (msgID)
  469. {
  470. case MSG_CREATENODE:
  471. {
  472. unsigned nodeID = msg.ReadNetID();
  473. // In case of the root node (scene), it should already exist. Do not create in that case
  474. Node* node = scene_->GetNode(nodeID);
  475. if (!node)
  476. {
  477. // Add initially to the root level. May be moved as we receive the parent attribute
  478. node = scene_->CreateChild(nodeID, REPLICATED);
  479. // Create smoothed transform component
  480. node->CreateComponent<SmoothedTransform>(LOCAL);
  481. }
  482. // Read initial attributes, then snap the motion smoothing immediately to the end
  483. node->ReadDeltaUpdate(msg);
  484. SmoothedTransform* transform = node->GetComponent<SmoothedTransform>();
  485. if (transform)
  486. transform->Update(1.0f, 0.0f);
  487. // Read initial user variables
  488. unsigned numVars = msg.ReadVLE();
  489. while (numVars)
  490. {
  491. StringHash key = msg.ReadStringHash();
  492. node->SetVar(key, msg.ReadVariant());
  493. --numVars;
  494. }
  495. // Read components
  496. unsigned numComponents = msg.ReadVLE();
  497. while (numComponents)
  498. {
  499. --numComponents;
  500. StringHash type = msg.ReadStringHash();
  501. unsigned componentID = msg.ReadNetID();
  502. // Check if the component by this ID and type already exists in this node
  503. Component* component = scene_->GetComponent(componentID);
  504. if (!component || component->GetType() != type || component->GetNode() != node)
  505. {
  506. if (component)
  507. component->Remove();
  508. component = node->CreateComponent(type, REPLICATED, componentID);
  509. }
  510. // If was unable to create the component, would desync the message and therefore have to abort
  511. if (!component)
  512. {
  513. LOGERROR("CreateNode message parsing aborted due to unknown component");
  514. return;
  515. }
  516. // Read initial attributes and apply
  517. component->ReadDeltaUpdate(msg);
  518. component->ApplyAttributes();
  519. }
  520. }
  521. break;
  522. case MSG_NODEDELTAUPDATE:
  523. {
  524. unsigned nodeID = msg.ReadNetID();
  525. Node* node = scene_->GetNode(nodeID);
  526. if (node)
  527. {
  528. node->ReadDeltaUpdate(msg);
  529. // ApplyAttributes() is deliberately skipped, as Node has no attributes that require late applying.
  530. // Furthermore it would propagate to components and child nodes, which is not desired in this case
  531. unsigned changedVars = msg.ReadVLE();
  532. while (changedVars)
  533. {
  534. StringHash key = msg.ReadStringHash();
  535. node->SetVar(key, msg.ReadVariant());
  536. --changedVars;
  537. }
  538. }
  539. else
  540. LOGWARNING("NodeDeltaUpdate message received for missing node " + String(nodeID));
  541. }
  542. break;
  543. case MSG_NODELATESTDATA:
  544. {
  545. unsigned nodeID = msg.ReadNetID();
  546. Node* node = scene_->GetNode(nodeID);
  547. if (node)
  548. {
  549. node->ReadLatestDataUpdate(msg);
  550. // ApplyAttributes() is deliberately skipped, as Node has no attributes that require late applying.
  551. // Furthermore it would propagate to components and child nodes, which is not desired in this case
  552. }
  553. else
  554. {
  555. // Latest data messages may be received out-of-order relative to node creation, so cache if necessary
  556. PODVector<unsigned char>& data = nodeLatestData_[nodeID];
  557. data.Resize(msg.GetSize());
  558. memcpy(&data[0], msg.GetData(), msg.GetSize());
  559. }
  560. }
  561. break;
  562. case MSG_REMOVENODE:
  563. {
  564. unsigned nodeID = msg.ReadNetID();
  565. Node* node = scene_->GetNode(nodeID);
  566. if (node)
  567. node->Remove();
  568. nodeLatestData_.Erase(nodeID);
  569. }
  570. break;
  571. case MSG_CREATECOMPONENT:
  572. {
  573. unsigned nodeID = msg.ReadNetID();
  574. Node* node = scene_->GetNode(nodeID);
  575. if (node)
  576. {
  577. StringHash type = msg.ReadStringHash();
  578. unsigned componentID = msg.ReadNetID();
  579. // Check if the component by this ID and type already exists in this node
  580. Component* component = scene_->GetComponent(componentID);
  581. if (!component || component->GetType() != type || component->GetNode() != node)
  582. {
  583. if (component)
  584. component->Remove();
  585. component = node->CreateComponent(type, REPLICATED, componentID);
  586. }
  587. // If was unable to create the component, would desync the message and therefore have to abort
  588. if (!component)
  589. {
  590. LOGERROR("CreateComponent message parsing aborted due to unknown component");
  591. return;
  592. }
  593. // Read initial attributes and apply
  594. component->ReadDeltaUpdate(msg);
  595. component->ApplyAttributes();
  596. }
  597. else
  598. LOGWARNING("CreateComponent message received for missing node " + String(nodeID));
  599. }
  600. break;
  601. case MSG_COMPONENTDELTAUPDATE:
  602. {
  603. unsigned componentID = msg.ReadNetID();
  604. Component* component = scene_->GetComponent(componentID);
  605. if (component)
  606. {
  607. component->ReadDeltaUpdate(msg);
  608. component->ApplyAttributes();
  609. }
  610. else
  611. LOGWARNING("ComponentDeltaUpdate message received for missing component " + String(componentID));
  612. }
  613. break;
  614. case MSG_COMPONENTLATESTDATA:
  615. {
  616. unsigned componentID = msg.ReadNetID();
  617. Component* component = scene_->GetComponent(componentID);
  618. if (component)
  619. {
  620. component->ReadLatestDataUpdate(msg);
  621. component->ApplyAttributes();
  622. }
  623. else
  624. {
  625. // Latest data messages may be received out-of-order relative to component creation, so cache if necessary
  626. PODVector<unsigned char>& data = componentLatestData_[componentID];
  627. data.Resize(msg.GetSize());
  628. memcpy(&data[0], msg.GetData(), msg.GetSize());
  629. }
  630. }
  631. break;
  632. case MSG_REMOVECOMPONENT:
  633. {
  634. unsigned componentID = msg.ReadNetID();
  635. Component* component = scene_->GetComponent(componentID);
  636. if (component)
  637. component->Remove();
  638. componentLatestData_.Erase(componentID);
  639. }
  640. break;
  641. }
  642. }
  643. void Connection::ProcessPackageDownload(int msgID, MemoryBuffer& msg)
  644. {
  645. switch (msgID)
  646. {
  647. case MSG_REQUESTPACKAGE:
  648. if (!IsClient())
  649. {
  650. LOGWARNING("Received unexpected RequestPackage message from server");
  651. return;
  652. }
  653. else
  654. {
  655. String name = msg.ReadString();
  656. if (!scene_)
  657. {
  658. LOGWARNING("Received a RequestPackage message without an assigned scene from client " + ToString());
  659. return;
  660. }
  661. // The package must be one of those required by the scene
  662. const Vector<SharedPtr<PackageFile> >& packages = scene_->GetRequiredPackageFiles();
  663. for (unsigned i = 0; i < packages.Size(); ++i)
  664. {
  665. PackageFile* package = packages[i];
  666. String packageFullName = package->GetName();
  667. if (!GetFileNameAndExtension(packageFullName).Compare(name, false))
  668. {
  669. StringHash nameHash(name);
  670. // Do not restart upload if already exists
  671. if (uploads_.Contains(nameHash))
  672. {
  673. LOGWARNING("Received a request for package " + name + " already in transfer");
  674. return;
  675. }
  676. // Try to open the file now
  677. SharedPtr<File> file(new File(context_, packageFullName));
  678. if (!file->IsOpen())
  679. {
  680. LOGERROR("Failed to transmit package file " + name);
  681. SendPackageError(name);
  682. return;
  683. }
  684. LOGINFO("Transmitting package file " + name + " to client " + ToString());
  685. uploads_[nameHash].file_ = file;
  686. uploads_[nameHash].fragment_ = 0;
  687. uploads_[nameHash].totalFragments_ = (file->GetSize() + PACKAGE_FRAGMENT_SIZE - 1) / PACKAGE_FRAGMENT_SIZE;
  688. return;
  689. }
  690. }
  691. LOGERROR("Client requested an unexpected package file " + name);
  692. // Send the name hash only to indicate a failed download
  693. SendPackageError(name);
  694. return;
  695. }
  696. break;
  697. case MSG_PACKAGEDATA:
  698. if (IsClient())
  699. {
  700. LOGWARNING("Received unexpected PackageData message from client");
  701. return;
  702. }
  703. else
  704. {
  705. StringHash nameHash = msg.ReadStringHash();
  706. HashMap<StringHash, PackageDownload>::Iterator i = downloads_.Find(nameHash);
  707. // In case of being unable to create the package file into the cache, we will still receive all data from the server.
  708. // Simply disregard it
  709. if (i == downloads_.End())
  710. return;
  711. PackageDownload& download = i->second_;
  712. // If no further data, this is an error reply
  713. if (msg.IsEof())
  714. {
  715. OnPackageDownloadFailed(download.name_);
  716. return;
  717. }
  718. // If file has not yet been opened, try to open now. Prepend the checksum to the filename to allow multiple versions
  719. if (!download.file_)
  720. {
  721. download.file_ = new File(context_, GetSubsystem<Network>()->GetPackageCacheDir() + ToStringHex(download.checksum_) + "_" + download.name_, FILE_WRITE);
  722. if (!download.file_->IsOpen())
  723. {
  724. OnPackageDownloadFailed(download.name_);
  725. return;
  726. }
  727. }
  728. // Write the fragment data to the proper index
  729. unsigned char buffer[PACKAGE_FRAGMENT_SIZE];
  730. unsigned index = msg.ReadUInt();
  731. unsigned fragmentSize = msg.GetSize() - msg.GetPosition();
  732. msg.Read(buffer, fragmentSize);
  733. download.file_->Seek(index * PACKAGE_FRAGMENT_SIZE);
  734. download.file_->Write(buffer, fragmentSize);
  735. download.receivedFragments_.Insert(index);
  736. // Check if all fragments received
  737. if (download.receivedFragments_.Size() == download.totalFragments_)
  738. {
  739. LOGINFO("Package " + download.name_ + " downloaded successfully");
  740. // Instantiate the package and add to the resource system, as we will need it to load the scene
  741. download.file_->Close();
  742. SharedPtr<PackageFile> newPackage(new PackageFile(context_, download.file_->GetName()));
  743. GetSubsystem<ResourceCache>()->AddPackageFile(newPackage, true);
  744. // Then start the next download if there are more
  745. downloads_.Erase(i);
  746. if (downloads_.Empty())
  747. OnPackagesReady();
  748. else
  749. {
  750. PackageDownload& nextDownload = downloads_.Begin()->second_;
  751. LOGINFO("Requesting package " + nextDownload.name_ + " from server");
  752. msg_.Clear();
  753. msg_.WriteString(nextDownload.name_);
  754. SendMessage(MSG_REQUESTPACKAGE, true, true, msg_);
  755. nextDownload.initiated_ = true;
  756. }
  757. }
  758. }
  759. break;
  760. }
  761. }
  762. void Connection::ProcessIdentity(int msgID, MemoryBuffer& msg)
  763. {
  764. if (!IsClient())
  765. {
  766. LOGWARNING("Received unexpected Identity message from server");
  767. return;
  768. }
  769. identity_ = msg.ReadVariantMap();
  770. using namespace ClientIdentity;
  771. VariantMap eventData = identity_;
  772. eventData[P_CONNECTION] = this;
  773. eventData[P_ALLOW] = true;
  774. SendEvent(E_CLIENTIDENTITY, eventData);
  775. // If connection was denied as a response to the identity event, disconnect now
  776. if (!eventData[P_ALLOW].GetBool())
  777. Disconnect();
  778. }
  779. void Connection::ProcessControls(int msgID, MemoryBuffer& msg)
  780. {
  781. if (!IsClient())
  782. {
  783. LOGWARNING("Received unexpected Controls message from server");
  784. return;
  785. }
  786. Controls newControls;
  787. newControls.buttons_ = msg.ReadUInt();
  788. newControls.yaw_ = msg.ReadFloat();
  789. newControls.pitch_ = msg.ReadFloat();
  790. newControls.extraData_ = msg.ReadVariantMap();
  791. SetControls(newControls);
  792. SetPosition(msg.ReadVector3());
  793. }
  794. void Connection::ProcessSceneLoaded(int msgID, MemoryBuffer& msg)
  795. {
  796. if (!IsClient())
  797. {
  798. LOGWARNING("Received unexpected SceneLoaded message from server");
  799. return;
  800. }
  801. if (!scene_)
  802. {
  803. LOGWARNING("Received a SceneLoaded message without an assigned scene from client " + ToString());
  804. return;
  805. }
  806. unsigned checksum = msg.ReadUInt();
  807. if (checksum != scene_->GetChecksum())
  808. {
  809. LOGINFO("Scene checksum error from client " + ToString());
  810. msg_.Clear();
  811. SendMessage(MSG_SCENECHECKSUMERROR, true, true, msg_);
  812. OnSceneLoadFailed();
  813. }
  814. else
  815. {
  816. sceneLoaded_ = true;
  817. using namespace ClientSceneLoaded;
  818. VariantMap& eventData = GetEventDataMap();
  819. eventData[P_CONNECTION] = this;
  820. SendEvent(E_CLIENTSCENELOADED, eventData);
  821. }
  822. }
  823. void Connection::ProcessRemoteEvent(int msgID, MemoryBuffer& msg)
  824. {
  825. using namespace RemoteEventData;
  826. if (msgID == MSG_REMOTEEVENT)
  827. {
  828. StringHash eventType = msg.ReadStringHash();
  829. if (!GetSubsystem<Network>()->CheckRemoteEvent(eventType))
  830. {
  831. LOGWARNING("Discarding not allowed remote event " + eventType.ToString());
  832. return;
  833. }
  834. VariantMap eventData = msg.ReadVariantMap();
  835. eventData[P_CONNECTION] = this;
  836. SendEvent(eventType, eventData);
  837. }
  838. else
  839. {
  840. if (!scene_)
  841. {
  842. LOGERROR("Can not receive remote node event without an assigned scene");
  843. return;
  844. }
  845. unsigned nodeID = msg.ReadNetID();
  846. StringHash eventType = msg.ReadStringHash();
  847. if (!GetSubsystem<Network>()->CheckRemoteEvent(eventType))
  848. {
  849. LOGWARNING("Discarding not allowed remote event " + eventType.ToString());
  850. return;
  851. }
  852. VariantMap eventData = msg.ReadVariantMap();
  853. Node* sender = scene_->GetNode(nodeID);
  854. if (!sender)
  855. {
  856. LOGWARNING("Missing sender for remote node event, discarding");
  857. return;
  858. }
  859. eventData[P_CONNECTION] = this;
  860. sender->SendEvent(eventType, eventData);
  861. }
  862. }
  863. kNet::MessageConnection* Connection::GetMessageConnection() const
  864. {
  865. return const_cast<kNet::MessageConnection*>(connection_.ptr());
  866. }
  867. Scene* Connection::GetScene() const
  868. {
  869. return scene_;
  870. }
  871. bool Connection::IsConnected() const
  872. {
  873. return connection_->GetConnectionState() == kNet::ConnectionOK;
  874. }
  875. String Connection::ToString() const
  876. {
  877. return GetAddress() + ":" + String(GetPort());
  878. }
  879. unsigned Connection::GetNumDownloads() const
  880. {
  881. return downloads_.Size();
  882. }
  883. const String& Connection::GetDownloadName() const
  884. {
  885. for (HashMap<StringHash, PackageDownload>::ConstIterator i = downloads_.Begin(); i != downloads_.End(); ++i)
  886. {
  887. if (i->second_.initiated_)
  888. return i->second_.name_;
  889. }
  890. return String::EMPTY;
  891. }
  892. float Connection::GetDownloadProgress() const
  893. {
  894. for (HashMap<StringHash, PackageDownload>::ConstIterator i = downloads_.Begin(); i != downloads_.End(); ++i)
  895. {
  896. if (i->second_.initiated_)
  897. return (float)i->second_.receivedFragments_.Size() / (float)i->second_.totalFragments_;
  898. }
  899. return 1.0f;
  900. }
  901. void Connection::HandleAsyncLoadFinished(StringHash eventType, VariantMap& eventData)
  902. {
  903. sceneLoaded_ = true;
  904. msg_.Clear();
  905. msg_.WriteUInt(scene_->GetChecksum());
  906. SendMessage(MSG_SCENELOADED, true, true, msg_);
  907. }
  908. void Connection::ProcessNode(unsigned nodeID)
  909. {
  910. // Check that we have not already processed this due to dependency recursion
  911. if (!nodesToProcess_.Erase(nodeID))
  912. return;
  913. // Find replication state for the node
  914. HashMap<unsigned, NodeReplicationState>::Iterator i = sceneState_.nodeStates_.Find(nodeID);
  915. if (i != sceneState_.nodeStates_.End())
  916. {
  917. // Replication state found: the node is either be existing or removed
  918. Node* node = i->second_.node_;
  919. if (!node)
  920. {
  921. msg_.Clear();
  922. msg_.WriteNetID(nodeID);
  923. // Note: we will send MSG_REMOVENODE redundantly for each node in the hierarchy, even if removing the root node
  924. // would be enough. However, this may be better due to the client not possibly having updated parenting
  925. // information at the time of receiving this message
  926. SendMessage(MSG_REMOVENODE, true, true, msg_);
  927. sceneState_.nodeStates_.Erase(nodeID);
  928. }
  929. else
  930. ProcessExistingNode(node, i->second_);
  931. }
  932. else
  933. {
  934. // Replication state not found: this is a new node
  935. Node* node = scene_->GetNode(nodeID);
  936. if (node)
  937. ProcessNewNode(node);
  938. else
  939. {
  940. // Did not find the new node (may have been created, then removed immediately): erase from dirty set.
  941. sceneState_.dirtyNodes_.Erase(nodeID);
  942. }
  943. }
  944. }
  945. void Connection::ProcessNewNode(Node* node)
  946. {
  947. // Process depended upon nodes first, if they are dirty
  948. const PODVector<Node*>& dependencyNodes = node->GetDependencyNodes();
  949. for (PODVector<Node*>::ConstIterator i = dependencyNodes.Begin(); i != dependencyNodes.End(); ++i)
  950. {
  951. unsigned nodeID = (*i)->GetID();
  952. if (sceneState_.dirtyNodes_.Contains(nodeID))
  953. ProcessNode(nodeID);
  954. }
  955. msg_.Clear();
  956. msg_.WriteNetID(node->GetID());
  957. NodeReplicationState& nodeState = sceneState_.nodeStates_[node->GetID()];
  958. nodeState.connection_ = this;
  959. nodeState.sceneState_ = &sceneState_;
  960. nodeState.node_ = node;
  961. node->AddReplicationState(&nodeState);
  962. // Write node's attributes
  963. node->WriteInitialDeltaUpdate(msg_);
  964. // Write node's user variables
  965. const VariantMap& vars = node->GetVars();
  966. msg_.WriteVLE(vars.Size());
  967. for (VariantMap::ConstIterator i = vars.Begin(); i != vars.End(); ++i)
  968. {
  969. msg_.WriteStringHash(i->first_);
  970. msg_.WriteVariant(i->second_);
  971. }
  972. // Write node's components
  973. msg_.WriteVLE(node->GetNumNetworkComponents());
  974. const Vector<SharedPtr<Component> >& components = node->GetComponents();
  975. for (unsigned i = 0; i < components.Size(); ++i)
  976. {
  977. Component* component = components[i];
  978. // Check if component is not to be replicated
  979. if (component->GetID() >= FIRST_LOCAL_ID)
  980. continue;
  981. ComponentReplicationState& componentState = nodeState.componentStates_[component->GetID()];
  982. componentState.connection_ = this;
  983. componentState.nodeState_ = &nodeState;
  984. componentState.component_ = component;
  985. component->AddReplicationState(&componentState);
  986. msg_.WriteStringHash(component->GetType());
  987. msg_.WriteNetID(component->GetID());
  988. component->WriteInitialDeltaUpdate(msg_);
  989. }
  990. SendMessage(MSG_CREATENODE, true, true, msg_);
  991. nodeState.markedDirty_ = false;
  992. sceneState_.dirtyNodes_.Erase(node->GetID());
  993. }
  994. void Connection::ProcessExistingNode(Node* node, NodeReplicationState& nodeState)
  995. {
  996. // Process depended upon nodes first, if they are dirty
  997. const PODVector<Node*>& dependencyNodes = node->GetDependencyNodes();
  998. for (PODVector<Node*>::ConstIterator i = dependencyNodes.Begin(); i != dependencyNodes.End(); ++i)
  999. {
  1000. unsigned nodeID = (*i)->GetID();
  1001. if (sceneState_.dirtyNodes_.Contains(nodeID))
  1002. ProcessNode(nodeID);
  1003. }
  1004. // Check from the interest management component, if exists, whether should update
  1005. /// \todo Searching for the component is a potential CPU hotspot. It should be cached
  1006. NetworkPriority* priority = node->GetComponent<NetworkPriority>();
  1007. if (priority && (!priority->GetAlwaysUpdateOwner() || node->GetOwner() != this))
  1008. {
  1009. float distance = (node->GetWorldPosition() - position_).Length();
  1010. if (!priority->CheckUpdate(distance, nodeState.priorityAcc_))
  1011. return;
  1012. }
  1013. // Check if attributes have changed
  1014. if (nodeState.dirtyAttributes_.Count())
  1015. {
  1016. const Vector<AttributeInfo>* attributes = node->GetNetworkAttributes();
  1017. unsigned numAttributes = attributes->Size();
  1018. bool hasLatestData = false;
  1019. for (unsigned i = 0; i < numAttributes; ++i)
  1020. {
  1021. if (nodeState.dirtyAttributes_.IsSet(i) && (attributes->At(i).mode_ & AM_LATESTDATA))
  1022. {
  1023. hasLatestData = true;
  1024. nodeState.dirtyAttributes_.Clear(i);
  1025. }
  1026. }
  1027. // Send latestdata message if necessary
  1028. if (hasLatestData)
  1029. {
  1030. msg_.Clear();
  1031. msg_.WriteNetID(node->GetID());
  1032. node->WriteLatestDataUpdate(msg_);
  1033. SendMessage(MSG_NODELATESTDATA, true, false, msg_, node->GetID());
  1034. }
  1035. // Send deltaupdate if remaining dirty bits, or vars have changed
  1036. if (nodeState.dirtyAttributes_.Count() || nodeState.dirtyVars_.Size())
  1037. {
  1038. msg_.Clear();
  1039. msg_.WriteNetID(node->GetID());
  1040. node->WriteDeltaUpdate(msg_, nodeState.dirtyAttributes_);
  1041. // Write changed variables
  1042. msg_.WriteVLE(nodeState.dirtyVars_.Size());
  1043. const VariantMap& vars = node->GetVars();
  1044. for (HashSet<StringHash>::ConstIterator i = nodeState.dirtyVars_.Begin(); i != nodeState.dirtyVars_.End(); ++i)
  1045. {
  1046. VariantMap::ConstIterator j = vars.Find(*i);
  1047. if (j != vars.End())
  1048. {
  1049. msg_.WriteStringHash(j->first_);
  1050. msg_.WriteVariant(j->second_);
  1051. }
  1052. else
  1053. {
  1054. // Variable has been marked dirty, but is removed (which is unsupported): send a dummy variable in place
  1055. LOGWARNING("Sending dummy user variable as original value was removed");
  1056. msg_.WriteStringHash(StringHash());
  1057. msg_.WriteVariant(Variant::EMPTY);
  1058. }
  1059. }
  1060. SendMessage(MSG_NODEDELTAUPDATE, true, true, msg_);
  1061. nodeState.dirtyAttributes_.ClearAll();
  1062. nodeState.dirtyVars_.Clear();
  1063. }
  1064. }
  1065. // Check for removed or changed components
  1066. for (HashMap<unsigned, ComponentReplicationState>::Iterator i = nodeState.componentStates_.Begin();
  1067. i != nodeState.componentStates_.End(); )
  1068. {
  1069. HashMap<unsigned, ComponentReplicationState>::Iterator current = i++;
  1070. ComponentReplicationState& componentState = current->second_;
  1071. Component* component = componentState.component_;
  1072. if (!component)
  1073. {
  1074. // Removed component
  1075. msg_.Clear();
  1076. msg_.WriteNetID(current->first_);
  1077. SendMessage(MSG_REMOVECOMPONENT, true, true, msg_);
  1078. nodeState.componentStates_.Erase(current);
  1079. }
  1080. else
  1081. {
  1082. // Existing component. Check if attributes have changed
  1083. if (componentState.dirtyAttributes_.Count())
  1084. {
  1085. const Vector<AttributeInfo>* attributes = component->GetNetworkAttributes();
  1086. unsigned numAttributes = attributes->Size();
  1087. bool hasLatestData = false;
  1088. for (unsigned i = 0; i < numAttributes; ++i)
  1089. {
  1090. if (componentState.dirtyAttributes_.IsSet(i) && (attributes->At(i).mode_ & AM_LATESTDATA))
  1091. {
  1092. hasLatestData = true;
  1093. componentState.dirtyAttributes_.Clear(i);
  1094. }
  1095. }
  1096. // Send latestdata message if necessary
  1097. if (hasLatestData)
  1098. {
  1099. msg_.Clear();
  1100. msg_.WriteNetID(component->GetID());
  1101. component->WriteLatestDataUpdate(msg_);
  1102. SendMessage(MSG_COMPONENTLATESTDATA, true, false, msg_, component->GetID());
  1103. }
  1104. // Send deltaupdate if remaining dirty bits
  1105. if (componentState.dirtyAttributes_.Count())
  1106. {
  1107. msg_.Clear();
  1108. msg_.WriteNetID(component->GetID());
  1109. component->WriteDeltaUpdate(msg_, componentState.dirtyAttributes_);
  1110. SendMessage(MSG_COMPONENTDELTAUPDATE, true, true, msg_);
  1111. componentState.dirtyAttributes_.ClearAll();
  1112. }
  1113. }
  1114. }
  1115. }
  1116. // Check for new components
  1117. if (nodeState.componentStates_.Size() != node->GetNumNetworkComponents())
  1118. {
  1119. const Vector<SharedPtr<Component> >& components = node->GetComponents();
  1120. for (unsigned i = 0; i < components.Size(); ++i)
  1121. {
  1122. Component* component = components[i];
  1123. // Check if component is not to be replicated
  1124. if (component->GetID() >= FIRST_LOCAL_ID)
  1125. continue;
  1126. HashMap<unsigned, ComponentReplicationState>::Iterator j = nodeState.componentStates_.Find(component->GetID());
  1127. if (j == nodeState.componentStates_.End())
  1128. {
  1129. // New component
  1130. ComponentReplicationState& componentState = nodeState.componentStates_[component->GetID()];
  1131. componentState.connection_ = this;
  1132. componentState.nodeState_ = &nodeState;
  1133. componentState.component_ = component;
  1134. component->AddReplicationState(&componentState);
  1135. msg_.Clear();
  1136. msg_.WriteNetID(node->GetID());
  1137. msg_.WriteStringHash(component->GetType());
  1138. msg_.WriteNetID(component->GetID());
  1139. component->WriteInitialDeltaUpdate(msg_);
  1140. SendMessage(MSG_CREATECOMPONENT, true, true, msg_);
  1141. }
  1142. }
  1143. }
  1144. nodeState.markedDirty_ = false;
  1145. sceneState_.dirtyNodes_.Erase(node->GetID());
  1146. }
  1147. void Connection::RequestPackage(const String& name, unsigned fileSize, unsigned checksum)
  1148. {
  1149. StringHash nameHash(name);
  1150. if (downloads_.Contains(nameHash))
  1151. return; // Download already exists
  1152. PackageDownload& download = downloads_[nameHash];
  1153. download.name_ = name;
  1154. download.totalFragments_ = (fileSize + PACKAGE_FRAGMENT_SIZE - 1) / PACKAGE_FRAGMENT_SIZE;
  1155. download.checksum_ = checksum;
  1156. // Start download now only if no existing downloads, else wait for the existing ones to finish
  1157. if (downloads_.Size() == 1)
  1158. {
  1159. LOGINFO("Requesting package " + name + " from server");
  1160. msg_.Clear();
  1161. msg_.WriteString(name);
  1162. SendMessage(MSG_REQUESTPACKAGE, true, true, msg_);
  1163. download.initiated_ = true;
  1164. }
  1165. }
  1166. void Connection::SendPackageError(const String& name)
  1167. {
  1168. msg_.Clear();
  1169. msg_.WriteStringHash(name);
  1170. SendMessage(MSG_PACKAGEDATA, true, false, msg_);
  1171. }
  1172. void Connection::OnSceneLoadFailed()
  1173. {
  1174. sceneLoaded_ = false;
  1175. using namespace NetworkSceneLoadFailed;
  1176. VariantMap& eventData = GetEventDataMap();
  1177. eventData[P_CONNECTION] = this;
  1178. SendEvent(E_NETWORKSCENELOADFAILED, eventData);
  1179. }
  1180. void Connection::OnPackageDownloadFailed(const String& name)
  1181. {
  1182. LOGERROR("Download of package " + name + " failed");
  1183. // As one package failed, we can not join the scene in any case. Clear the downloads
  1184. downloads_.Clear();
  1185. OnSceneLoadFailed();
  1186. }
  1187. void Connection::OnPackagesReady()
  1188. {
  1189. if (!scene_)
  1190. return;
  1191. if (sceneFileName_.Empty())
  1192. {
  1193. // If the scene filename is empty, just clear the scene of all existing replicated content, and send the loaded reply
  1194. scene_->Clear(true, false);
  1195. sceneLoaded_ = true;
  1196. msg_.Clear();
  1197. msg_.WriteUInt(scene_->GetChecksum());
  1198. SendMessage(MSG_SCENELOADED, true, true, msg_);
  1199. }
  1200. else
  1201. {
  1202. // Otherwise start the async loading process
  1203. String extension = GetExtension(sceneFileName_);
  1204. SharedPtr<File> file = GetSubsystem<ResourceCache>()->GetFile(sceneFileName_);
  1205. bool success;
  1206. if (extension == ".xml")
  1207. success = scene_->LoadAsyncXML(file);
  1208. else
  1209. success = scene_->LoadAsync(file);
  1210. if (!success)
  1211. OnSceneLoadFailed();
  1212. }
  1213. }
  1214. }