Przeglądaj źródła

sample updated, unused functionality removed

Arnis Lielturks 7 lat temu
rodzic
commit
76bd85472c

+ 35 - 169
Source/Samples/54_P2PMultiplayer/P2PMultiplayer.cpp

@@ -65,6 +65,7 @@ URHO3D_DEFINE_APPLICATION_MAIN(P2PMultiplayer)
 P2PMultiplayer::P2PMultiplayer(Context* context) :
     Sample(context)
 {
+    Peer::RegisterObject(context);
 }
 
 // Control bits we define
@@ -147,8 +148,7 @@ void P2PMultiplayer::CreateUI()
 void P2PMultiplayer::SubscribeToEvents()
 {
     SubscribeToEvent(E_UPDATE, URHO3D_HANDLER(P2PMultiplayer, HandleUpdate));
-    SubscribeToEvent(E_PHYSICSPRESTEP, URHO3D_HANDLER(P2PMultiplayer, HandlePhysicsPrestep));
-//
+
     SubscribeToEvent(startSession_, "Released", URHO3D_HANDLER(P2PMultiplayer, HandleStartP2PSession));
     SubscribeToEvent(joinSession_, "Released", URHO3D_HANDLER(P2PMultiplayer, HandleJoinP2PSession));
 
@@ -177,7 +177,8 @@ void P2PMultiplayer::HandleJoinP2PSession(StringHash eventType, VariantMap& even
 {
     URHO3D_LOGINFO("HandleJoinP2PSession " + guid_->GetText());
     GetSubsystem<Network>()->P2PJoinSession(guid_->GetText(), scene_);
-    GetSubsystem<Network>()->SetSimulatedLatency(Random(10.0f));
+//    GetSubsystem<Network>()->SetSimulatedLatency(Random(10.0f));
+//    GetSubsystem<Network>()->SetSimulatedLatency(10 + Random(100));
 }
 
 void P2PMultiplayer::HandleSessionStarted(StringHash eventType, VariantMap& eventData)
@@ -202,7 +203,6 @@ void P2PMultiplayer::HandleReady(StringHash eventType, VariantMap& eventData)
 void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
 {
     using namespace Update;
-    static int i = 0;
     auto input = GetSubsystem<Input>();
     float timestep = eventData[P_TIMESTEP].GetFloat();
     static float gametime;
@@ -237,7 +237,8 @@ void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
     }
 
     if (timer_.GetMSec(false) > 1000) {
-        if (GetSubsystem<Network>()->GetClientConnections().Size() != playerNodes_.Size() - 1) {
+//        GetSubsystem<Network>()->SetSimulatedLatency(100 + Random(1000));
+        if (GetSubsystem<Network>()->GetClientConnections().Size() != peers_.Size() - 1) {
             UpdateClientObjects();
         }
 
@@ -248,8 +249,7 @@ void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
 //            URHO3D_LOGINFO("Node " + String((*it)->GetID()) + " => " + (*it)->GetVar("GUID").GetString());
 //        }
 //        URHO3D_LOGINFO("----------------");
-//        GetSubsystem<Network>()->DisplayPingTimes();
-        i++;
+
         timer_.Reset();
 //        URHO3D_LOGINFO(" ");
 //        URHO3D_LOGINFO(" " + String(i));
@@ -315,13 +315,15 @@ void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
 
     auto serverConnection = GetSubsystem<Network>()->GetServerConnection();
     if (serverConnection) {
-        if (playerNodes_[serverConnection]) {
+        if (peers_[serverConnection] && peers_[serverConnection]->GetNode()) {
 //            GetSubsystem<Input>()->SetMouseVisible(false);
-//            cameraNode_->LookAt(playerNodes_[serverConnection]->GetWorldPosition());
-            const float CAMERA_DISTANCE = 5.0f;
+//            GetSubsystem<Input>()->SetMouseGrabbed(true);
+//            GetSubsystem<Input>()->SetMouseMode(MouseMode::MM_WRAP);
+
+            const float CAMERA_DISTANCE = 7.0f;
 
             // Move camera some distance away from the ball
-            cameraNode_->SetPosition(playerNodes_[serverConnection]->GetPosition() + cameraNode_->GetRotation() * Vector3::BACK * CAMERA_DISTANCE);
+            cameraNode_->SetPosition(peers_[serverConnection]->GetNode()->GetPosition() + cameraNode_->GetRotation() * Vector3::BACK * CAMERA_DISTANCE);
         } else {
             UpdateClientObjects();
 //            GetSubsystem<Input>()->SetMouseVisible(true);
@@ -329,75 +331,6 @@ void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
     }
 }
 
-void P2PMultiplayer::HandlePhysicsPrestep(StringHash eventType, VariantMap& eventData)
-{
-    if (!GetSubsystem<Network>()->P2PIsHostSystem()) {
-        return;
-    }
-
-    // Apply client controls to the nodes only if we're the host
-    using namespace PhysicsPreStep;
-    float timestep = eventData[P_TIMESTEP].GetFloat();
-    auto clients = GetSubsystem<Network>()->GetClientConnections();
-    for (auto it = clients.Begin(); it != clients.End(); ++it) {
-        // Get the last controls sent by the client
-        const Controls& controls = (*it)->GetControls();
-        // Torque is relative to the forward vector
-        Quaternion rotation(0.0f, controls.yaw_, 0.0f);
-
-        const float MOVE_TORQUE = 3.0f;
-
-        if (!playerNodes_[(*it)]) {
-            continue;
-        }
-        RigidBody* body = playerNodes_[(*it)]->GetComponent<RigidBody>();
-        // Movement torque is applied before each simulation step, which happen at 60 FPS. This makes the simulation
-        // independent from rendering framerate. We could also apply forces (which would enable in-air control),
-        // but want to emphasize that it's a ball which should only control its motion by rolling along the ground
-        if (controls.buttons_ & CTRL_FORWARD) {
-            body->ApplyTorque(rotation * Vector3::RIGHT * MOVE_TORQUE);
-        }
-        if (controls.buttons_ & CTRL_BACK) {
-            body->ApplyTorque(rotation * Vector3::LEFT * MOVE_TORQUE);
-        }
-        if (controls.buttons_ & CTRL_LEFT) {
-            body->ApplyTorque(rotation * Vector3::FORWARD * MOVE_TORQUE);
-        }
-        if (controls.buttons_ & CTRL_RIGHT) {
-            body->ApplyTorque(rotation * Vector3::BACK * MOVE_TORQUE);
-        }
-    }
-
-    auto serverConnection = GetSubsystem<Network>()->GetServerConnection();
-    if (serverConnection) {
-        const Controls& controls = serverConnection->GetControls();
-        // Torque is relative to the forward vector
-        Quaternion rotation(0.0f, controls.yaw_, 0.0f);
-
-        const float MOVE_TORQUE = 3.0f;
-        if (!playerNodes_[serverConnection]) {
-            return;
-        }
-
-        RigidBody* body = playerNodes_[serverConnection]->GetComponent<RigidBody>();
-        // Movement torque is applied before each simulation step, which happen at 60 FPS. This makes the simulation
-        // independent from rendering framerate. We could also apply forces (which would enable in-air control),
-        // but want to emphasize that it's a ball which should only control its motion by rolling along the ground
-        if (controls.buttons_ & CTRL_FORWARD) {
-            body->ApplyTorque(rotation * Vector3::RIGHT * MOVE_TORQUE);
-        }
-        if (controls.buttons_ & CTRL_BACK) {
-            body->ApplyTorque(rotation * Vector3::LEFT * MOVE_TORQUE);
-        }
-        if (controls.buttons_ & CTRL_LEFT) {
-            body->ApplyTorque(rotation * Vector3::FORWARD * MOVE_TORQUE);
-        }
-        if (controls.buttons_ & CTRL_RIGHT) {
-            body->ApplyTorque(rotation * Vector3::BACK * MOVE_TORQUE);
-        }
-    }
-}
-
 void P2PMultiplayer::Init()
 {
     GetSubsystem<Network>()->SetMode(NetworkMode::PEER_TO_PEER);
@@ -514,32 +447,6 @@ void P2PMultiplayer::CreateScene()
     // Set an initial position for the camera scene node above the plane
     cameraNode_->SetPosition(Vector3(-10.0f, 10.0f, 10.0f));
     cameraNode_->LookAt(Vector3(0, 0, 0));
-
-    // Create the scene node & visual representation. This will be a replicated object
-    Node* ballNode = scene_->CreateChild("Ball");
-    ballNode->SetPosition(Vector3(0, 10, 0));
-    ballNode->SetScale(0.5f);
-    auto* ballObject = ballNode->CreateComponent<StaticModel>();
-    ballObject->SetModel(cache->GetResource<Model>("Models/Sphere.mdl"));
-    ballObject->SetMaterial(cache->GetResource<Material>("Materials/StoneSmall.xml"));
-
-    // Create the physics components
-    auto* body = ballNode->CreateComponent<RigidBody>();
-    body->SetMass(1.0f);
-    body->SetFriction(1.0f);
-    body->SetRestitution(0.0);
-    // In addition to friction, use motion damping so that the ball can not accelerate limitlessly
-    body->SetLinearDamping(0.5f);
-//    body->SetAngularDamping(0.5f);
-    //body->SetLinearVelocity(Vector3(0.1, 1, 0.1));
-    auto* shape = ballNode->CreateComponent<CollisionShape>();
-    shape->SetSphere(1.0f);
-
-    // Create a random colored point light at the ball so that can see better where is going
-    auto* light2 = ballNode->CreateComponent<Light>();
-    light2->SetRange(3.0f);
-    light2->SetColor(
-        Color(0.5f + ((unsigned)Rand() & 1u) * 0.5f, 0.5f + ((unsigned)Rand() & 1u) * 0.5f, 0.5f + ((unsigned)Rand() & 1u) * 0.5f));
 }
 
 void P2PMultiplayer::SetupViewport()
@@ -552,12 +459,8 @@ void P2PMultiplayer::SetupViewport()
     renderer->SetViewport(0, viewport);
 }
 
-
-
 void P2PMultiplayer::HandleClientConnected(StringHash eventType, VariantMap& eventData)
 {
-    URHO3D_LOGERROR("CLIENT CONNECTED!");
-//    return;
     using namespace ClientConnected;
 
     // When a client connects, assign to scene to begin scene replication
@@ -571,9 +474,8 @@ void P2PMultiplayer::HandleClientConnected(StringHash eventType, VariantMap& eve
 
 void P2PMultiplayer::HandleClientDisconnected(StringHash eventType, VariantMap& eventData)
 {
-    URHO3D_LOGERROR("CLIENT DISCONNECTED!");
     using namespace ClientConnected;
-//
+
 //    // When a client disconnects, remove the controlled object
     auto* connection = static_cast<Connection*>(eventData[P_CONNECTION].GetPtr());
     DestroyPlayerNode(connection);
@@ -583,26 +485,32 @@ void P2PMultiplayer::HandleClientDisconnected(StringHash eventType, VariantMap&
 
 void P2PMultiplayer::UpdateClientObjects()
 {
+    URHO3D_LOGWARNING("UpdateClientObjects");
     PODVector<Node*> playerNodes;
     scene_->GetNodesWithTag(playerNodes, "Player");
     auto clients = GetSubsystem<Network>()->GetClientConnections();
     for (auto it = clients.Begin(); it != clients.End(); ++it) {
         for (auto it2 = playerNodes.Begin(); it2 != playerNodes.End(); ++it2) {
             if ((*it2)->GetVar("GUID").GetString() == (*it)->GetGUID()) {
-//                URHO3D_LOGERROR("Found client controlled node");
-                playerNodes_[(*it)] = (*it2);
+                if (!peers_[(*it)]) {
+                    peers_[(*it)] = new Peer(context_);
+                    peers_[(*it)]->SetConnection((*it));
+                    peers_[(*it)]->SetScene(scene_);
+                }
+                peers_[(*it)]->SetNode((*it2));
             }
         }
     }
     for (auto it2 = playerNodes.Begin(); it2 != playerNodes.End(); ++it2) {
-//        URHO3D_LOGERROR("GUID: " + (*it2)->GetVar("GUID").GetString() + " == " + GetSubsystem<Network>()->P2PGetGUID());
         if ((*it2)->GetVar("GUID").GetString() == GetSubsystem<Network>()->P2PGetGUID()) {
-//            URHO3D_LOGERROR("We found our node with specific GUID!");
-            playerNodes_[GetSubsystem<Network>()->GetServerConnection()] = (*it2);
+            if (!peers_[GetSubsystem<Network>()->GetServerConnection()]) {
+                peers_[GetSubsystem<Network>()->GetServerConnection()] = new Peer(context_);
+                peers_[GetSubsystem<Network>()->GetServerConnection()]->SetConnection(GetSubsystem<Network>()->GetServerConnection());
+                peers_[GetSubsystem<Network>()->GetServerConnection()]->SetScene(scene_);
+            }
+            peers_[GetSubsystem<Network>()->GetServerConnection()]->SetNode(*it2);
         }
     }
-//    URHO3D_LOGINFOF("Player nodes: %i", playerNodes_.Size());
-
 }
 
 void P2PMultiplayer::HandleResetHost(StringHash eventType, VariantMap& eventData)
@@ -619,70 +527,28 @@ void P2PMultiplayer::HandleAllReadyChanged(StringHash eventType, VariantMap& eve
 void P2PMultiplayer::HandleDisconnect(StringHash eventType, VariantMap& eventData)
 {
     GetSubsystem<Network>()->Disconnect(1000);
-    for (auto it = playerNodes_.Begin(); it != playerNodes_.End(); ++it) {
-        if ((*it).second_) {
-            (*it).second_->Remove();
-        }
-    }
-    playerNodes_.Clear();
+    peers_.Clear();
 }
 
 void P2PMultiplayer::CreatePlayerNode(Connection* connection)
 {
-    if (playerNodes_[connection]) {
+    if (peers_[connection]) {
         return;
     }
 
     if (GetSubsystem<Network>()->GetClientConnections().Size() != 0 && !GetSubsystem<Network>()->P2PIsHostSystem()) {
         return;
     }
-    // Then create a controllable object for that client
-//    Node* newObject = CreateControllableObject();
-//    serverObjects_[newConnection] = newObject;
-
-    // Finally send the object's node ID using a remote event
-//    VariantMap remoteEventData;
-//    remoteEventData[P_ID] = newObject->GetID();
-//    newConnection->SendRemoteEvent(E_CLIENTOBJECTID, true, remoteEventData);
-    auto* cache = GetSubsystem<ResourceCache>();
 
-    // Create the scene node & visual representation. This will be a replicated object
-    Node* ballNode = scene_->CreateChild();
-    ballNode->AddTag("Player");
-    ballNode->SetVar("GUID", connection->GetGUID());
-    ballNode->SetPosition(Vector3(0, 10, 0));
-    ballNode->SetScale(0.5f);
-    auto* ballObject = ballNode->CreateComponent<StaticModel>();
-    ballObject->SetModel(cache->GetResource<Model>("Models/Sphere.mdl"));
-    ballObject->SetMaterial(cache->GetResource<Material>("Materials/StoneSmall.xml"));
-
-    auto* titleText = ballNode->CreateComponent<Text3D>(REPLICATED);
-    titleText->SetText(connection->GetGUID());
-    titleText->SetFaceCameraMode(FaceCameraMode::FC_LOOKAT_XYZ);
-    titleText->SetFont(cache->GetResource<Font>("Fonts/BlueHighway.sdf"), 24);
-
-    // Create the physics components
-    auto* body = ballNode->CreateComponent<RigidBody>();
-    body->SetMass(1.0f);
-    body->SetFriction(1.0f);
-    // In addition to friction, use motion damping so that the ball can not accelerate limitlessly
-    body->SetLinearDamping(0.5f);
-    body->SetAngularDamping(0.5f);
-    //body->SetLinearVelocity(Vector3(0.1, 1, 0.1));
-    auto* shape = ballNode->CreateComponent<CollisionShape>();
-    shape->SetSphere(1.0f);
-
-    // Create a random colored point light at the ball so that can see better where is going
-    auto* light = ballNode->CreateComponent<Light>();
-    light->SetRange(3.0f);
-    light->SetColor(Color(0.5f + ((unsigned)Rand() & 1u) * 0.5f, 0.5f + ((unsigned)Rand() & 1u) * 0.5f, 0.5f + ((unsigned)Rand() & 1u) * 0.5f));
-    playerNodes_[connection] = ballNode;
+    peers_[connection] = new Peer(context_);
+    peers_[connection]->SetScene(scene_);
+    peers_[connection]->Create(connection);
 }
 
 void P2PMultiplayer::DestroyPlayerNode(Connection* connection)
 {
-    if (playerNodes_[connection]) {
-        playerNodes_[connection]->Remove();
-        playerNodes_.Erase(connection);
+    if (peers_[connection]) {
+        peers_[connection]->DestroyNode();
+        peers_.Erase(connection);
     }
 }

+ 3 - 2
Source/Samples/54_P2PMultiplayer/P2PMultiplayer.h

@@ -23,6 +23,7 @@
 #pragma once
 
 #include "Sample.h"
+#include "Peer.h"
 
 namespace Urho3D
 {
@@ -92,7 +93,6 @@ private:
     Text* CreateLabel(const String& text, IntVector2 pos);
 //    /// Start server
     void HandleUpdate(StringHash eventType, VariantMap& eventData);
-    void HandlePhysicsPrestep(StringHash eventType, VariantMap& eventData);
 
     void HandleStartP2PSession(StringHash eventType, VariantMap& eventData);
     void HandleJoinP2PSession(StringHash eventType, VariantMap& eventData);
@@ -125,8 +125,9 @@ private:
     SharedPtr<Text> roleTitle_;
     SharedPtr<Text> myGuid_;
     SharedPtr<Text> hostGuid_;
-    HashMap<Connection*, WeakPtr<Node>> playerNodes_;
     String message_;
     SharedPtr<HttpRequest> httpRequest_;
     bool _allReady;
+
+    HashMap<Connection*, SharedPtr<Peer>> peers_;
 };

+ 171 - 0
Source/Samples/54_P2PMultiplayer/Peer.cpp

@@ -0,0 +1,171 @@
+//
+// Copyright (c) 2008-2018 the Urho3D project.
+//
+// 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 <Urho3D/Input/Controls.h>
+#include <Urho3D/Scene/LogicComponent.h>
+#include <Urho3D/Network/Connection.h>
+#include <Urho3D/Core/Context.h>
+#include <Urho3D/IO/MemoryBuffer.h>
+#include <Urho3D/Physics/CollisionShape.h>
+#include <Urho3D/Physics/PhysicsEvents.h>
+#include <Urho3D/Physics/PhysicsWorld.h>
+#include <Urho3D/Physics/RigidBody.h>
+#include <Urho3D/Scene/Scene.h>
+#include <Urho3D/Scene/SceneEvents.h>
+#include <Urho3D/Graphics/Light.h>
+#include <Urho3D/Resource/ResourceCache.h>
+#include <Urho3D/Scene/Scene.h>
+#include <Urho3D/Graphics/Zone.h>
+#include <Urho3D/Graphics/Model.h>
+#include <Urho3D/Graphics/StaticModel.h>
+#include <Urho3D/UI/Text3D.h>
+#include <Urho3D/Graphics/Material.h>
+#include <Urho3D/UI/Font.h>
+#include <Urho3D/IO/Log.h>
+#include <Urho3D/Network/Network.h>
+
+#include "Peer.h"
+
+// Control bits we define
+static const unsigned CTRL_FORWARD = 1;
+static const unsigned CTRL_BACK = 2;
+static const unsigned CTRL_LEFT = 4;
+static const unsigned CTRL_RIGHT = 8;
+
+Peer::Peer(Context* context) :
+        Object(context)
+{
+    SubscribeToEvent(E_PHYSICSPRESTEP, URHO3D_HANDLER(Peer, HandlePhysicsPrestep));
+}
+
+Peer::~Peer()
+{
+    DestroyNode();
+}
+
+void Peer::RegisterObject(Context* context)
+{
+    context->RegisterFactory<Peer>();
+}
+
+void Peer::HandlePhysicsPrestep(StringHash eventType, VariantMap& eventData)
+{
+    // Only allow the host to update the player movements
+    if (!GetSubsystem<Network>()->P2PIsHostSystem()) {
+        return;
+    }
+
+    if (connection_) {
+        controls_ = connection_->GetControls();
+    }
+
+    const float MOVE_TORQUE = 3.0f;
+
+    if (!node_) {
+        return;
+    }
+
+    Quaternion rotation(0.0f, controls_.yaw_, 0.0f);
+    RigidBody* body = node_->GetComponent<RigidBody>();
+    // Movement torque is applied before each simulation step, which happen at 60 FPS. This makes the simulation
+    // independent from rendering framerate. We could also apply forces (which would enable in-air control),
+    // but want to emphasize that it's a ball which should only control its motion by rolling along the ground
+    if (controls_.buttons_ & CTRL_FORWARD) {
+        body->ApplyTorque(rotation * Vector3::RIGHT * MOVE_TORQUE);
+    }
+    if (controls_.buttons_ & CTRL_BACK) {
+        body->ApplyTorque(rotation * Vector3::LEFT * MOVE_TORQUE);
+    }
+    if (controls_.buttons_ & CTRL_LEFT) {
+        body->ApplyTorque(rotation * Vector3::FORWARD * MOVE_TORQUE);
+    }
+    if (controls_.buttons_ & CTRL_RIGHT) {
+        body->ApplyTorque(rotation * Vector3::BACK * MOVE_TORQUE);
+    }
+
+    Text3D* text = node_->GetComponent<Text3D>();
+    if (text) {
+        text->SetText(connection_->GetGUID() + " [" + String(connection_->GetLastPing()) + "]");
+    }
+}
+
+void Peer::SetScene(Scene* scene)
+{
+    scene_ = scene;
+}
+
+void Peer::Create(Connection* connection)
+{
+    connection_ = connection;
+
+    auto* cache = GetSubsystem<ResourceCache>();
+
+    // Create the scene node & visual representation. This will be a replicated object
+    node_ = scene_->CreateChild();
+    node_->AddTag("Player");
+    node_->SetVar("GUID", connection->GetGUID());
+    node_->SetPosition(Vector3(0, 10, 0));
+    node_->SetScale(0.5f);
+    auto* ballObject = node_->CreateComponent<StaticModel>();
+    ballObject->SetModel(cache->GetResource<Model>("Models/Sphere.mdl"));
+    ballObject->SetMaterial(cache->GetResource<Material>("Materials/StoneSmall.xml"));
+
+    auto* titleText = node_->CreateComponent<Text3D>(REPLICATED);
+    titleText->SetText(connection->GetGUID());
+    titleText->SetFaceCameraMode(FaceCameraMode::FC_LOOKAT_XYZ);
+    titleText->SetFont(cache->GetResource<Font>("Fonts/BlueHighway.sdf"), 24);
+
+    // Create the physics components
+    auto* body = node_->CreateComponent<RigidBody>();
+    body->SetMass(1.0f);
+    body->SetFriction(1.0f);
+    // In addition to friction, use motion damping so that the ball can not accelerate limitlessly
+    body->SetLinearDamping(0.5f);
+    body->SetAngularDamping(0.5f);
+    //body->SetLinearVelocity(Vector3(0.1, 1, 0.1));
+    auto* shape = node_->CreateComponent<CollisionShape>();
+    shape->SetSphere(1.0f);
+
+    // Create a random colored point light at the ball so that can see better where is going
+    auto* light = node_->CreateComponent<Light>();
+    light->SetRange(3.0f);
+    light->SetColor(Color(0.5f + ((unsigned)Rand() & 1u) * 0.5f, 0.5f + ((unsigned)Rand() & 1u) * 0.5f, 0.5f + ((unsigned)Rand() & 1u) * 0.5f));
+
+    //node_->SetScale(1.0f);
+}
+
+void Peer::SetNode(Node* node)
+{
+    node_ = node;
+}
+
+void Peer::SetConnection(Connection* connection)
+{
+    connection_ = connection;
+}
+
+void Peer::DestroyNode()
+{
+    if (node_) {
+        node_->Remove();
+    }
+}

+ 54 - 0
Source/Samples/54_P2PMultiplayer/Peer.h

@@ -0,0 +1,54 @@
+//
+// Created by arnislielturks on 18.6.11.
+//
+
+#pragma once
+
+#include <Urho3D/Input/Controls.h>
+#include <Urho3D/Scene/LogicComponent.h>
+#include <Urho3D/Network/Connection.h>
+#include <Urho3D/Core/Context.h>
+#include <Urho3D/Scene/Scene.h>
+
+using namespace Urho3D;
+
+class Peer: public Object {
+
+    URHO3D_OBJECT(Peer, Object);
+
+public:
+    /// Construct.
+    explicit Peer(Context* context);
+
+    ~Peer();
+
+    /// Register object factory and attributes.
+    static void RegisterObject(Context* context);
+
+    /// Handle physics world update. Called by LogicComponent base class.
+    void HandlePhysicsPrestep(StringHash eventType, VariantMap& eventData);
+
+    void Create(Connection* connection);
+
+    void SetScene(Scene* scene);
+
+    void SetConnection(Connection* connection);
+
+    void SetNode(Node* node);
+
+    const Node* GetNode() const { return node_; };
+
+    void DestroyNode();
+
+private:
+    /// Movement controls. Assigned by the main program each physics update step.
+    Controls controls_;
+
+    SharedPtr<Node> node_;
+
+    WeakPtr<Connection> connection_;
+
+    WeakPtr<Scene> scene_;
+};
+
+

+ 14 - 3
Source/Urho3D/Network/Connection.cpp

@@ -97,8 +97,7 @@ void Connection::SendMessage(int msgID, bool reliable, bool inOrder, const Vecto
     SendMessage(msgID, reliable, inOrder, msg.GetData(), msg.GetSize(), contentID);
 }
 
-void Connection::SendMessage(int msgID, bool reliable, bool inOrder, const unsigned char* data, unsigned numBytes,
-    unsigned contentID)
+void Connection::SendMessage(int msgID, bool reliable, bool inOrder, const unsigned char* data, unsigned numBytes, unsigned contentID)
 {
     /* Make sure not to use SLikeNet(RakNet) internal message ID's
      and since RakNet uses 1 byte message ID's, they cannot exceed 255 limit */
@@ -113,7 +112,7 @@ void Connection::SendMessage(int msgID, bool reliable, bool inOrder, const unsig
         URHO3D_LOGERROR("Null pointer supplied for network message data");
         return;
     }
-    
+
     VectorBuffer buffer;
     buffer.WriteUByte((unsigned char)msgID);
     buffer.Write(data, numBytes);
@@ -908,6 +907,8 @@ void Connection::ProcessIdentity(int msgID, MemoryBuffer& msg)
         return;
     }
 
+    URHO3D_LOGERROR("USER IDENTITY");
+
     identity_ = msg.ReadVariantMap();
 
     using namespace ClientIdentity;
@@ -1624,4 +1625,14 @@ String Connection::GetGUID()
     return address_->rakNetGuid.ToString();
 }
 
+int Connection::GetLastPing()
+{
+    return peer_->GetLastPing(*address_);
+}
+
+int Connection::GetAveragePing()
+{
+    return peer_->GetAveragePing(*address_);
+}
+
 }

+ 3 - 0
Source/Urho3D/Network/Connection.h

@@ -212,6 +212,9 @@ public:
     /// Return bytes received per second.
     float GetBytesInPerSec() const;
 
+    int GetLastPing();
+    int GetAveragePing();
+
     /// Return bytes sent per second.
     float GetBytesOutPerSec() const;
 

+ 13 - 21
Source/Urho3D/Network/Network.cpp

@@ -861,7 +861,6 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
     else if (packetID == ID_REMOTE_CONNECTION_LOST || packetID == ID_REMOTE_DISCONNECTION_NOTIFICATION)
     {
         //TODO find out who's really sending out this message
-        URHO3D_LOGWARNING("ID_REMOTE_CONNECTION_LOST");
         packetHandled = true;
     }
     else if (packetID == ID_ALREADY_CONNECTED)
@@ -902,6 +901,16 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
                 rakPeer_->Send(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->guid, false);
 
                 //TODO send out our identity
+//                {
+//                    VectorBuffer msg;
+//                    msg.WriteVariantMap(serverConnection_->GetIdentity());
+//
+//                    VectorBuffer buffer;
+//                    buffer.WriteUByte((unsigned char)MSG_IDENTITY);
+//                    buffer.Write(msg.GetData(), msg.GetSize());
+//                    rakPeer_->Send((const char *) buffer.GetData(), (int) buffer.GetSize(), HIGH_PRIORITY, RELIABLE_ORDERED, (char) 0, packet->guid, false);
+//                }
+
             }
         }
         packetHandled = true;
@@ -1311,8 +1320,9 @@ void Network::OnServerConnected(const SLNet::AddressOrGUID& address)
 
 void Network::OnServerDisconnected()
 {
-    // TODO dont destroy server connection when one of the peers disconnects
-    return;
+    if (networkMode_ == PEER_TO_PEER) {
+        return;
+    }
     // Differentiate between failed connection, and disconnection
     bool failedConnect = serverConnection_ && serverConnection_->IsConnectPending();
     serverConnection_.Reset();
@@ -1353,8 +1363,6 @@ bool Network::P2PStartSession(Scene* scene, const VariantMap& identity)
 
     UnsubscribeFromEvent(E_NATMASTERCONNECTIONSUCCEEDED);
     SubscribeToEvent(E_NATMASTERCONNECTIONSUCCEEDED, URHO3D_HANDLER(Network, HandleNATStartP2PSession));
-//    SetSimulatedLatency(500);
-//    SetSimulatedPacketLoss(0.3);
     scene_ = scene;
     identity_ = identity;
     return true;
@@ -1364,7 +1372,6 @@ bool Network::P2PStartSession(Scene* scene, const VariantMap& identity)
 void Network::HandleNATStartP2PSession(StringHash eventType, VariantMap& eventData)
 {
     UnsubscribeFromEvent(E_NATMASTERCONNECTIONSUCCEEDED);
-    URHO3D_LOGINFO("HandleNATStartP2PSession");
     isServer_ = false;
     if (!serverConnection_) {
         serverConnection_ = new Connection(context_, false, rakPeer_->GetMyGUID(), rakPeer_);
@@ -1415,8 +1422,6 @@ void Network::P2PJoinSession(String guid, Scene* scene, const VariantMap& identi
 void Network::HandleNATJoinP2PSession(StringHash eventType, VariantMap& eventData)
 {
     UnsubscribeFromEvent(E_NATMASTERCONNECTIONSUCCEEDED);
-//    SetSimulatedLatency(Random(100.0f));
-//    SetSimulatedPacketLoss(0.3);
     P2PSetReady(false);
     if (!serverConnection_) {
         serverConnection_ = new Connection(context_, false, rakPeer_->GetMyBoundAddress(), rakPeer_);
@@ -1564,19 +1569,6 @@ const NetworkMode  Network::GetMode() const
     return networkMode_;
 }
 
-void Network::DisplayPingTimes()
-{
-    if (clientConnections_.Size() > 0) {
-        URHO3D_LOGINFO("-------- PING TIMES --------");
-        for (auto it = clientConnections_.Begin(); it != clientConnections_.End(); ++it) {
-            SLNet::AddressOrGUID address = (*it).second_->GetAddressOrGUID();
-            int ping = rakPeer_->GetLastPing(address);
-            URHO3D_LOGINFO((*it).second_->ToString() + " : " + String(ping));
-        }
-        URHO3D_LOGINFO("----------------------------");
-    }
-}
-
 void RegisterNetworkLibrary(Context* context)
 {
     NetworkPriority::RegisterObject(context);

+ 0 - 2
Source/Urho3D/Network/Network.h

@@ -168,8 +168,6 @@ public:
     /// Get current network mode
     const NetworkMode  GetMode() const;
 
-    void DisplayPingTimes();
-
 private:
     /// Handle begin frame event.
     void HandleBeginFrame(StringHash eventType, VariantMap& eventData);