Connection.cpp 53 KB

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