NATPunchtrough.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. //
  2. // Copyright (c) 2008-2020 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include <Urho3D/Audio/Audio.h>
  23. #include <Urho3D/Audio/Sound.h>
  24. #include <Urho3D/Engine/Engine.h>
  25. #include <Urho3D/Graphics/Zone.h>
  26. #include <Urho3D/Input/Input.h>
  27. #include <Urho3D/IO/Log.h>
  28. #include <Urho3D/IO/MemoryBuffer.h>
  29. #include <Urho3D/IO/VectorBuffer.h>
  30. #include <Urho3D/Network/Network.h>
  31. #include <Urho3D/Network/NetworkEvents.h>
  32. #include <Urho3D/Resource/ResourceCache.h>
  33. #include <Urho3D/UI/Button.h>
  34. #include <Urho3D/UI/Font.h>
  35. #include <Urho3D/UI/LineEdit.h>
  36. #include <Urho3D/UI/Text.h>
  37. #include <Urho3D/UI/UI.h>
  38. #include "NATPunchtrough.h"
  39. // Undefine Windows macro, as our Connection class has a function called SendMessage
  40. #ifdef SendMessage
  41. #undef SendMessage
  42. #endif
  43. URHO3D_DEFINE_APPLICATION_MAIN(NATPunchtrough)
  44. NATPunchtrough::NATPunchtrough(Context* context) :
  45. Sample(context)
  46. {
  47. }
  48. void NATPunchtrough::Start()
  49. {
  50. // Execute base class startup
  51. Sample::Start();
  52. // Enable OS cursor
  53. GetSubsystem<Input>()->SetMouseVisible(true);
  54. // Create the user interface
  55. CreateUI();
  56. // Subscribe to UI and network events
  57. SubscribeToEvents();
  58. // Set the mouse mode to use in the sample
  59. Sample::InitMouseMode(MM_FREE);
  60. }
  61. void NATPunchtrough::CreateUI()
  62. {
  63. SetLogoVisible(true); // We need the full rendering window
  64. UIElement* root = GetSubsystem<UI>()->GetRoot();
  65. auto* cache = GetSubsystem<ResourceCache>();
  66. auto* uiStyle = cache->GetResource<XMLFile>("UI/DefaultStyle.xml");
  67. // Set style to the UI root so that elements will inherit it
  68. root->SetDefaultStyle(uiStyle);
  69. auto* font = cache->GetResource<Font>("Fonts/Anonymous Pro.ttf");
  70. logHistoryText_ = root->CreateChild<Text>();
  71. logHistoryText_->SetFont(font, 12);
  72. logHistoryText_->SetPosition(20, -20);
  73. logHistoryText_->SetVerticalAlignment(VA_BOTTOM);
  74. logHistory_.Resize(20);
  75. // Create NAT server config fields
  76. int marginTop = 40;
  77. CreateLabel("1. Run NAT server somewhere, enter NAT server info and press 'Save NAT settings'", IntVector2(20, marginTop-20));
  78. natServerAddress_ = CreateLineEdit("127.0.0.1", 200, IntVector2(20, marginTop));
  79. natServerPort_ = CreateLineEdit("61111", 100, IntVector2(240, marginTop));
  80. saveNatSettingsButton_ = CreateButton("Save NAT settings", 160, IntVector2(360, marginTop));
  81. // Create server start button
  82. marginTop = 120;
  83. CreateLabel("2. Create server and give others your server GUID", IntVector2(20, marginTop-20));
  84. guid_ = CreateLineEdit("Your server GUID", 200, IntVector2(20, marginTop));
  85. startServerButton_ = CreateButton("Start server", 160, IntVector2(240, marginTop));
  86. // Create client connection related fields
  87. marginTop = 200;
  88. CreateLabel("3. Input local or remote server GUID", IntVector2(20, marginTop-20));
  89. serverGuid_ = CreateLineEdit("Remote server GUID", 200, IntVector2(20, marginTop));
  90. connectButton_ = CreateButton("Connect", 160, IntVector2(240, marginTop));
  91. // No viewports or scene is defined. However, the default zone's fog color controls the fill color
  92. GetSubsystem<Renderer>()->GetDefaultZone()->SetFogColor(Color(0.0f, 0.0f, 0.1f));
  93. }
  94. void NATPunchtrough::SubscribeToEvents()
  95. {
  96. SubscribeToEvent(E_SERVERCONNECTED, URHO3D_HANDLER(NATPunchtrough, HandleServerConnected));
  97. SubscribeToEvent(E_SERVERDISCONNECTED, URHO3D_HANDLER(NATPunchtrough, HandleServerDisconnected));
  98. SubscribeToEvent(E_CONNECTFAILED, URHO3D_HANDLER(NATPunchtrough, HandleConnectFailed));
  99. // NAT server connection related events
  100. SubscribeToEvent(E_NATMASTERCONNECTIONFAILED, URHO3D_HANDLER(NATPunchtrough, HandleNatConnectionFailed));
  101. SubscribeToEvent(E_NATMASTERCONNECTIONSUCCEEDED, URHO3D_HANDLER(NATPunchtrough, HandleNatConnectionSucceeded));
  102. SubscribeToEvent(E_NATMASTERDISCONNECTED, URHO3D_HANDLER(NATPunchtrough, HandleNatDisconnected));
  103. // NAT punchtrough request events
  104. SubscribeToEvent(E_NETWORKNATPUNCHTROUGHSUCCEEDED, URHO3D_HANDLER(NATPunchtrough, HandleNatPunchtroughSucceeded));
  105. SubscribeToEvent(E_NETWORKNATPUNCHTROUGHFAILED, URHO3D_HANDLER(NATPunchtrough, HandleNatPunchtroughFailed));
  106. SubscribeToEvent(E_CLIENTCONNECTED, URHO3D_HANDLER(NATPunchtrough, HandleClientConnected));
  107. SubscribeToEvent(E_CLIENTDISCONNECTED, URHO3D_HANDLER(NATPunchtrough, HandleClientDisconnected));
  108. SubscribeToEvent(saveNatSettingsButton_, "Released", URHO3D_HANDLER(NATPunchtrough, HandleSaveNatSettings));
  109. SubscribeToEvent(startServerButton_, "Released", URHO3D_HANDLER(NATPunchtrough, HandleStartServer));
  110. SubscribeToEvent(connectButton_, "Released", URHO3D_HANDLER(NATPunchtrough, HandleConnect));
  111. }
  112. Button* NATPunchtrough::CreateButton(const String& text, int width, IntVector2 position)
  113. {
  114. auto* cache = GetSubsystem<ResourceCache>();
  115. auto* font = cache->GetResource<Font>("Fonts/Anonymous Pro.ttf");
  116. auto* button = GetSubsystem<UI>()->GetRoot()->CreateChild<Button>();
  117. button->SetStyleAuto();
  118. button->SetFixedWidth(width);
  119. button->SetFixedHeight(30);
  120. button->SetPosition(position);
  121. auto* buttonText = button->CreateChild<Text>();
  122. buttonText->SetFont(font, 12);
  123. buttonText->SetAlignment(HA_CENTER, VA_CENTER);
  124. buttonText->SetText(text);
  125. return button;
  126. }
  127. LineEdit* NATPunchtrough::CreateLineEdit(const String& placeholder, int width, IntVector2 pos)
  128. {
  129. auto* textEdit = GetSubsystem<UI>()->GetRoot()->CreateChild<LineEdit>("");
  130. textEdit->SetStyleAuto();
  131. textEdit->SetFixedWidth(width);
  132. textEdit->SetFixedHeight(30);
  133. textEdit->SetText(placeholder);
  134. textEdit->SetPosition(pos);
  135. return textEdit;
  136. }
  137. void NATPunchtrough::CreateLabel(const String& text, IntVector2 pos)
  138. {
  139. auto* cache = GetSubsystem<ResourceCache>();
  140. // Create log element to view latest logs from the system
  141. auto* font = cache->GetResource<Font>("Fonts/Anonymous Pro.ttf");
  142. auto* label = GetSubsystem<UI>()->GetRoot()->CreateChild<Text>();
  143. label->SetFont(font, 12);
  144. label->SetColor(Color(0.0f, 1.0f, 0.0f));
  145. label->SetPosition(pos);
  146. label->SetText(text);
  147. }
  148. void NATPunchtrough::ShowLogMessage(const String& row)
  149. {
  150. logHistory_.Erase(0);
  151. logHistory_.Push(row);
  152. // Concatenate all the rows in history
  153. String allRows;
  154. for (unsigned i = 0; i < logHistory_.Size(); ++i)
  155. allRows += logHistory_[i] + "\n";
  156. logHistoryText_->SetText(allRows);
  157. }
  158. void NATPunchtrough::HandleSaveNatSettings(StringHash eventType, VariantMap& eventData)
  159. {
  160. // Save NAT server configuration
  161. GetSubsystem<Network>()->SetNATServerInfo(natServerAddress_->GetText(), ToInt(natServerPort_->GetText()));
  162. ShowLogMessage("Saving NAT settings: " + natServerAddress_->GetText() + ":" + natServerPort_->GetText());
  163. }
  164. void NATPunchtrough::HandleServerConnected(StringHash eventType, VariantMap& eventData)
  165. {
  166. ShowLogMessage("Client: Server connected!");
  167. }
  168. void NATPunchtrough::HandleServerDisconnected(StringHash eventType, VariantMap& eventData)
  169. {
  170. ShowLogMessage("Client: Server disconnected!");
  171. }
  172. void NATPunchtrough::HandleConnectFailed(StringHash eventType, VariantMap& eventData)
  173. {
  174. ShowLogMessage("Client: Connection failed!");
  175. }
  176. void NATPunchtrough::HandleNatDisconnected(StringHash eventType, VariantMap& eventData)
  177. {
  178. ShowLogMessage("Disconnected from NAT master server");
  179. }
  180. void NATPunchtrough::HandleStartServer(StringHash eventType, VariantMap& eventData)
  181. {
  182. GetSubsystem<Network>()->StartServer(SERVER_PORT);
  183. ShowLogMessage("Server: Server started on port: " + String(SERVER_PORT));
  184. // Connect to the NAT server
  185. GetSubsystem<Network>()->StartNATClient();
  186. ShowLogMessage("Server: Starting NAT client for server...");
  187. // Output our assigned GUID which others will use to connect to our server
  188. guid_->SetText(GetSubsystem<Network>()->GetGUID());
  189. serverGuid_->SetText(GetSubsystem<Network>()->GetGUID());
  190. }
  191. void NATPunchtrough::HandleConnect(StringHash eventType, VariantMap& eventData)
  192. {
  193. VariantMap userData;
  194. userData["Name"] = "Urho3D";
  195. // Attempt connecting to server using custom GUID, Scene = null as a second parameter and user identity is passed as third parameter
  196. GetSubsystem<Network>()->AttemptNATPunchtrough(serverGuid_->GetText(), nullptr, userData);
  197. ShowLogMessage("Client: Attempting NAT punchtrough to guid: " + serverGuid_->GetText());
  198. }
  199. void NATPunchtrough::HandleNatConnectionFailed(StringHash eventType, VariantMap& eventData)
  200. {
  201. ShowLogMessage("Connection to NAT master server failed!");
  202. }
  203. void NATPunchtrough::HandleNatConnectionSucceeded(StringHash eventType, VariantMap& eventData)
  204. {
  205. ShowLogMessage("Connection to NAT master server succeeded!");
  206. }
  207. void NATPunchtrough::HandleNatPunchtroughSucceeded(StringHash eventType, VariantMap& eventData)
  208. {
  209. ShowLogMessage("NAT punchtrough succeeded!");
  210. }
  211. void NATPunchtrough::HandleNatPunchtroughFailed(StringHash eventType, VariantMap& eventData)
  212. {
  213. ShowLogMessage("NAT punchtrough failed!");
  214. }
  215. void NATPunchtrough::HandleClientConnected(StringHash eventType, VariantMap& eventData)
  216. {
  217. ShowLogMessage("Server: Client connected!");
  218. }
  219. void NATPunchtrough::HandleClientDisconnected(StringHash eventType, VariantMap& eventData)
  220. {
  221. ShowLogMessage("Server: Client disconnected!");
  222. }