|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "ServerInfoPanel.h"
#include "MapCycleEditDialog.h"
#include <vgui/ISystem.h>
#include <ctype.h>
#include <stdio.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CServerInfoPanel::CServerInfoPanel(vgui::Panel *parent, const char *name) : CVarListPropertyPage(parent, name) { LoadControlSettings("Admin/GamePanelInfo.res", "PLATFORM"); LoadVarList("Admin/MainServerConfig.vdf"); m_iLastUptimeDisplayed = 0; m_flUpdateTime = 0.0f; m_bMapListRetrieved = false; RemoteServer().AddServerMessageHandler(this, "UpdatePlayers"); RemoteServer().AddServerMessageHandler(this, "UpdateMap"); }
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CServerInfoPanel::~CServerInfoPanel() { RemoteServer().RemoveServerDataResponseTarget(this); }
//-----------------------------------------------------------------------------
// Purpose: gets the current hostname
//-----------------------------------------------------------------------------
const char *CServerInfoPanel::GetHostname() { return GetVarString("hostname"); }
//-----------------------------------------------------------------------------
// Purpose: Refreshes page if necessary
//-----------------------------------------------------------------------------
void CServerInfoPanel::OnThink() { if (m_flUpdateTime < vgui::system()->GetFrameTime()) { OnResetData(); }
// check uptime count
int time = m_iLastUptimeReceived + (int)(vgui::system()->GetFrameTime() - m_flLastUptimeReceiveTime); if (time != m_iLastUptimeDisplayed) { m_iLastUptimeDisplayed = time; char timeText[64]; _snprintf(timeText, sizeof(timeText), "%0.1i:%0.2i:%0.2i:%0.2i", (time / 3600) / 24, (time / 3600), (time / 60) % 60, time % 60); SetControlString("UpTimeText", timeText); } }
//-----------------------------------------------------------------------------
// Purpose: Data is be reloaded from document into controls.
//-----------------------------------------------------------------------------
void CServerInfoPanel::OnResetData() { // only ask for maps list once
if (!m_bMapListRetrieved) { RemoteServer().RequestValue(this, "maplist"); m_bMapListRetrieved = true; }
// refresh our vars
RefreshVarList();
// ask for the constant data
RemoteServer().RequestValue(this, "playercount"); RemoteServer().RequestValue(this, "maxplayers"); RemoteServer().RequestValue(this, "gamedescription"); RemoteServer().RequestValue(this, "uptime"); RemoteServer().RequestValue(this, "ipaddress");
// update once every minute
m_flUpdateTime = (float)system()->GetFrameTime() + (60 * 1.0f); }
//-----------------------------------------------------------------------------
// Purpose: handles responses from the server
//-----------------------------------------------------------------------------
void CServerInfoPanel::OnServerDataResponse(const char *value, const char *response) { if (!stricmp(value, "playercount")) { m_iPlayerCount = atoi(response); } else if (!stricmp(value, "maxplayers")) { m_iMaxPlayers = atoi(response);
// update control
char buf[128]; buf[0] = 0; if (m_iMaxPlayers > 0) { sprintf(buf, "%d / %d", m_iPlayerCount, m_iMaxPlayers); } SetControlString("PlayersText", buf); } else if (!stricmp(value, "gamedescription")) { SetControlString("GameText", response); } else if (!stricmp(value, "hostname")) { PostActionSignal(new KeyValues("UpdateTitle")); } else if (!stricmp(value, "UpdateMap") || !stricmp(value, "UpdatePlayers")) { // server has indicated a change, force an update
m_flUpdateTime = 0.0f; } else if (!stricmp(value, "maplist")) { SetCustomStringList("map", response); // save off maplist for use in mapcycle editing
ParseIntoMapList(response, m_AvailableMaps); // don't chain through, not in varlist
return; } else if (!stricmp(value, "uptime")) { // record uptime for extrapolation
m_iLastUptimeReceived = atoi(response); m_flLastUptimeReceiveTime = (float)system()->GetFrameTime(); } else if (!stricmp(value, "ipaddress")) { SetControlString("ServerIPText", response); } else if (!stricmp(value, "mapcycle")) { ParseIntoMapList(response, m_MapCycle); UpdateMapCycleValue(); // don't chain through, we set the value ourself
return; }
// always chain through, in case this variable is in the list as well
BaseClass::OnServerDataResponse(value, response);
// post update
if (!stricmp(value, "map")) { // map has changed, update map cycle view
UpdateMapCycleValue(); } }
//-----------------------------------------------------------------------------
// Purpose: special editing of map cycle list
//-----------------------------------------------------------------------------
void CServerInfoPanel::OnEditVariable(KeyValues *rule) { if (!stricmp(rule->GetName(), "mapcycle")) { CMapCycleEditDialog *dlg = new CMapCycleEditDialog(this, "MapCycleEditDialog"); dlg->Activate(this, m_AvailableMaps, m_MapCycle); } else { BaseClass::OnEditVariable(rule); } }
//-----------------------------------------------------------------------------
// Purpose: Updates the value shown in the mapcycle field
//-----------------------------------------------------------------------------
void CServerInfoPanel::UpdateMapCycleValue() { // look at current map
CUtlSymbol currentMap = GetVarString("map"); if (!currentMap.IsValid()) return;
// find it in the map cycle list
int listPoint = -1; for (int i = 0; i < m_MapCycle.Count(); i++) { if (!stricmp(m_MapCycle[i].String(), currentMap.String())) { listPoint = i; } }
// take out the next 2 maps and make them the value
char nextMaps[512]; nextMaps[0] = 0; bool needComma = false; for (int i = 0; i < 2; i++) { int point = listPoint + i + 1; if (point >= m_MapCycle.Count()) { point -= m_MapCycle.Count(); }
if (m_MapCycle.IsValidIndex(point)) { if (needComma) { strcat(nextMaps, ", "); } strcat(nextMaps, m_MapCycle[point].String()); needComma = true; } }
// add some elipses to show there is more maps
if (needComma) { strcat(nextMaps, ", "); } strcat(nextMaps, "...");
// show in varlist
SetVarString("mapcycle", nextMaps); }
//-----------------------------------------------------------------------------
// Purpose: Seperates out a newline-seperated map list into an array
//-----------------------------------------------------------------------------
void CServerInfoPanel::ParseIntoMapList(const char *maplist, CUtlVector<CUtlSymbol> &mapArray) { mapArray.RemoveAll();
const char *parse = maplist; while (*parse) { // newline-seperated map list
//!! this should be done with a more standard tokenizer
if (isspace(*parse)) { parse++; continue; }
// pull out the map name
const char *end = strstr(parse, "\n"); const char *end2 = strstr(parse, "\r"); if (end && end2 && end2 < end) { end = end2; } if (!end) break;
char customString[64]; int nameSize = end - parse; if (nameSize >= sizeof(customString)) { nameSize = sizeof(customString) - 1; }
// copy in the name
strncpy(customString, parse, nameSize); customString[nameSize] = 0; parse = end;
// add to the list string that aren't comments
if (nameSize > 0 && !(customString[0] == '/' && customString[1] == '/')) { int i = mapArray.AddToTail(); mapArray[i] = customString; } } }
|