소스 검색

player list added, network server connection guid fixed, client control sending fixed

Arnis Lielturkss 7 년 전
부모
커밋
b69c76069b

+ 124 - 67
Source/Samples/54_P2PMultiplayer/P2PMultiplayer.cpp

@@ -92,6 +92,8 @@ void P2PMultiplayer::Start()
     Sample::InitMouseMode(MM_FREE);
 
     Init();
+
+    CreatePlayerListWindow();
 }
 
 void P2PMultiplayer::CreateUI()
@@ -116,20 +118,15 @@ void P2PMultiplayer::CreateUI()
 
 	marginTop += 80;
     clientCount_ = CreateLabel("Connections: 0", IntVector2(20, marginTop));
-    marginTop += 40;
-    myGuid_ = CreateLabel("My GUID: ", IntVector2(20, marginTop));
-    marginTop += 40;
-    hostGuid_ = CreateLabel("HOST GUID:", IntVector2(20, marginTop));
 
     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";
+    String information = "R - Reset host";
     information += "\nE - Disconnect";
-    information += "\nT - Toggle ready state";
+    information += "\nTAB - Show player list";
     information += "\nWASD - move around";
     information += "\nH - Toggle mouse visible/hidden";
-    information += "\nN - Start game with other peers\n(requires that all peers are ready)";
 
     info_ = CreateLabel(information, IntVector2(0, 50));
     info_->SetHorizontalAlignment(HA_RIGHT);
@@ -212,6 +209,9 @@ void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
     if (input->GetKeyPress(KEY_R)) {
         GetSubsystem<Network>()->ResetHost();
     }
+    if (input->GetKeyPress(KEY_TAB)) {
+        playerList_->SetVisible(!playerList_->IsVisible());
+    }
     if (input->GetKeyPress(KEY_E)) {
         GetSubsystem<Network>()->Disconnect(1000);
         peers_.Clear();
@@ -221,6 +221,8 @@ void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
         GetSubsystem<Input>()->SetMouseMode(MouseMode::MM_FREE);
 
         statusMessage_->SetText("Status: Disconnected");
+
+        UpdatePlayerList();
     }
 
     if (input->GetKeyPress(KEY_H)) {
@@ -235,18 +237,6 @@ void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
         }
     }
 
-    if (input->GetKeyPress(KEY_T)) {
-        GetSubsystem<Network>()->SetReady(!GetSubsystem<Network>()->GetReady());
-    }
-    if (GetSubsystem<Network>()->IsHostSystem() && input->GetKeyPress(KEY_N)) {
-        if (_allReady) {
-            startGame_ = true;
-            startCountdown_.Reset();
-        } else {
-            statusMessage_->SetText("Status: Can't start game, not all players are ready!");
-        }
-    }
-
     if (startGame_) {
         int timeRemaining = 5 - (int)(startCountdown_.GetMSec(false) / 1000);
         statusMessage_->SetText("Status: Countdown till start " + String(timeRemaining));
@@ -281,7 +271,7 @@ void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
         GetSubsystem<Network>()->GetServerConnection()->SetControls(controls);
     }
 
-    if (timer_.GetMSec(false) > 5000) {
+    if (timer_.GetMSec(false) > 1000) {
         timer_.Reset();
 
         //TODO fix this
@@ -294,22 +284,11 @@ void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
             }
         }
 
-        UpdatePlayerList();
         if (GetSubsystem<Network>()->GetClientConnections().Size() != peers_.Size() - 1) {
             UpdateClientObjects();
         }
 
         clientCount_->SetText("Connections: " + String(GetSubsystem<Network>()->GetParticipantCount()));
