Prechádzať zdrojové kódy

lobby started, message handling between client/server fixed, additional status messages added to sample

Arnis Lielturks 7 rokov pred
rodič
commit
c7d0abf8d0

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

@@ -36,6 +36,7 @@
 #include <Urho3D/Network/Network.h>
 #include <Urho3D/Network/NetworkEvents.h>
 #include <Urho3D/Network/HttpRequest.h>
+#include <Urho3D/Network/Protocol.h>
 #include <Urho3D/Physics/CollisionShape.h>
 #include <Urho3D/Physics/PhysicsEvents.h>
 #include <Urho3D/Physics/PhysicsWorld.h>
@@ -63,18 +64,12 @@
 URHO3D_DEFINE_APPLICATION_MAIN(P2PMultiplayer)
 
 P2PMultiplayer::P2PMultiplayer(Context* context) :
-    Sample(context)
+    Sample(context),
+    gameState_(GameState::IN_MENU)
 {
     Peer::RegisterObject(context);
 }
 
-// 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;
-
-
 void P2PMultiplayer::Start()
 {
     // Execute base class startup
@@ -126,10 +121,15 @@ void P2PMultiplayer::CreateUI()
     marginTop += 40;
     hostGuid_ = CreateLabel("HOST GUID:", IntVector2(20, marginTop));
 
-    String information = "R - Reset host (if you are the host, \nthis role will be passed to other peers";
+    statusMessage_ = CreateLabel("Status: Started", IntVector2(20, -20));
+    statusMessage_->SetAlignment(HA_LEFT, VA_BOTTOM);
+
+    String information = "R - Reset host, if you are the host, \nthis role will be passed to other peers";
     information += "\nE - Disconnect";
     information += "\nT - Toggle ready state";
     information += "\nWASD - move around";
+    information += "\nH - Toggle mouse visible/hidden";
+
     info_ = CreateLabel(information, IntVector2(0, 50));
     info_->SetHorizontalAlignment(HA_RIGHT);
 
@@ -149,6 +149,10 @@ void P2PMultiplayer::SubscribeToEvents()
     SubscribeToEvent(E_P2PALLREADYCHANGED, URHO3D_HANDLER(P2PMultiplayer, HandleAllReadyChanged));
     SubscribeToEvent(E_P2PNEWHOST, URHO3D_HANDLER(P2PMultiplayer, HandleNewHost));
     SubscribeToEvent(E_NETWORKBANNED, URHO3D_HANDLER(P2PMultiplayer, HandleBanned));
+    SubscribeToEvent(E_CLIENTIDENTITY, URHO3D_HANDLER(P2PMultiplayer, HandleClientIdentity));
+
+    GetSubsystem<Network>()->RegisterRemoteEvent("GameStart");
+    SubscribeToEvent("GameStart", URHO3D_HANDLER(P2PMultiplayer, HandleGameState));
 }
 
 void P2PMultiplayer::HandleStartP2PSession(StringHash eventType, VariantMap& eventData)
@@ -158,9 +162,11 @@ void P2PMultiplayer::HandleStartP2PSession(StringHash eventType, VariantMap& eve
     VariantMap identity;
     identity["Name"] = nickname_->GetText();
     GetSubsystem<Network>()->StartSession(scene_, identity);
+    statusMessage_->SetText("Status: Starting P2P session");
     httpRequest_ = GetSubsystem<Network>()->MakeHttpRequest("http://frameskippers.com:82/?guid=" + GetSubsystem<Network>()->GetGUID());
 
     SubscribeToEvent(E_P2PSESSIONSTARTED, URHO3D_HANDLER(P2PMultiplayer, HandleSessionStarted));
+    SubscribeToEvent(E_P2PSESSIONJOINED, URHO3D_HANDLER(P2PMultiplayer, HandleSessionJoined));
 }
 
 void P2PMultiplayer::HandleJoinP2PSession(StringHash eventType, VariantMap& eventData)
