Bläddra i källkod

initial attempt

Arnis Lielturks 7 år sedan
förälder
incheckning
51e145a03f

+ 3 - 3
Source/CMakeLists.txt

@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2008-2018 the Urho3D project.
+# Copyright (c) 2008-2018 the Urho3Dproject.
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal
@@ -142,12 +142,12 @@ if (URHO3D_CLANG_TOOLS)
 endif ()
 
 # Urho3D tools
-add_subdirectory (Tools)
+#add_subdirectory (Tools)
 
 # Urho3D samples
 add_subdirectory (Samples)
 
 # Urho3D extras
 if (URHO3D_EXTRAS)
-    add_subdirectory (Extras)
+#    add_subdirectory (Extras)
 endif ()

+ 37 - 0
Source/Samples/54_P2PMultiplayer/CMakeLists.txt

@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+if (NOT URHO3D_NETWORK)
+    return ()
+endif ()
+
+# Define target name
+set (TARGET_NAME 54_P2PMultiplayer)
+
+# Define source files
+define_source_files (EXTRA_H_FILES ${COMMON_SAMPLE_H_FILES})
+
+# Setup target with resource copying
+setup_main_executable ()
+
+# Setup test cases
+setup_test ()

+ 214 - 0
Source/Samples/54_P2PMultiplayer/P2PMultiplayer.cpp

