NATPunchtrough.cpp 12 KB

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