| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- //
- // Urho3D Engine
- // Copyright (c) 2008-2011 Lasse Öörni
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- //
- #include "Precompiled.h"
- #include "Connection.h"
- #include "Log.h"
- #include "Protocol.h"
- #include "ProtocolEvents.h"
- #include "Scene.h"
- #include "DebugNew.h"
- static const float RTT_LERP_FACTOR = 0.1f;
- OBJECTTYPESTATIC(Connection);
- Connection::Connection(Context* context, Peer* peer) :
- Object(context),
- peer_(peer),
- frameNumber_(0),
- frameAck_(0),
- eventFrameNumber_(0),
- roundTripTime_(0.0f),
- challenge_(0),
- hasChallenge_(false),
- joinState_(JS_NOTINSCENE),
- position_(Vector3::ZERO)
- {
- }
- Connection::~Connection()
- {
- // Make sure any references in the scene are cleared
- LeftScene();
- }
- void Connection::SendReliable(const VectorBuffer& packet)
- {
- Send(packet, true);
- }
- void Connection::SendUnreliable(const VectorBuffer& packet)
- {
- Send(packet, false);
- }
- bool Connection::ReceiveReliable(VectorBuffer& packet)
- {
- return Receive(packet, true);
- }
- bool Connection::ReceiveUnreliable(VectorBuffer& packet)
- {
- return Receive(packet, false);
- }
- void Connection::Disconnect()
- {
- LeftScene();
- peer_->Disconnect();
- }
- void Connection::forceDisconnect()
- {
- LeftScene();
- peer_->ForceDisconnect();
- }
- void Connection::SetLoginData(const VariantMap& loginData)
- {
- loginData_ = loginData;
- }
- void Connection::SetScene(Scene* scene)
- {
- // Leave previous scene first
- if (scene_ && scene_ != scene)
- LeftScene();
-
- scene_ = scene;
- joinState_ = JS_PREPARESCENE;
-
- // Client: set the proxy flag to the scene
- if (peer_->GetPeerType() == PEER_SERVER)
- scene_->SetNetworkMode(NM_CLIENT);
- }
- void Connection::JoinedScene()
- {
- if (!scene_)
- return;
-
- if (scene_->GetNetworkMode() == NM_SERVER)
- {
- // Server: send event, so that game-specific code may create the player node/nodes
- using namespace ClientJoinedScene;
-
- VariantMap eventData;
- eventData[P_CONNECTION] = (void*)this;
- eventData[P_SCENE] = (void*)scene_.GetPtr();
- SendEvent(E_CLIENTJOINEDSCENE, eventData);
-
- LOGINFO("Client " + GetIdentity() + " joined scene " + scene_->GetName());
- }
-
- joinState_ = JS_SENDFULLUPDATE;
- }
- void Connection::LeftScene()
- {
- if (scene_)
- {
- NetworkMode mode = scene_->GetNetworkMode();
-
- if (mode == NM_SERVER)
- {
- // Server: send event so that game-specific code may remove the player node/nodes
- using namespace ClientLeftScene;
-
- VariantMap eventData;
- eventData[P_CONNECTION] = (void*)this;
- eventData[P_SCENE] = (void*)scene_.GetPtr();
- SendEvent(E_CLIENTLEFTSCENE, eventData);
-
- LOGINFO("Client " + GetIdentity() + " left scene " + scene_->GetName());
- }
-
- // Remove owner reference from any nodes
- scene_->ResetOwner(this);
-
- // Reset the client mode if set (scene can now be reused as singleplayer again)
- if (mode == NM_CLIENT)
- {
- scene_->Clear();
- scene_->SetNetworkMode(NM_NONETWORK);
- }
- }
-
- scene_.Reset();
- remoteEvents_.Clear();
- sceneState_.Clear();
- joinState_ = JS_NOTINSCENE;
- }
- void Connection::SetChallenge(unsigned challenge)
- {
- challenge_ = challenge;
- hasChallenge_ = true;
- }
- void Connection::SetJoinState(JoinState state)
- {
- joinState_ = state;
- }
- void Connection::SetFrameNumbers(unsigned short frameNumber, unsigned short frameAck)
- {
- frameNumber_ = frameNumber;
- frameAck_ = frameAck;
- }
- void Connection::UpdateRoundTripTime(int netFps, unsigned short frameNumber)
- {
- unsigned short frameDiff = frameNumber - frameAck_;
- if (frameDiff >= 0x8000)
- frameDiff = frameAck_ - frameNumber;
-
- float newRtt = (1.0f / netFps) * frameDiff;
- roundTripTime_ = Lerp(roundTripTime_, newRtt, RTT_LERP_FACTOR);
- }
- void Connection::SetControls(const Controls& controls)
- {
- controls_ = controls;
- }
- void Connection::SetPosition(const Vector3& position)
- {
- position_ = position;
- }
- void Connection::addRemoteEvent(const RemoteEvent& remoteEvent)
- {
- remoteEvents_.Push(remoteEvent);
- }
- bool Connection::CheckRemoteEventFrame(const RemoteEvent& remoteEvent, unsigned short previousEventFrameNumber)
- {
- // Check against previous event framenumber, and update current
- if (!CheckFrameNumber(remoteEvent.frameNumber_, previousEventFrameNumber, false))
- return false;
- if (CheckFrameNumber(remoteEvent.frameNumber_, eventFrameNumber_))
- eventFrameNumber_ = remoteEvent.frameNumber_;
- return true;
- }
- void Connection::PurgeAckedSceneState()
- {
- sceneState_.Acked(frameAck_);
- }
- void Connection::PurgeAckedRemoteEvents(unsigned short frameNumber)
- {
- for (Vector<RemoteEvent>::Iterator i = remoteEvents_.Begin(); i != remoteEvents_.End();)
- {
- bool erase = false;
-
- if (!CheckFrameNumber(i->frameNumber_, frameAck_, false))
- erase = true;
- else if (i->timeToLive_)
- {
- unsigned short expiryFrameNumber = i->frameNumber_ + i->timeToLive_;
- if (!expiryFrameNumber)
- ++expiryFrameNumber;
- if (!CheckFrameNumber(expiryFrameNumber, frameNumber))
- erase = true;
- }
-
- if (erase)
- i = remoteEvents_.Erase(i);
- else
- ++i;
- }
- }
- void Connection::ClearSceneState()
- {
- sceneState_.Clear();
- }
- void Connection::ClearRemoteEvents()
- {
- remoteEvents_.Clear();
- }
- String Connection::GetIdentity() const
- {
- if (peer_)
- return peer_->GetAddress() + ":" + String(peer_->GetPort());
- else
- return "Unknown";
- }
- bool Connection::IsConnected() const
- {
- return peer_->GetConnectionState() == CS_CONNECTED;
- }
- void Connection::Send(const VectorBuffer& packet, bool reliable)
- {
- if (packet.GetSize() && peer_->GetConnectionState() == CS_CONNECTED)
- peer_->Send(packet, reliable ? CHN_RELIABLE : CHN_UNRELIABLE, reliable);
- }
- bool Connection::Receive(VectorBuffer& packet, bool reliable)
- {
- if (peer_->GetConnectionState() == CS_CONNECTED)
- return peer_->Receive(packet, reliable ? CHN_RELIABLE : CHN_UNRELIABLE);
- else
- {
- peer_->FlushPackets();
- return false;
- }
- }
|