@@ -173,12 +179,25 @@ void P2PMultiplayer::HandleJoinP2PSession(StringHash eventType, VariantMap& even
     GetSubsystem<Network>()->JoinSession(guid_->GetText(), scene_, identity);
 //    GetSubsystem<Network>()->SetSimulatedLatency(Random(10.0f));
 //    GetSubsystem<Network>()->SetSimulatedLatency(10 + Random(100));
+
+    statusMessage_->SetText("Status: Joining " + guid_->GetText() + " P2P session");
 }
 
 void P2PMultiplayer::HandleSessionStarted(StringHash eventType, VariantMap& eventData)
 {
     UnsubscribeFromEvent(E_P2PSESSIONSTARTED);
-    CreatePlayerNode(GetSubsystem<Network>()->GetServerConnection());
+//    CreatePlayerNode(GetSubsystem<Network>()->GetServerConnection());
+
+    statusMessage_->SetText("Status: P2P Session started");
+
+    gameState_ = GameState::IN_LOBBY;
+}
+
+void P2PMultiplayer::HandleSessionJoined(StringHash eventType, VariantMap& eventData)
+{
+    statusMessage_->SetText("Status: joined P2P Session");
+
+    gameState_ = GameState::IN_LOBBY;
 }
 
 void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
@@ -199,12 +218,29 @@ void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
         GetSubsystem<Input>()->SetMouseVisible(true);
         GetSubsystem<Input>()->SetMouseGrabbed(false);
         GetSubsystem<Input>()->SetMouseMode(MouseMode::MM_FREE);
+
+        statusMessage_->SetText("Status: Disconnected");
+    }
+
+    if (input->GetKeyPress(KEY_H)) {
+        if (input->IsMouseVisible()) {
+            input->SetMouseVisible(false);
+            input->SetMouseGrabbed(true);
+            input->SetMouseMode(MouseMode::MM_WRAP);
+        } else {
+            input->SetMouseVisible(true);
+            input->SetMouseGrabbed(false);
+            input->SetMouseMode(MouseMode::MM_FREE);
+        }
     }
 
     if (input->GetKeyPress(KEY_T)) {
         GetSubsystem<Network>()->SetReady(!GetSubsystem<Network>()->GetReady());
+        statusMessage_->SetText("Status: Ready state changed");
+
     }
-    if (GetSubsystem<Network>()->IsHostSystem() && _allReady) {
+    if (GetSubsystem<Network>()->IsHostSystem() && input->GetKeyPress(KEY_N)) {
+        InitPlayers();
     }
 
     // Mouse sensitivity as degrees per pixel
@@ -233,11 +269,23 @@ void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
     }
 
     if (timer_.GetMSec(false) > 1000) {
+
+
+        //TODO fix this
+        if (GetSubsystem<Network>()->GetServerConnection()) {
+            auto clients = GetSubsystem<Network>()->GetClientConnections();
+            for (auto it = clients.Begin(); it != clients.End(); ++it) {
+                VectorBuffer msg;
+                msg.WriteVariantMap(GetSubsystem<Network>()->GetServerConnection()->GetIdentity());
+                (*it)->SendMessage(MSG_IDENTITY, true, true, msg);
+            }
+        }
+
+        UpdatePlayerList();
         if (GetSubsystem<Network>()->GetClientConnections().Size() != peers_.Size() - 1) {
             UpdateClientObjects();
         }
 
-
         timer_.Reset();
         clientCount_->SetText("Connections: " + String(GetSubsystem<Network>()->GetParticipantCount()));
         myGuid_->SetText("My GUID: " + GetSubsystem<Network>()->GetGUID());
@@ -279,28 +327,22 @@ void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
         }
     }
 