@@ -0,0 +1,214 @@
+//
+// 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/Audio/Audio.h>
+#include <Urho3D/Audio/Sound.h>
+#include <Urho3D/Engine/Engine.h>
+#include <Urho3D/Graphics/Graphics.h>
+#include <Urho3D/Graphics/Zone.h>
+#include <Urho3D/Input/Input.h>
+#include <Urho3D/IO/IOEvents.h>
+#include <Urho3D/IO/Log.h>
+#include <Urho3D/IO/MemoryBuffer.h>
+#include <Urho3D/IO/VectorBuffer.h>
+#include <Urho3D/Network/Network.h>
+#include <Urho3D/Network/NetworkEvents.h>
+#include <Urho3D/Resource/ResourceCache.h>
+#include <Urho3D/Scene/Scene.h>
+#include <Urho3D/UI/Button.h>
+#include <Urho3D/UI/Font.h>
+#include <Urho3D/UI/LineEdit.h>
+#include <Urho3D/UI/Text.h>
+#include <Urho3D/UI/UI.h>
+#include <Urho3D/UI/UIEvents.h>
+#include <Urho3D/Core/CoreEvents.h>
+
+#include "P2PMultiplayer.h"
+
+#include <Urho3D/DebugNew.h>
+
+// Undefine Windows macro, as our Connection class has a function called SendMessage
+#ifdef SendMessage
+#undef SendMessage
+#endif
+
+URHO3D_DEFINE_APPLICATION_MAIN(P2PMultiplayer)
+
+P2PMultiplayer::P2PMultiplayer(Context* context) :
+    Sample(context)
+{
+}
+
+void P2PMultiplayer::Start()
+{
+    // Execute base class startup
+    Sample::Start();
+
+    // Enable OS cursor
+    GetSubsystem<Input>()->SetMouseVisible(true);
+
+    // Create the user interface
+    CreateUI();
+
+    // Subscribe to UI and network events
+    SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
+
+    Init();
+}
+
+void P2PMultiplayer::CreateUI()
+{
+    SetLogoVisible(false); // We need the full rendering window
+
+    auto* graphics = GetSubsystem<Graphics>();
+    UIElement* root = GetSubsystem<UI>()->GetRoot();
+    auto* cache = GetSubsystem<ResourceCache>();
+    auto* uiStyle = cache->GetResource<XMLFile>("UI/DefaultStyle.xml");
+    // Set style to the UI root so that elements will inherit it
+    root->SetDefaultStyle(uiStyle);
+//
+//    int marginTop = 20;
+//    CreateLabel("1. Start server", IntVector2(20, marginTop-20));
+//    startServer_ = CreateButton("Start server", 160, IntVector2(20, marginTop));
+//    stopServer_ = CreateButton("Stop server", 160, IntVector2(20, marginTop));
+//	stopServer_->SetVisible(false);
+//
+//    // Create client connection related fields
+//    marginTop += 80;
+//    CreateLabel("2. Discover LAN servers", IntVector2(20, marginTop-20));
+//    refreshServerList_ = CreateButton("Search...", 160, IntVector2(20, marginTop));
+//
+//	marginTop += 80;
+//	CreateLabel("Local servers:", IntVector2(20, marginTop - 20));
+//	serverList_ = CreateLabel("", IntVector2(20, marginTop));
+
+    // No viewports or scene is defined. However, the default zone's fog color controls the fill color
+    GetSubsystem<Renderer>()->GetDefaultZone()->SetFogColor(Color(0.0f, 0.0f, 0.1f));
+}
+
+void P2PMultiplayer::SubscribeToEvents()
+{
+    SubscribeToEvent(E_SERVERCONNECTED, URHO3D_HANDLER(P2PMultiplayer, HandleServerConnected));
+    SubscribeToEvent(E_UPDATE, URHO3D_HANDLER(P2PMultiplayer, HandleUpdate));
+//
+//    SubscribeToEvent(startServer_, "Released", URHO3D_HANDLER(LANDiscovery, HandleStartServer));
+//    SubscribeToEvent(stopServer_, "Released", URHO3D_HANDLER(LANDiscovery, HandleStopServer));
+//    SubscribeToEvent(refreshServerList_, "Released", URHO3D_HANDLER(LANDiscovery, HandleDoNetworkDiscovery));
+}
+
+void P2PMultiplayer::HandleServerConnected(StringHash eventType, VariantMap& eventData)
+{
+    URHO3D_LOGINFO("Start P2P Session");
+    GetSubsystem<Network>()->StartP2PSession();
+
+}
+
+void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
+{
+    if (timer_.GetMSec(false) > 2000) {
+        timer_.Reset();
+        URHO3D_LOGINFO("-----");
+        URHO3D_LOGINFO("Participats: " + String(GetSubsystem<Network>()->GetP2PParticipantCount()));
+        URHO3D_LOGINFO("P2PIsConnectedHost: " + String(GetSubsystem<Network>()->P2PIsConnectedHost()));
+        URHO3D_LOGINFO("P2PIsHostSystem: " + String(GetSubsystem<Network>()->P2PIsHostSystem()));
+        URHO3D_LOGINFO("P2PGetGUID: " + GetSubsystem<Network>()->P2PGetGUID());
+    }
+}
+
+void P2PMultiplayer::Init()
+{
+//    GetSubsystem<Network>()->SetNATServerInfo("frameskippers.com", 61111);
+    GetSubsystem<Network>()->Connect("frameskippers.com", 61111, nullptr);
+}
+
+//
+//Button* LANDiscovery::CreateButton(const String& text, int width, IntVector2 position)
+//{
+//    auto* cache = GetSubsystem<ResourceCache>();
+//    auto* font = cache->GetResource<Font>("Fonts/Anonymous Pro.ttf");
+//
+//    auto* button = GetSubsystem<UI>()->GetRoot()->CreateChild<Button>();
+//    button->SetStyleAuto();
+//    button->SetFixedWidth(width);
+//    button->SetFixedHeight(30);
+//    button->SetPosition(position);
+//
+//    auto* buttonText = button->CreateChild<Text>();
+//    buttonText->SetFont(font, 12);
+//    buttonText->SetAlignment(HA_CENTER, VA_CENTER);
+//    buttonText->SetText(text);
+//
+//    return button;
+//}
+//
+//Text* LANDiscovery::CreateLabel(const String& text, IntVector2 pos)
+//{
+//    auto* cache = GetSubsystem<ResourceCache>();
+//    // Create log element to view latest logs from the system
+//    auto* font = cache->GetResource<Font>("Fonts/Anonymous Pro.ttf");
+//    auto* label = GetSubsystem<UI>()->GetRoot()->CreateChild<Text>();
+//    label->SetFont(font, 12);
+//    label->SetColor(Color(0.0f, 1.0f, 0.0f));
+//    label->SetPosition(pos);
+//    label->SetText(text);
+//	return label;
+//}
+//
+//void LANDiscovery::HandleNetworkHostDiscovered(StringHash eventType, VariantMap& eventData)
+//{
+//	using namespace NetworkHostDiscovered;
+//	URHO3D_LOGINFO("Server discovered!");
+//	String text = serverList_->GetText();
+//	VariantMap data = eventData[P_BEACON].GetVariantMap();
+//	text += "\n" + data["Name"].GetString() + "(" + String(data["Players"].GetInt()) + ")" + eventData[P_ADDRESS].GetString() + ":" + String(eventData[P_PORT].GetInt());
+//	serverList_->SetText(text);
+//}
+//
+//void LANDiscovery::HandleStartServer(StringHash eventType, VariantMap& eventData)
+//{
+//	if (GetSubsystem<Network>()->StartServer(SERVER_PORT)) {
+//		VariantMap data;
+//		data["Name"] = "Test server";
+//		data["Players"] = 100;
+//		/// Set data which will be sent to all who requests LAN network discovery
+//		GetSubsystem<Network>()->SetDiscoveryBeacon(data);
+//		startServer_->SetVisible(false);
+//		stopServer_->SetVisible(true);
+//	}
+//}
+//
+//void LANDiscovery::HandleStopServer(StringHash eventType, VariantMap& eventData)
+//{
+//	GetSubsystem<Network>()->StopServer();
+//	startServer_->SetVisible(true);
+//	stopServer_->SetVisible(false);
+//}
+//
+//void LANDiscovery::HandleDoNetworkDiscovery(StringHash eventType, VariantMap& eventData)
+//{
+//	/// Pass in the port that should be checked
+//	GetSubsystem<Network>()->DiscoverHosts(SERVER_PORT);
+//	serverList_->SetText("");
+//}

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

