diff options
Diffstat (limited to 'tracker/AdminServer/serverinfopanel.cpp')
| -rw-r--r-- | tracker/AdminServer/serverinfopanel.cpp | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/tracker/AdminServer/serverinfopanel.cpp b/tracker/AdminServer/serverinfopanel.cpp new file mode 100644 index 0000000..c384d55 --- /dev/null +++ b/tracker/AdminServer/serverinfopanel.cpp @@ -0,0 +1,285 @@ +//========= 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; + } + } +} + |