-        myGuid_->SetText("My GUID: " + GetSubsystem<Network>()->GetGUID());
-        hostGuid_->SetText("Host GUID: " + GetSubsystem<Network>()->GetHostAddress());
-
-        if (GetSubsystem<Network>()->GetGUID() == GetSubsystem<Network>()->GetHostAddress()) {
-            hostGuid_->SetColor(Color::RED);
-            myGuid_->SetColor(Color::RED);
-        } else {
-            myGuid_->SetColor(Color::GREEN);
-            hostGuid_->SetColor(Color::GREEN);
-        }
 
         if (httpRequest_.Null()) {
             httpRequest_ = GetSubsystem<Network>()->MakeHttpRequest("http://frameskippers.com:82/guid.txt");
@@ -494,6 +473,8 @@ void P2PMultiplayer::HandleClientConnected(StringHash eventType, VariantMap& eve
     //UpdateClientObjects();
 
     statusMessage_->SetText("Status: Client connected");
+
+    UpdatePlayerList();
 }
 
 void P2PMultiplayer::HandleClientDisconnected(StringHash eventType, VariantMap& eventData)
@@ -507,6 +488,8 @@ void P2PMultiplayer::HandleClientDisconnected(StringHash eventType, VariantMap&
     UpdateClientObjects();
 
     statusMessage_->SetText("Status: Client discconnected");
+
+    UpdatePlayerList();
 }
 
 void P2PMultiplayer::UpdateClientObjects()
@@ -544,13 +527,16 @@ void P2PMultiplayer::HandleAllReadyChanged(StringHash eventType, VariantMap& eve
     _allReady = eventData[P_READY].GetBool();
 
     if (_allReady) {
-        statusMessage_->SetText("Status: All players are ready");
+        startGame_ = true;
+        startCountdown_.Reset();
     } else {
         if (startGame_) {
             startGame_ = false;
             statusMessage_->SetText("Status: Countdown stopped! Not all players are ready!");
         }
     }
+
+    UpdatePlayerList();
 }
 
 void P2PMultiplayer::CreatePlayerNode(Connection* connection)
@@ -583,6 +569,8 @@ void P2PMultiplayer::HandleNewHost(StringHash eventType, VariantMap& eventData)
 //        // Non-hosts should clear the previous state
 //        peers_.Clear();
 //    }
+
+    UpdatePlayerList();
 }
 
 void P2PMultiplayer::HandleBanned(StringHash eventType, VariantMap& eventData)
@@ -606,10 +594,14 @@ void P2PMultiplayer::HandleClientIdentity(StringHash eventType, VariantMap& even
     Connection* connection = static_cast<Connection*>(eventData[P_CONNECTION].GetPtr());
     URHO3D_LOGINFO("Client identity: Client " + connection->GetGUID() + " => " + connection->GetIdentity()["Name"].GetString());
     //statusMessage_->SetText("Status: Client " + connection->GetGUID() + " => " + connection->GetIdentity()["Name"].GetString());
+    UpdatePlayerList();
 }
 
 void P2PMultiplayer::InitPlayers()
 {
+    if (!GetSubsystem<Network>()->IsHostSystem()) {
+        return;
+    }
     if (!_allReady) {
         statusMessage_->SetText("Status: Can't start, not all players are ready!");
         return;
@@ -619,7 +611,9 @@ void P2PMultiplayer::InitPlayers()
         CreatePlayerNode((*it));
     }
 
-    CreatePlayerNode(GetSubsystem<Network>()->GetServerConnection());
+    if (GetSubsystem<Network>()->GetServerConnection()) {
+        CreatePlayerNode(GetSubsystem<Network>()->GetServerConnection());
+    }
 
     statusMessage_->SetText("Status: Initializing all players");
 
@@ -627,6 +621,7 @@ void P2PMultiplayer::InitPlayers()
     VariantMap data = GetEventDataMap();
     data["GameState"] = gameState_;
     GetSubsystem<Network>()->BroadcastRemoteEvent("GameStart", false, data);
+    playerList_->SetVisible(false);
 }
 
 void P2PMultiplayer::HandleGameState(StringHash eventType, VariantMap& eventData)