@@ -0,0 +1,99 @@
+//
+// 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.
+//
+
+#pragma once
+
+#include "Sample.h"
+
+namespace Urho3D
+{
+
+class Button;
+class LineEdit;
+class Text;
+class UIElement;
+
+}
+
+const int SERVER_PORT = 54654;
+
+/// Chat example
+/// This sample demonstrates:
+///     - Starting up a network server or connecting to it
+///     - Implementing simple chat functionality with network messages
+class P2PMultiplayer : public Sample
+{
+    URHO3D_OBJECT(P2PMultiplayer, Sample);
+
+public:
+    /// Construct.
+    explicit P2PMultiplayer(Context* context);
+
+    /// Setup after engine initialization and before running the main loop.
+    void Start() override;
+
+protected:
+    /// Return XML patch instructions for screen joystick layout for a specific sample app, if any.
+    String GetScreenJoystickPatchString() const override { return
+        "<patch>"
+        "    <add sel=\"/element/element[./attribute[@name='Name' and @value='Button2']]\">"
+        "        <attribute name=\"Is Visible\" value=\"false\" />"
+        "    </add>"
+        "    <add sel=\"/element/element[./attribute[@name='Name' and @value='Hat0']]\">"
+        "        <attribute name=\"Is Visible\" value=\"false\" />"
+        "    </add>"
+        "</patch>";
+    }
+
+private:
+    /// Create the UI.
+    void CreateUI();
+    /// Subscribe to log message, UI and network events.
+    void SubscribeToEvents();
+
+    //
+    void Init();
+
+    /// Create a button to the button container.
+//    Button* CreateButton(const String& text, int width, IntVector2 position);
+//    /// Create label
+//    Text* CreateLabel(const String& text, IntVector2 pos);
+//
+//    /// Handle found LAN server
+    void HandleServerConnected(StringHash eventType, VariantMap& eventData);
+//    /// Start server
+    void HandleUpdate(StringHash eventType, VariantMap& eventData);
+
+    Timer timer_;
+//    /// Stop server
+//	void HandleStopServer(StringHash eventType, VariantMap& eventData);
+//	/// Start network discovery
+//	void HandleDoNetworkDiscovery(StringHash eventType, VariantMap& eventData);
+//    /// Start server
+//    SharedPtr<Button> startServer_;
+//    /// Stop server
+//    SharedPtr<Button> stopServer_;
+//    /// Redo LAN discovery
+//    SharedPtr<Button> refreshServerList_;
+//    /// Found server list
+//	SharedPtr<Text> serverList_;
+};

+ 7 - 6
Source/Samples/CMakeLists.txt

