halflife25-sdk/cl_dll/vgui_ServerBrowser.cpp
2013-08-30 13:34:05 -07:00

623 lines
13 KiB
C++

//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include<VGUI_HeaderPanel.h>
#include<VGUI_TablePanel.h>
#include<VGUI_LineBorder.h>
#include<VGUI_Label.h>
#include<VGUI_Button.h>
#include<VGUI_ActionSignal.h>
#include "hud.h"
#include "cl_util.h"
#include "hud_servers.h"
#include "net_api.h"
#include "vgui_TeamFortressViewport.h"
#include "vgui_ServerBrowser.h"
using namespace vgui;
namespace
{
#define MAX_SB_ROWS 24
#define NUM_COLUMNS 5
#define HEADER_SIZE_Y YRES(18)
// Column sizes
#define CSIZE_ADDRESS XRES(200)
#define CSIZE_SERVER XRES(400)
#define CSIZE_MAP XRES(500)
#define CSIZE_CURRENT XRES(570)
#define CSIZE_PING XRES(640)
#define CELL_HEIGHT YRES(15)
class ServerBrowserTablePanel;
class CBrowser_InputSignal : public InputSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
CBrowser_InputSignal( ServerBrowserTablePanel *pBrowser )
{
m_pBrowser = pBrowser;
}
virtual void cursorMoved(int x,int y,Panel* panel) {};
virtual void cursorEntered(Panel* panel){};
virtual void cursorExited(Panel* Panel) {};
virtual void mousePressed(MouseCode code,Panel* panel);
virtual void mouseDoublePressed(MouseCode code,Panel* panel);
virtual void mouseReleased(MouseCode code,Panel* panel) {};
virtual void mouseWheeled(int delta,Panel* panel) {};
virtual void keyPressed(KeyCode code,Panel* panel) {};
virtual void keyTyped(KeyCode code,Panel* panel) {};
virtual void keyReleased(KeyCode code,Panel* panel) {};
virtual void keyFocusTicked(Panel* panel) {};
};
class ServerBrowserTablePanel : public TablePanel
{
private:
Label *m_pLabel;
int m_nMouseOverRow;
public:
ServerBrowserTablePanel( int x,int y,int wide,int tall,int columnCount) : TablePanel( x,y,wide,tall,columnCount)
{
m_pLabel = new Label( "", 0, 0 /*,wide, tall*/ );
m_nMouseOverRow = 0;
}
public:
void setMouseOverRow( int row )
{
m_nMouseOverRow = row;
}
void DoSort( char *sortkey )
{
// Request server list and refresh servers...
SortServers( sortkey );
}
void DoRefresh( void )
{
// Request server list and refresh servers...
ServersList();
BroadcastServersList( 0 );
}
void DoBroadcastRefresh( void )
{
// Request server list and refresh servers...
BroadcastServersList( 1 );
}
void DoStop( void )
{
// Stop requesting
ServersCancel();
}
void DoCancel( void )
{
EngineClientCmd( "togglebrowser\n" );
}
void DoConnect( void )
{
const char *info;
const char *address;
char sz[ 256 ];
info = ServersGetInfo( m_nMouseOverRow );
if ( !info )
return;
address = gEngfuncs.pNetAPI->ValueForKey( info, "address" );
//gEngfuncs.Con_Printf( "Connecting to %s\n", address );
sprintf( sz, "connect %s\n", address );
EngineClientCmd( sz );
DoCancel();
}
void DoPing( void )
{
ServerPing( 0 );
ServerRules( 0 );
ServerPlayers( 0 );
}
virtual int getRowCount()
{
int rowcount;
int height, width;
getSize( width, height );
// Space for buttons
height -= YRES(20);
height = max( 0, height );
rowcount = height / CELL_HEIGHT;
return rowcount;
}
virtual int getCellTall(int row)
{
return CELL_HEIGHT - 2;
}
virtual Panel* getCellRenderer(int column,int row,bool columnSelected,bool rowSelected,bool cellSelected)
{
const char *info;
const char *val, *val2;
char sz[ 32 ];
info = ServersGetInfo( row );
if ( row == m_nMouseOverRow )
{
m_pLabel->setFgColor( 200, 240, 63, 100 );
}
else
{
m_pLabel->setFgColor( 255, 255, 255, 0 );
}
m_pLabel->setBgColor( 0, 0, 0, 200 );
m_pLabel->setContentAlignment( vgui::Label::a_west );
m_pLabel->setFont( Scheme::sf_primary2 );
if ( info )
{
// Fill out with the correct data
switch ( column )
{
case 0:
val = gEngfuncs.pNetAPI->ValueForKey( info, "address" );
if ( val )
{
strncpy( sz, val, 31 );
sz[ 31 ] = '\0';
// Server Name;
m_pLabel->setText( sz );
}
break;
case 1:
val = gEngfuncs.pNetAPI->ValueForKey( info, "hostname" );
if ( val )
{
strncpy( sz, val, 31 );
sz[ 31 ] = '\0';
// Server Map;
m_pLabel->setText( sz );
}
break;
case 2:
val = gEngfuncs.pNetAPI->ValueForKey( info, "map" );
if ( val )
{
strncpy( sz, val, 31 );
sz[ 31 ] = '\0';
// Server Name;
m_pLabel->setText( sz );
}
break;
case 3:
val = gEngfuncs.pNetAPI->ValueForKey( info, "current" );
val2 = gEngfuncs.pNetAPI->ValueForKey( info, "max" );
if ( val && val2 )
{
sprintf( sz, "%s/%s", val, val2 );
sz[ 31 ] = '\0';
// Server Map;
m_pLabel->setText( sz );
}
break;
case 4:
val = gEngfuncs.pNetAPI->ValueForKey( info, "ping" );
if ( val )
{
strncpy( sz, val, 31 );
sz[ 31 ] = '\0';
// Server Name;
m_pLabel->setText( sz );
}
break;
default:
break;
}
}
else
{
if ( !row && !column )
{
if ( ServersIsQuerying() )
{
m_pLabel->setText( "Waiting for servers to respond..." );
}
else
{
m_pLabel->setText( "Press 'Refresh' to search for servers..." );
}
}
else
{
m_pLabel->setText( "" );
}
}
return m_pLabel;
}
virtual Panel* startCellEditing(int column,int row)
{
return null;
}
};
class ConnectHandler : public ActionSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
ConnectHandler( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
}
virtual void actionPerformed( Panel *panel )
{
m_pBrowser->DoConnect();
}
};
class RefreshHandler : public ActionSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
RefreshHandler( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
}
virtual void actionPerformed( Panel *panel )
{
m_pBrowser->DoRefresh();
}
};
class BroadcastRefreshHandler : public ActionSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
BroadcastRefreshHandler( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
}
virtual void actionPerformed( Panel *panel )
{
m_pBrowser->DoBroadcastRefresh();
}
};
class StopHandler : public ActionSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
StopHandler( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
}
virtual void actionPerformed( Panel *panel )
{
m_pBrowser->DoStop();
}
};
class CancelHandler : public ActionSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
CancelHandler( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
}
virtual void actionPerformed( Panel *panel )
{
m_pBrowser->DoCancel();
}
};
class PingHandler : public ActionSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
PingHandler( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
}
virtual void actionPerformed( Panel *panel )
{
m_pBrowser->DoPing();
}
};
class SortHandler : public ActionSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
SortHandler( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
}
virtual void actionPerformed( Panel *panel )
{
m_pBrowser->DoSort( "map" );
}
};
}
class LabelSortInputHandler : public InputSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
char m_szSortKey[ 64 ];
public:
LabelSortInputHandler( ServerBrowserTablePanel *pBrowser, char *name )
{
m_pBrowser = pBrowser;
strcpy( m_szSortKey, name );
}
virtual void cursorMoved(int x,int y,Panel* panel) {};
virtual void cursorEntered(Panel* panel){};
virtual void cursorExited(Panel* Panel) {};
virtual void mousePressed(MouseCode code,Panel* panel)
{
m_pBrowser->DoSort( m_szSortKey );
}
virtual void mouseDoublePressed(MouseCode code,Panel* panel)
{
m_pBrowser->DoSort( m_szSortKey );
}
virtual void mouseReleased(MouseCode code,Panel* panel) {};
virtual void mouseWheeled(int delta,Panel* panel) {};
virtual void keyPressed(KeyCode code,Panel* panel) {};
virtual void keyTyped(KeyCode code,Panel* panel) {};
virtual void keyReleased(KeyCode code,Panel* panel) {};
virtual void keyFocusTicked(Panel* panel) {};
};
class CSBLabel : public Label
{
private:
char m_szSortKey[ 64 ];
ServerBrowserTablePanel *m_pBrowser;
public:
CSBLabel( char *name, char *sortkey ) : Label( name )
{
m_pBrowser = NULL;
strcpy( m_szSortKey, sortkey );
int label_bg_r = 120,
label_bg_g = 75,
label_bg_b = 32,
label_bg_a = 200;
int label_fg_r = 255,
label_fg_g = 0,
label_fg_b = 0,
label_fg_a = 0;
setContentAlignment( vgui::Label::a_west );
setFgColor( label_fg_r, label_fg_g, label_fg_b, label_fg_a );
setBgColor( label_bg_r, label_bg_g, label_bg_b, label_bg_a );
setFont( Scheme::sf_primary2 );
}
void setTable( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
addInputSignal( new LabelSortInputHandler( (ServerBrowserTablePanel * )m_pBrowser, m_szSortKey ) );
}
};
ServerBrowser::ServerBrowser(int x,int y,int wide,int tall) : CTransparentPanel( 100, x,y,wide,tall )
{
int i;
_headerPanel = new HeaderPanel(0,0,wide,HEADER_SIZE_Y);
_headerPanel->setParent(this);
_headerPanel->setFgColor( 100,100,100, 100 );
_headerPanel->setBgColor( 0, 0, 0, 100 );
CSBLabel *pLabel[5];
pLabel[0] = new CSBLabel( "Address", "address" );
pLabel[1] = new CSBLabel( "Server", "hostname" );
pLabel[2] = new CSBLabel( "Map", "map" );
pLabel[3] = new CSBLabel( "Current", "current" );
pLabel[4] = new CSBLabel( "Latency", "ping" );
for ( i = 0; i < 5; i++ )
{
_headerPanel->addSectionPanel( pLabel[i] );
}
// _headerPanel->setFont( Scheme::sf_primary1 );
_headerPanel->setSliderPos( 0, CSIZE_ADDRESS );
_headerPanel->setSliderPos( 1, CSIZE_SERVER );
_headerPanel->setSliderPos( 2, CSIZE_MAP );
_headerPanel->setSliderPos( 3, CSIZE_CURRENT );
_headerPanel->setSliderPos( 4, CSIZE_PING );
_tablePanel = new ServerBrowserTablePanel( 0, HEADER_SIZE_Y, wide, tall - HEADER_SIZE_Y, NUM_COLUMNS );
_tablePanel->setParent(this);
_tablePanel->setHeaderPanel(_headerPanel);
_tablePanel->setFgColor( 100,100,100, 100 );
_tablePanel->setBgColor( 0, 0, 0, 100 );
_tablePanel->addInputSignal( new CBrowser_InputSignal( (ServerBrowserTablePanel *)_tablePanel ) );
for ( i = 0; i < 5; i++ )
{
pLabel[i]->setTable( (ServerBrowserTablePanel * )_tablePanel );
}
int bw = 80, bh = 15;
int by = tall - HEADER_SIZE_Y;
int btnx = 10;
_connectButton = new CommandButton( "Connect", btnx, by, bw, bh );
_connectButton->setParent( this );
_connectButton->addActionSignal( new ConnectHandler( (ServerBrowserTablePanel * )_tablePanel ) );
btnx += bw;
_refreshButton = new CommandButton( "Refresh", btnx, by, bw, bh );
_refreshButton->setParent( this );
_refreshButton->addActionSignal( new RefreshHandler( (ServerBrowserTablePanel * )_tablePanel ) );
/*
btnx += bw;
_broadcastRefreshButton = new CommandButton( "LAN", btnx, by, bw, bh );
_broadcastRefreshButton->setParent( this );
_broadcastRefreshButton->addActionSignal( new BroadcastRefreshHandler( (ServerBrowserTablePanel * )_tablePanel ) );
*/
btnx += bw;
_stopButton = new CommandButton( "Stop", btnx, by, bw, bh );
_stopButton->setParent( this );
_stopButton->addActionSignal( new StopHandler( (ServerBrowserTablePanel * )_tablePanel ) );
/*
btnx += bw;
_pingButton = new CommandButton( "Test", btnx, by, bw, bh );
_pingButton->setParent( this );
_pingButton->addActionSignal( new PingHandler( (ServerBrowserTablePanel * )_tablePanel ) );
btnx += bw;
_sortButton = new CommandButton( "Sort", btnx, by, bw, bh );
_sortButton->setParent( this );
_sortButton->addActionSignal( new SortHandler( (ServerBrowserTablePanel * )_tablePanel ) );
*/
btnx += bw;
_cancelButton = new CommandButton( "Close", btnx, by, bw, bh );
_cancelButton->setParent( this );
_cancelButton->addActionSignal( new CancelHandler( (ServerBrowserTablePanel * )_tablePanel ) );
setPaintBorderEnabled(false);
setPaintBackgroundEnabled(false);
setPaintEnabled(false);
}
void ServerBrowser::setSize(int wide,int tall)
{
Panel::setSize(wide,tall);
_headerPanel->setBounds(0,0,wide,HEADER_SIZE_Y);
_tablePanel->setBounds(0,HEADER_SIZE_Y,wide,tall - HEADER_SIZE_Y);
_connectButton->setBounds( 5, tall - HEADER_SIZE_Y, 75, 15 );
_refreshButton->setBounds( 85, tall - HEADER_SIZE_Y, 75, 15 );
/*
_broadcastRefreshButton->setBounds( 165, tall - HEADER_SIZE_Y, 75, 15 );
*/
_stopButton->setBounds( 165, tall - HEADER_SIZE_Y, 75, 15 );
/*
_pingButton->setBounds( 325, tall - HEADER_SIZE_Y, 75, 15 );
*/
_cancelButton->setBounds( 245, tall - HEADER_SIZE_Y, 75, 15 );
}
void CBrowser_InputSignal::mousePressed(MouseCode code,Panel* panel)
{
int x, y;
int therow = 2;
if ( code != MOUSE_LEFT )
return;
panel->getApp()->getCursorPos(x,y);
panel->screenToLocal( x, y );
therow = y / CELL_HEIGHT;
// Figure out which row it's on
m_pBrowser->setMouseOverRow( therow );
}
void CBrowser_InputSignal::mouseDoublePressed(MouseCode code,Panel* panel)
{
int x, y;
int therow = 2;
if ( code != MOUSE_LEFT )
return;
panel->getApp()->getCursorPos(x,y);
panel->screenToLocal( x, y );
therow = y / CELL_HEIGHT;
// Figure out which row it's on
m_pBrowser->setMouseOverRow( therow );
m_pBrowser->DoConnect();
}