-    auto serverConnection = GetSubsystem<Network>()->GetServerConnection();
-    if (serverConnection) {
-        if (peers_[serverConnection] && peers_[serverConnection]->GetNode()) {
-            GetSubsystem<Input>()->SetMouseVisible(false);
-            GetSubsystem<Input>()->SetMouseGrabbed(true);
-//            GetSubsystem<Input>()->SetMouseMode(MouseMode::MM_WRAP);
-
-            const float CAMERA_DISTANCE = 4.0f;
+    if (gameState_ == IN_GAME) {
+        auto serverConnection = GetSubsystem<Network>()->GetServerConnection();
+        if (serverConnection) {
+            if (peers_[serverConnection] && peers_[serverConnection]->GetNode()) {
+                const float CAMERA_DISTANCE = 4.0f;
 
-            // Move camera some distance away from the ball
-            cameraNode_->SetPosition(peers_[serverConnection]->GetNode()->GetPosition() + cameraNode_->GetRotation() * Vector3::BACK * CAMERA_DISTANCE);
-        } else {
-            UpdateClientObjects();
-            GetSubsystem<Input>()->SetMouseVisible(true);
-            GetSubsystem<Input>()->SetMouseGrabbed(false);
-//            GetSubsystem<Input>()->SetMouseMode(MouseMode::MM_FREE);
+                // Move camera some distance away from the ball
+                cameraNode_->SetPosition(peers_[serverConnection]->GetNode()->GetPosition() + cameraNode_->GetRotation() * Vector3::BACK * CAMERA_DISTANCE);
+            } else {
+                UpdateClientObjects();
+            }
         }
     }
 }
 
-void P2PMultiplayer::Init()
-{
+void P2PMultiplayer::Init() {
     GetSubsystem<Network>()->SetMode(NetworkMode::PEER_TO_PEER);
     GetSubsystem<Network>()->SetNATServerInfo("frameskippers.com", 61111);
     GetSubsystem<Network>()->SetUpdateFps(30);
@@ -435,9 +477,11 @@ void P2PMultiplayer::HandleClientConnected(StringHash eventType, VariantMap& eve
     auto* newConnection = static_cast<Connection*>(eventData[P_CONNECTION].GetPtr());
     newConnection->SetScene(scene_);
 
-    CreatePlayerNode(newConnection);
+    //CreatePlayerNode(newConnection);
 
-    UpdateClientObjects();
+    //UpdateClientObjects();
+
+    statusMessage_->SetText("Status: Client connected");
 }
 
 void P2PMultiplayer::HandleClientDisconnected(StringHash eventType, VariantMap& eventData)
@@ -449,6 +493,8 @@ void P2PMultiplayer::HandleClientDisconnected(StringHash eventType, VariantMap&
     DestroyPlayerNode(connection);
 
     UpdateClientObjects();
+
+    statusMessage_->SetText("Status: Client discconnected");
 }
 
 void P2PMultiplayer::UpdateClientObjects()
@@ -484,6 +530,10 @@ void P2PMultiplayer::HandleAllReadyChanged(StringHash eventType, VariantMap& eve
 {
     using namespace P2PAllReadyChanged;
     _allReady = eventData[P_READY].GetBool();
+
+    if (_allReady) {
+        statusMessage_->SetText("Status: All players are ready");
+    }
 }
 
 void P2PMultiplayer::CreatePlayerNode(Connection* connection)
@@ -492,10 +542,6 @@ void P2PMultiplayer::CreatePlayerNode(Connection* connection)
         return;
     }
 
-    if (GetSubsystem<Network>()->GetClientConnections().Size() != 0 && !GetSubsystem<Network>()->IsHostSystem()) {
-        return;
-    }
-
     peers_[connection] = new Peer(context_);
     peers_[connection]->SetScene(scene_);
     peers_[connection]->Create(connection);
@@ -515,6 +561,7 @@ void P2PMultiplayer::HandleNewHost(StringHash eventType, VariantMap& eventData)
     URHO3D_LOGINFOF("Host changed %s, %i => %s", eventData[P_ADDRESS].GetString().CString(), eventData[P_PORT].GetInt(), eventData[P_GUID].GetString().CString());
     SetRandomSeed(Time::GetSystemTime());
 
+    statusMessage_->SetText("Status: New host elected: " + eventData[P_GUID].GetString());
 //    if (!GetSubsystem<Network>()->IsHostSystem()) {
 //        // Non-hosts should clear the previous state
 //        peers_.Clear();
@@ -532,4 +579,85 @@ void P2PMultiplayer::HandleBanned(StringHash eventType, VariantMap& eventData)
 
     using namespace NetworkBanned;
     URHO3D_LOGWARNING("We have been banned, reason: " + eventData[P_REASON].GetString());
+
+    statusMessage_->SetText("Status: You are banned");
+}
+
+void P2PMultiplayer::HandleClientIdentity(StringHash eventType, VariantMap& eventData)
+{
+    using namespace ClientIdentity;
+    Connection* connection = static_cast<Connection*>(eventData[P_CONNECTION].GetPtr());
+    statusMessage_->SetText("Status: Client " + connection->GetGUID() + " => " + connection->GetIdentity()["Name"].GetString());
+}
+
+void P2PMultiplayer::InitPlayers()
+{
+    if (!_allReady) {
+        statusMessage_->SetText("Status: Can't start, not all players are ready!");
+        return;
+    }
+    auto clients = GetSubsystem<Network>()->GetClientConnections();
+    for (auto it = clients.Begin(); it != clients.End(); ++it) {
+        CreatePlayerNode((*it));
+    }
+
+    CreatePlayerNode(GetSubsystem<Network>()->GetServerConnection());
+
+    statusMessage_->SetText("Status: Initializing all players");
+
+    gameState_ = IN_GAME;
+    VariantMap data = GetEventDataMap();
+    data["GameState"] = gameState_;
+    GetSubsystem<Network>()->BroadcastRemoteEvent("GameStart", false, data);
+}
+
+void P2PMultiplayer::HandleGameState(StringHash eventType, VariantMap& eventData)
+{
+    if (eventType == "GameStart") {
+        gameState_ = (GameState) eventData["GameState"].GetUInt();
+        statusMessage_->SetText("Status: Game started!");
+    }
+}
+
+void P2PMultiplayer::UpdatePlayerList()
+{
+    if (!GetSubsystem<Network>()->GetServerConnection()) {
+        return;
+    }
+    for (auto it = playerList_.Begin(); it != playerList_.End(); ++it) {
+        if ((*it)) {
+            (*it)->Remove();
+        }
+    }
+    playerList_.Clear();
+
+    int margin = 0;
+    SharedPtr<Text> me(CreateLabel("", IntVector2(0, margin)));
+    me->SetAlignment(HA_RIGHT, VA_BOTTOM);
+    String ready = "READY";
+    if (!GetSubsystem<Network>()->GetServerConnection()->GetReady()) {
+        ready = "NOT READY";
+        me->SetColor(Color::YELLOW);
+    } else {
+        me->SetColor(Color::GREEN);
+    }
+    me->SetText(GetSubsystem<Network>()->GetServerConnection()->GetIdentity()["Name"].GetString() + " [" + ready + "]");
+
+    playerList_.Push(me);
+
+    auto clients = GetSubsystem<Network>()->GetClientConnections();
+    for (auto it = clients.Begin(); it != clients.End(); ++it) {
+        margin -= 20;
+        ready = "READY";
+        SharedPtr<Text> peer(CreateLabel("", IntVector2(0, margin)));
+        if (!(*it)->GetReady()) {
+            ready = "NOT READY";
+            peer->SetColor(Color::YELLOW);
+        } else {
+            peer->SetColor(Color::GREEN);
+        }
+        peer->SetAlignment(HA_RIGHT, VA_BOTTOM);
+        peer->SetText((*it)->GetIdentity()["Name"].GetString() + " [" + ready + "]");
+        playerList_.Push(peer);
+    }
 }

+ 19 - 0
Source/Samples/54_P2PMultiplayer/P2PMultiplayer.h

@@ -39,6 +39,12 @@ class HttpRequest;
 
 const int SERVER_PORT = 54654;
 
+enum GameState {
+    IN_MENU,
+    IN_LOBBY,
+    IN_GAME
+};
+
 /// Chat example
 /// This sample demonstrates:
 ///     - Starting up a network server or connecting to it
@@ -100,6 +106,9 @@ private:
     void HandleAllReadyChanged(StringHash eventType, VariantMap& eventData);
 
     void HandleSessionStarted(StringHash eventType, VariantMap& eventData);
+    void HandleSessionJoined(StringHash eventType, VariantMap& eventData);
+
+    void HandleGameState(StringHash eventType, VariantMap& eventData);
 
     void UpdateClientObjects();
 
@@ -107,9 +116,15 @@ private:
 
     void HandleBanned(StringHash eventType, VariantMap& eventData);
 
+    void HandleClientIdentity(StringHash eventType, VariantMap& eventData);
+
     void CreatePlayerNode(Connection* connection);
     void DestroyPlayerNode(Connection* connection);
 
+    void InitPlayers();
+
+    void UpdatePlayerList();
+
     Timer timer_;
     /// Start P2P Session
     SharedPtr<Button> startSession_;
@@ -122,10 +137,14 @@ private:
     SharedPtr<Text> myGuid_;
     SharedPtr<Text> hostGuid_;
     SharedPtr<Text> info_;
+    SharedPtr<Text> statusMessage_;
     String message_;
     SharedPtr<HttpRequest> httpRequest_;
     bool _allReady{};
     Controls controls_;
+    List<SharedPtr<Text>> playerList_;
 
     HashMap<Connection*, SharedPtr<Peer>> peers_;
+
+    GameState gameState_;
 };

+ 12 - 6
Source/Samples/54_P2PMultiplayer/Peer.cpp

@@ -45,12 +45,6 @@
 
 #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)
 {
@@ -195,4 +189,16 @@ void Peer::DestroyNode()
     if (node_) {
         node_->Remove();
     }
+}
+
+void Peer::SetIdentity(VariantMap identity)
+{
+//    identity_ = identity;
+//    if (node_) {
+//        for (auto it = identity.Begin(); it != identity.End(); ++it) {
+//            if (node_->SetVar((*it).first_), (*it).second_) {
+//
+//            }
+//        }
+//    }
 }

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

@@ -12,6 +12,12 @@
 
 using namespace Urho3D;
 
+// 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;
+
 class Peer: public Object {
 
     URHO3D_OBJECT(Peer, Object);
@@ -40,6 +46,8 @@ public:
 
     void DestroyNode();
 
+    void SetIdentity(VariantMap identity);
+
 private:
     /// Movement controls. Assigned by the main program each physics update step.
     Controls controls_;
@@ -51,6 +59,8 @@ private:
     WeakPtr<Scene> scene_;
 
     Timer updateTimer_;
+
+    VariantMap  identity_;
 };
 
 

+ 13 - 12
Source/Urho3D/Network/Connection.cpp

@@ -81,6 +81,8 @@ Connection::Connection(Context* context, bool isClient, const SLNet::AddressOrGU
     sceneState_.connection_ = this;
     port_ = address.systemAddress.GetPort();
     SetAddressOrGUID(address);
+
+    URHO3D_LOGINFO("Creating connection " + String(address_->ToString()));
 }
 
 Connection::~Connection()
@@ -426,7 +428,7 @@ bool Connection::ProcessMessage(int msgID, MemoryBuffer& msg)
     switch (msgID)
     {
     case MSG_IDENTITY:
-        ProcessIdentity(msgID, msg);
+        processed = ProcessIdentity(msgID, msg);
         break;
 
     case MSG_CONTROLS:
@@ -482,7 +484,7 @@ bool Connection::ProcessMessage(int msgID, MemoryBuffer& msg)
     return processed;
 }
 
-void Connection::Ban(String reason)
+void Connection::Ban(const String& reason)
 {
     if (peer_ && !ipAddress_.Empty() && IsClient())
     {
@@ -490,7 +492,7 @@ void Connection::Ban(String reason)
     }
 }
 
-void Connection::SetIP(String ipAddress)
+void Connection::SetIP(const String& ipAddress)
 {
     ipAddress_ = ipAddress;
 }
@@ -904,17 +906,16 @@ void Connection::ProcessPackageDownload(int msgID, MemoryBuffer& msg)
     }
 }
 
