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.
285 lines
7.7 KiB
285 lines
7.7 KiB
//========= 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;
|
|
}
|
|
}
|
|
}
|
|
|