@@ -53,9 +53,10 @@ endmacro ()
 # Add samples
 file (GLOB_RECURSE DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} CMakeLists.txt)
 list (SORT DIRS)
-foreach (DIR ${DIRS})
-    get_filename_component (DIR ${DIR} PATH)
-    if (DIR)
-        add_sample_subdirectory (${DIR})
-    endif ()
-endforeach ()
+#foreach (DIR ${DIRS})
+#    get_filename_component (DIR ${DIR} PATH)
+#    if (DIR)
+#        add_sample_subdirectory (${DIR})
+#    endif ()
+#endforeach ()
+add_sample_subdirectory (54_P2PMultiplayer)

+ 8 - 2
Source/ThirdParty/SLikeNet/CMakeLists.txt

@@ -13,16 +13,22 @@
 # Define target name
 set (TARGET_NAME SLikeNet)
 
+# Disable unneeded modules
 add_definitions (-DRAKNET_ENABLE_STATIC -D_RAKNET_SUPPORT_NatTypeDetectionServer=0 -D_RAKNET_SUPPORT_UDPForwarder=0 -D_RAKNET_SUPPORT_TwoWayAuthentication=0)
 add_definitions (-D_RAKNET_SUPPORT_CloudClient=0 -D_RAKNET_SUPPORT_CloudServer=0 -D_RAKNET_SUPPORT_ConnectionGraph2=0 -D_RAKNET_SUPPORT_NatPunchthroughServer=0)
 add_definitions (-D_RAKNET_SUPPORT_RelayPlugin=0 -D_RAKNET_SUPPORT_LibVoice=0 -D_RAKNET_SUPPORT_DynDNS=0 -D_RAKNET_SUPPORT_HTTPConnection2=0 -D_RAKNET_SUPPORT_HTTPConnection=0)
 add_definitions (-D_RAKNET_SUPPORT_EmailSender=0 -D_RAKNET_SUPPORT_UDPProxyClient=0 -D_RAKNET_SUPPORT_UDPProxyCoordinator=0 -D_RAKNET_SUPPORT_TeamManager=0 -D_RAKNET_SUPPORT_TeamBalancer=0)
-add_definitions (-D_RAKNET_SUPPORT_NatTypeDetectionClient=0 -D_RAKNET_SUPPORT_FullyConnectedMesh2=0 -D_RAKNET_SUPPORT_ConnectionGraph2=0 -D_RAKNET_SUPPORT_FullyConnectedMesh=0 -D_RAKNET_SUPPORT_TelnetTransport=0)
-add_definitions (-D_RAKNET_SUPPORT_PacketLogger=0 -D_RAKNET_SUPPORT_DirectoryDeltaTransfer=0 -D_RAKNET_SUPPORT_FileOperations=0 -D_RAKNET_SUPPORT_UDPProxyServer=0)
+add_definitions (-D_RAKNET_SUPPORT_NatTypeDetectionClient=0 -D_RAKNET_SUPPORT_ConnectionGraph2=0 -D_RAKNET_SUPPORT_FullyConnectedMesh=0 -D_RAKNET_SUPPORT_TelnetTransport=0)
+add_definitions (-D_RAKNET_SUPPORT_DirectoryDeltaTransfer=0 -D_RAKNET_SUPPORT_FileOperations=0 -D_RAKNET_SUPPORT_UDPProxyServer=0)
 add_definitions (-D_RAKNET_SUPPORT_ConsoleServer=0 -D_RAKNET_SUPPORT_RakNetTransport=0 -D_RAKNET_SUPPORT_TCPInterface=0 -D_RAKNET_SUPPORT_LogCommandParser=0 -D_RAKNET_SUPPORT_RakNetCommandParser=0)
 add_definitions (-D_RAKNET_SUPPORT_Rackspace=0 -D_RAKNET_SUPPORT_PacketizedTCP=0 -D_RAKNET_SUPPORT_RPC4Plugin=0 -D_RAKNET_SUPPORT_Router2=0 -D_RAKNET_SUPPORT_ReplicaManager3=0)
 add_definitions (-D_RAKNET_SUPPORT_ReadyEvent=0 -D_RAKNET_SUPPORT_MessageFilter=0 -D_RAKNET_SUPPORT_FileListTransfer=0)
 