-void Connection::ProcessIdentity(int msgID, MemoryBuffer& msg)
+bool Connection::ProcessIdentity(int msgID, MemoryBuffer& msg)
 {
-    URHO3D_LOGERROR("------------ Receiving client identity!");
     if (!IsClient())
     {
-        URHO3D_LOGWARNING("Received unexpected Identity message from server");
-        return;
+        if (GetSubsystem<Network>()->GetMode() == SERVER_CLIENT) {
+            URHO3D_LOGWARNING("Received unexpected Identity message from server " + GetGUID());
+        }
+        return false;
     }
 
-    URHO3D_LOGERROR("USER IDENTITY");
-
     identity_ = msg.ReadVariantMap();
 
     using namespace ClientIdentity;
@@ -924,18 +925,18 @@ void Connection::ProcessIdentity(int msgID, MemoryBuffer& msg)
     eventData[P_ALLOW] = true;
     SendEvent(E_CLIENTIDENTITY, eventData);
 
-    URHO3D_LOGERROR("Name: " + identity_["Name"].GetString());
-
     // If connection was denied as a response to the identity event, disconnect now
     if (!eventData[P_ALLOW].GetBool())
         Disconnect();
+
+    return true;
 }
 
 void Connection::ProcessControls(int msgID, MemoryBuffer& msg)
 {
     if (!IsClient())
     {
-        URHO3D_LOGWARNING("Received unexpected Controls message from server");
+        URHO3D_LOGWARNING("Received unexpected Controls message from server " + GetGUID());
         return;
     }
 

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

@@ -156,7 +156,7 @@ public:
     /// Process a message from the server or client. Called by Network.
     bool ProcessMessage(int msgID, MemoryBuffer& msg);
     /// Ban this connections IP address.
-    void Ban(String reason);
+    void Ban(const String& reason);
     /// Return the RakNet address/guid.
     const SLNet::AddressOrGUID& GetAddressOrGUID() const { return *address_; }
 
@@ -248,7 +248,7 @@ public:
     const bool GetReady() const { return ready_; }
 
     /// Set the IP address for this connection
-    void SetIP(String ipAddress);
+    void SetIP(const String& ipAddress);
     /// Retrieve IP address for this connection
     const String GetIP() const { return ipAddress_; }
 
@@ -264,7 +264,7 @@ private:
     /// Process package download related messages. Called by Network.
     void ProcessPackageDownload(int msgID, MemoryBuffer& msg);
     /// Process an Identity message from the client. Called by Network.
-    void ProcessIdentity(int msgID, MemoryBuffer& msg);
+    bool ProcessIdentity(int msgID, MemoryBuffer& msg);
     /// Process a Controls message from the client. Called by Network.
     void ProcessControls(int msgID, MemoryBuffer& msg);
     /// Process a SceneLoaded message from the client. Called by Network.

+ 78 - 25
Source/Urho3D/Network/Network.cpp

@@ -356,19 +356,41 @@ void Network::HandleMessage(const SLNet::AddressOrGUID& source, int packetID, in
     }
 }
 
