//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============ // // Purpose: // // $NoKeywords: $ //============================================================================= #include #include #include #include #include #include #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 ) { ClientCmd( "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 ); ClientCmd( 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(); }