Connection.cpp 45 KB

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