+void Network::HandleMessageClient(const SLNet::AddressOrGUID& source, int packetID, int msgID, const char* data, size_t numBytes)
+{
+    // Only process messages from known sources
+    Connection* connection = GetClientConnection(source);
+    if (connection)
+    {
+        MemoryBuffer msg(data, (unsigned)numBytes);
+        if (connection->ProcessMessage((int)msgID, msg))
+            return;
+
+        // If message was not handled internally, forward as an event
+        using namespace NetworkMessage;
+
+        VariantMap& eventData = GetEventDataMap();
+        eventData[P_CONNECTION] = connection;
+        eventData[P_MESSAGEID] = (int)msgID;
+        eventData[P_DATA].SetBuffer(msg.GetData(), msg.GetSize());
+        connection->SendEvent(E_NETWORKMESSAGE, eventData);
+    }
+    else {
+        URHO3D_LOGWARNING("Discarding message from unknown MessageConnection " + String(source.ToString()) + " => " + source.rakNetGuid.ToString());
+    }
+}
+
 void Network::NewConnectionEstablished(const SLNet::AddressOrGUID& connection, const char* address)
 {
 
-    URHO3D_LOGINFO("NewConnectionEstablished: " + String(address));
+    URHO3D_LOGINFO("NewConnectionEstablished: " + String(connection.ToString()));
     ReadyStatusChanged();
     if (networkMode_ == PEER_TO_PEER && clientConnections_[connection]) {
-//        URHO3D_LOGWARNINGF("Client already in the client list.", connection.rakNetGuid.ToString());
         //TODO proper scene state management
         clientConnections_[connection]->SetSceneLoaded(true);
         return;
     }
 
-//    URHO3D_LOGINFOF("NewConnectionEstablished ---------------------------", connection.rakNetGuid.ToString());
     // Create a new client connection corresponding to this MessageConnection
     SharedPtr<Connection> newConnection(new Connection(context_, true, connection, rakPeer_));
     newConnection->ConfigureNetworkSimulator(simulatedLatency_, simulatedPacketLoss_);
@@ -385,6 +407,19 @@ void Network::NewConnectionEstablished(const SLNet::AddressOrGUID& connection, c
     VariantMap& eventData = GetEventDataMap();
     eventData[P_CONNECTION] = newConnection;
     newConnection->SendEvent(E_CLIENTCONNECTED, eventData);
+
+//    if (GetSubsystem<Network>()->GetServerConnection()) {
+//        auto clients = GetSubsystem<Network>()->GetClientConnections();
+//        for (auto it = clients.Begin(); it != clients.End(); ++it) {
+//        if (serverConnection_) {
+//            VectorBuffer msg;
+//            msg.WriteVariantMap(serverConnection_->GetIdentity());
+//            newConnection->SendMessage(MSG_IDENTITY, true, true, msg);
+//        }
+//        }
+//    }
+
+
 }
 
 void Network::ClientDisconnected(const SLNet::AddressOrGUID& connection)
@@ -638,7 +673,7 @@ void Network::BroadcastMessage(int msgID, bool reliable, bool inOrder, const uns
     msgData.WriteUByte((unsigned char)msgID);
     msgData.Write(data, numBytes);
 
-    if (isServer_) {
+    if (isServer_ || networkMode_ == PEER_TO_PEER) {
         rakPeer_->Send((const char *) msgData.GetData(), (int) msgData.GetSize(), HIGH_PRIORITY, RELIABLE, (char) 0, SLNet::UNASSIGNED_RAKNET_GUID, true);
     }
     else
@@ -765,7 +800,7 @@ void Network::BanAddress(const String& address)
     rakPeer_->AddToBanList(address.CString(), 0);
 }
 
-void Network::BanConnection(Connection* connection, String reason)
+void Network::BanConnection(Connection* connection, const String& reason)
 {
     using namespace NetworkBanned;
     VariantMap data = GetEventDataMap();
@@ -789,6 +824,15 @@ Connection* Network::GetConnection(const SLNet::AddressOrGUID& connection) const
     }
 }
 
+Connection* Network::GetClientConnection(const SLNet::AddressOrGUID& connection) const
+{
+    HashMap<SLNet::AddressOrGUID, SharedPtr<Connection> >::ConstIterator i = clientConnections_.Find(connection);
+    if (i != clientConnections_.End())
+        return i->second_;
+
+    return nullptr;
+}
+
 Connection* Network::GetServerConnection() const
 {
     return serverConnection_;
@@ -842,7 +886,7 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
     if (packetID == ID_NEW_INCOMING_CONNECTION)
     {
         URHO3D_LOGINFOF("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.", packet->systemAddress.ToString(true), packet->guid.ToString());
-        if (isServer)
+        if (isServer || networkMode_ == PEER_TO_PEER)
         {
             NewConnectionEstablished(packet->guid, packet->systemAddress.ToString(false));
         }
@@ -860,15 +904,19 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
             bsIn.Read(count);
             SLNet::SystemAddress remoteAddress;
             SLNet::RakNetGUID remoteGuid;
+            URHO3D_LOGINFO("AAAA GUID " + String(packet->guid.ToString()));
             NewConnectionEstablished(packet->guid, packet->systemAddress.ToString(false));
-            for (unsigned int i=0; i < count; i++)
-            {
-                bsIn.Read(remoteAddress);
-                bsIn.Read(remoteGuid);
-                if (!remoteAddress.EqualsExcludingPort(*natPunchServerAddress_)) {
-                    NewConnectionEstablished(remoteGuid, remoteAddress.ToString(false));
-                }
-            }
+
+//            for (unsigned int i=0; i < count; i++)
+//            {
+//                bsIn.Read(remoteAddress);
+//                bsIn.Read(remoteGuid);
+//                if (!remoteAddress.EqualsExcludingPort(*natPunchServerAddress_)) {
+//                    URHO3D_LOGINFO("BBBB GUID " + String(remoteGuid.ToString()));
+//                    NewConnectionEstablished(remoteGuid, remoteAddress.ToString(false));
+//
+//                }
+//            }
         } else {
             NewConnectionEstablished(packet->guid, packet->systemAddress.ToString(false));
         }
@@ -1105,7 +1153,7 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
                 URHO3D_LOGINFOF("ID_FCM2_NEW_HOST: System %s is host, GUID=%s", packet->systemAddress.ToString(true), packet->guid.ToString());
             }
 
-            // Send the identity map now
+//            // Send the identity map now to our new host
             VectorBuffer msg;
             msg.WriteVariantMap(serverConnection_->GetIdentity());
             serverConnection_->SendMessage(MSG_IDENTITY, true, true, msg);
@@ -1194,7 +1242,7 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
             bool processed = serverConnection_->ProcessMessage(packetID, buffer);
             if (!processed)
             {
-                HandleMessage(packet->guid, 0, packetID, (const char*)(packet->data + dataStart), packet->length - dataStart);
+                HandleMessageClient(packet->guid, 0, packetID, (const char*)(packet->data + dataStart), packet->length - dataStart);
             }
         }
         packetHandled = true;
