Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

341 lines
11 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include <stdio.h>
  8. #include "winsock.h" // this BUGGER defines PropertySheet to PropertySheetA ....
  9. #undef PropertySheet
  10. #include "tokenline.h"
  11. #include "GamePanelInfo.h"
  12. //#include "Info.h"
  13. #include "IRunGameEngine.h"
  14. #include "DialogCvarChange.h"
  15. #include "DialogAddBan.h"
  16. #include "BudgetPanelContainer.h"
  17. #include <vgui/ISystem.h>
  18. #include <vgui/ISurface.h>
  19. #include <vgui/IVGui.h>
  20. #include <KeyValues.h>
  21. #include <vgui/Cursor.h>
  22. #include <vgui/ILocalize.h>
  23. #include <vgui_controls/Label.h>
  24. #include <vgui_controls/TextEntry.h>
  25. #include <vgui_controls/Button.h>
  26. #include <vgui_controls/PHandle.h>
  27. #include <vgui_controls/MessageBox.h>
  28. #include <vgui_controls/QueryBox.h>
  29. #include <vgui_controls/Image.h>
  30. #include <vgui_controls/ImagePanel.h>
  31. #include "tier0/icommandline.h"
  32. #include <proto_oob.h>
  33. #include <netadr.h>
  34. using namespace vgui;
  35. static const long RETRY_TIME = 10000; // refresh server every 10 seconds
  36. static const long MAP_CHANGE_TIME = 20000; // refresh 20 seconds after a map change
  37. static const long RESTART_TIME = 60000; // refresh 60 seconds after a "_restart"
  38. #include "IManageServer.h"
  39. //-----------------------------------------------------------------------------
  40. // Purpose: Constructor
  41. //-----------------------------------------------------------------------------
  42. CGamePanelInfo::CGamePanelInfo(vgui::Panel *parent, const char *name, const char *mod) : Frame(parent, name)
  43. {
  44. SetSize(560, 420);
  45. SetMinimumSize(560, 420);
  46. m_bRemoteServer = false;
  47. m_bShuttingDown = false;
  48. // Create an Animating Image Panel
  49. m_pAnimImagePanel = new AnimatingImagePanel(this, "AnAnimatingImagePanel");
  50. // Each image file is named ss1, ss2, ss3... ss20, one image for each frame of the animation.
  51. // This loads the 20 images in to the Animation class.
  52. m_pAnimImagePanel->LoadAnimation("resource\\steam\\g", 12);
  53. //!! animation temporarily disabled until UI pass done
  54. //m_pAnimImagePanel->StartAnimation();
  55. m_pAnimImagePanel->SetVisible(false);
  56. // the main container for the various sub panels
  57. m_pDetailsSheet = new PropertySheet(this, "Panels");
  58. // the sub panels
  59. m_pPlayerListPanel = new CPlayerPanel(this, "Player List");
  60. m_pBanListPanel = new CBanPanel(this, "Ban List");
  61. m_pServerLogPanel = new CRawLogPanel(this, "ServerLog");
  62. // chat panel disabled until we get the parsing done
  63. // m_pServerChatPanel = new CChatPanel(this, "ChatPanel");
  64. m_pServerConfigPanel = new CServerConfigPanel(this, "ServerConfigPanel", mod);
  65. m_pGraphsPanel = new CGraphPanel(this,"GraphsPanel");
  66. m_pServerInfoPanel = new CServerInfoPanel(this, "ServerInfo");
  67. if ( CommandLine()->CheckParm( "-BudgetPanel" ) )
  68. m_pBudgetPanel = new CBudgetPanelContainer( this, "BudgetPanel" );
  69. else
  70. m_pBudgetPanel = NULL;
  71. m_pServerInfoPanel->AddActionSignalTarget(this);
  72. m_pDetailsSheet->AddPage(m_pServerInfoPanel,"#Game_Main_Settings");
  73. m_pDetailsSheet->AddPage(m_pServerConfigPanel,"#Game_Configure");
  74. m_pDetailsSheet->AddPage(m_pGraphsPanel,"#Game_Server_Statistics");
  75. m_pDetailsSheet->AddPage(m_pPlayerListPanel,"#Game_Current_Players");
  76. m_pDetailsSheet->AddPage(m_pBanListPanel,"#Game_Bans");
  77. if ( m_pBudgetPanel )
  78. m_pDetailsSheet->AddPage(m_pBudgetPanel,"#Game_Budgets");
  79. // chat panel disabled until we get the parsing done
  80. // m_pDetailsSheet->AddPage(m_pServerChatPanel,"#Game_Chat");
  81. m_pDetailsSheet->AddPage(m_pServerLogPanel,"#Game_Console");
  82. // let us be ticked every frame
  83. ivgui()->AddTickSignal(this->GetVPanel());
  84. LoadControlSettingsAndUserConfig("Admin\\DialogGamePanelInfo.res");
  85. SetNewTitle(false, name);
  86. SetVisible(true);
  87. MoveToCenterOfScreen();
  88. RequestFocus();
  89. MoveToFront();
  90. //!! hack, force the server info panel to refresh fast
  91. // because the info it receives while loading the server is wrong
  92. PostMessage(m_pServerInfoPanel, new KeyValues("ResetData"), 0.1f);
  93. }
  94. //-----------------------------------------------------------------------------
  95. // Purpose: Destructor
  96. //-----------------------------------------------------------------------------
  97. CGamePanelInfo::~CGamePanelInfo()
  98. {
  99. }
  100. //-----------------------------------------------------------------------------
  101. // Purpose: Sets the title of the dialog
  102. //-----------------------------------------------------------------------------
  103. void CGamePanelInfo::SetNewTitle(bool connectionFailed, const char *additional_text)
  104. {
  105. const char *localized_title = "#Game_RemoteTitle";
  106. if (!m_bRemoteServer)
  107. {
  108. localized_title = "Game_LocalTitle";
  109. }
  110. else if (connectionFailed)
  111. {
  112. localized_title = "#Game_RemoteTitle_Failed";
  113. }
  114. wchar_t serverName[256];
  115. g_pVGuiLocalize->ConvertANSIToUnicode(additional_text, serverName, sizeof(serverName));
  116. wchar_t title[256];
  117. g_pVGuiLocalize->ConstructString(title, sizeof(title), g_pVGuiLocalize->Find(localized_title), 1, serverName);
  118. SetTitle(title, true);
  119. }
  120. //-----------------------------------------------------------------------------
  121. // Purpose: Updates the title
  122. //-----------------------------------------------------------------------------
  123. void CGamePanelInfo::OnUpdateTitle()
  124. {
  125. SetNewTitle(false, m_pServerInfoPanel->GetHostname());
  126. Repaint();
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Purpose: data accessor
  130. //-----------------------------------------------------------------------------
  131. void CGamePanelInfo::SetAsRemoteServer(bool remote)
  132. {
  133. m_bRemoteServer = remote;
  134. }
  135. //-----------------------------------------------------------------------------
  136. // Purpose: Relayouts the data
  137. //-----------------------------------------------------------------------------
  138. void CGamePanelInfo::PerformLayout()
  139. {
  140. BaseClass::PerformLayout();
  141. }
  142. //-----------------------------------------------------------------------------
  143. // Purpose: Called every frame, handles resending network messages
  144. //-----------------------------------------------------------------------------
  145. void CGamePanelInfo::OnTick()
  146. {
  147. // service the server I/O queue
  148. RemoteServer().ProcessServerResponse();
  149. }
  150. //-----------------------------------------------------------------------------
  151. // Purpose: handles button responses
  152. //-----------------------------------------------------------------------------
  153. void CGamePanelInfo::OnCommand(const char *command)
  154. {
  155. if (!stricmp(command, "stop2"))
  156. {
  157. RemoteServer().SendCommand("quit");
  158. m_bShuttingDown = true;
  159. Close();
  160. }
  161. else
  162. {
  163. BaseClass::OnCommand(command);
  164. }
  165. }
  166. //-----------------------------------------------------------------------------
  167. // Purpose: produces a dialog asking a player to enter a new ban
  168. //-----------------------------------------------------------------------------
  169. void CGamePanelInfo::OnStop()
  170. {
  171. QueryBox *box = new QueryBox("#Game_Stop_Server_Title", "#Game_Restart_Server");
  172. box->AddActionSignalTarget(this);
  173. box->SetOKButtonText("#Game_Stop_Server");
  174. box->SetOKCommand(new KeyValues("Command", "command", "stop2"));
  175. box->ShowWindow();
  176. }
  177. //-----------------------------------------------------------------------------
  178. // Purpose: displays the help page
  179. //-----------------------------------------------------------------------------
  180. void CGamePanelInfo::OnHelp()
  181. {
  182. system()->ShellExecute("open", "Admin\\Admin.html");
  183. }
  184. //-----------------------------------------------------------------------------
  185. // Purpose: Does any processing needed before closing the dialog
  186. //-----------------------------------------------------------------------------
  187. void CGamePanelInfo::OnClose()
  188. {
  189. if (m_bRemoteServer || m_bShuttingDown)
  190. {
  191. BaseClass::OnClose();
  192. return;
  193. }
  194. // closing the window will kill the local server, notify user
  195. OnStop();
  196. }
  197. //-----------------------------------------------------------------------------
  198. // Purpose: allow the build mode editor to edit the current sub panel
  199. //-----------------------------------------------------------------------------
  200. void CGamePanelInfo::ActivateBuildMode()
  201. {
  202. // BaseClass::ActivateBuildMode();
  203. // return;
  204. // no subpanel, no build mode
  205. EditablePanel *pg = dynamic_cast<EditablePanel *>(m_pDetailsSheet->GetActivePage());
  206. if (pg)
  207. {
  208. pg->ActivateBuildMode();
  209. }
  210. }
  211. //-----------------------------------------------------------------------------
  212. // Purpose: Writes text to the console
  213. //-----------------------------------------------------------------------------
  214. void CGamePanelInfo::AddToConsole(const char *msg)
  215. {
  216. if (m_pServerLogPanel)
  217. {
  218. // hack, look for restart message
  219. if (*msg == 3 && !strncmp(msg + 1, "MasterRequestRestart", strlen("MasterRequestRestart")))
  220. {
  221. OnMasterRequestRestart();
  222. }
  223. else if (*msg == 3 && !strncmp(msg + 1, "MasterOutOfDate", strlen("MasterOutOfDate")))
  224. {
  225. const char *details = strstr( msg, "MasterOutOfDate" );
  226. if ( details )
  227. {
  228. OnMasterOutOfDate(details + strlen("MasterOutOfDate"));
  229. }
  230. }
  231. else
  232. {
  233. // nothing special, just print
  234. m_pServerLogPanel->DoInsertString(msg);
  235. }
  236. }
  237. }
  238. void CGamePanelInfo::OnMasterOutOfDate( const char *msg)
  239. {
  240. #if !defined(_DEBUG)
  241. // open a dialog informing user that they need to restart the server
  242. if (!m_hOutOfDateQueryBox.Get())
  243. {
  244. char *fullmsg = (char *) _alloca( strlen(msg) + strlen( "\n\nDo you wish to shutdown now?\n") + 1 );
  245. _snprintf( fullmsg, strlen(msg) + strlen( "\n\nDo you wish to shutdown now?\n") + 1 , "%s\n\nDo you wish to shutdown now?\n", msg );
  246. m_hOutOfDateQueryBox = new QueryBox("Server restart pending", fullmsg);
  247. m_hOutOfDateQueryBox->AddActionSignalTarget(this);
  248. m_hOutOfDateQueryBox->SetOKCommand(new KeyValues("RestartServer"));
  249. m_hOutOfDateQueryBox->ShowWindow();
  250. }
  251. else
  252. {
  253. // reshow the existing window
  254. m_hOutOfDateQueryBox->Activate();
  255. }
  256. #endif // !defined(_DEBUG)
  257. }
  258. //-----------------------------------------------------------------------------
  259. // Purpose: Called when master server has requested the dedicated server restart
  260. //-----------------------------------------------------------------------------
  261. void CGamePanelInfo::OnMasterRequestRestart()
  262. {
  263. #if !defined(_DEBUG)
  264. // open a dialog informing user that they need to restart the server
  265. if (!m_hRestartQueryBox.Get())
  266. {
  267. m_hRestartQueryBox = new QueryBox("Server restart needed", "Your server is out of date, and will not be listed\non the master server until you restart.\n\nDo you wish to shutdown now?\n");
  268. m_hRestartQueryBox->AddActionSignalTarget(this);
  269. m_hRestartQueryBox->SetOKCommand(new KeyValues("RestartServer"));
  270. m_hRestartQueryBox->ShowWindow();
  271. }
  272. else
  273. {
  274. // reshow the existing window
  275. m_hRestartQueryBox->Activate();
  276. }
  277. #endif // !defined(_DEBUG)
  278. }
  279. //-----------------------------------------------------------------------------
  280. // Purpose: Restarts the server
  281. //-----------------------------------------------------------------------------
  282. void CGamePanelInfo::OnRestartServer()
  283. {
  284. //!! mark us as needing restart
  285. //!! this doesn't work yet, just shut us down
  286. // shut us down
  287. RemoteServer().SendCommand("quit");
  288. m_bShuttingDown = true;
  289. Close();
  290. }