NATPunchtrough.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #include <Urho3D/Audio/Audio.h>
  4. #include <Urho3D/Audio/Sound.h>
  5. #include <Urho3D/Engine/Engine.h>
  6. #include <Urho3D/Graphics/Zone.h>
  7. #include <Urho3D/Input/Input.h>
  8. #include <Urho3D/IO/Log.h>
  9. #include <Urho3D/IO/MemoryBuffer.h>
  10. #include <Urho3D/IO/VectorBuffer.h>
  11. #include <Urho3D/Network/Network.h>
  12. #include <Urho3D/Network/NetworkEvents.h>
  13. #include <Urho3D/Resource/ResourceCache.h>
  14. #include <Urho3D/UI/Button.h>
  15. #include <Urho3D/UI/Font.h>
  16. #include <Urho3D/UI/LineEdit.h>
  17. #include <Urho3D/UI/Text.h>
  18. #include <Urho3D/UI/UI.h>
  19. #include "NATPunchtrough.h"
  20. // Undefine Windows macro, as our Connection class has a function called SendMessage
  21. #ifdef SendMessage
  22. #undef SendMessage
  23. #endif
  24. URHO3D_DEFINE_APPLICATION_MAIN(NATPunchtrough)
  25. NATPunchtrough::NATPunchtrough(Context* context) :
  26. Sample(context)
  27. {
  28. }
  29. void NATPunchtrough::Start()
  30. {
  31. // Execute base class startup
  32. Sample::Start();
  33. // Enable OS cursor
  34. GetSubsystem<Input>()->SetMouseVisible(true);
  35. // Create the user interface
  36. CreateUI();
  37. // Subscribe to UI and network events
  38. SubscribeToEvents();
  39. // Set the mouse mode to use in the sample
  40. Sample::InitMouseMode(MM_FREE);
  41. }
  42. void NATPunchtrough::CreateUI()
  43. {
  44. SetLogoVisible(true); // We need the full rendering window
  45. UIElement* root = GetSubsystem<UI>()->GetRoot();
  46. auto* cache = GetSubsystem<ResourceCache>();
  47. auto* uiStyle = cache->GetResource<XMLFile>("UI/DefaultStyle.xml");
  48. // Set style to the UI root so that elements will inherit it
  49. root->SetDefaultStyle(uiStyle);
  50. auto* font = cache->GetResource<Font>("Fonts/Anonymous Pro.ttf");
  51. logHistoryText_ = root->CreateChild<Text>();
  52. logHistoryText_->SetFont(font, 12);
  53. logHistoryText_->SetPosition(20, -20);
  54. logHistoryText_->SetVerticalAlignment(VA_BOTTOM);
  55. logHistory_.Resize(20);
  56. // Create NAT server config fields
  57. int marginTop = 40;
  58. CreateLabel("1. Run NAT server somewhere, enter NAT server info and press 'Save NAT settings'", IntVector2(20, marginTop-20));
  59. natServerAddress_ = CreateLineEdit("127.0.0.1", 200, IntVector2(20, marginTop));
  60. natServerPort_ = CreateLineEdit("61111", 100, IntVector2(240, marginTop));
  61. saveNatSettingsButton_ = CreateButton("Save NAT settings", 160, IntVector2(360, marginTop));
  62. // Create server start button
  63. marginTop = 120;
  64. CreateLabel("2. Create server and give others your server GUID", IntVector2(20, marginTop-20));
  65. guid_ = CreateLineEdit("Your server GUID", 200, IntVector2(20, marginTop));
  66. startServerButton_ = CreateButton("Start server", 160, IntVector2(240, marginTop));
  67. // Create client connection related fields
  68. marginTop = 200;
  69. CreateLabel("3. Input local or remote server GUID", IntVector2(20, marginTop-20));
  70. serverGuid_ = CreateLineEdit("Remote server GUID", 200, IntVector2(20, marginTop));
  71. connectButton_ = CreateButton("Connect", 160, IntVector2(240, marginTop));
  72. // No viewports or scene is defined. However, the default zone's fog color controls the fill color
  73. GetSubsystem<Renderer>()->GetDefaultZone()->SetFogColor(Color(0.0f, 0.0f, 0.1f));
  74. }
  75. void NATPunchtrough::SubscribeToEvents()
  76. {
  77. SubscribeToEvent(E_SERVERCONNECTED, URHO3D_HANDLER(NATPunchtrough, HandleServerConnected));
  78. SubscribeToEvent(E_SERVERDISCONNECTED, URHO3D_HANDLER(NATPunchtrough, HandleServerDisconnected));
  79. SubscribeToEvent(E_CONNECTFAILED, URHO3D_HANDLER(NATPunchtrough, HandleConnectFailed));
  80. // NAT server connection related events
  81. SubscribeToEvent(E_NATMASTERCONNECTIONFAILED, URHO3D_HANDLER(NATPunchtrough, HandleNatConnectionFailed));
  82. SubscribeToEvent(E_NATMASTERCONNECTIONSUCCEEDED, URHO3D_HANDLER(NATPunchtrough, HandleNatConnectionSucceeded));
  83. SubscribeToEvent(E_NATMASTERDISCONNECTED, URHO3D_HANDLER(NATPunchtrough, HandleNatDisconnected));
  84. // NAT punchtrough request events
  85. SubscribeToEvent(E_NETWORKNATPUNCHTROUGHSUCCEEDED, URHO3D_HANDLER(NATPunchtrough, HandleNatPunchtroughSucceeded));
  86. SubscribeToEvent(E_NETWORKNATPUNCHTROUGHFAILED, URHO3D_HANDLER(NATPunchtrough, HandleNatPunchtroughFailed));
  87. SubscribeToEvent(E_CLIENTCONNECTED, URHO3D_HANDLER(NATPunchtrough, HandleClientConnected));
  88. SubscribeToEvent(E_CLIENTDISCONNECTED, URHO3D_HANDLER(NATPunchtrough, HandleClientDisconnected));
  89. SubscribeToEvent(saveNatSettingsButton_, "Released", URHO3D_HANDLER(NATPunchtrough, HandleSaveNatSettings));
  90. SubscribeToEvent(startServerButton_, "Released", URHO3D_HANDLER(NATPunchtrough, HandleStartServer));
  91. SubscribeToEvent(connectButton_, "Released", URHO3D_HANDLER(NATPunchtrough, HandleConnect));
  92. }
  93. Button* NATPunchtrough::CreateButton(const String& text, int width, IntVector2 position)
  94. {
  95. auto* cache = GetSubsystem<ResourceCache>();
  96. auto* font = cache->GetResource<Font>("Fonts/Anonymous Pro.ttf");
  97. auto* button = GetSubsystem<UI>()->GetRoot()->CreateChild<Button>();
  98. button->SetStyleAuto();
  99. button->SetFixedWidth(width);
  100. button->SetFixedHeight(30);
  101. button->SetPosition(position);
  102. auto* buttonText = button->CreateChild<Text>();
  103. buttonText->SetFont(font, 12);
  104. buttonText->SetAlignment(HA_CENTER, VA_CENTER);
  105. buttonText->SetText(text);
  106. return button;
  107. }
  108. LineEdit* NATPunchtrough::CreateLineEdit(const String& placeholder, int width, IntVector2 pos)
  109. {
  110. auto* textEdit = GetSubsystem<UI>()->GetRoot()->CreateChild<LineEdit>("");
  111. textEdit->SetStyleAuto();
  112. textEdit->SetFixedWidth(width);
  113. textEdit->SetFixedHeight(30);
  114. textEdit->SetText(placeholder);
  115. textEdit->SetPosition(pos);
  116. return textEdit;
  117. }
  118. void NATPunchtrough::CreateLabel(const String& text, IntVector2 pos)
  119. {
  120. auto* cache = GetSubsystem<ResourceCache>();
  121. // Create log element to view latest logs from the system
  122. auto* font = cache->GetResource<Font>("Fonts/Anonymous Pro.ttf");
  123. auto* label = GetSubsystem<UI>()->GetRoot()->CreateChild<Text>();
  124. label->SetFont(font, 12);
  125. label->SetColor(Color(0.0f, 1.0f, 0.0f));
  126. label->SetPosition(pos);
  127. label->SetText(text);
  128. }
  129. void NATPunchtrough::ShowLogMessage(const String& row)
  130. {
  131. logHistory_.Erase(0);
  132. logHistory_.Push(row);
  133. // Concatenate all the rows in history
  134. String allRows;
  135. for (const String& row : logHistory_)
  136. allRows += row + "\n";
  137. logHistoryText_->SetText(allRows);
  138. }
  139. void NATPunchtrough::HandleSaveNatSettings(StringHash eventType, VariantMap& eventData)
  140. {
  141. // Save NAT server configuration
  142. GetSubsystem<Network>()->SetNATServerInfo(natServerAddress_->GetText(), ToI32(natServerPort_->GetText()));
  143. ShowLogMessage("Saving NAT settings: " + natServerAddress_->GetText() + ":" + natServerPort_->GetText());
  144. }
  145. void NATPunchtrough::HandleServerConnected(StringHash eventType, VariantMap& eventData)
  146. {
  147. ShowLogMessage("Client: Server connected!");
  148. }
  149. void NATPunchtrough::HandleServerDisconnected(StringHash eventType, VariantMap& eventData)
  150. {
  151. ShowLogMessage("Client: Server disconnected!");
  152. }
  153. void NATPunchtrough::HandleConnectFailed(StringHash eventType, VariantMap& eventData)
  154. {
  155. ShowLogMessage("Client: Connection failed!");
  156. }
  157. void NATPunchtrough::HandleNatDisconnected(StringHash eventType, VariantMap& eventData)
  158. {
  159. ShowLogMessage("Disconnected from NAT master server");
  160. }
  161. void NATPunchtrough::HandleStartServer(StringHash eventType, VariantMap& eventData)
  162. {
  163. GetSubsystem<Network>()->StartServer(SERVER_PORT);
  164. ShowLogMessage("Server: Server started on port: " + String(SERVER_PORT));
  165. // Connect to the NAT server
  166. GetSubsystem<Network>()->StartNATClient();
  167. ShowLogMessage("Server: Starting NAT client for server...");
  168. // Output our assigned GUID which others will use to connect to our server
  169. guid_->SetText(GetSubsystem<Network>()->GetGUID());
  170. serverGuid_->SetText(GetSubsystem<Network>()->GetGUID());
  171. }
  172. void NATPunchtrough::HandleConnect(StringHash eventType, VariantMap& eventData)
  173. {
  174. VariantMap userData;
  175. userData["Name"] = "Urho3D";
  176. // Attempt connecting to server using custom GUID, Scene = null as a second parameter and user identity is passed as third parameter
  177. GetSubsystem<Network>()->AttemptNATPunchtrough(serverGuid_->GetText(), nullptr, userData);
  178. ShowLogMessage("Client: Attempting NAT punchtrough to guid: " + serverGuid_->GetText());
  179. }
  180. void NATPunchtrough::HandleNatConnectionFailed(StringHash eventType, VariantMap& eventData)
  181. {
  182. ShowLogMessage("Connection to NAT master server failed!");
  183. }
  184. void NATPunchtrough::HandleNatConnectionSucceeded(StringHash eventType, VariantMap& eventData)
  185. {
  186. ShowLogMessage("Connection to NAT master server succeeded!");
  187. }
  188. void NATPunchtrough::HandleNatPunchtroughSucceeded(StringHash eventType, VariantMap& eventData)
  189. {
  190. ShowLogMessage("NAT punchtrough succeeded!");
  191. }
  192. void NATPunchtrough::HandleNatPunchtroughFailed(StringHash eventType, VariantMap& eventData)
  193. {
  194. ShowLogMessage("NAT punchtrough failed!");
  195. }
  196. void NATPunchtrough::HandleClientConnected(StringHash eventType, VariantMap& eventData)
  197. {
  198. ShowLogMessage("Server: Client connected!");
  199. }
  200. void NATPunchtrough::HandleClientDisconnected(StringHash eventType, VariantMap& eventData)
  201. {
  202. ShowLogMessage("Server: Client disconnected!");
  203. }