@@ -1463,6 +1511,10 @@ void Network::HandleNATJoinSession(StringHash eventType, VariantMap& eventData)
 
     URHO3D_LOGINFO("Attempting to Join P2P Session : " + String(remoteGUID_->ToString()));
     natPunchthroughServerClient_->OpenNAT(*remoteGUID_, *natPunchServerAddress_);
+
+    ReadyStatusChanged();
+
+    SendEvent(E_P2PSESSIONJOINED);
 }
 
 int Network::GetParticipantCount()
@@ -1533,15 +1585,16 @@ void Network::ReadyStatusChanged()
     for (unsigned int i = 0; i < participantList.Size(); i++) {
         if (participantList[i] != rakPeer_->GetMyGUID()) {
             int ready = readyEvent_->GetReadyStatus(0, participantList[i]);
-            Connection* connection = GetConnection(participantList[i]);
-            if (ready != SLNet::RES_ALL_READY && ready != SLNet::RES_READY) {
-                if (connection) {
-                    connection->SetReady(false);
-                }
-            }
-            else {
-                if (connection) {
-                    connection->SetReady(true);
+            Connection* connection = GetClientConnection(participantList[i]);
+            if (connection) {
+                if (ready != SLNet::RES_ALL_READY && ready != SLNet::RES_READY) {
+                    if (connection) {
+                        connection->SetReady(false);
+                    }
+                } else {
+                    if (connection) {
+                        connection->SetReady(true);
+                    }
                 }
             }
         }

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

@@ -53,6 +53,8 @@ public:
 
     /// Handle an inbound message.
     void HandleMessage(const SLNet::AddressOrGUID& source, int packetID, int msgID, const char* data, size_t numBytes);
+    /// Handle an inbound message.
+    void HandleMessageClient(const SLNet::AddressOrGUID& source, int packetID, int msgID, const char* data, size_t numBytes);
     /// Handle a new client connection.
     void NewConnectionEstablished(const SLNet::AddressOrGUID& connection, const char* address = nullptr);
     /// Handle a client disconnection.
@@ -134,10 +136,10 @@ public:
     void SendPackageToClients(Scene* scene, PackageFile* package);
     /// Perform an HTTP request to the specified URL. Empty verb defaults to a GET request. Return a request object which can be used to read the response data.
     SharedPtr<HttpRequest> MakeHttpRequest(const String& url, const String& verb = String::EMPTY, const Vector<String>& headers = Vector<String>(), const String& postData = String::EMPTY);
-    /// Ban specific IP addresses.
+    /// Ban specific IP addresses. Also supports wildcard addresses like 192.68.1.*
     void BanAddress(const String& address);
     /// Ban specific connection
-    void BanConnection(Connection* connection, String reason);
+    void BanConnection(Connection* connection, const String& reason);
     /// Return network update FPS.
     int GetUpdateFps() const { return updateFps_; }
 
@@ -149,6 +151,8 @@ public:
 
     /// Return a client or server connection by kNet MessageConnection, or null if none exist.
     Connection* GetConnection(const SLNet::AddressOrGUID& connection) const;
+    /// Return a client or server connection by kNet MessageConnection, or null if none exist.
+    Connection* GetClientConnection(const SLNet::AddressOrGUID& connection) const;
     /// Return the connection to the server. Null if not connected.
     Connection* GetServerConnection() const;
     /// Return all client connections.

+ 5 - 0
Source/Urho3D/Network/NetworkEvents.h

@@ -160,6 +160,11 @@ URHO3D_EVENT(E_P2PSESSIONSTARTED, P2PSessionStarted)
 {
 }
 
+/// P2P session join succesfull
+URHO3D_EVENT(E_P2PSESSIONJOINED, P2PSessionJoined)
+{
+}
+
 /// When host system is elected
 URHO3D_EVENT(E_P2PNEWHOST, P2PNewHost)
 {