+# Enable the ones we actually need
+# P2P Multiplayer
+add_definitions (-D_RAKNET_SUPPORT_FullyConnectedMesh2=1)
+add_definitions (-D_RAKNET_SUPPORT_PacketLogger=1)
+
 if (URHO3D_LIB_TYPE STREQUAL SHARED)
     add_definitions(-D_RAKNET_DLL=1)
 endif ()

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

@@ -37,6 +37,7 @@ namespace SLNet
     struct Packet;
     class NatPunchthroughClient;
     class RakPeerInterface;
+    class FullyConnectedMesh2;
 }
 
 namespace Urho3D

+ 71 - 5
Source/Urho3D/Network/Network.cpp

@@ -42,6 +42,8 @@
 #include <SLikeNet/NatPunchthroughClient.h>
 #include <SLikeNet/peerinterface.h>
 #include <SLikeNet/statistics.h>
+#include <SLikeNet/FullyConnectedMesh2.h>
+#include <SLikeNet/DS_List.h>
 
 #ifdef SendMessage
 #undef SendMessage
@@ -203,10 +205,18 @@ Network::Network(Context* context) :
     isServer_(false),
     scene_(nullptr),
     natPunchServerAddress_(nullptr),
-    remoteGUID_(nullptr)
+    remoteGUID_(nullptr),
+    natPunchtroughAttempt_(false)
 {
     rakPeer_ = SLNet::RakPeerInterface::GetInstance();
     rakPeerClient_ = SLNet::RakPeerInterface::GetInstance();
+
+#if NETWORK_P2P
+    fullyConnectedMesh2_ = SLNet::FullyConnectedMesh2::GetInstance();
+    rakPeerClient_->AttachPlugin(fullyConnectedMesh2_);
+    fullyConnectedMesh2_->SetAutoparticipateConnections(true);
+#endif
+
     rakPeer_->SetTimeoutTime(SERVER_TIMEOUT_TIME, SLNet::UNASSIGNED_SYSTEM_ADDRESS);
     SetPassword("");
     SetDiscoveryBeacon(VariantMap());
@@ -287,6 +297,9 @@ Network::~Network()
 
     SLNet::RakPeerInterface::DestroyInstance(rakPeer_);
     SLNet::RakPeerInterface::DestroyInstance(rakPeerClient_);
+#if NETWORK_P2P
+    SLNet::FullyConnectedMesh2::DestroyInstance(fullyConnectedMesh2_);
+#endif
     rakPeer_ = nullptr;
     rakPeerClient_ = nullptr;
 }
@@ -492,6 +505,7 @@ void Network::StartNATClient()
 
 void Network::AttemptNATPunchtrough(const String& guid, Scene* scene, const VariantMap& identity)
 {
+    natPunchtroughAttempt_ = true;
     scene_ = scene;
     identity_ = identity;
     if (!remoteGUID_)
@@ -732,7 +746,7 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
         }
         packetHandled = true;
     }