@@ -634,48 +629,110 @@ void P2PMultiplayer::HandleGameState(StringHash eventType, VariantMap& eventData
     if (eventType == "GameStart") {
         gameState_ = (GameState) eventData["GameState"].GetUInt();
         statusMessage_->SetText("Status: Game started!");
+        playerList_->SetVisible(false);
     }
 }
 
 void P2PMultiplayer::UpdatePlayerList()
 {
-    if (!GetSubsystem<Network>()->GetServerConnection()) {
-        return;
-    }
-    for (auto it = playerList_.Begin(); it != playerList_.End(); ++it) {
+    auto* cache = GetSubsystem<ResourceCache>();
+    auto* font = cache->GetResource<Font>("Fonts/Anonymous Pro.ttf");
+    auto* label = GetSubsystem<UI>()->GetRoot()->CreateChild<Text>();
+
+    playerList_->RemoveAllChildren();
+
+    Text* playerName = playerList_->CreateChild<Text>();
+    playerName->SetPosition(IntVector2(10, 10));
+    playerName->SetAlignment(HA_LEFT, VA_TOP);
+    playerName->SetText("Nickname");
+    playerName->SetFont(font, 12);
+    playerName->SetFontSize(16);
+    playerName->SetTextEffect(TextEffect::TE_SHADOW);
+    playerName->SetColor(Color::GRAY);
+
+    Text* playerGuid = playerList_->CreateChild<Text>();
+    playerGuid->SetPosition(IntVector2(0, 10));
+    playerGuid->SetAlignment(HA_CENTER, VA_TOP);
+    playerGuid->SetText("GUID");
+    playerGuid->SetFont(font, 12);
+    playerGuid->SetFontSize(16);
+    playerGuid->SetTextEffect(TextEffect::TE_SHADOW);
+    playerGuid->SetColor(Color::GRAY);
+
+    Text* playerStatus = playerList_->CreateChild<Text>();
+    playerStatus->SetPosition(IntVector2(-10, 10));
+    playerStatus->SetAlignment(HA_RIGHT, VA_TOP);
+    playerStatus->SetText("Ready status");
+    playerStatus->SetFont(font, 12);
+    playerStatus->SetFontSize(16);
+    playerStatus->SetTextEffect(TextEffect::TE_SHADOW);
+    playerStatus->SetColor(Color::GRAY);
+
+    int marginTop = 40;
+
+    auto connections = GetSubsystem<Network>()->GetClientConnections();
+    connections.Push(SharedPtr<Connection>(GetSubsystem<Network>()->GetServerConnection()));
+    for (auto it = connections.Begin(); it != connections.End(); ++it) {
         if ((*it)) {
-            (*it)->Remove();
-        }
-    }
-    playerList_.Clear();
-
-    int margin = -10;
-    SharedPtr<Text> me(CreateLabel("", IntVector2(-10, 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 + "]");
+            Text* playerName = playerList_->CreateChild<Text>();
+            playerName->SetPosition(IntVector2(20, marginTop));
+            playerName->SetAlignment(HA_LEFT, VA_TOP);
+            playerName->SetText((*it)->GetIdentity()["Name"].GetString());
+            playerName->SetFont(font, 12);
+            playerName->SetTextEffect(TextEffect::TE_SHADOW);
+
+            if ((*it)->GetGUID() == GetSubsystem<Network>()->GetHostAddress()) {
+                playerName->SetText(playerName->GetText() + " [HOST]");
+            }
 
-    playerList_.Push(me);
+            Text* playerGuid = playerList_->CreateChild<Text>();
+            playerGuid->SetPosition(IntVector2(0, marginTop));
+            playerGuid->SetAlignment(HA_CENTER, VA_TOP);
+            playerGuid->SetText((*it)->GetGUID());
+            playerGuid->SetFont(font, 12);
+            playerGuid->SetTextEffect(TextEffect::TE_SHADOW);
+
+            if ((*it) == GetSubsystem<Network>()->GetServerConnection()) {
+                playerName->SetColor(Color::GREEN);
+
+                Button* readyState = playerList_->CreateChild<Button>();
+                readyState->SetPosition(IntVector2(-20, marginTop - 5));
+                readyState->SetAlignment(HA_RIGHT, VA_TOP);
+                readyState->SetStyleAuto();
+                readyState->SetWidth(100);
+                readyState->SetHeight(30);
+
+                SubscribeToEvent(readyState, "Released", [&](StringHash eventType, VariantMap& eventData) {
+                    GetSubsystem<Network>()->SetReady(!GetSubsystem<Network>()->GetReady());
+                });
+
+                Text* playerStatus = readyState->CreateChild<Text>();
+                playerStatus->SetAlignment(HA_CENTER, VA_CENTER);
+                playerStatus->SetText((*it)->GetReady() ? "Ready" : "Not ready");
+                playerStatus->SetColor((*it)->GetReady() ? Color::GREEN : Color::RED);
+                playerStatus->SetFont(font, 12);
+                playerStatus->SetTextEffect(TextEffect::TE_SHADOW);
 
-    auto clients = GetSubsystem<Network>()->GetClientConnections();
-    for (auto it = clients.Begin(); it != clients.End(); ++it) {
-        margin -= 20;
-        ready = "READY";
-        SharedPtr<Text> peer(CreateLabel("", IntVector2(-10, margin)));
-        if (!(*it)->GetReady()) {
-            ready = "NOT READY";
-            peer->SetColor(Color::YELLOW);
-        } else {
-            peer->SetColor(Color::GREEN);
+            }
+            else {
+                Text* playerStatus = playerList_->CreateChild<Text>();
+                playerStatus->SetPosition(IntVector2(-20, marginTop));
+                playerStatus->SetAlignment(HA_RIGHT, VA_TOP);
+                playerStatus->SetText((*it)->GetReady() ? "Ready" : "Not ready");
+                playerStatus->SetColor((*it)->GetReady() ? Color::GREEN : Color::RED);
+                playerStatus->SetFont(font, 12);
+                playerStatus->SetTextEffect(TextEffect::TE_SHADOW);
+            }
+            marginTop += 25;
         }
-        peer->SetAlignment(HA_RIGHT, VA_BOTTOM);
-        peer->SetText((*it)->GetIdentity()["Name"].GetString() + " [" + ready + "]");
-        playerList_.Push(peer);
     }
+}
+
+void P2PMultiplayer::CreatePlayerListWindow()
+{
+    playerList_ = GetSubsystem<UI>()->GetRoot()->CreateChild<Window>();
+    playerList_->SetStyleAuto();
+    playerList_->SetAlignment(HA_CENTER, VA_CENTER);
+    playerList_->SetSize(IntVector2(GetSubsystem<Graphics>()->GetWidth() - 200, GetSubsystem<Graphics>()->GetHeight() - 400));
+    playerList_->BringToFront();
 }

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

@@ -24,6 +24,7 @@
 
 #include "Sample.h"
 #include "Peer.h"
+#include <Urho3D/UI/Window.h>
 
 namespace Urho3D
 {
@@ -84,6 +85,8 @@ private:
 
     void CreateScene();
 
+    void CreatePlayerListWindow();
+
     /// Set up viewport.
     void SetupViewport();
 
@@ -134,15 +137,13 @@ private:
     SharedPtr<LineEdit> nickname_;
 //    /// Found server list
 	SharedPtr<Text> clientCount_;
-    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_;
+    SharedPtr<Window> playerList_;
 
     HashMap<Connection*, SharedPtr<Peer>> peers_;
 

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

@@ -40,6 +40,8 @@ public:
 
     void SetConnection(Connection* connection);
 
+    const WeakPtr<Connection> GetConnection() const { return connection_; }
+
     void SetNode(Node* node);
 
     const Node* GetNode() const { return node_; };

+ 2 - 2
Source/Samples/Sample.inl

@@ -62,8 +62,8 @@ void Sample::Setup()
     engineParameters_[EP_FULL_SCREEN]  = false;
     engineParameters_[EP_HEADLESS]     = false;
     engineParameters_[EP_SOUND]        = false;
-    engineParameters_[EP_WINDOW_HEIGHT] = 480;
-    engineParameters_[EP_WINDOW_WIDTH] = 640;
+    engineParameters_[EP_WINDOW_HEIGHT] = 600;
+    engineParameters_[EP_WINDOW_WIDTH] = 800;
     engineParameters_[EP_LOG_LEVEL] = LOG_INFO;
     engineParameters_[EP_MONITOR] = 1;
 

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

@@ -1631,6 +1631,9 @@ void Connection::SetAddressOrGUID(const SLNet::AddressOrGUID& addr)
 
 String Connection::GetGUID()
 {
+    if (!IsClient()) {
+        return GetSubsystem<Network>()->GetGUID();
+    }
     return address_->rakNetGuid.ToString();
 }
 

+ 1 - 1
Source/Urho3D/Network/Network.cpp

@@ -1340,7 +1340,7 @@ void Network::PostUpdate(float timeStep)
 
         if (serverConnection_)
         {
-            if (networkMode_ == PEER_TO_PEER && !isServer_ && serverConnection_->GetGUID() != GetGUID()) {
+            if (networkMode_ == PEER_TO_PEER && !IsHostSystem()) {
                 // Send the client update
                 serverConnection_->SendClientUpdate();
                 serverConnection_->SendRemoteEvents();