|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include <stdio.h>
#include "PlayerPanel.h"
#include "PlayerContextMenu.h"
#include "PlayerListCompare.h"
#include "DialogAddBan.h"
#include <vgui/ISystem.h>
#include <vgui/ISurface.h>
#include <vgui/ILocalize.h>
#include <vgui/IVGui.h>
#include <vgui/KeyCode.h>
#include <KeyValues.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/ListPanel.h>
#include <vgui_controls/QueryBox.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CPlayerPanel::CPlayerPanel(vgui::Panel *parent, const char *name) : vgui::PropertyPage(parent, name) { m_pPlayerListPanel = new vgui::ListPanel(this, "Players list");
m_pPlayerListPanel->AddColumnHeader(0, "name", "#Player_Panel_Name", 200, ListPanel::COLUMN_RESIZEWITHWINDOW ); m_pPlayerListPanel->AddColumnHeader(1, "authid", "#Player_Panel_ID", 100); m_pPlayerListPanel->AddColumnHeader(2, "ping", "#Player_Panel_Ping", 50); m_pPlayerListPanel->AddColumnHeader(3, "loss", "#Player_Panel_Loss", 50); m_pPlayerListPanel->AddColumnHeader(4, "frags", "#Player_Panel_Frags", 50); m_pPlayerListPanel->AddColumnHeader(5, "time", "#Player_Panel_Time", 75);
/*
// TODO: update me!!
m_pPlayerListPanel->SetSortFunc(0, PlayerNameCompare); m_pPlayerListPanel->SetSortFunc(1, PlayerAuthCompare); m_pPlayerListPanel->SetSortFunc(2, PlayerPingCompare); m_pPlayerListPanel->SetSortFunc(3, PlayerLossCompare); m_pPlayerListPanel->SetSortFunc(4, PlayerFragsCompare); */ m_pPlayerListPanel->SetSortFunc(5, PlayerTimeCompare); m_pPlayerListPanel->SetEmptyListText("#Player_Panel_No_Players"); // Sort by ping time by default
m_pPlayerListPanel->SetSortColumn(0);
m_pKickButton = new Button(this, "Kick", "#Player_Panel_Kick"); m_pBanButton = new Button(this, "Ban", "#Player_Panel_Ban");
m_pPlayerContextMenu = new CPlayerContextMenu(this); m_pPlayerContextMenu->SetVisible(false);
LoadControlSettings("Admin/PlayerPanel.res", "PLATFORM");
m_pKickButton->SetCommand(new KeyValues("KickPlayer")); m_pBanButton->SetCommand(new KeyValues("BanPlayer"));
OnItemSelected(); // disable the buttons
m_flUpdateTime = 0.0f; RemoteServer().AddServerMessageHandler(this, "UpdatePlayers"); }
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CPlayerPanel::~CPlayerPanel() { RemoteServer().RemoveServerDataResponseTarget(this); }
//-----------------------------------------------------------------------------
// Purpose: Rebuilds player info
//-----------------------------------------------------------------------------
void CPlayerPanel::OnResetData() { RemoteServer().RequestValue(this, "playerlist");
// update once every minute
m_flUpdateTime = (float)system()->GetFrameTime() + (60 * 1.0f); }
//-----------------------------------------------------------------------------
// Purpose: Checks to see if we should update player info
//-----------------------------------------------------------------------------
void CPlayerPanel::OnThink() { if (m_flUpdateTime < vgui::system()->GetFrameTime()) { OnResetData(); } }
//-----------------------------------------------------------------------------
// Purpose: Refreshes page if user hits F5
//-----------------------------------------------------------------------------
void CPlayerPanel::OnKeyCodeTyped(vgui::KeyCode code) { if (code == KEY_F5) { OnResetData(); } else { BaseClass::OnKeyCodeTyped(code); } }
//-----------------------------------------------------------------------------
// Purpose: Returns data on the player who is currently selected in the list
//-----------------------------------------------------------------------------
KeyValues *CPlayerPanel::GetSelected() { return m_pPlayerListPanel->GetItem(m_pPlayerListPanel->GetSelectedItem(0)); }
static const char *FormatSeconds( int seconds ) { static char string[64];
int hours = 0; int minutes = seconds / 60;
if ( minutes > 0 ) { seconds -= (minutes * 60); hours = minutes / 60;
if ( hours > 0 ) { minutes -= (hours * 60); } } if ( hours > 0 ) { Q_snprintf( string, sizeof(string), "%2i:%02i:%02i", hours, minutes, seconds ); } else { Q_snprintf( string, sizeof(string), "%02i:%02i", minutes, seconds ); }
return string; }
//-----------------------------------------------------------------------------
// Purpose: called when the server has returned a requested value
//-----------------------------------------------------------------------------
void CPlayerPanel::OnServerDataResponse(const char *value, const char *response) { if (!stricmp(value, "UpdatePlayers")) { // server has indicated a change, force an update
m_flUpdateTime = 0.0f; } else if (!stricmp(value, "playerlist")) { // new list of players
m_pPlayerListPanel->DeleteAllItems(); // parse response
const char *parse = response; while (parse && *parse) { // first should be the size of the player name
char name[64]; name[0] = '\0'; char authID[64]; authID[0] = '\0'; char netAdr[32]; netAdr[0] = '\0'; int ping = 0, packetLoss = 0, frags = 0, connectTime = 0;
ivgui()->DPrintf2("orig: %s\n", parse);
// parse out the name, which is quoted
Assert(*parse == '\"'); if (*parse != '\"') break; ++parse; // move past start quote
int pos = 0; while (*parse && *parse != '\"') { name[pos++] = *parse; parse++; } name[pos] = 0; parse++; // move past end quote
if (6 != sscanf(parse, " %s %s %d %d %d %d\n", authID, netAdr, &ping, &packetLoss, &frags, &connectTime)) break;
const char *timeStr = FormatSeconds(connectTime);
ivgui()->DPrintf2("pars: \"%s\" %s %s %d %d %d %s\n", name, authID, netAdr, ping, packetLoss, frags, timeStr);
// add to list
KeyValues *player = new KeyValues("Player"); player->SetString("name", name); player->SetString("authID", authID); player->SetString("netAdr", netAdr); player->SetInt("ping", ping); player->SetInt("loss", packetLoss); player->SetInt("frags", frags); player->SetString("time", timeStr); m_pPlayerListPanel->AddItem(player, 0, false, false);
// move to next line
parse = strchr(parse, '\n'); if (parse) { parse++; } } } }
//-----------------------------------------------------------------------------
// Purpose: Buttom command handlers
//-----------------------------------------------------------------------------
void CPlayerPanel::OnCommand(const char *command) { BaseClass::OnCommand(command); }
//-----------------------------------------------------------------------------
// Purpose: Handles the UI for kicking a player from the server
//-----------------------------------------------------------------------------
void CPlayerPanel::OnKickButtonPressed() { if (m_pPlayerListPanel->GetSelectedItemsCount() < 1) return;
// open a message box to ask the user if they want to follow through on this
QueryBox *box; if (m_pPlayerListPanel->GetSelectedItemsCount() > 1) { box = new QueryBox("#Kick_Multiple_Players_Title", "#Kick_Multiple_Players_Question"); } else { // show the player name in the message box if only one player is being booted
KeyValues *kv = m_pPlayerListPanel->GetItem(m_pPlayerListPanel->GetSelectedItem(0)); Assert(kv != NULL); if (!kv) return;
wchar_t playerName[64]; g_pVGuiLocalize->ConvertANSIToUnicode( kv->GetString("name"), playerName, sizeof(playerName) );
wchar_t msg[512]; g_pVGuiLocalize->ConstructString( msg, sizeof(msg), g_pVGuiLocalize->Find("Kick_Single_Player_Question"), 1, playerName ); box = new QueryBox(g_pVGuiLocalize->Find("#Kick_Single_Player_Title"), msg); } box->AddActionSignalTarget(this); box->SetOKCommand(new KeyValues("KickSelectedPlayers")); box->ShowWindow(); }
//-----------------------------------------------------------------------------
// Purpose: Prompts a user to be banned
//-----------------------------------------------------------------------------
void CPlayerPanel::OnBanButtonPressed() { if (m_pPlayerListPanel->GetSelectedItemsCount() != 1) return;
// open a message box to ask the user if they want to follow through on this
KeyValues *kv = m_pPlayerListPanel->GetItem(m_pPlayerListPanel->GetSelectedItem(0)); Assert(kv != NULL); if (!kv) return;
const char *player = kv->GetString("name"); const char *authid = kv->GetString("authid"); const char *netAdr = kv->GetString("netAdr");
char buf[64]; if ( !strcmp( authid, "UNKNOWN" ) ) { int s1, s2, s3, s4; if (4 == sscanf(netAdr, "%d.%d.%d.%d", &s1, &s2, &s3, &s4)) { Q_snprintf( buf, sizeof(buf), "%d.%d.%d.%d", s1, s2, s3, s4 ); authid = buf; } }
CDialogAddBan *box = new CDialogAddBan(this); box->AddActionSignalTarget(this); box->Activate("addban", player, authid); }
//-----------------------------------------------------------------------------
// Purpose: Kicks all the players currently selected
//-----------------------------------------------------------------------------
void CPlayerPanel::KickSelectedPlayers() { for (int i = 0; i < m_pPlayerListPanel->GetSelectedItemsCount(); i++) { // get the player info
int row = m_pPlayerListPanel->GetSelectedItem(i); KeyValues *pl = m_pPlayerListPanel->GetItem(row); if (!pl) continue;
// kick 'em
char cmd[512]; _snprintf(cmd, sizeof(cmd), "kick \"%s\"", pl->GetString("name")); RemoteServer().SendCommand(cmd); }
m_pPlayerListPanel->ClearSelectedItems(); m_pKickButton->SetEnabled(false); m_pBanButton->SetEnabled(false); OnResetData(); }
//-----------------------------------------------------------------------------
// Purpose: Adds a new ban
//-----------------------------------------------------------------------------
void CPlayerPanel::AddBanByID(const char *id, const char *newtime) { Assert(id && *id); if (!id || !*id) return;
// if the newtime string is not valid, then set it to 0 (permanent ban)
if (!newtime || atof(newtime) < 0.001) { newtime = "0"; }
const char *banCmd = "banid"; const char *saveCmd = "writeip"; int s1, s2, s3, s4; if (4 == sscanf(id, "%d.%d.%d.%d", &s1, &s2, &s3, &s4)) { banCmd = "addip"; saveCmd = "writeid"; }
// send down the ban command
char cmd[512]; _snprintf(cmd, sizeof(cmd) -1, "%s %s %s\n", banCmd, newtime, id); RemoteServer().SendCommand(cmd);
// force the file to update
RemoteServer().SendCommand(saveCmd);
// refresh
OnResetData(); }
//-----------------------------------------------------------------------------
// Purpose: opens context menu (user right clicked on a server)
//-----------------------------------------------------------------------------
void CPlayerPanel::OnOpenContextMenu(int itemID) { /* CODE DISABLED UNTIL VERIFIED AS WORKING
// show the player menus only if the cursor is over it
if (IsCursorOver() && m_pPlayerListPanel->GetNumSelectedRows()) { // get the server
unsigned int playerID = m_pPlayerListPanel->GetDataItem(m_pPlayerListPanel->GetSelectedRow(0))->userData; // activate context menu
m_pPlayerContextMenu->ShowMenu(this, playerID); } */ }
//-----------------------------------------------------------------------------
// Purpose: called when an item on the list panel is selected.
//-----------------------------------------------------------------------------
void CPlayerPanel::OnItemSelected() { bool state = true;
if ( m_pPlayerListPanel->GetSelectedItemsCount() == 0 ) { state = false; }
m_pKickButton->SetEnabled(state); m_pBanButton->SetEnabled(state);
if ( m_pPlayerListPanel->GetSelectedItemsCount() > 1 ) { m_pBanButton->SetEnabled(false); } }
|