-    else if (packetID == ID_CONNECTION_REQUEST_ACCEPTED) // We're a client, our connection as been accepted
+    else if (packetID == ID_CONNECTION_REQUEST_ACCEPTED) // We're a client, our connection has been accepted
     {
         if(natPunchServerAddress_ && packet->systemAddress == *natPunchServerAddress_) {
             URHO3D_LOGINFO("Succesfully connected to NAT punchtrough server! ");
@@ -797,7 +811,7 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
     {
         SLNet::SystemAddress remotePeer = packet->systemAddress;
         URHO3D_LOGINFO("NAT punchtrough succeeded! Remote peer: " + String(remotePeer.ToString()));
-        if (!isServer)
+        if (!isServer && natPunchtroughAttempt_)
         {
             using namespace NetworkNatPunchtroughSucceeded;
             VariantMap eventMap;
@@ -809,7 +823,7 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
         }
         packetHandled = true;
     }
-    else if (packetID == ID_NAT_PUNCHTHROUGH_FAILED)
+    else if (packetID == ID_NAT_PUNCHTHROUGH_FAILED || packetID == ID_NAT_TARGET_NOT_CONNECTED || packetID == ID_NAT_TARGET_UNRESPONSIVE || packetID == ID_NAT_CONNECTION_TO_TARGET_LOST)
     {
         URHO3D_LOGERROR("NAT punchtrough failed!");
         SLNet::SystemAddress remotePeer = packet->systemAddress;
@@ -863,7 +877,28 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
         }
         packetHandled = true;
     }
-
+#if NETWORK_P2P
+    else if (packetID == ID_FCM2_NEW_HOST)
+    {
+        URHO3D_LOGINFO("ID_FCM2_NEW_HOST");
+    }
+    else if (packetID == ID_FCM2_VERIFIED_JOIN_START)
+    {
+        URHO3D_LOGINFO("ID_FCM2_VERIFIED_JOIN_START");
+    }
+    else if (packetID == ID_FCM2_VERIFIED_JOIN_CAPABLE)
+    {
+        URHO3D_LOGINFO("ID_FCM2_VERIFIED_JOIN_CAPABLE");
+    }
+    else if (packetID == ID_FCM2_VERIFIED_JOIN_ACCEPTED)
+    {
+        URHO3D_LOGINFO("ID_FCM2_VERIFIED_JOIN_ACCEPTED");
+    }
+    else if (packetID == ID_FCM2_VERIFIED_JOIN_REJECTED)
+    {
+        URHO3D_LOGINFO("ID_FCM2_VERIFIED_JOIN_REJECTED");
+    }
+#endif
     // Urho3D messages
     if (packetID >= ID_USER_PACKET_ENUM)
     {
@@ -1029,6 +1064,37 @@ void Network::ConfigureNetworkSimulator()
         i->second_->ConfigureNetworkSimulator(simulatedLatency_, simulatedPacketLoss_);
 }
 
+bool Network::StartP2PSession()
+{
+    fullyConnectedMesh2_->ResetHostCalculation();
+    return true;
+}
+
+int Network::GetP2PParticipantCount()
+{
+    // First time calculated host. Add existing connections to ReplicaManager3
+    DataStructures::List<SLNet::RakNetGUID> participantList;
+    fullyConnectedMesh2_->GetParticipantList(participantList);
+    return participantList.Size();
+//    for (unsigned int i=0; i < participantList.Size(); i++) {
+//
+//    }
+}
+
+bool Network::P2PIsConnectedHost()
+{
+    return fullyConnectedMesh2_->IsConnectedHost();
+}
+
+bool Network::P2PIsHostSystem()
+{
+    return fullyConnectedMesh2_->IsHostSystem();
+}
+
+String Network::P2PGetGUID()
+{
+    return String(rakPeerClient_->GetGuidFromSystemAddress(SLNet::UNASSIGNED_SYSTEM_ADDRESS).ToString());
+}
 void RegisterNetworkLibrary(Context* context)
 {
     NetworkPriority::RegisterObject(context);

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

@@ -27,6 +27,8 @@
 #include "../IO/VectorBuffer.h"
 #include "../Network/Connection.h"
 
+#define NETWORK_P2P true
+
 namespace Urho3D
 {
 
@@ -66,6 +68,14 @@ public:
     void Disconnect(int waitMSec = 0);
     /// Start a server on a port using UDP protocol. Return true if successful.
     bool StartServer(unsigned short port);
+#if NETWORK_P2P
+    /// Start P2P session
+    bool StartP2PSession();
+    int GetP2PParticipantCount();
+    bool P2PIsConnectedHost();
+    bool P2PIsHostSystem();
+    String P2PGetGUID();
+#endif
     /// Stop the server.
     void StopServer();
     /// Start NAT punchtrough client to allow remote connections.
@@ -150,6 +160,10 @@ private:
     SLNet::RakPeerInterface* rakPeer_;
     /// SLikeNet peer instance for client connection.
     SLNet::RakPeerInterface* rakPeerClient_;
+#if NETWORK_P2P
+    /// P2P functionality
+    SLNet::FullyConnectedMesh2 *fullyConnectedMesh2_;
+#endif
     /// Client's server connection.
     SharedPtr<Connection> serverConnection_;
     /// Server's client connections.
@@ -190,6 +204,8 @@ private:
     SLNet::RakNetGUID* remoteGUID_;
     /// Local server GUID.
     String guid_;
+    /// Attempting NAT punchtrough
+    bool natPunchtroughAttempt_;
 };
 
 /// Register Network library objects.