diff options
Diffstat (limited to 'tracker/AdminServer/DialogGameInfo.cpp')
| -rw-r--r-- | tracker/AdminServer/DialogGameInfo.cpp | 532 |
1 files changed, 532 insertions, 0 deletions
diff --git a/tracker/AdminServer/DialogGameInfo.cpp b/tracker/AdminServer/DialogGameInfo.cpp new file mode 100644 index 0000000..7299c51 --- /dev/null +++ b/tracker/AdminServer/DialogGameInfo.cpp @@ -0,0 +1,532 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "DialogGameInfo.h" +#include "Info.h" +#include "IRunGameEngine.h" +#include "IGameList.h" +#include "TrackerProtocol.h" +#include "serverpage.h" +#include "ServerList.h" +#include "DialogServerPassword.h" + +#include <VGUI_Controls.h> +#include <VGUI_ISystem.h> +#include <VGUI_ISurface.h> +#include <VGUI_IVGui.h> +#include <VGUI_KeyValues.h> +#include <VGUI_Label.h> +#include <VGUI_TextEntry.h> +#include <VGUI_Button.h> +#include <VGUI_ToggleButton.h> +#include <VGUI_RadioButton.h> + +#include <stdio.h> + +using namespace vgui; + +static const long RETRY_TIME = 10000; // refresh server every 10 seconds + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CDialogGameInfo::CDialogGameInfo(IGameList *gameList, unsigned int serverID, int serverIP, int serverPort) : Frame(NULL, "DialogGameInfo"), m_Servers(this) +{ + MakePopup(); + SetBounds(0, 0, 512, 384); + m_bConnecting = false; + m_bServerFull = false; + m_bShowAutoRetryToggle = false; + m_bServerNotResponding = false; + m_bShowingExtendedOptions = false; + + m_szPassword[0] = 0; + + m_iServerID = serverID; + + m_pConnectButton = new Button(this, "Connect", "&Join Game"); + m_pCloseButton = new Button(this, "Close", "&Close"); + m_pRefreshButton = new Button(this, "Refresh", "&Refresh"); + m_pInfoLabel = new Label(this, "InfoLabel", ""); + m_pAutoRetry = new ToggleButton(this, "AutoRetry", "&Auto-Retry"); + m_pAutoRetry->AddActionSignalTarget(this); + + m_pAutoRetryAlert = new RadioButton(this, "AutoRetryAlert", "A&lert me when a player slot is available on server."); + m_pAutoRetryJoin = new RadioButton(this, "AutoRetryJoin", "J&oin the server as soon as a player slot is available."); + + m_pAutoRetryAlert->SetSelected(true); + + m_pConnectButton->SetCommand(new KeyValues("Connect")); + m_pCloseButton->SetCommand(new KeyValues("Close")); + m_pRefreshButton->SetCommand(new KeyValues("Refresh")); + + m_iRequestRetry = 0; + + SetSizeable(false); + + if (gameList) + { + // we already have the game info, fill it in + serveritem_t &server = gameList->GetServer(serverID); + m_iServerID = m_Servers.AddNewServer(server); + } + else + { + // create a new server to watch + serveritem_t server; + memset(&server, 0, sizeof(server)); + *((int *)server.ip) = serverIP; + server.port = serverPort; + m_iServerID = m_Servers.AddNewServer(server); + } + + // refresh immediately + RequestInfo(); + + // let us be ticked every frame + ivgui()->AddTickSignal(this->GetVPanel()); + + LoadControlSettings("Admin\\DialogGameInfo.res"); +} + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +CDialogGameInfo::~CDialogGameInfo() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Activates the dialog +//----------------------------------------------------------------------------- +void CDialogGameInfo::Run(const char *titleName) +{ + char buf[512]; + if (titleName) + { + sprintf(buf, "Game Info - %s", titleName); + } + else + { + strcpy(buf, "Game Info"); + } + SetTitle(buf, true); + + // get the info from the user + RequestInfo(); + + RequestFocus(); +} + +//----------------------------------------------------------------------------- +// Purpose: Changes which server to watch +//----------------------------------------------------------------------------- +void CDialogGameInfo::ChangeGame(int serverIP, int serverPort) +{ + // check to see if it's the same game + serveritem_t &server = m_Servers.GetServer(m_iServerID); + + if (*(int *)server.ip == serverIP && server.port == serverPort) + { + return; + } + + // change the server + m_Servers.Clear(); + + // create a new server to watch + serveritem_t newServer; + memset(&newServer, 0, sizeof(newServer)); + *((int *)newServer.ip) = serverIP; + newServer.port = serverPort; + m_iServerID = m_Servers.AddNewServer(newServer); + + // start refresh immediately + RequestInfo(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Relayouts the data +//----------------------------------------------------------------------------- +void CDialogGameInfo::PerformLayout() +{ + BaseClass::PerformLayout(); + + // get the server we're watching + serveritem_t &server = m_Servers.GetServer(m_iServerID); + + SetControlText("ServerText", server.name); + SetControlText("GameText", server.gameDescription); + SetControlText("MapText", server.map); + + char buf[128]; + if (server.maxPlayers > 0) + { + sprintf(buf, "%d / %d", server.players, server.maxPlayers); + } + else + { + buf[0] = 0; + } + SetControlText("PlayersText", buf); + + if (server.ip[0] && server.port) + { + char buf[64]; + sprintf(buf, "%d.%d.%d.%d:%d", server.ip[0], server.ip[1], server.ip[2], server.ip[3], server.port); + SetControlText("ServerIPText", buf); + m_pConnectButton->SetEnabled(true); + } + else + { + SetControlText("ServerIPText", ""); + m_pConnectButton->SetEnabled(false); + } + + sprintf(buf, "%d", server.ping); + SetControlText("PingText", buf); + + // set the info text + if (m_pAutoRetry->IsSelected()) + { + if (server.players < server.maxPlayers) + { + m_pInfoLabel->SetText("Press 'Join Game' to connect to the server."); + } + else if (m_pAutoRetryJoin->IsSelected()) + { + m_pInfoLabel->SetText("You will join the server as soon as a player slot is free."); + } + else + { + m_pInfoLabel->SetText("You will be alerted as soon player slot is free on the server."); + } + } + else if (m_bServerFull) + { + m_pInfoLabel->SetText("Could not connect - server is full."); + } + else if (m_bServerNotResponding) + { + char text[100]; + _snprintf(text,100,"Server is not responding.%d.%d.%d.%d:%d", server.ip[0], server.ip[1], server.ip[2], server.ip[3], server.port); + + m_pInfoLabel->SetText(text); + } + else + { + // clear the status + m_pInfoLabel->SetText(""); + } + + // auto-retry layout + m_pAutoRetry->SetVisible(m_bShowAutoRetryToggle); + + if (m_pAutoRetry->IsSelected()) + { + m_pAutoRetryAlert->SetVisible(true); + m_pAutoRetryJoin->SetVisible(true); + } + else + { + m_pAutoRetryAlert->SetVisible(false); + m_pAutoRetryJoin->SetVisible(false); + } + + Repaint(); +} + +//----------------------------------------------------------------------------- +// Purpose: Sets up the current scheme colors +//----------------------------------------------------------------------------- +void CDialogGameInfo::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + + // force the label to get it's scheme settings + m_pInfoLabel->InvalidateLayout(true); + // override them + m_pInfoLabel->SetFgColor(GetSchemeColor("BrightControlText")); +} + +//----------------------------------------------------------------------------- +// Purpose: Forces the game info dialog to try and connect +//----------------------------------------------------------------------------- +void CDialogGameInfo::Connect() +{ + OnConnect(); +} + +//----------------------------------------------------------------------------- +// Purpose: Connects the user to this game +//----------------------------------------------------------------------------- +void CDialogGameInfo::OnConnect() +{ + // flag that we are attempting connection + m_bConnecting = true; + + // reset state + m_bServerFull = false; + m_bServerNotResponding = false; + + InvalidateLayout(); + + // need to refresh server before attempting to connect, to make sure there is enough room on the server + RequestInfo(); +} + +//----------------------------------------------------------------------------- +// Purpose: Handles Refresh button press, starts a re-ping of the server +//----------------------------------------------------------------------------- +void CDialogGameInfo::OnRefresh() +{ + // re-ask the server for the game info + RequestInfo(); +} + +//----------------------------------------------------------------------------- +// Purpose: Deletes the dialog when it's closed +//----------------------------------------------------------------------------- +void CDialogGameInfo::OnClose() +{ + BaseClass::OnClose(); + MarkForDeletion(); +} + +//----------------------------------------------------------------------------- +// Purpose: Forces the whole dialog to redraw when the auto-retry button is toggled +//----------------------------------------------------------------------------- +void CDialogGameInfo::OnButtonToggled(Panel *panel) +{ + if (panel == m_pAutoRetry) + { + ShowAutoRetryOptions(m_pAutoRetry->IsSelected()); + } + + InvalidateLayout(); +} + +//----------------------------------------------------------------------------- +// Purpose: Sets whether the extended auto-retry options are visible or not +// Input : state - +//----------------------------------------------------------------------------- +void CDialogGameInfo::ShowAutoRetryOptions(bool state) +{ + // we need to extend the dialog + int growSize = 60; + if (!state) + { + growSize = -growSize; + } + + // alter the dialog size accordingly + int wide, tall; + GetSize(wide, tall); + tall += growSize; + SetSize(wide, tall); + + InvalidateLayout(); +} + +//----------------------------------------------------------------------------- +// Purpose: Sets the text of a control by name +//----------------------------------------------------------------------------- +void CDialogGameInfo::SetControlText(const char *textEntryName, const char *text) +{ + TextEntry *entry = dynamic_cast<TextEntry *>(FindChildByName(textEntryName)); + if (entry) + { + entry->SetText(text); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Requests the right info from the server +//----------------------------------------------------------------------------- +void CDialogGameInfo::RequestInfo() +{ + // reset the time at which we auto-refresh + m_iRequestRetry = system()->GetTimeMillis() + RETRY_TIME; + + if (!m_Servers.IsRefreshing()) + { + m_Servers.AddServerToRefreshList(m_iServerID); + m_Servers.StartRefresh(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Called every frame, handles resending network messages +//----------------------------------------------------------------------------- +void CDialogGameInfo::OnTick() +{ + // check to see if we should perform an auto-refresh + if (m_iRequestRetry && m_iRequestRetry < system()->GetTimeMillis()) + { + // reask + RequestInfo(); + } + + m_Servers.RunFrame(); +} + +//----------------------------------------------------------------------------- +// Purpose: called when the server has successfully responded +//----------------------------------------------------------------------------- +void CDialogGameInfo::ServerResponded(serveritem_t &server) +{ + if (m_bConnecting) + { + ConnectToServer(); + } + else if (m_pAutoRetry->IsSelected()) + { + // auto-retry is enabled, see if we can join + if (server.players < server.maxPlayers) + { + // there is a slot free, we can join + + // make the sound + surface()->PlaySound("Servers\\game_ready.wav"); + + // flash this window + FlashWindow(); + + // if it's set, connect right away + if (m_pAutoRetryJoin->IsSelected()) + { + ConnectToServer(); + } + } + } + + m_bServerNotResponding = false; + + InvalidateLayout(); + Repaint(); +} + +//----------------------------------------------------------------------------- +// Purpose: called when a server response has timed out +//----------------------------------------------------------------------------- +void CDialogGameInfo::ServerFailedToRespond(serveritem_t &server) +{ + // the server didn't respond, mark that in the UI + // only mark if we haven't ever received a response + if (!server.hadSuccessfulResponse) + { + m_bServerNotResponding = true; + } + + InvalidateLayout(); + Repaint(); +} + +//----------------------------------------------------------------------------- +// Purpose: Connects to the server +//----------------------------------------------------------------------------- +void CDialogGameInfo::ConnectToServer() +{ + m_bConnecting = false; + serveritem_t &server = m_Servers.GetServer(m_iServerID); + + // check to see if we need a password + if (server.password && !m_szPassword[0]) + { + CDialogServerPassword *box = new CDialogServerPassword(); + box->AddActionSignalTarget(this); + box->Activate(server.name, server.serverID); + return; + } + + // check the player count + if (server.players >= server.maxPlayers) + { + // mark why we cannot connect + m_bServerFull = true; + // give them access to auto-retry options + m_bShowAutoRetryToggle = true; + InvalidateLayout(); + return; + } + + // tell the engine to connect + char buf[64]; + sprintf(buf, "%d.%d.%d.%d:%d", server.ip[0], server.ip[1], server.ip[2], server.ip[3], server.port); + + const char *gameDir = server.gameDir; + if (g_pRunGameEngine->IsRunning()) + { + char command[256]; + + // set the server password, if any + if (m_szPassword[0]) + { + sprintf(command, "password \"%s\"\n", m_szPassword); + g_pRunGameEngine->AddTextCommand(command); + } + + // send engine command to change servers + sprintf(command, "connect %s\n", buf); + g_pRunGameEngine->AddTextCommand(command); + } + else + { + char command[256]; +// sprintf(command, " -game %s +connect %s", gameDir, buf); + sprintf(command, " +connect %s", buf); + if (m_szPassword[0]) + { + strcat(command, " +password \""); + strcat(command, m_szPassword); + strcat(command, "\"");\ + } + + g_pRunGameEngine->RunEngine(gameDir, command); + } + + // close this dialog + PostMessage(this, new KeyValues("Close")); +} + + +//----------------------------------------------------------------------------- +// Purpose: called when the current refresh list is complete +//----------------------------------------------------------------------------- +void CDialogGameInfo::RefreshComplete() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: handles response from the get password dialog +//----------------------------------------------------------------------------- +void CDialogGameInfo::OnJoinServerWithPassword(const char *password) +{ + // copy out the password + v_strncpy(m_szPassword, password, sizeof(m_szPassword)); + + // retry connecting to the server again + OnConnect(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Message map +//----------------------------------------------------------------------------- +MessageMapItem_t CDialogGameInfo::m_MessageMap[] = +{ + MAP_MESSAGE( CDialogGameInfo, "Refresh", OnRefresh ), + MAP_MESSAGE( CDialogGameInfo, "Connect", OnConnect ), + + MAP_MESSAGE_PTR( CDialogGameInfo, "ButtonToggled", OnButtonToggled, "panel" ), + MAP_MESSAGE_PTR( CDialogGameInfo, "RadioButtonChecked", OnButtonToggled, "panel" ), + + MAP_MESSAGE_CONSTCHARPTR( CDialogGameInfo, "JoinServerWithPassword", OnJoinServerWithPassword, "password" ), +}; + +IMPLEMENT_PANELMAP( CDialogGameInfo, Frame ); |