Connection.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  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 "Connection.h"
  25. #include "Log.h"
  26. #include "Protocol.h"
  27. #include "ProtocolEvents.h"
  28. #include "Scene.h"
  29. #include "DebugNew.h"
  30. static const float RTT_LERP_FACTOR = 0.1f;
  31. OBJECTTYPESTATIC(Connection);
  32. Connection::Connection(Context* context, Peer* peer) :
  33. Object(context),
  34. peer_(peer),
  35. frameNumber_(0),
  36. frameAck_(0),
  37. eventFrameNumber_(0),
  38. roundTripTime_(0.0f),
  39. challenge_(0),
  40. hasChallenge_(false),
  41. joinState_(JS_NOTINSCENE),
  42. position_(Vector3::ZERO)
  43. {
  44. }
  45. Connection::~Connection()
  46. {
  47. // Make sure any references in the scene are cleared
  48. LeftScene();
  49. }
  50. void Connection::SendReliable(const VectorBuffer& packet)
  51. {
  52. Send(packet, true);
  53. }
  54. void Connection::SendUnreliable(const VectorBuffer& packet)
  55. {
  56. Send(packet, false);
  57. }
  58. bool Connection::ReceiveReliable(VectorBuffer& packet)
  59. {
  60. return Receive(packet, true);
  61. }
  62. bool Connection::ReceiveUnreliable(VectorBuffer& packet)
  63. {
  64. return Receive(packet, false);
  65. }
  66. void Connection::Disconnect()
  67. {
  68. LeftScene();
  69. peer_->Disconnect();
  70. }
  71. void Connection::forceDisconnect()
  72. {
  73. LeftScene();
  74. peer_->ForceDisconnect();
  75. }
  76. void Connection::SetLoginData(const VariantMap& loginData)
  77. {
  78. loginData_ = loginData;
  79. }
  80. void Connection::SetScene(Scene* scene)
  81. {
  82. // Leave previous scene first
  83. if (scene_ && scene_ != scene)
  84. LeftScene();
  85. scene_ = scene;
  86. joinState_ = JS_PREPARESCENE;
  87. // Client: set the proxy flag to the scene
  88. if (peer_->GetPeerType() == PEER_SERVER)
  89. scene_->SetNetworkMode(NM_CLIENT);
  90. }
  91. void Connection::JoinedScene()
  92. {
  93. if (!scene_)
  94. return;
  95. if (scene_->GetNetworkMode() == NM_SERVER)
  96. {
  97. // Server: send event, so that game-specific code may create the player node/nodes
  98. using namespace ClientJoinedScene;
  99. VariantMap eventData;
  100. eventData[P_CONNECTION] = (void*)this;
  101. eventData[P_SCENE] = (void*)scene_.GetPtr();
  102. SendEvent(E_CLIENTJOINEDSCENE, eventData);
  103. LOGINFO("Client " + GetIdentity() + " joined scene " + scene_->GetName());
  104. }
  105. joinState_ = JS_SENDFULLUPDATE;
  106. }
  107. void Connection::LeftScene()
  108. {
  109. if (scene_)
  110. {
  111. NetworkMode mode = scene_->GetNetworkMode();
  112. if (mode == NM_SERVER)
  113. {
  114. // Server: send event so that game-specific code may remove the player node/nodes
  115. using namespace ClientLeftScene;
  116. VariantMap eventData;
  117. eventData[P_CONNECTION] = (void*)this;
  118. eventData[P_SCENE] = (void*)scene_.GetPtr();
  119. SendEvent(E_CLIENTLEFTSCENE, eventData);
  120. LOGINFO("Client " + GetIdentity() + " left scene " + scene_->GetName());
  121. }
  122. // Remove owner reference from any nodes
  123. scene_->ResetOwner(this);
  124. // Reset the client mode if set (scene can now be reused as singleplayer again)
  125. if (mode == NM_CLIENT)
  126. {
  127. scene_->Clear();
  128. scene_->SetNetworkMode(NM_NONETWORK);
  129. }
  130. }
  131. scene_.Reset();
  132. remoteEvents_.Clear();
  133. sceneState_.Clear();
  134. joinState_ = JS_NOTINSCENE;
  135. }
  136. void Connection::SetChallenge(unsigned challenge)
  137. {
  138. challenge_ = challenge;
  139. hasChallenge_ = true;
  140. }
  141. void Connection::SetJoinState(JoinState state)
  142. {
  143. joinState_ = state;
  144. }
  145. void Connection::SetFrameNumbers(unsigned short frameNumber, unsigned short frameAck)
  146. {
  147. frameNumber_ = frameNumber;
  148. frameAck_ = frameAck;
  149. }
  150. void Connection::UpdateRoundTripTime(int netFps, unsigned short frameNumber)
  151. {
  152. unsigned short frameDiff = frameNumber - frameAck_;
  153. if (frameDiff >= 0x8000)
  154. frameDiff = frameAck_ - frameNumber;
  155. float newRtt = (1.0f / netFps) * frameDiff;
  156. roundTripTime_ = Lerp(roundTripTime_, newRtt, RTT_LERP_FACTOR);
  157. }
  158. void Connection::SetControls(const Controls& controls)
  159. {
  160. controls_ = controls;
  161. }
  162. void Connection::SetPosition(const Vector3& position)
  163. {
  164. position_ = position;
  165. }
  166. void Connection::addRemoteEvent(const RemoteEvent& remoteEvent)
  167. {
  168. remoteEvents_.Push(remoteEvent);
  169. }
  170. bool Connection::CheckRemoteEventFrame(const RemoteEvent& remoteEvent, unsigned short previousEventFrameNumber)
  171. {
  172. // Check against previous event framenumber, and update current
  173. if (!CheckFrameNumber(remoteEvent.frameNumber_, previousEventFrameNumber, false))
  174. return false;
  175. if (CheckFrameNumber(remoteEvent.frameNumber_, eventFrameNumber_))
  176. eventFrameNumber_ = remoteEvent.frameNumber_;
  177. return true;
  178. }
  179. void Connection::PurgeAckedSceneState()
  180. {
  181. sceneState_.Acked(frameAck_);
  182. }
  183. void Connection::PurgeAckedRemoteEvents(unsigned short frameNumber)
  184. {
  185. for (Vector<RemoteEvent>::Iterator i = remoteEvents_.Begin(); i != remoteEvents_.End();)
  186. {
  187. bool erase = false;
  188. if (!CheckFrameNumber(i->frameNumber_, frameAck_, false))
  189. erase = true;
  190. else if (i->timeToLive_)
  191. {
  192. unsigned short expiryFrameNumber = i->frameNumber_ + i->timeToLive_;
  193. if (!expiryFrameNumber)
  194. ++expiryFrameNumber;
  195. if (!CheckFrameNumber(expiryFrameNumber, frameNumber))
  196. erase = true;
  197. }
  198. if (erase)
  199. i = remoteEvents_.Erase(i);
  200. else
  201. ++i;
  202. }
  203. }
  204. void Connection::ClearSceneState()
  205. {
  206. sceneState_.Clear();
  207. }
  208. void Connection::ClearRemoteEvents()
  209. {
  210. remoteEvents_.Clear();
  211. }
  212. String Connection::GetIdentity() const
  213. {
  214. if (peer_)
  215. return peer_->GetAddress() + ":" + String(peer_->GetPort());
  216. else
  217. return "Unknown";
  218. }
  219. bool Connection::IsConnected() const
  220. {
  221. return peer_->GetConnectionState() == CS_CONNECTED;
  222. }
  223. void Connection::Send(const VectorBuffer& packet, bool reliable)
  224. {
  225. if (packet.GetSize() && peer_->GetConnectionState() == CS_CONNECTED)
  226. peer_->Send(packet, reliable ? CHN_RELIABLE : CHN_UNRELIABLE, reliable);
  227. }
  228. bool Connection::Receive(VectorBuffer& packet, bool reliable)
  229. {
  230. if (peer_->GetConnectionState() == CS_CONNECTED)
  231. return peer_->Receive(packet, reliable ? CHN_RELIABLE : CHN_UNRELIABLE);
  232. else
  233. {
  234. peer_->FlushPackets();
  235. return false;
  236. }
  237. }