This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,325 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef BASEGAMESPAGE_H
#define BASEGAMESPAGE_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utldict.h"
class CBaseGamesPage;
//-----------------------------------------------------------------------------
// Purpose: Acts like a regular ListPanel but forwards enter key presses
// to its outer control.
//-----------------------------------------------------------------------------
class CGameListPanel : public vgui::ListPanel
{
public:
DECLARE_CLASS_SIMPLE( CGameListPanel, vgui::ListPanel );
CGameListPanel( CBaseGamesPage *pOuter, const char *pName );
virtual void OnKeyCodePressed(vgui::KeyCode code);
private:
CBaseGamesPage *m_pOuter;
};
class CQuickListMapServerList : public CUtlVector< int >
{
public:
CQuickListMapServerList() : CUtlVector< int >( 1, 0 )
{
}
CQuickListMapServerList( const CQuickListMapServerList& src )
{
CopyArray( src.Base(), src.Count() );
}
CQuickListMapServerList &operator=( const CQuickListMapServerList &src )
{
CopyArray( src.Base(), src.Count() );
return *this;
}
};
class CCheckBoxWithStatus : public vgui::CheckButton
{
public:
DECLARE_CLASS_SIMPLE( CCheckBoxWithStatus, vgui::CheckButton );
CCheckBoxWithStatus(Panel *parent, const char *panelName, const char *text) : vgui::CheckButton( parent, panelName, text )
{
}
virtual void OnCursorEntered();
virtual void OnCursorExited();
};
struct servermaps_t
{
const char *pOriginalName;
const char *pFriendlyName;
int iPanelIndex;
bool bOnDisk;
};
struct gametypes_t
{
const char *pPrefix;
const char *pGametypeName;
};
//-----------------------------------------------------------------------------
// Purpose: Base property page for all the games lists (internet/favorites/lan/etc.)
//-----------------------------------------------------------------------------
class CBaseGamesPage : public vgui::PropertyPage, public IGameList, public ISteamMatchmakingServerListResponse, public ISteamMatchmakingPingResponse
{
DECLARE_CLASS_SIMPLE( CBaseGamesPage, vgui::PropertyPage );
public:
enum EPageType
{
eInternetServer,
eLANServer,
eFriendsServer,
eFavoritesServer,
eHistoryServer,
eSpectatorServer
};
// Column indices
enum
{
k_nColumn_Password = 0,
k_nColumn_Secure = 1,
k_nColumn_Replay = 2,
k_nColumn_Name = 3,
k_nColumn_IPAddr = 4,
k_nColumn_GameDesc = 5,
k_nColumn_Players = 6,
k_nColumn_Bots = 7,
k_nColumn_Map = 8,
k_nColumn_Ping = 9,
};
CBaseGamesPage( vgui::Panel *parent, const char *name, EPageType eType, const char *pCustomResFilename=NULL);
~CBaseGamesPage();
virtual void PerformLayout();
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
// gets information about specified server
virtual gameserveritem_t *GetServer(unsigned int serverID);
virtual const char *GetConnectCode();
uint32 GetServerFilters( MatchMakingKeyValuePair_t **pFilters );
virtual void SetRefreshing(bool state);
// loads filter settings from disk
virtual void LoadFilterSettings();
// Called by CGameList when the enter key is pressed.
// This is overridden in the add server dialog - since there is no Connect button, the message
// never gets handled, but we want to add a server when they dbl-click or press enter.
virtual bool OnGameListEnterPressed();
int GetSelectedItemsCount();
// adds a server to the favorites
MESSAGE_FUNC( OnAddToFavorites, "AddToFavorites" );
MESSAGE_FUNC( OnAddToBlacklist, "AddToBlacklist" );
virtual void StartRefresh();
virtual void UpdateDerivedLayouts( void );
void PrepareQuickListMap( const char *pMapName, int iListID );
void SelectQuickListServers( void );
vgui::Panel *GetActiveList( void );
virtual bool IsQuickListButtonChecked()
{
return m_pQuickListCheckButton ? m_pQuickListCheckButton->IsSelected() : false;
}
STEAM_CALLBACK( CBaseGamesPage, OnFavoritesMsg, FavoritesListChanged_t, m_CallbackFavoritesMsg );
// applies games filters to current list
void ApplyGameFilters();
void OnLoadingStarted()
{
StopRefresh();
}
protected:
virtual void OnCommand(const char *command);
virtual void OnKeyCodePressed(vgui::KeyCode code);
virtual int GetRegionCodeToFilter() { return 255; }
MESSAGE_FUNC( OnItemSelected, "ItemSelected" );
// updates server count UI
void UpdateStatus();
// ISteamMatchmakingServerListResponse callbacks
virtual void ServerResponded( HServerListRequest hReq, int iServer );
virtual void ServerResponded( int iServer, gameserveritem_t *pServerItem );
virtual void ServerFailedToRespond( HServerListRequest hReq, int iServer );
virtual void RefreshComplete( HServerListRequest hReq, EMatchMakingServerResponse response ) = 0;
// ISteamMatchmakingPingResponse callbacks
virtual void ServerResponded( gameserveritem_t &server );
virtual void ServerFailedToRespond() {}
// Removes server from list
void RemoveServer( serverdisplay_t &server );
virtual bool BShowServer( serverdisplay_t &server ) { return server.m_bDoNotRefresh; }
void ClearServerList();
// filtering methods
// returns true if filters passed; false if failed
virtual bool CheckPrimaryFilters( gameserveritem_t &server);
virtual bool CheckSecondaryFilters( gameserveritem_t &server );
virtual bool CheckTagFilter( gameserveritem_t &server ) { return true; }
virtual bool CheckWorkshopFilter( gameserveritem_t &server ) { return true; }
virtual int GetInvalidServerListID();
virtual void OnSaveFilter(KeyValues *filter);
virtual void OnLoadFilter(KeyValues *filter);
virtual void UpdateFilterSettings();
// whether filter settings limit which master server to query
CGameID &GetFilterAppID() { return m_iLimitToAppID; }
virtual void GetNewServerList();
virtual void StopRefresh();
virtual bool IsRefreshing();
virtual void OnPageShow();
virtual void OnPageHide();
// called when Connect button is pressed
MESSAGE_FUNC( OnBeginConnect, "ConnectToServer" );
// called to look at game info
MESSAGE_FUNC( OnViewGameInfo, "ViewGameInfo" );
// refreshes a single server
MESSAGE_FUNC_INT( OnRefreshServer, "RefreshServer", serverID );
// If true, then we automatically select the first item that comes into the games list.
bool m_bAutoSelectFirstItemInGameList;
CGameListPanel *m_pGameList;
vgui::PanelListPanel *m_pQuickList;
vgui::ComboBox *m_pLocationFilter;
// command buttons
vgui::Button *m_pConnect;
vgui::Button *m_pRefreshAll;
vgui::Button *m_pRefreshQuick;
vgui::Button *m_pAddServer;
vgui::Button *m_pAddCurrentServer;
vgui::Button *m_pAddToFavoritesButton;
vgui::ToggleButton *m_pFilter;
CUtlMap<uint64, int> m_mapGamesFilterItem;
CUtlMap<int, serverdisplay_t> m_mapServers;
CUtlMap<netadr_t, int> m_mapServerIP;
CUtlVector<MatchMakingKeyValuePair_t> m_vecServerFilters;
CUtlDict< CQuickListMapServerList, int > m_quicklistserverlist;
int m_iServerRefreshCount;
CUtlVector< servermaps_t > m_vecMapNamesFound;
EPageType m_eMatchMakingType;
HServerListRequest m_hRequest;
int GetSelectedServerID( KeyValues **pKV = NULL );
void ClearQuickList( void );
bool TagsExclude( void );
enum eWorkshopMode {
// These correspond to the dropdown indices
eWorkshop_None = 0,
eWorkshop_WorkshopOnly = 1,
eWorkshop_SubscribedOnly = 2
};
eWorkshopMode WorkshopMode();
void HideReplayFilter( void );
protected:
virtual void CreateFilters();
virtual void UpdateGameFilter();
MESSAGE_FUNC_PTR_CHARPTR( OnTextChanged, "TextChanged", panel, text );
MESSAGE_FUNC_PTR_INT( OnButtonToggled, "ButtonToggled", panel, state );
void UpdateFilterAndQuickListVisibility();
bool BFiltersVisible() { return m_bFiltersVisible; }
private:
void RequestServersResponse( int iServer, EMatchMakingServerResponse response, bool bLastServer ); // callback for matchmaking interface
void RecalculateFilterString();
void SetQuickListEnabled( bool bEnabled );
void SetFiltersVisible( bool bVisible );
// If set, it uses the specified resfile name instead of its default one.
const char *m_pCustomResFilename;
// filter controls
vgui::ComboBox *m_pGameFilter;
vgui::TextEntry *m_pMapFilter;
vgui::TextEntry *m_pMaxPlayerFilter;
vgui::ComboBox *m_pPingFilter;
vgui::ComboBox *m_pSecureFilter;
vgui::ComboBox *m_pTagsIncludeFilter;
vgui::ComboBox *m_pWorkshopFilter;
vgui::CheckButton *m_pNoFullServersFilterCheck;
vgui::CheckButton *m_pNoEmptyServersFilterCheck;
vgui::CheckButton *m_pNoPasswordFilterCheck;
CCheckBoxWithStatus *m_pQuickListCheckButton;
vgui::Label *m_pFilterString;
char m_szComboAllText[64];
vgui::CheckButton *m_pReplayFilterCheck;
KeyValues *m_pFilters; // base filter data
bool m_bFiltersVisible; // true if filter section is currently visible
vgui::HFont m_hFont;
int m_nImageIndexPassword;
int m_nImageIndexSecure;
int m_nImageIndexSecureVacBanned;
int m_nImageIndexReplay;
// filter data
char m_szGameFilter[32];
char m_szMapFilter[32];
int m_iMaxPlayerFilter;
int m_iPingFilter;
bool m_bFilterNoFullServers;
bool m_bFilterNoEmptyServers;
bool m_bFilterNoPasswordedServers;
int m_iSecureFilter;
int m_iServersBlacklisted;
bool m_bFilterReplayServers;
CGameID m_iLimitToAppID;
};
#endif // BASEGAMESPAGE_H

View File

@ -0,0 +1,500 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "pch_serverbrowser.h"
using namespace vgui;
ConVar sb_showblacklists( "sb_showblacklists", "0", FCVAR_NONE, "If set to 1, blacklist rules will be printed to the console as they're applied." );
//-----------------------------------------------------------------------------
// Purpose: Server name comparison function
//-----------------------------------------------------------------------------
int __cdecl BlacklistedServerNameCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
blacklisted_server_t *pSvr1 = ServerBrowserDialog().GetBlacklistPage()->GetBlacklistedServer( p1.userData );
blacklisted_server_t *pSvr2 = ServerBrowserDialog().GetBlacklistPage()->GetBlacklistedServer( p2.userData );
if ( !pSvr1 && pSvr2 )
return -1;
if ( !pSvr2 && pSvr1 )
return 1;
if ( !pSvr1 && !pSvr2 )
return 0;
return Q_stricmp( pSvr1->m_szServerName, pSvr2->m_szServerName );
}
//-----------------------------------------------------------------------------
// Purpose: list column sort function
//-----------------------------------------------------------------------------
int __cdecl BlacklistedIPAddressCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
blacklisted_server_t *pSvr1 = ServerBrowserDialog().GetBlacklistPage()->GetBlacklistedServer( p1.userData );
blacklisted_server_t *pSvr2 = ServerBrowserDialog().GetBlacklistPage()->GetBlacklistedServer( p2.userData );
if ( !pSvr1 && pSvr2 )
return -1;
if ( !pSvr2 && pSvr1 )
return 1;
if ( !pSvr1 && !pSvr2 )
return 0;
if ( pSvr1->m_NetAdr < pSvr2->m_NetAdr )
return -1;
else if ( pSvr2->m_NetAdr < pSvr1->m_NetAdr )
return 1;
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: Player number comparison function
//-----------------------------------------------------------------------------
int __cdecl BlacklistedAtCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
blacklisted_server_t *pSvr1 = ServerBrowserDialog().GetBlacklistPage()->GetBlacklistedServer( p1.userData );
blacklisted_server_t *pSvr2 = ServerBrowserDialog().GetBlacklistPage()->GetBlacklistedServer( p2.userData );
if ( !pSvr1 && pSvr2 )
return -1;
if ( !pSvr2 && pSvr1 )
return 1;
if ( !pSvr1 && !pSvr2 )
return 0;
if ( pSvr1->m_ulTimeBlacklistedAt > pSvr2->m_ulTimeBlacklistedAt )
return -1;
if ( pSvr1->m_ulTimeBlacklistedAt < pSvr2->m_ulTimeBlacklistedAt )
return 1;
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CBlacklistedServers::CBlacklistedServers( vgui::Panel *parent ) :
vgui::PropertyPage( parent, "BlacklistedGames" )
{
SetSize( 624, 278 );
m_pAddServer = new Button(this, "AddServerButton", "#ServerBrowser_AddServer");
m_pAddCurrentServer = new Button(this, "AddCurrentServerButton", "#ServerBrowser_AddCurrentServer");
m_pGameList = vgui::SETUP_PANEL( new vgui::ListPanel(this, "gamelist") );
m_pGameList->SetAllowUserModificationOfColumns(true);
// Add the column headers
m_pGameList->AddColumnHeader(0, "Name", "#ServerBrowser_BlacklistedServers", 50, ListPanel::COLUMN_RESIZEWITHWINDOW | ListPanel::COLUMN_UNHIDABLE);
m_pGameList->AddColumnHeader(1, "IPAddr", "#ServerBrowser_IPAddress", 64, ListPanel::COLUMN_HIDDEN);
m_pGameList->AddColumnHeader(2, "BlacklistedAt", "#ServerBrowser_BlacklistedDate", 100);
//m_pGameList->SetColumnHeaderTooltip(0, "#ServerBrowser_PasswordColumn_Tooltip");
// setup fast sort functions
m_pGameList->SetSortFunc(0, BlacklistedServerNameCompare);
m_pGameList->SetSortFunc(1, BlacklistedIPAddressCompare);
m_pGameList->SetSortFunc(2, BlacklistedAtCompare);
// Sort by name by default
m_pGameList->SetSortColumn(0);
m_blackList.Reset();
m_blackListTimestamp = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CBlacklistedServers::~CBlacklistedServers()
{
ClearServerList();
}
//-----------------------------------------------------------------------------
// Purpose: loads the initial blacklist from disk
//-----------------------------------------------------------------------------
void CBlacklistedServers::LoadBlacklistedList()
{
m_pGameList->SetEmptyListText("#ServerBrowser_NoBlacklistedServers");
ClearServerList();
m_blackList.Reset();
int count = m_blackList.LoadServersFromFile( BLACKLIST_DEFAULT_SAVE_FILE, false );
m_blackListTimestamp = g_pFullFileSystem->GetFileTime( BLACKLIST_DEFAULT_SAVE_FILE );
for( int i=0; i<count; ++i )
{
UpdateBlacklistUI( m_blackList.GetServer(i) );
}
}
//-----------------------------------------------------------------------------
// Purpose: adds all the servers inside the specified file to the blacklist
//-----------------------------------------------------------------------------
bool CBlacklistedServers::AddServersFromFile( const char *pszFilename, bool bResetTimes )
{
KeyValues *pKV = new KeyValues( "serverblacklist" );
if ( !pKV->LoadFromFile( g_pFullFileSystem, pszFilename, "GAME" ) )
return false;
for ( KeyValues *pData = pKV->GetFirstSubKey(); pData != NULL; pData = pData->GetNextKey() )
{
const char *pszName = pData->GetString( "name" );
uint32 ulDate = pData->GetInt( "date" );
if ( bResetTimes )
{
time_t today;
time( &today );
ulDate = today;
}
const char *pszNetAddr = pData->GetString( "addr" );
if ( pszNetAddr && pszNetAddr[0] && pszName && pszName[0] )
{
blacklisted_server_t *blackServer = m_blackList.AddServer( pszName, pszNetAddr, ulDate );
UpdateBlacklistUI( blackServer );
}
}
// write out blacklist to preserve changes
SaveBlacklistedList();
pKV->deleteThis();
return true;
}
//-----------------------------------------------------------------------------
// Purpose: save blacklist to disk
//-----------------------------------------------------------------------------
void CBlacklistedServers::SaveBlacklistedList()
{
m_blackList.SaveToFile( BLACKLIST_DEFAULT_SAVE_FILE );
m_blackListTimestamp = g_pFullFileSystem->GetFileTime( BLACKLIST_DEFAULT_SAVE_FILE );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlacklistedServers::AddServer( gameserveritem_t &server )
{
blacklisted_server_t *blackServer = m_blackList.AddServer( server );
if ( !blackServer )
{
return;
}
SaveBlacklistedList();
UpdateBlacklistUI( blackServer );
if ( GameSupportsReplay() )
{
// send command to propagate to the client so the client can send it on to the GC
char command[ 256 ];
Q_snprintf( command, Q_ARRAYSIZE( command ), "rbgc %s\n", blackServer->m_NetAdr.ToString() );
g_pRunGameEngine->AddTextCommand( command );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
blacklisted_server_t *CBlacklistedServers::GetBlacklistedServer( int iServerID )
{
return m_blackList.GetServer( iServerID );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CBlacklistedServers::IsServerBlacklisted( gameserveritem_t &server )
{
// if something has changed the blacklist file, reload it
if ( g_pFullFileSystem->GetFileTime( BLACKLIST_DEFAULT_SAVE_FILE ) != m_blackListTimestamp )
{
LoadBlacklistedList();
}
return m_blackList.IsServerBlacklisted( server );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlacklistedServers::UpdateBlacklistUI( blacklisted_server_t *blackServer )
{
if ( !blackServer )
return;
KeyValues *kv;
int iItemId = m_pGameList->GetItemIDFromUserData( blackServer->m_nServerID );
if ( m_pGameList->IsValidItemID( iItemId ) )
{
// we're updating an existing entry
kv = m_pGameList->GetItem( iItemId );
m_pGameList->SetUserData( iItemId, blackServer->m_nServerID );
}
else
{
// new entry
kv = new KeyValues("Server");
}
kv->SetString( "name", blackServer->m_szServerName );
// construct a time string for blacklisted time
struct tm *now;
now = localtime( (time_t*)&blackServer->m_ulTimeBlacklistedAt );
if ( now )
{
char buf[64];
strftime(buf, sizeof(buf), "%a %d %b %I:%M%p", now);
Q_strlower(buf + strlen(buf) - 4);
kv->SetString("BlacklistedAt", buf);
}
kv->SetString( "IPAddr", blackServer->m_NetAdr.ToString() );
if ( !m_pGameList->IsValidItemID( iItemId ) )
{
// new server, add to list
iItemId = m_pGameList->AddItem(kv, blackServer->m_nServerID, false, false);
kv->deleteThis();
}
else
{
// tell the list that we've changed the data
m_pGameList->ApplyItemChanges( iItemId );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlacklistedServers::ApplySchemeSettings(vgui::IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
const char *pPathID = "PLATFORM";
const char *pszFileName = "servers/BlacklistedServersPage.res";
if ( g_pFullFileSystem->FileExists( pszFileName, "MOD" ) )
{
pPathID = "MOD";
}
LoadControlSettings( pszFileName, pPathID );
vgui::HFont hFont = pScheme->GetFont( "ListSmall", IsProportional() );
if ( !hFont )
{
hFont = pScheme->GetFont( "DefaultSmall", IsProportional() );
}
m_pGameList->SetFont( hFont );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlacklistedServers::OnPageShow( void )
{
// reload list since client may have changed it
LoadBlacklistedList();
m_pGameList->SetEmptyListText("#ServerBrowser_NoBlacklistedServers");
m_pGameList->SortList();
BaseClass::OnPageShow();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CBlacklistedServers::GetSelectedServerID( void )
{
int serverID = -1;
if ( m_pGameList->GetSelectedItemsCount() )
{
serverID = m_pGameList->GetItemUserData( m_pGameList->GetSelectedItem(0) );
}
return serverID;
}
//-----------------------------------------------------------------------------
// Purpose: opens context menu (user right clicked on a server)
//-----------------------------------------------------------------------------
void CBlacklistedServers::OnOpenContextMenu(int itemID)
{
CServerContextMenu *menu = ServerBrowserDialog().GetContextMenu( m_pGameList );
// get the server
int serverID = GetSelectedServerID();
menu->ShowMenu( this,(uint32)-1, false, false, false, false );
if ( serverID != -1 )
{
menu->AddMenuItem("RemoveServer", "#ServerBrowser_RemoveServerFromBlacklist", new KeyValues("RemoveFromBlacklist"), this);
}
menu->AddMenuItem("AddServerByName", "#ServerBrowser_AddServerByIP", new KeyValues("AddServerByName"), this);
}
//-----------------------------------------------------------------------------
// Purpose: Adds a server by IP address
//-----------------------------------------------------------------------------
void CBlacklistedServers::OnAddServerByName()
{
// open the add server dialog
CDialogAddBlacklistedServer *dlg = new CDialogAddBlacklistedServer( &ServerBrowserDialog(), NULL );
dlg->MoveToCenterOfScreen();
dlg->DoModal();
}
//-----------------------------------------------------------------------------
// Purpose: removes a server from the blacklist
//-----------------------------------------------------------------------------
void CBlacklistedServers::OnRemoveFromBlacklist()
{
// iterate the selection
for ( int iGame = (m_pGameList->GetSelectedItemsCount() - 1); iGame >= 0; iGame-- )
{
int itemID = m_pGameList->GetSelectedItem( iGame );
int serverID = m_pGameList->GetItemData( itemID )->userData;
m_pGameList->RemoveItem( itemID );
m_blackList.RemoveServer( serverID );
}
InvalidateLayout();
Repaint();
ServerBrowserDialog().BlacklistsChanged();
SaveBlacklistedList();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlacklistedServers::ClearServerList( void )
{
m_pGameList->RemoveAll();
m_blackList.Reset();
m_blackListTimestamp = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Adds the currently connected server to the list
//-----------------------------------------------------------------------------
void CBlacklistedServers::OnAddCurrentServer()
{
gameserveritem_t *pConnected = ServerBrowserDialog().GetCurrentConnectedServer();
if ( pConnected )
{
blacklisted_server_t *blackServer = m_blackList.AddServer( *pConnected );
if ( !blackServer )
{
return;
}
UpdateBlacklistUI( blackServer );
ServerBrowserDialog().BlacklistsChanged();
SaveBlacklistedList();
if ( GameSupportsReplay() )
{
// send command to propagate to the client so the client can send it on to the GC
char command[ 256 ];
Q_snprintf( command, Q_ARRAYSIZE( command ), "rbgc %s\n", pConnected->m_NetAdr.GetConnectionAddressString() );
g_pRunGameEngine->AddTextCommand( command );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlacklistedServers::OnImportBlacklist()
{
if ( m_hImportDialog.Get() )
{
m_hImportDialog.Get()->MarkForDeletion();
}
m_hImportDialog = new FileOpenDialog( this, "#ServerBrowser_ImportBlacklistTitle", true );
if ( m_hImportDialog.Get() )
{
m_hImportDialog->SetStartDirectory( "cfg/" );
m_hImportDialog->AddFilter( "*.txt", "#ServerBrowser_BlacklistFiles", true );
m_hImportDialog->DoModal( false );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlacklistedServers::OnFileSelected( char const *fullpath )
{
AddServersFromFile( fullpath, true );
if ( m_hImportDialog.Get() )
{
m_hImportDialog.Get()->MarkForDeletion();
}
}
//-----------------------------------------------------------------------------
// Purpose: Parse posted messages
//
//-----------------------------------------------------------------------------
void CBlacklistedServers::OnCommand(const char *command)
{
if (!Q_stricmp(command, "AddServerByName"))
{
OnAddServerByName();
}
else if (!Q_stricmp(command, "AddCurrentServer" ))
{
OnAddCurrentServer();
}
else if (!Q_stricmp(command, "ImportBlacklist" ))
{
OnImportBlacklist();
}
else
{
BaseClass::OnCommand(command);
}
}
//-----------------------------------------------------------------------------
// Purpose: enables adding server
//-----------------------------------------------------------------------------
void CBlacklistedServers::OnConnectToGame()
{
m_pAddCurrentServer->SetEnabled( true );
}
//-----------------------------------------------------------------------------
// Purpose: disables adding current server
//-----------------------------------------------------------------------------
void CBlacklistedServers::OnDisconnectFromGame( void )
{
m_pAddCurrentServer->SetEnabled( false );
}

View File

@ -0,0 +1,68 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef BLACKLISTEDSERVERS_H
#define BLACKLISTEDSERVERS_H
#ifdef _WIN32
#pragma once
#endif
#include "ServerBrowser/blacklisted_server_manager.h"
//-----------------------------------------------------------------------------
// Purpose: Blacklisted servers list
//-----------------------------------------------------------------------------
class CBlacklistedServers : public vgui::PropertyPage
{
DECLARE_CLASS_SIMPLE( CBlacklistedServers, vgui::PropertyPage );
public:
CBlacklistedServers(vgui::Panel *parent);
~CBlacklistedServers();
// blacklist list, loads/saves from file
void LoadBlacklistedList();
void SaveBlacklistedList();
void AddServer(gameserveritem_t &server);
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
// passed from main server browser window instead of messages
void OnConnectToGame();
void OnDisconnectFromGame( void );
blacklisted_server_t *GetBlacklistedServer( int iServerID );
bool IsServerBlacklisted(gameserveritem_t &server);
private:
// context menu message handlers
MESSAGE_FUNC( OnPageShow, "PageShow" );
MESSAGE_FUNC_INT( OnOpenContextMenu, "OpenContextMenu", itemID );
MESSAGE_FUNC( OnAddServerByName, "AddServerByName" );
MESSAGE_FUNC( OnRemoveFromBlacklist, "RemoveFromBlacklist" );
MESSAGE_FUNC_CHARPTR( OnFileSelected, "FileSelected", fullpath );
void ClearServerList( void );
void OnAddCurrentServer( void );
void OnImportBlacklist( void );
void OnCommand(const char *command);
void UpdateBlacklistUI( blacklisted_server_t *blackServer );
int GetSelectedServerID( void );
bool AddServersFromFile( const char *pszFilename, bool bResetTimes );
private:
vgui::Button *m_pAddServer;
vgui::Button *m_pAddCurrentServer;
vgui::ListPanel *m_pGameList;
vgui::DHANDLE< vgui::FileOpenDialog > m_hImportDialog;
CBlacklistedServerManager m_blackList;
long m_blackListTimestamp;
};
#endif // BLACKLISTEDSERVERS_H

View File

@ -0,0 +1,448 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "pch_serverbrowser.h"
#include <vgui_controls/HTML.h>
#include <vgui_controls/MessageDialog.h>
using namespace vgui;
#define NUM_COMMON_TAGS 20
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
TagMenuButton::TagMenuButton(Panel *parent, const char *panelName, const char *text) : BaseClass(parent,panelName,text)
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void TagMenuButton::OnShowMenu( vgui::Menu *menu )
{
PostActionSignal(new KeyValues("TagMenuButtonOpened"));
BaseClass::OnShowMenu(menu);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CCustomServerInfoURLQuery : public vgui::QueryBox
{
DECLARE_CLASS_SIMPLE( CCustomServerInfoURLQuery, vgui::QueryBox );
public:
CCustomServerInfoURLQuery(const char *title, const char *queryText,vgui::Panel *parent) : BaseClass( title, queryText, parent )
{
SetOKButtonText( "#ServerBrowser_CustomServerURLButton" );
}
};
DECLARE_BUILD_FACTORY( TagInfoLabel );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
TagInfoLabel::TagInfoLabel(Panel *parent, const char *panelName) : BaseClass(parent,panelName, (const char *)NULL, NULL)
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
TagInfoLabel::TagInfoLabel(Panel *parent, const char *panelName, const char *text, const char *pszURL) : BaseClass(parent,panelName,text,pszURL)
{
}
//-----------------------------------------------------------------------------
// Purpose: If we were left clicked on, launch the URL
//-----------------------------------------------------------------------------
void TagInfoLabel::OnMousePressed(MouseCode code)
{
if (code == MOUSE_LEFT)
{
if ( GetURL() )
{
// Pop up the dialog with the url in it
CCustomServerInfoURLQuery *qb = new CCustomServerInfoURLQuery( "#ServerBrowser_CustomServerURLWarning", "#ServerBrowser_CustomServerURLOpen", this );
if (qb != NULL)
{
qb->SetOKCommand( new KeyValues("DoOpenCustomServerInfoURL") );
qb->AddActionSignalTarget(this);
qb->MoveToFront();
qb->DoModal();
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void TagInfoLabel::DoOpenCustomServerInfoURL( void )
{
if ( GetURL() )
{
system()->ShellExecute("open", GetURL() );
}
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CCustomGames::CCustomGames(vgui::Panel *parent) :
BaseClass(parent, "CustomGames", eInternetServer )
{
m_pGameList->AddColumnHeader(10, "Tags", "#ServerBrowser_Tags", 200);
m_pGameList->SetSortFunc(10, TagsCompare);
if ( !IsSteamGameServerBrowsingEnabled() )
{
m_pGameList->SetEmptyListText("#ServerBrowser_OfflineMode");
m_pConnect->SetEnabled( false );
m_pRefreshAll->SetEnabled( false );
m_pRefreshQuick->SetEnabled( false );
m_pAddServer->SetEnabled( false );
m_pFilter->SetEnabled( false );
}
m_szTagFilter[0] = 0;
m_pTagFilter = new TextEntry(this, "TagFilter");
m_pTagFilter->SetEnabled( false );
m_pTagFilter->SetMaximumCharCount( MAX_TAG_CHARACTERS );
m_pAddTagList = new TagMenuButton( this, "AddTagList", "#ServerBrowser_AddCommonTags" );
m_pTagListMenu = new Menu( m_pAddTagList, "TagList" );
m_pAddTagList->SetMenu( m_pTagListMenu );
m_pAddTagList->SetOpenDirection( Menu::UP );
m_pAddTagList->SetEnabled( false );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CCustomGames::~CCustomGames()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCustomGames::UpdateDerivedLayouts( void )
{
const char *pPathID = "PLATFORM";
KeyValues *pConditions = NULL;
if ( ServerBrowser().IsWorkshopEnabled() )
{
pConditions = new KeyValues( "conditions" );
if ( pConditions )
{
KeyValues *pNewKey = new KeyValues( "if_workshop_enabled" );
if ( pNewKey )
{
pConditions->AddSubKey( pNewKey );
}
}
}
if ( m_pFilter->IsSelected() )
{
if ( g_pFullFileSystem->FileExists( "servers/CustomGamesPage_Filters.res", "MOD" ) )
{
pPathID = "MOD";
}
LoadControlSettings( "servers/CustomGamesPage_Filters.res", pPathID, NULL, pConditions );
}
else
{
if ( g_pFullFileSystem->FileExists( "servers/CustomGamesPage.res", "MOD" ) )
{
pPathID = "MOD";
}
LoadControlSettings( "servers/CustomGamesPage.res", pPathID, NULL, pConditions );
}
if ( pConditions )
{
pConditions->deleteThis();
}
if ( !GameSupportsReplay() )
{
HideReplayFilter();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCustomGames::OnLoadFilter(KeyValues *filter)
{
BaseClass::OnLoadFilter( filter );
Q_strncpy(m_szTagFilter, filter->GetString("gametype"), sizeof(m_szTagFilter));
if ( m_pTagFilter )
{
m_pTagFilter->SetText(m_szTagFilter);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CCustomGames::CheckTagFilter( gameserveritem_t &server )
{
bool bRetVal = true;
// Custom games substring matches tags with the server's tags
int count = Q_strlen( m_szTagFilter );
if ( count )
{
CUtlVector<char*> TagList;
V_SplitString( m_szTagFilter, ",", TagList );
for ( int i = 0; i < TagList.Count(); i++ )
{
if ( ( Q_strnistr( server.m_szGameTags, TagList[i], MAX_TAG_CHARACTERS ) > 0 ) == TagsExclude() )
{
bRetVal = false;
break;
}
}
TagList.PurgeAndDeleteElements();
}
return bRetVal;
}
//-----------------------------------------------------------------------------
// Purpose: Checks the workshop filtering setting, taking into account workshop filtering might be disabled
//-----------------------------------------------------------------------------
bool CCustomGames::CheckWorkshopFilter( gameserveritem_t &server )
{
eWorkshopMode workshopMode = WorkshopMode();
const char szWorkshopPrefix[] = "workshop/";
if ( workshopMode == eWorkshop_WorkshopOnly )
{
return V_strncasecmp( server.m_szMap, szWorkshopPrefix, sizeof( szWorkshopPrefix ) - 1 ) == 0;
}
else if ( workshopMode == eWorkshop_SubscribedOnly )
{
return ServerBrowser().IsWorkshopSubscribedMap( server.m_szMap );
}
Assert( workshopMode == eWorkshop_None );
return true;
}
//-----------------------------------------------------------------------------
// Purpose: gets filter settings from controls
//-----------------------------------------------------------------------------
void CCustomGames::OnSaveFilter(KeyValues *filter)
{
BaseClass::OnSaveFilter( filter );
if ( m_pTagFilter )
{
// tags
m_pTagFilter->GetText(m_szTagFilter, sizeof(m_szTagFilter) - 1);
}
if ( m_szTagFilter[0] )
{
Q_strlower(m_szTagFilter);
}
if ( TagsExclude() )
{
m_vecServerFilters.AddToTail( MatchMakingKeyValuePair_t( "gametype", "" ) );
}
else
{
m_vecServerFilters.AddToTail( MatchMakingKeyValuePair_t( "gametype", m_szTagFilter ) );
}
filter->SetString("gametype", m_szTagFilter);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCustomGames::SetRefreshing(bool state)
{
if ( state )
{
m_pAddTagList->SetEnabled( false );
}
BaseClass::SetRefreshing( state );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCustomGames::ServerResponded( int iServer, gameserveritem_t *pServerItem )
{
CBaseGamesPage::ServerResponded( iServer, pServerItem );
// If we've found a server with some tags, enable the add tag button
if ( pServerItem->m_szGameTags[0] )
{
m_pAddTagList->SetEnabled( true );
}
}
struct tagentry_t
{
const char *pszTag;
int iCount;
};
int __cdecl SortTagsInUse( const tagentry_t *pTag1, const tagentry_t *pTag2 )
{
return (pTag1->iCount < pTag2->iCount);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCustomGames::RecalculateCommonTags( void )
{
// Regenerate our tag list
m_pTagListMenu->DeleteAllItems();
// Loop through our servers, and build a list of all the tags
CUtlVector<tagentry_t> aTagsInUse;
int iCount = m_pGameList->GetItemCount();
for ( int i = 0; i < iCount; i++ )
{
int serverID = m_pGameList->GetItemUserData( i );
gameserveritem_t *pServer = GetServer( serverID );
if ( pServer && pServer->m_szGameTags && pServer->m_szGameTags[0] )
{
CUtlVector<char*> TagList;
V_SplitString( pServer->m_szGameTags, ",", TagList );
for ( int iTag = 0; iTag < TagList.Count(); iTag++ )
{
// First make sure it's not already in our list
bool bFound = false;
for ( int iCheck = 0; iCheck < aTagsInUse.Count(); iCheck++ )
{
if ( !Q_strnicmp(TagList[iTag], aTagsInUse[iCheck].pszTag, MAX_TAG_CHARACTERS ) )
{
aTagsInUse[iCheck].iCount++;
bFound = true;
}
}
if ( !bFound )
{
int iIdx = aTagsInUse.AddToTail();
aTagsInUse[iIdx].pszTag = TagList[iTag];
aTagsInUse[iIdx].iCount = 0;
}
}
}
}
aTagsInUse.Sort( SortTagsInUse );
int iTagsToAdd = min( aTagsInUse.Count(), NUM_COMMON_TAGS );
for ( int i = 0; i < iTagsToAdd; i++ )
{
const char *pszTag = aTagsInUse[i].pszTag;
m_pTagListMenu->AddMenuItem( pszTag, new KeyValues("AddTag", "tag", pszTag), this, new KeyValues( "data", "tag", pszTag ) );
}
m_pTagListMenu->SetFixedWidth( m_pAddTagList->GetWide() );
m_pTagListMenu->InvalidateLayout( true, false );
m_pTagListMenu->PositionRelativeToPanel( m_pAddTagList, Menu::UP );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCustomGames::OnTagMenuButtonOpened( void )
{
RecalculateCommonTags();
}
//-----------------------------------------------------------------------------
// Purpose: Sets the text from the message
//-----------------------------------------------------------------------------
void CCustomGames::OnAddTag(KeyValues *params)
{
KeyValues *pkvText = params->FindKey("tag", false);
if (!pkvText)
return;
AddTagToFilterList( pkvText->GetString() );
}
int SortServerTags( char* const *p1, char* const *p2 )
{
return ( Q_strcmp( *p1, *p2 ) > 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCustomGames::AddTagToFilterList( const char *pszTag )
{
char txt[ 128 ];
m_pTagFilter->GetText( txt, sizeof( txt ) );
CUtlVector<char*> TagList;
V_SplitString( txt, ",", TagList );
if ( txt[0] )
{
for ( int i = 0; i < TagList.Count(); i++ )
{
// Already in the tag list?
if ( !Q_stricmp( TagList[i], pszTag ) )
{
TagList.PurgeAndDeleteElements();
return;
}
}
}
char *pszNewTag = new char[64];
Q_strncpy( pszNewTag, pszTag, 64 );
TagList.AddToHead( pszNewTag );
TagList.Sort( SortServerTags );
// Append it
char tmptags[MAX_TAG_CHARACTERS];
tmptags[0] = '\0';
for ( int i = 0; i < TagList.Count(); i++ )
{
if ( i > 0 )
{
Q_strncat( tmptags, ",", MAX_TAG_CHARACTERS );
}
Q_strncat( tmptags, TagList[i], MAX_TAG_CHARACTERS );
}
m_pTagFilter->SetText( tmptags );
TagList.PurgeAndDeleteElements();
// Update & apply filters now that the tag list has changed
UpdateFilterSettings();
ApplyGameFilters();
}

View File

@ -0,0 +1,70 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef CUSTOMGAMES_H
#define CUSTOMGAMES_H
#ifdef _WIN32
#pragma once
#endif
#define MAX_TAG_CHARACTERS 128
class TagInfoLabel : public vgui::URLLabel
{
DECLARE_CLASS_SIMPLE( TagInfoLabel, vgui::URLLabel );
public:
TagInfoLabel(Panel *parent, const char *panelName);
TagInfoLabel(Panel *parent, const char *panelName, const char *text, const char *pszURL);
virtual void OnMousePressed(vgui::MouseCode code);
MESSAGE_FUNC( DoOpenCustomServerInfoURL, "DoOpenCustomServerInfoURL" );
};
class TagMenuButton : public vgui::MenuButton
{
DECLARE_CLASS_SIMPLE( TagMenuButton, vgui::MenuButton );
public:
TagMenuButton( Panel *parent, const char *panelName, const char *text);
virtual void OnShowMenu(vgui::Menu *menu);
};
//-----------------------------------------------------------------------------
// Purpose: Internet games with tags
//-----------------------------------------------------------------------------
class CCustomGames : public CInternetGames
{
DECLARE_CLASS_SIMPLE( CCustomGames, CInternetGames );
public:
CCustomGames(vgui::Panel *parent);
~CCustomGames();
virtual void UpdateDerivedLayouts( void ) OVERRIDE;
virtual void OnLoadFilter(KeyValues *filter) OVERRIDE;
virtual void OnSaveFilter(KeyValues *filter) OVERRIDE;
bool CheckTagFilter( gameserveritem_t &server ) OVERRIDE;
bool CheckWorkshopFilter( gameserveritem_t &server ) OVERRIDE;
virtual void SetRefreshing(bool state) OVERRIDE;
virtual void ServerResponded( int iServer, gameserveritem_t *pServerItem ) OVERRIDE;
MESSAGE_FUNC_PARAMS( OnAddTag, "AddTag", params );
MESSAGE_FUNC( OnTagMenuButtonOpened, "TagMenuButtonOpened" );
void RecalculateCommonTags( void );
void AddTagToFilterList( const char *pszTag );
private:
TagInfoLabel *m_pTagInfoURL;
TagMenuButton *m_pAddTagList;
vgui::Menu *m_pTagListMenu;
vgui::TextEntry *m_pTagFilter;
char m_szTagFilter[MAX_TAG_CHARACTERS];
};
#endif // CUSTOMGAMES_H

View File

@ -0,0 +1,392 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "pch_serverbrowser.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
// Input : *gameList - game list to add specified server to
//-----------------------------------------------------------------------------
CDialogAddServer::CDialogAddServer(vgui::Panel *parent, IGameList *gameList) : Frame(parent, "DialogAddServer")
{
SetDeleteSelfOnClose(true);
m_pGameList = gameList;
SetTitle("#ServerBrowser_AddServersTitle", true);
SetSizeable( false );
m_pTabPanel = new PropertySheet(this, "GameTabs");
m_pTabPanel->SetTabWidth(72);
m_pDiscoveredGames = new ListPanel( this, "Servers" );
// Add the column headers
m_pDiscoveredGames->AddColumnHeader(0, "Password", "#ServerBrowser_Password", 16, ListPanel::COLUMN_FIXEDSIZE | ListPanel::COLUMN_IMAGE);
m_pDiscoveredGames->AddColumnHeader(1, "Bots", "#ServerBrowser_Bots", 16, ListPanel::COLUMN_FIXEDSIZE | ListPanel::COLUMN_IMAGE | ListPanel::COLUMN_HIDDEN);
m_pDiscoveredGames->AddColumnHeader(2, "Secure", "#ServerBrowser_Secure", 16, ListPanel::COLUMN_FIXEDSIZE | ListPanel::COLUMN_IMAGE);
bool bGameSupportsReplay = GameSupportsReplay();
int nReplayWidth = 16;
if ( !bGameSupportsReplay )
{
nReplayWidth = 0;
}
m_pDiscoveredGames->AddColumnHeader(3, "Replay", "#ServerBrowser_Replay", nReplayWidth, ListPanel::COLUMN_FIXEDSIZE | ListPanel::COLUMN_IMAGE);
m_pDiscoveredGames->AddColumnHeader(4, "Name", "#ServerBrowser_Servers", 20, ListPanel::COLUMN_RESIZEWITHWINDOW | ListPanel::COLUMN_UNHIDABLE);
m_pDiscoveredGames->AddColumnHeader(5, "IPAddr", "#ServerBrowser_IPAddress", 60, ListPanel::COLUMN_HIDDEN);
m_pDiscoveredGames->AddColumnHeader(6, "GameDesc", "#ServerBrowser_Game", 150);
m_pDiscoveredGames->AddColumnHeader(7, "Players", "#ServerBrowser_Players", 60);
m_pDiscoveredGames->AddColumnHeader(8, "Map", "#ServerBrowser_Map", 80);
m_pDiscoveredGames->AddColumnHeader(9, "Ping", "#ServerBrowser_Latency", 60);
m_pDiscoveredGames->SetColumnHeaderTooltip(0, "#ServerBrowser_PasswordColumn_Tooltip");
m_pDiscoveredGames->SetColumnHeaderTooltip(1, "#ServerBrowser_BotColumn_Tooltip");
m_pDiscoveredGames->SetColumnHeaderTooltip(2, "#ServerBrowser_SecureColumn_Tooltip");
if ( bGameSupportsReplay )
{
m_pDiscoveredGames->SetColumnHeaderTooltip(3, "#ServerBrowser_ReplayColumn_Tooltip");
}
// setup fast sort functions
m_pDiscoveredGames->SetSortFunc(0, PasswordCompare);
m_pDiscoveredGames->SetSortFunc(1, BotsCompare);
m_pDiscoveredGames->SetSortFunc(2, SecureCompare);
if ( bGameSupportsReplay )
{
m_pDiscoveredGames->SetSortFunc(3, ReplayCompare);
}
m_pDiscoveredGames->SetSortFunc(4, ServerNameCompare);
m_pDiscoveredGames->SetSortFunc(5, IPAddressCompare);
m_pDiscoveredGames->SetSortFunc(6, GameCompare);
m_pDiscoveredGames->SetSortFunc(7, PlayersCompare);
m_pDiscoveredGames->SetSortFunc(8, MapCompare);
m_pDiscoveredGames->SetSortFunc(9, PingCompare);
m_pDiscoveredGames->SetSortColumn(9); // sort on ping
m_pTextEntry = new vgui::TextEntry( this, "ServerNameText" );
m_pTextEntry->AddActionSignalTarget( this );
m_pTestServersButton = new vgui::Button( this, "TestServersButton", "" );
m_pAddServerButton = new vgui::Button( this, "OKButton", "" );
m_pAddSelectedServerButton = new vgui::Button( this, "SelectedOKButton", "", this, "addselected" );
m_pTabPanel->AddPage( m_pDiscoveredGames, "#ServerBrowser_Servers" );
LoadControlSettings("Servers/DialogAddServer.res");
// Setup the buttons. We leave them disabled until there is text in the textbox.
m_pAddServerButton->SetEnabled( false );
m_pTestServersButton->SetEnabled( false );
m_pAddSelectedServerButton->SetEnabled( false );
m_pAddSelectedServerButton->SetVisible( false );
m_pTabPanel->SetVisible( false );
m_pTextEntry->RequestFocus();
// Initially, we aren't high enough to show the tab panel.
int x, y;
m_pTabPanel->GetPos( x, y );
m_OriginalHeight = m_pTabPanel->GetTall() + y + 50;
SetTall( y );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CDialogAddServer::~CDialogAddServer()
{
FOR_EACH_VEC( m_Queries, i )
{
if ( steamapicontext->SteamMatchmakingServers() )
steamapicontext->SteamMatchmakingServers()->CancelServerQuery( m_Queries[ i ] );
}
}
//-----------------------------------------------------------------------------
// Lets us know when the text entry has changed.
//-----------------------------------------------------------------------------
void CDialogAddServer::OnTextChanged()
{
bool bAnyText = (m_pTextEntry->GetTextLength() > 0);
m_pAddServerButton->SetEnabled( bAnyText );
m_pTestServersButton->SetEnabled( bAnyText );
}
//-----------------------------------------------------------------------------
// Purpose: button command handler
//-----------------------------------------------------------------------------
void CDialogAddServer::OnCommand(const char *command)
{
if ( Q_stricmp(command, "OK") == 0 )
{
OnOK();
}
else if ( Q_stricmp( command, "TestServers" ) == 0 )
{
SetTall( m_OriginalHeight );
m_pTabPanel->SetVisible( true );
m_pAddSelectedServerButton->SetVisible( true );
TestServers();
}
else if ( !Q_stricmp( command, "addselected" ) )
{
if ( m_pDiscoveredGames->GetSelectedItemsCount() )
{
// get the server
int serverID = m_pDiscoveredGames->GetItemUserData( m_pDiscoveredGames->GetSelectedItem(0) );
FinishAddServer( m_Servers[ serverID ] );
m_pDiscoveredGames->RemoveItem( m_pDiscoveredGames->GetSelectedItem(0) ); // as we add to favs remove from the list
m_pDiscoveredGames->SetEmptyListText( "" );
}
}
else
{
BaseClass::OnCommand(command);
}
}
//-----------------------------------------------------------------------------
// Purpose: Handles the OK button being pressed; adds the server to the game list
//-----------------------------------------------------------------------------
void CDialogAddServer::OnOK()
{
// try and parse out IP address
const char *address = GetControlString("ServerNameText", "");
netadr_t netaddr;
netaddr.SetFromString( address, true );
if ( !netaddr.GetPort() && !AllowInvalidIPs() )
{
// use the default port since it was not entered
netaddr.SetPort( 27015 );
}
if ( AllowInvalidIPs() || netaddr.IsValid() )
{
gameserveritem_t server;
memset(&server, 0, sizeof(server));
server.SetName( address );
// We assume here that the query and connection ports are the same. This is why it's much
// better if they click "Servers" and choose a server in there.
server.m_NetAdr.Init( netaddr.GetIPHostByteOrder(), netaddr.GetPort(), netaddr.GetPort() );
server.m_nAppID = 0;
FinishAddServer( server );
}
else
{
// could not parse the ip address, popup an error
MessageBox *dlg = new MessageBox("#ServerBrowser_AddServerErrorTitle", "#ServerBrowser_AddServerError");
dlg->DoModal();
}
// mark ourselves to be closed
PostMessage(this, new KeyValues("Close"));
}
//-----------------------------------------------------------------------------
// Purpose: Ping a particular IP for server presence
//-----------------------------------------------------------------------------
void CDialogAddServer::TestServers()
{
if ( !steamapicontext->SteamMatchmakingServers() )
return;
m_pDiscoveredGames->SetEmptyListText( "" );
m_pDiscoveredGames->RemoveAll();
// If they specified a port, then send a query to that port.
const char *address = GetControlString("ServerNameText", "");
netadr_t netaddr;
netaddr.SetFromString( address, true );
m_Servers.RemoveAll();
CUtlVector<netadr_t> vecAdress;
if ( netaddr.GetPort() == 0 )
{
// No port specified. Go to town on the ports.
CUtlVector<uint16> portsToTry;
GetMostCommonQueryPorts( portsToTry );
for ( int i=0; i < portsToTry.Count(); i++ )
{
netadr_t newAddr = netaddr;
newAddr.SetPort( portsToTry[i] );
vecAdress.AddToTail( newAddr );
}
}
else
{
vecAdress.AddToTail( netaddr );
}
// Change the text on the tab panel..
m_pTabPanel->RemoveAllPages();
wchar_t wstr[512];
if ( address[0] == 0 )
{
Q_wcsncpy( wstr, g_pVGuiLocalize->Find( "#ServerBrowser_ServersRespondingLocal"), sizeof( wstr ) );
}
else
{
wchar_t waddress[512];
Q_UTF8ToUnicode( address, waddress, sizeof( waddress ) );
g_pVGuiLocalize->ConstructString( wstr, sizeof( wstr ), g_pVGuiLocalize->Find( "#ServerBrowser_ServersResponding"), 1, waddress );
}
char str[512];
Q_UnicodeToUTF8( wstr, str, sizeof( str ) );
m_pTabPanel->AddPage( m_pDiscoveredGames, str );
m_pTabPanel->InvalidateLayout();
FOR_EACH_VEC( vecAdress, iAddress )
{
m_Queries.AddToTail( steamapicontext->SteamMatchmakingServers()->PingServer( vecAdress[ iAddress ].GetIPHostByteOrder(), vecAdress[ iAddress ].GetPort(), this ) );
}
}
//-----------------------------------------------------------------------------
// Purpose: A server answered our ping
//-----------------------------------------------------------------------------
void CDialogAddServer::ServerResponded( gameserveritem_t &server )
{
KeyValues *kv = new KeyValues( "Server" );
kv->SetString( "name", server.GetName() );
kv->SetString( "map", server.m_szMap );
kv->SetString( "GameDir", server.m_szGameDir );
kv->SetString( "GameDesc", server.m_szGameDescription );
kv->SetString( "GameTags", server.m_szGameTags );
kv->SetInt( "password", server.m_bPassword ? 1 : 0);
kv->SetInt( "bots", server.m_nBotPlayers ? 2 : 0);
kv->SetInt( "Replay", IsReplayServer( server ) ? 5 : 0 );
if ( server.m_bSecure )
{
// show the denied icon if banned from secure servers, the secure icon otherwise
kv->SetInt("secure", ServerBrowser().IsVACBannedFromGame( server.m_nAppID ) ? 4 : 3);
}
else
{
kv->SetInt("secure", 0);
}
netadr_t reportedIPAddr;
reportedIPAddr.SetIP( server.m_NetAdr.GetIP() );
reportedIPAddr.SetPort( server.m_NetAdr.GetConnectionPort() );
kv->SetString("IPAddr", reportedIPAddr.ToString() );
char buf[32];
Q_snprintf(buf, sizeof(buf), "%d / %d", server.m_nPlayers, server.m_nMaxPlayers);
kv->SetString("Players", buf);
kv->SetInt("Ping", server.m_nPing);
// new server, add to list
int iServer = m_Servers.AddToTail( server );
int iListID = m_pDiscoveredGames->AddItem(kv, iServer, false, false);
if ( m_pDiscoveredGames->GetItemCount() == 1 )
{
m_pDiscoveredGames->AddSelectedItem( iListID );
}
kv->deleteThis();
m_pDiscoveredGames->InvalidateLayout();
}
void CDialogAddServer::ServerFailedToRespond()
{
m_pDiscoveredGames->SetEmptyListText( "#ServerBrowser_ServerNotResponding" );
}
void CDialogAddServer::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
ImageList *imageList = new ImageList(false);
imageList->AddImage(scheme()->GetImage("servers/icon_password", false));
imageList->AddImage(scheme()->GetImage("servers/icon_bots", false));
imageList->AddImage(scheme()->GetImage("servers/icon_robotron", false));
imageList->AddImage(scheme()->GetImage("servers/icon_secure_deny", false));
imageList->AddImage(scheme()->GetImage("servers/icon_replay", false));
int passwordColumnImage = imageList->AddImage(scheme()->GetImage("servers/icon_password_column", false));
int botColumnImage = imageList->AddImage(scheme()->GetImage("servers/icon_bots_column", false));
int secureColumnImage = imageList->AddImage(scheme()->GetImage("servers/icon_robotron_column", false));
int replayColumnImage = imageList->AddImage(scheme()->GetImage("servers/icon_replay_column", false));
m_pDiscoveredGames->SetImageList(imageList, true);
vgui::HFont hFont = pScheme->GetFont( "ListSmall", IsProportional() );
if ( !hFont )
hFont = pScheme->GetFont( "DefaultSmall", IsProportional() );
m_pDiscoveredGames->SetFont( hFont );
m_pDiscoveredGames->SetColumnHeaderImage(0, passwordColumnImage);
m_pDiscoveredGames->SetColumnHeaderImage(1, botColumnImage);
m_pDiscoveredGames->SetColumnHeaderImage(2, secureColumnImage);
m_pDiscoveredGames->SetColumnHeaderImage(3, replayColumnImage);
}
//-----------------------------------------------------------------------------
// Purpose: A server on the listed IP responded
//-----------------------------------------------------------------------------
void CDialogAddServer::OnItemSelected()
{
int nSelectedItem = m_pDiscoveredGames->GetSelectedItem(0);
if( nSelectedItem != -1 )
{
m_pAddSelectedServerButton->SetEnabled( true );
}
else
{
m_pAddSelectedServerButton->SetEnabled( false );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CDialogAddServer::FinishAddServer( gameserveritem_t &pServer )
{
ServerBrowserDialog().AddServerToFavorites( pServer );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CDialogAddBlacklistedServer::FinishAddServer( gameserveritem_t &pServer )
{
ServerBrowserDialog().AddServerToBlacklist( pServer );
ServerBrowserDialog().BlacklistsChanged();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CDialogAddBlacklistedServer::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
m_pAddServerButton->SetText( "#ServerBrowser_AddAddressToBlacklist" );
m_pAddSelectedServerButton->SetText( "#ServerBrowser_AddSelectedToBlacklist" );
}

View File

@ -0,0 +1,75 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef DIALOGADDSERVER_H
#define DIALOGADDSERVER_H
#ifdef _WIN32
#pragma once
#endif
class CAddServerGameList;
class IGameList;
//-----------------------------------------------------------------------------
// Purpose: Dialog which lets the user add a server by IP address
//-----------------------------------------------------------------------------
class CDialogAddServer : public vgui::Frame, public ISteamMatchmakingPingResponse
{
DECLARE_CLASS_SIMPLE( CDialogAddServer, vgui::Frame );
friend class CAddServerGameList;
public:
CDialogAddServer(vgui::Panel *parent, IGameList *gameList);
~CDialogAddServer();
void ServerResponded( gameserveritem_t &server );
void ServerFailedToRespond();
void ApplySchemeSettings( vgui::IScheme *pScheme );
MESSAGE_FUNC( OnItemSelected, "ItemSelected" );
private:
virtual void OnCommand(const char *command);
void OnOK();
void TestServers();
MESSAGE_FUNC( OnTextChanged, "TextChanged" );
virtual void FinishAddServer( gameserveritem_t &pServer );
virtual bool AllowInvalidIPs( void ) { return false; }
protected:
IGameList *m_pGameList;
vgui::Button *m_pTestServersButton;
vgui::Button *m_pAddServerButton;
vgui::Button *m_pAddSelectedServerButton;
vgui::PropertySheet *m_pTabPanel;
vgui::TextEntry *m_pTextEntry;
vgui::ListPanel *m_pDiscoveredGames;
int m_OriginalHeight;
CUtlVector<gameserveritem_t> m_Servers;
CUtlVector<HServerQuery> m_Queries;
};
class CDialogAddBlacklistedServer : public CDialogAddServer
{
DECLARE_CLASS_SIMPLE( CDialogAddBlacklistedServer, CDialogAddServer );
public:
CDialogAddBlacklistedServer( vgui::Panel *parent, IGameList *gameList) :
CDialogAddServer( parent, gameList )
{
}
virtual void FinishAddServer( gameserveritem_t &pServer );
void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual bool AllowInvalidIPs( void ) { return true; }
};
#endif // DIALOGADDSERVER_H

View File

@ -0,0 +1,802 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "pch_serverbrowser.h"
using namespace vgui;
static const long RETRY_TIME = 10000; // refresh server every 10 seconds
static const long CHALLENGE_ENTRIES = 1024;
extern "C"
{
DLL_EXPORT bool JoiningSecureServerCall()
{
return true;
}
}
//-----------------------------------------------------------------------------
// Purpose: Comparison function used in query redblack tree
//-----------------------------------------------------------------------------
bool QueryLessFunc( const struct challenge_s &item1, const struct challenge_s &item2 )
{
// compare port then ip
if ( item1.addr.GetPort() < item2.addr.GetPort() )
return true;
else if ( item1.addr.GetPort() > item2.addr.GetPort() )
return false;
int ip1 = item1.addr.GetIPNetworkByteOrder();
int ip2 = item2.addr.GetIPNetworkByteOrder();
return ip1 < ip2;
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CDialogGameInfo::CDialogGameInfo( vgui::Panel *parent, int serverIP, int queryPort, unsigned short connectionPort, const char *pszConnectCode ) :
Frame(parent, "DialogGameInfo"),
m_CallbackPersonaStateChange( this, &CDialogGameInfo::OnPersonaStateChange ),
m_sConnectCode( pszConnectCode )
{
SetBounds(0, 0, 512, 512);
SetMinimumSize(416, 340);
SetDeleteSelfOnClose(true);
m_bConnecting = false;
m_bServerFull = false;
m_bShowAutoRetryToggle = false;
m_bServerNotResponding = false;
m_bShowingExtendedOptions = false;
m_SteamIDFriend = 0;
m_hPingQuery = HSERVERQUERY_INVALID;
m_hPlayersQuery = HSERVERQUERY_INVALID;
m_bPlayerListUpdatePending = false;
m_szPassword[0] = 0;
m_pConnectButton = new Button(this, "Connect", "#ServerBrowser_JoinGame");
m_pCloseButton = new Button(this, "Close", "#ServerBrowser_Close");
m_pRefreshButton = new Button(this, "Refresh", "#ServerBrowser_Refresh");
m_pInfoLabel = new Label(this, "InfoLabel", "");
m_pAutoRetry = new ToggleButton(this, "AutoRetry", "#ServerBrowser_AutoRetry");
m_pAutoRetry->AddActionSignalTarget(this);
m_pAutoRetryAlert = new RadioButton(this, "AutoRetryAlert", "#ServerBrowser_AlertMeWhenSlotOpens");
m_pAutoRetryJoin = new RadioButton(this, "AutoRetryJoin", "#ServerBrowser_JoinWhenSlotOpens");
m_pPlayerList = new ListPanel(this, "PlayerList");
m_pPlayerList->AddColumnHeader(0, "PlayerName", "#ServerBrowser_PlayerName", 156);
m_pPlayerList->AddColumnHeader(1, "Score", "#ServerBrowser_Score", 64);
m_pPlayerList->AddColumnHeader(2, "Time", "#ServerBrowser_Time", 64);
m_pPlayerList->SetSortFunc(2, &PlayerTimeColumnSortFunc);
// set the defaults for sorting
// hack, need to make this more explicit functions in ListPanel
PostMessage(m_pPlayerList, new KeyValues("SetSortColumn", "column", 2));
PostMessage(m_pPlayerList, new KeyValues("SetSortColumn", "column", 1));
PostMessage(m_pPlayerList, new KeyValues("SetSortColumn", "column", 1));
m_pAutoRetryAlert->SetSelected(true);
m_pConnectButton->SetCommand(new KeyValues("Connect"));
m_pCloseButton->SetCommand(new KeyValues("Close"));
m_pRefreshButton->SetCommand(new KeyValues("Refresh"));
m_iRequestRetry = 0;
// create a new server to watch
memset(&m_Server, 0, sizeof(m_Server) );
m_Server.m_NetAdr.Init( serverIP, queryPort, connectionPort );
// refresh immediately
RequestInfo();
// let us be ticked every frame
ivgui()->AddTickSignal(this->GetVPanel());
LoadControlSettings("Servers/DialogGameInfo.res");
RegisterControlSettingsFile( "Servers/DialogGameInfo_SinglePlayer.res" );
RegisterControlSettingsFile( "Servers/DialogGameInfo_AutoRetry.res" );
MoveToCenterOfScreen();
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CDialogGameInfo::~CDialogGameInfo()
{
if ( !steamapicontext->SteamMatchmakingServers() )
return;
if ( m_hPingQuery != HSERVERQUERY_INVALID )
steamapicontext->SteamMatchmakingServers()->CancelServerQuery( m_hPingQuery );
if ( m_hPlayersQuery != HSERVERQUERY_INVALID )
steamapicontext->SteamMatchmakingServers()->CancelServerQuery( m_hPlayersQuery );
}
//-----------------------------------------------------------------------------
// Purpose: send a player query to a server
//-----------------------------------------------------------------------------
void CDialogGameInfo::SendPlayerQuery( uint32 unIP, uint16 usQueryPort )
{
if ( !steamapicontext->SteamMatchmakingServers() )
return;
if ( m_hPlayersQuery != HSERVERQUERY_INVALID )
steamapicontext->SteamMatchmakingServers()->CancelServerQuery( m_hPlayersQuery );
m_hPlayersQuery = steamapicontext->SteamMatchmakingServers()->PlayerDetails( unIP, usQueryPort, this );
m_bPlayerListUpdatePending = true;
}
//-----------------------------------------------------------------------------
// Purpose: Activates the dialog
//-----------------------------------------------------------------------------
void CDialogGameInfo::Run(const char *titleName)
{
if ( titleName )
{
SetTitle( "#ServerBrowser_GameInfoWithNameTitle", true );
}
else
{
SetTitle( "#ServerBrowser_GameInfoWithNameTitle", true );
}
SetDialogVariable( "game", titleName );
// get the info from the user
RequestInfo();
Activate();
}
//-----------------------------------------------------------------------------
// Purpose: Changes which server to watch
//-----------------------------------------------------------------------------
void CDialogGameInfo::ChangeGame( int serverIP, int queryPort, unsigned short connectionPort )
{
memset( &m_Server, 0x0, sizeof(m_Server) );
m_Server.m_NetAdr.Init( serverIP, queryPort, connectionPort );
// remember the dialogs position so we can keep it the same
int x, y;
GetPos( x, y );
// see if we need to change dialog state
if ( !m_Server.m_NetAdr.GetIP() || !m_Server.m_NetAdr.GetQueryPort() )
{
// not in a server, load the simple settings dialog
SetMinimumSize(0, 0);
SetSizeable( false );
LoadControlSettings( "Servers/DialogGameInfo_SinglePlayer.res" );
}
else
{
// moving from a single-player game -> multiplayer, reset dialog
SetMinimumSize(416, 340);
SetSizeable( true );
LoadControlSettings( "Servers/DialogGameInfo.res" );
}
SetPos( x, y );
// Start refresh immediately
m_iRequestRetry = 0;
RequestInfo();
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: updates the dialog if it's watching a friend who changes servers
//-----------------------------------------------------------------------------
void CDialogGameInfo::OnPersonaStateChange( PersonaStateChange_t *pPersonaStateChange )
{
#if 0 // TBD delete this func
if ( m_SteamIDFriend && m_SteamIDFriend == pPersonaStateChange->m_ulSteamID )
{
// friend may have changed servers
uint64 nGameID;
uint32 unGameIP;
uint16 usGamePort;
uint16 usQueryPort;
if ( SteamFriends()->GetFriendGamePlayed( m_SteamIDFriend, &nGameID, &unGameIP, &usGamePort, &usQueryPort ) )
{
if ( pPersonaStateChange->m_nChangeFlags & k_EPersonaChangeGamePlayed )
{
ChangeGame( unGameIP, usQueryPort, usGamePort );
}
}
else
{
// bugbug johnc: change to not be in a game anymore
}
}
#endif
}
//-----------------------------------------------------------------------------
// Purpose: Associates a user with this dialog
//-----------------------------------------------------------------------------
void CDialogGameInfo::SetFriend( uint64 ulSteamIDFriend )
{
// set the title to include the friends name
SetTitle( "#ServerBrowser_GameInfoWithNameTitle", true );
SetDialogVariable( "game", steamapicontext->SteamFriends()->GetFriendPersonaName( ulSteamIDFriend ) );
SetDialogVariable( "friend", steamapicontext->SteamFriends()->GetFriendPersonaName( ulSteamIDFriend ) );
// store the friend we're associated with
m_SteamIDFriend = ulSteamIDFriend;
FriendGameInfo_t friendGameInfo;
if ( steamapicontext->SteamFriends()->GetFriendGamePlayed( ulSteamIDFriend, &friendGameInfo ) )
{
uint16 usConnPort = friendGameInfo.m_usGamePort;
if ( friendGameInfo.m_usQueryPort < QUERY_PORT_ERROR )
usConnPort = friendGameInfo.m_usQueryPort;
ChangeGame( friendGameInfo.m_unGameIP, usConnPort, friendGameInfo.m_usGamePort );
}
}
//-----------------------------------------------------------------------------
// Purpose: data access
//-----------------------------------------------------------------------------
uint64 CDialogGameInfo::GetAssociatedFriend()
{
return m_SteamIDFriend;
}
//-----------------------------------------------------------------------------
// Purpose: lays out the data
//-----------------------------------------------------------------------------
void CDialogGameInfo::PerformLayout()
{
BaseClass::PerformLayout();
SetControlString( "ServerText", m_Server.GetName() );
SetControlString( "GameText", m_Server.m_szGameDescription );
SetControlString( "MapText", m_Server.m_szMap );
SetControlString( "GameTags", m_Server.m_szGameTags );
if ( !m_Server.m_bHadSuccessfulResponse )
{
SetControlString("SecureText", "");
}
else if ( m_Server.m_bSecure )
{
SetControlString("SecureText", "#ServerBrowser_Secure");
}
else
{
SetControlString("SecureText", "#ServerBrowser_NotSecure");
}
char buf[128];
if ( m_Server.m_nMaxPlayers > 0)
{
Q_snprintf(buf, sizeof(buf), "%d / %d", m_Server.m_nPlayers, m_Server.m_nMaxPlayers);
}
else
{
buf[0] = 0;
}
SetControlString("PlayersText", buf);
if ( m_Server.m_NetAdr.GetIP() && m_Server.m_NetAdr.GetQueryPort() )
{
SetControlString("ServerIPText", m_Server.m_NetAdr.GetConnectionAddressString() );
m_pConnectButton->SetEnabled(true);
if ( m_pAutoRetry->IsSelected() )
{
m_pAutoRetryAlert->SetVisible(true);
m_pAutoRetryJoin->SetVisible(true);
}
else
{
m_pAutoRetryAlert->SetVisible(false);
m_pAutoRetryJoin->SetVisible(false);
}
}
else
{
SetControlString("ServerIPText", "");
m_pConnectButton->SetEnabled(false);
}
if ( m_Server.m_bHadSuccessfulResponse )
{
Q_snprintf(buf, sizeof(buf), "%d", m_Server.m_nPing );
SetControlString("PingText", buf);
}
else
{
SetControlString("PingText", "");
}
// set the info text
if ( m_pAutoRetry->IsSelected() )
{
if ( m_Server.m_nPlayers < m_Server.m_nMaxPlayers )
{
m_pInfoLabel->SetText("#ServerBrowser_PressJoinToConnect");
}
else if (m_pAutoRetryJoin->IsSelected())
{
m_pInfoLabel->SetText("#ServerBrowser_JoinWhenSlotIsFree");
}
else
{
m_pInfoLabel->SetText("#ServerBrowser_AlertWhenSlotIsFree");
}
}
else if (m_bServerFull)
{
m_pInfoLabel->SetText("#ServerBrowser_CouldNotConnectServerFull");
}
else if (m_bServerNotResponding)
{
m_pInfoLabel->SetText("#ServerBrowser_ServerNotResponding");
}
else
{
// clear the status
m_pInfoLabel->SetText("");
}
if ( m_Server.m_bHadSuccessfulResponse && !(m_Server.m_nPlayers + m_Server.m_nBotPlayers) )
{
m_pPlayerList->SetEmptyListText("#ServerBrowser_ServerHasNoPlayers");
}
else
{
m_pPlayerList->SetEmptyListText("#ServerBrowser_ServerNotResponding");
}
// auto-retry layout
m_pAutoRetry->SetVisible(m_bShowAutoRetryToggle);
Repaint();
}
void CDialogGameInfo::OnKeyCodePressed( vgui::KeyCode code )
{
if ( code == KEY_XBUTTON_B || code == KEY_XBUTTON_A || code == STEAMCONTROLLER_A || code == STEAMCONTROLLER_B )
{
m_pCloseButton->DoClick();
}
else
{
BaseClass::OnKeyCodePressed(code);
}
}
//-----------------------------------------------------------------------------
// Purpose: Forces the game info dialog to try and connect
//-----------------------------------------------------------------------------
void CDialogGameInfo::Connect()
{
OnConnect();
}
//-----------------------------------------------------------------------------
// Purpose: Connects the user to this game
//-----------------------------------------------------------------------------
void CDialogGameInfo::OnConnect()
{
// flag that we are attempting connection
m_bConnecting = true;
// reset state
m_bServerFull = false;
m_bServerNotResponding = false;
InvalidateLayout();
// need to refresh server before attempting to connect, to make sure there is enough room on the server
m_iRequestRetry = 0;
RequestInfo();
}
//-----------------------------------------------------------------------------
// Purpose: Cancel auto-retry if we connect to the game by other means
//-----------------------------------------------------------------------------
void CDialogGameInfo::OnConnectToGame( int ip, int port )
{
// if we just connected to the server we were looking at, close the dialog
// important so that we don't auto-retry a server that we are already on
if ( m_Server.m_NetAdr.GetIP() == (uint32)ip && m_Server.m_NetAdr.GetConnectionPort() == (uint16)port )
{
// close this dialog
Close();
}
}
//-----------------------------------------------------------------------------
// Purpose: Handles Refresh button press, starts a re-ping of the server
//-----------------------------------------------------------------------------
void CDialogGameInfo::OnRefresh()
{
m_iRequestRetry = 0;
// re-ask the server for the game info
RequestInfo();
}
//-----------------------------------------------------------------------------
// Purpose: Forces the whole dialog to redraw when the auto-retry button is toggled
//-----------------------------------------------------------------------------
void CDialogGameInfo::OnButtonToggled(Panel *panel)
{
if (panel == m_pAutoRetry)
{
ShowAutoRetryOptions(m_pAutoRetry->IsSelected());
}
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: Sets whether the extended auto-retry options are visible or not
//-----------------------------------------------------------------------------
void CDialogGameInfo::ShowAutoRetryOptions(bool state)
{
// we need to extend the dialog
int growSize = 60;
if (!state)
{
growSize = -growSize;
}
// alter the dialog size accordingly
int x, y, wide, tall;
GetBounds( x, y, wide, tall );
// load a new layout file depending on the state
SetMinimumSize(416, 340);
if ( state )
LoadControlSettings( "Servers/DialogGameInfo_AutoRetry.res" );
else
LoadControlSettings( "Servers/DialogGameInfo.res" );
// restore size and position as
// load control settings will override them
SetBounds( x, y, wide, tall + growSize );
// restore other properties of the dialog
PerformLayout();
m_pAutoRetryAlert->SetSelected( true );
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: Requests the right info from the server
//-----------------------------------------------------------------------------
void CDialogGameInfo::RequestInfo()
{
if ( !steamapicontext->SteamMatchmakingServers() )
return;
if ( m_iRequestRetry == 0 )
{
// reset the time at which we auto-refresh
m_iRequestRetry = system()->GetTimeMillis() + RETRY_TIME;
if ( m_hPingQuery != HSERVERQUERY_INVALID )
steamapicontext->SteamMatchmakingServers()->CancelServerQuery( m_hPingQuery );
m_hPingQuery = steamapicontext->SteamMatchmakingServers()->PingServer( m_Server.m_NetAdr.GetIP(), m_Server.m_NetAdr.GetQueryPort(), this );
}
}
//-----------------------------------------------------------------------------
// Purpose: Called every frame, handles resending network messages
//-----------------------------------------------------------------------------
void CDialogGameInfo::OnTick()
{
// check to see if we should perform an auto-refresh
if ( m_iRequestRetry && m_iRequestRetry < system()->GetTimeMillis() )
{
m_iRequestRetry = 0;
RequestInfo();
}
}
//-----------------------------------------------------------------------------
// Purpose: called when the server has successfully responded
//-----------------------------------------------------------------------------
void CDialogGameInfo::ServerResponded( gameserveritem_t &server )
{
if( m_Server.m_NetAdr.GetQueryPort() &&
m_Server.m_NetAdr.GetQueryPort() != server.m_NetAdr.GetQueryPort() )
{
return; // this is not the guy we talked about
}
uint16 connectionPort = m_Server.m_NetAdr.GetConnectionPort();
// FIXME(johns): This is a workaround for a steam bug, where it inproperly reads signed bytes out of the
// message. Once the upstream fix makes it into our SteamSDK, this block can be removed.
server.m_nPlayers = (uint8)(int8)server.m_nPlayers;
server.m_nBotPlayers = (uint8)(int8)server.m_nBotPlayers;
server.m_nMaxPlayers = (uint8)(int8)server.m_nMaxPlayers;
m_hPingQuery = HSERVERQUERY_INVALID;
m_Server = server;
// Preserve our connection port, since we may be querying the sourceTV port but getting a response for the real
// server. This is a limitation of the steam Matchmaking API where it doesn't properly send us a sourcetv response
// but instead the main server's response (unless we're connecting to a proxy, THEN we get the sourcetv response!)
m_Server.m_NetAdr.SetConnectionPort( connectionPort );
if ( m_bConnecting )
{
ConnectToServer();
}
else if ( m_pAutoRetry->IsSelected() && server.m_nPlayers < server.m_nMaxPlayers )
{
// there is a slot free, we can join
// make the sound
surface()->PlaySound("Servers/game_ready.wav");
// flash this window
FlashWindow();
// if it's set, connect right away
if (m_pAutoRetryJoin->IsSelected())
{
ConnectToServer();
}
}
else
{
SendPlayerQuery( server.m_NetAdr.GetIP(), server.m_NetAdr.GetQueryPort() );
}
m_bServerNotResponding = false;
InvalidateLayout();
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: called when a server response has timed out
//-----------------------------------------------------------------------------
void CDialogGameInfo::ServerFailedToRespond()
{
// the server didn't respond, mark that in the UI
// only mark if we haven't ever received a response
if ( !m_Server.m_bHadSuccessfulResponse )
{
m_bServerNotResponding = true;
}
InvalidateLayout();
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: Constructs a command to send a running game to connect to a server,
// based on the server type
//
// TODO it would be nice to push this logic into the IRunGameEngine interface; that
// way we could ask the engine itself to construct arguments in ways that fit.
// Might be worth the effort as we start to add more engines.
//-----------------------------------------------------------------------------
void CDialogGameInfo::ApplyConnectCommand( const gameserveritem_t &server )
{
char command[ 256 ];
// set the server password, if any
if ( m_szPassword[0] )
{
Q_snprintf( command, Q_ARRAYSIZE( command ), "password \"%s\"\n", m_szPassword );
g_pRunGameEngine->AddTextCommand( command );
}
// send engine command to change servers
Q_snprintf( command, Q_ARRAYSIZE( command ), "connect %s %s\n", server.m_NetAdr.GetConnectionAddressString(), m_sConnectCode.String() );
g_pRunGameEngine->AddTextCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose: Constructs game options to use when running a game to connect to a server
//-----------------------------------------------------------------------------
void CDialogGameInfo::ConstructConnectArgs( char *pchOptions, int cchOptions, const gameserveritem_t &server )
{
Q_snprintf( pchOptions, cchOptions, " +connect %s", server.m_NetAdr.GetConnectionAddressString() );
if ( m_szPassword[0] )
{
Q_strcat( pchOptions, " +password \"", cchOptions );
Q_strcat( pchOptions, m_szPassword, cchOptions );
Q_strcat( pchOptions, "\"", cchOptions );
}
}
//-----------------------------------------------------------------------------
// Purpose: Connects to the server
//-----------------------------------------------------------------------------
void CDialogGameInfo::ConnectToServer()
{
m_bConnecting = false;
// check VAC status
if ( m_Server.m_bSecure && ServerBrowser().IsVACBannedFromGame( m_Server.m_nAppID ) )
{
// refuse the user
CVACBannedConnRefusedDialog *pDlg = new CVACBannedConnRefusedDialog( GetVParent(), "VACBannedConnRefusedDialog" );
pDlg->Activate();
Close();
return;
}
// check to see if we need a password
if ( m_Server.m_bPassword && !m_szPassword[0] )
{
CDialogServerPassword *box = new CDialogServerPassword(this);
box->AddActionSignalTarget(this);
box->Activate( m_Server.GetName(), 0 );
return;
}
// check the player count
if ( m_Server.m_nPlayers >= m_Server.m_nMaxPlayers )
{
// mark why we cannot connect
m_bServerFull = true;
// give them access to auto-retry options
m_bShowAutoRetryToggle = true;
InvalidateLayout();
return;
}
// tell the engine to connect
const char *gameDir = m_Server.m_szGameDir;
if (g_pRunGameEngine->IsRunning())
{
ApplyConnectCommand( m_Server );
}
else
{
char connectArgs[256];
ConstructConnectArgs( connectArgs, Q_ARRAYSIZE( connectArgs ), m_Server );
if ( ( m_Server.m_bSecure && JoiningSecureServerCall() )|| !m_Server.m_bSecure )
{
switch ( g_pRunGameEngine->RunEngine( m_Server.m_nAppID, gameDir, connectArgs ) )
{
case IRunGameEngine::k_ERunResultModNotInstalled:
{
MessageBox *dlg = new MessageBox( "#ServerBrowser_GameInfoTitle", "#ServerBrowser_ModNotInstalled" );
dlg->DoModal();
SetVisible(false);
return;
}
break;
case IRunGameEngine::k_ERunResultAppNotFound:
{
MessageBox *dlg = new MessageBox( "#ServerBrowser_GameInfoTitle", "#ServerBrowser_AppNotFound" );
dlg->DoModal();
SetVisible(false);
return;
}
break;
case IRunGameEngine::k_ERunResultNotInitialized:
{
MessageBox *dlg = new MessageBox( "#ServerBrowser_GameInfoTitle", "#ServerBrowser_NotInitialized" );
dlg->DoModal();
SetVisible(false);
return;
}
break;
case IRunGameEngine::k_ERunResultOkay:
default:
break;
};
}
}
// close this dialog
PostMessage(this, new KeyValues("Close"));
}
//-----------------------------------------------------------------------------
// Purpose: called when the current refresh list is complete
//-----------------------------------------------------------------------------
void CDialogGameInfo::RefreshComplete( EMatchMakingServerResponse response )
{
}
//-----------------------------------------------------------------------------
// Purpose: handles response from the get password dialog
//-----------------------------------------------------------------------------
void CDialogGameInfo::OnJoinServerWithPassword(const char *password)
{
// copy out the password
Q_strncpy(m_szPassword, password, sizeof(m_szPassword));
// retry connecting to the server again
OnConnect();
}
//-----------------------------------------------------------------------------
// Purpose: player list received
//-----------------------------------------------------------------------------
void CDialogGameInfo::ClearPlayerList()
{
m_pPlayerList->DeleteAllItems();
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: on individual player added
//-----------------------------------------------------------------------------
void CDialogGameInfo::AddPlayerToList(const char *playerName, int score, float timePlayedSeconds)
{
if ( m_bPlayerListUpdatePending )
{
m_bPlayerListUpdatePending = false;
m_pPlayerList->RemoveAll();
}
KeyValues *player = new KeyValues("player");
player->SetString("PlayerName", playerName);
player->SetInt("Score", score);
player->SetInt("TimeSec", (int)timePlayedSeconds);
// construct a time string
int seconds = (int)timePlayedSeconds;
int minutes = seconds / 60;
int hours = minutes / 60;
seconds %= 60;
minutes %= 60;
char buf[64];
buf[0] = 0;
if (hours)
{
Q_snprintf(buf, sizeof(buf), "%dh %dm %ds", hours, minutes, seconds);
}
else if (minutes)
{
Q_snprintf(buf, sizeof(buf), "%dm %ds", minutes, seconds);
}
else
{
Q_snprintf(buf, sizeof(buf), "%ds", seconds);
}
player->SetString("Time", buf);
m_pPlayerList->AddItem(player, 0, false, true);
player->deleteThis();
}
//-----------------------------------------------------------------------------
// Purpose: Sorting function for time column
//-----------------------------------------------------------------------------
int CDialogGameInfo::PlayerTimeColumnSortFunc(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
int p1time = p1.kv->GetInt("TimeSec");
int p2time = p2.kv->GetInt("TimeSec");
if (p1time > p2time)
return -1;
if (p1time < p2time)
return 1;
return 0;
}

View File

@ -0,0 +1,126 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef DIALOGGAMEINFO_H
#define DIALOGGAMEINFO_H
#ifdef _WIN32
#pragma once
#endif
struct challenge_s
{
netadr_t addr;
int challenge;
};
//-----------------------------------------------------------------------------
// Purpose: Dialog for displaying information about a game server
//-----------------------------------------------------------------------------
class CDialogGameInfo : public vgui::Frame, public ISteamMatchmakingPlayersResponse, public ISteamMatchmakingPingResponse
{
DECLARE_CLASS_SIMPLE( CDialogGameInfo, vgui::Frame );
public:
CDialogGameInfo(vgui::Panel *parent, int serverIP, int queryPort, unsigned short connectionPort, const char *pszConnectCode );
~CDialogGameInfo();
void Run(const char *titleName);
void ChangeGame(int serverIP, int queryPort, unsigned short connectionPort);
void SetFriend( uint64 ulSteamIDFriend );
uint64 GetAssociatedFriend();
// forces the dialog to attempt to connect to the server
void Connect();
// implementation of IServerRefreshResponse interface
// called when the server has successfully responded
virtual void ServerResponded( gameserveritem_t &server );
// called when a server response has timed out
virtual void ServerFailedToRespond();
// on individual player added
virtual void AddPlayerToList(const char *playerName, int score, float timePlayedSeconds);
virtual void PlayersFailedToRespond() {}
virtual void PlayersRefreshComplete() { m_hPlayersQuery = HSERVERQUERY_INVALID; }
// called when the current refresh list is complete
virtual void RefreshComplete( EMatchMakingServerResponse response );
// player list received
virtual void ClearPlayerList();
//virtual void SendChallengeQuery( const netadr_t & to );
virtual void SendPlayerQuery( uint32 unIP, uint16 usQueryPort );
//virtual void InsertChallengeResponse( const netadr_t & to, int nChallenge );
protected:
// message handlers
MESSAGE_FUNC( OnConnect, "Connect" );
MESSAGE_FUNC( OnRefresh, "Refresh" );
MESSAGE_FUNC_PTR( OnButtonToggled, "ButtonToggled", panel );
MESSAGE_FUNC_PTR( OnRadioButtonChecked, "RadioButtonChecked", panel )
{
OnButtonToggled( panel );
}
// response from the get password dialog
MESSAGE_FUNC_CHARPTR( OnJoinServerWithPassword, "JoinServerWithPassword", password );
MESSAGE_FUNC_INT_INT( OnConnectToGame, "ConnectedToGame", ip, port );
// vgui overrides
virtual void OnTick();
virtual void PerformLayout();
virtual void OnKeyCodePressed( vgui::KeyCode code );
private:
STEAM_CALLBACK( CDialogGameInfo, OnPersonaStateChange, PersonaStateChange_t, m_CallbackPersonaStateChange );
long m_iRequestRetry; // time at which to retry the request
static int PlayerTimeColumnSortFunc(vgui::ListPanel *pPanel, const vgui::ListPanelItem &p1, const vgui::ListPanelItem &p2);
// methods
void RequestInfo();
void ConnectToServer();
void ShowAutoRetryOptions(bool state);
void ConstructConnectArgs( char *pchOptions, int cchOptions, const gameserveritem_t &server );
void ApplyConnectCommand( const gameserveritem_t &server );
vgui::Button *m_pConnectButton;
vgui::Button *m_pCloseButton;
vgui::Button *m_pRefreshButton;
vgui::Label *m_pInfoLabel;
vgui::ToggleButton *m_pAutoRetry;
vgui::RadioButton *m_pAutoRetryAlert;
vgui::RadioButton *m_pAutoRetryJoin;
vgui::ListPanel *m_pPlayerList;
enum { PING_TIMES_MAX = 4 };
// true if we should try connect to the server when it refreshes
bool m_bConnecting;
// password, if entered
char m_szPassword[64];
// state
bool m_bServerNotResponding;
bool m_bServerFull;
bool m_bShowAutoRetryToggle;
bool m_bShowingExtendedOptions;
uint64 m_SteamIDFriend;
CUtlString m_sConnectCode;
gameserveritem_t m_Server;
HServerQuery m_hPingQuery;
HServerQuery m_hPlayersQuery;
bool m_bPlayerListUpdatePending;
};
#endif // DIALOGGAMEINFO_H

View File

@ -0,0 +1,89 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "pch_serverbrowser.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CDialogServerPassword::CDialogServerPassword(vgui::Panel *parent) : Frame(parent, "DialogServerPassword")
{
m_iServerID = -1;
SetSize(320, 240);
SetDeleteSelfOnClose(true);
SetSizeable(false);
m_pInfoLabel = new Label(this, "InfoLabel", "#ServerBrowser_ServerRequiresPassword");
m_pGameLabel = new Label(this, "GameLabel", "<game label>");
m_pPasswordEntry = new TextEntry(this, "PasswordEntry");
m_pConnectButton = new Button(this, "ConnectButton", "#ServerBrowser_Connect");
m_pPasswordEntry->SetTextHidden(true);
LoadControlSettings("Servers/DialogServerPassword.res");
SetTitle("#ServerBrowser_ServerRequiresPasswordTitle", true);
// set our initial position in the middle of the workspace
MoveToCenterOfScreen();
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CDialogServerPassword::~CDialogServerPassword()
{
}
//-----------------------------------------------------------------------------
// Purpose: initializes the dialog and brings it to the foreground
//-----------------------------------------------------------------------------
void CDialogServerPassword::Activate(const char *serverName, unsigned int serverID)
{
m_pGameLabel->SetText(serverName);
m_iServerID = serverID;
m_pConnectButton->SetAsDefaultButton(true);
m_pPasswordEntry->RequestFocus();
BaseClass::Activate();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *command -
//-----------------------------------------------------------------------------
void CDialogServerPassword::OnCommand(const char *command)
{
bool bClose = false;
if (!Q_stricmp(command, "Connect"))
{
KeyValues *msg = new KeyValues("JoinServerWithPassword");
char buf[64];
m_pPasswordEntry->GetText(buf, sizeof(buf)-1);
msg->SetString("password", buf);
msg->SetInt("serverID", m_iServerID);
PostActionSignal(msg);
bClose = true;
}
else if (!Q_stricmp(command, "Close"))
{
bClose = true;
}
else
{
BaseClass::OnCommand(command);
}
if (bClose)
{
PostMessage(this, new KeyValues("Close"));
}
}

View File

@ -0,0 +1,46 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef DIALOGSERVERPASSWORD_H
#define DIALOGSERVERPASSWORD_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Prompt for user to enter a password to be able to connect to the server
//-----------------------------------------------------------------------------
class CDialogServerPassword : public vgui::Frame
{
public:
CDialogServerPassword(vgui::Panel *parent);
~CDialogServerPassword();
// initializes the dialog and brings it to the foreground
void Activate(const char *serverName, unsigned int serverID);
/* message returned:
"JoinServerWithPassword"
"serverID"
"password"
*/
private:
virtual void OnCommand(const char *command);
vgui::Label *m_pInfoLabel;
vgui::Label *m_pGameLabel;
vgui::TextEntry *m_pPasswordEntry;
vgui::Button *m_pConnectButton;
typedef vgui::Frame BaseClass;
int m_iServerID;
};
#endif // DIALOGSERVERPASSWORD_H

View File

@ -0,0 +1,214 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "pch_serverbrowser.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CFavoriteGames::CFavoriteGames(vgui::Panel *parent) :
CBaseGamesPage(parent, "FavoriteGames", eFavoritesServer )
{
m_bRefreshOnListReload = false;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CFavoriteGames::~CFavoriteGames()
{
}
//-----------------------------------------------------------------------------
// Purpose: loads favorites list from disk
//-----------------------------------------------------------------------------
void CFavoriteGames::LoadFavoritesList()
{
if ( steamapicontext->SteamMatchmaking() && steamapicontext->SteamMatchmaking()->GetFavoriteGameCount() == 0 )
{
// set empty message
m_pGameList->SetEmptyListText("#ServerBrowser_NoFavoriteServers");
}
else
{
m_pGameList->SetEmptyListText("#ServerBrowser_NoInternetGamesResponded");
}
if ( m_bRefreshOnListReload )
{
m_bRefreshOnListReload = false;
StartRefresh();
}
}
//-----------------------------------------------------------------------------
// Purpose: returns true if the game list supports the specified ui elements
//-----------------------------------------------------------------------------
bool CFavoriteGames::SupportsItem(InterfaceItem_e item)
{
switch (item)
{
case FILTERS:
case ADDSERVER:
return true;
case ADDCURRENTSERVER:
return !IsSteam() && BFiltersVisible();
case GETNEWLIST:
default:
return false;
}
}
//-----------------------------------------------------------------------------
// Purpose: called when the current refresh list is complete
//-----------------------------------------------------------------------------
void CFavoriteGames::RefreshComplete( HServerListRequest hReq, EMatchMakingServerResponse response )
{
SetRefreshing(false);
if ( steamapicontext->SteamMatchmaking() && steamapicontext->SteamMatchmaking()->GetFavoriteGameCount() == 0 )
{
// set empty message
m_pGameList->SetEmptyListText("#ServerBrowser_NoFavoriteServers");
}
else
{
m_pGameList->SetEmptyListText("#ServerBrowser_NoInternetGamesResponded");
}
m_pGameList->SortList();
BaseClass::RefreshComplete( hReq, response );
}
//-----------------------------------------------------------------------------
// Purpose: opens context menu (user right clicked on a server)
//-----------------------------------------------------------------------------
void CFavoriteGames::OnOpenContextMenu(int itemID)
{
CServerContextMenu *menu = ServerBrowserDialog().GetContextMenu(GetActiveList());
// get the server
int serverID = GetSelectedServerID();
if ( serverID != -1 )
{
// Activate context menu
menu->ShowMenu(this, serverID, true, true, true, false);
menu->AddMenuItem("RemoveServer", "#ServerBrowser_RemoveServerFromFavorites", new KeyValues("RemoveFromFavorites"), this);
}
else
{
// no selected rows, so don't display default stuff in menu
menu->ShowMenu( this,(uint32)-1, false, false, false, false );
}
menu->AddMenuItem("AddServerByName", "#ServerBrowser_AddServerByIP", new KeyValues("AddServerByName"), this);
}
//-----------------------------------------------------------------------------
// Purpose: removes a server from the favorites
//-----------------------------------------------------------------------------
void CFavoriteGames::OnRemoveFromFavorites()
{
if ( !steamapicontext->SteamMatchmakingServers() || !steamapicontext->SteamMatchmaking() )
return;
// iterate the selection
for ( int iGame = 0; iGame < m_pGameList->GetSelectedItemsCount(); iGame++ )
{
int itemID = m_pGameList->GetSelectedItem( iGame );
int serverID = m_pGameList->GetItemData(itemID)->userData;
gameserveritem_t *pServer = steamapicontext->SteamMatchmakingServers()->GetServerDetails( m_hRequest, serverID );
if ( pServer )
{
steamapicontext->SteamMatchmaking()->RemoveFavoriteGame( pServer->m_nAppID, pServer->m_NetAdr.GetIP(), pServer->m_NetAdr.GetConnectionPort(), pServer->m_NetAdr.GetQueryPort(), k_unFavoriteFlagFavorite );
}
}
UpdateStatus();
InvalidateLayout();
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: Adds a server by IP address
//-----------------------------------------------------------------------------
void CFavoriteGames::OnAddServerByName()
{
// open the add server dialog
CDialogAddServer *dlg = new CDialogAddServer( &ServerBrowserDialog(), this );
dlg->MoveToCenterOfScreen();
dlg->DoModal();
}
//-----------------------------------------------------------------------------
// Purpose: Adds the currently connected server to the list
//-----------------------------------------------------------------------------
void CFavoriteGames::OnAddCurrentServer()
{
gameserveritem_t *pConnected = ServerBrowserDialog().GetCurrentConnectedServer();
if ( pConnected && steamapicontext->SteamMatchmaking() )
{
steamapicontext->SteamMatchmaking()->AddFavoriteGame( pConnected->m_nAppID, pConnected->m_NetAdr.GetIP(), pConnected->m_NetAdr.GetConnectionPort(), pConnected->m_NetAdr.GetQueryPort(), k_unFavoriteFlagFavorite, time( NULL ) );
m_bRefreshOnListReload = true;
if ( GameSupportsReplay() )
{
// send command to propagate to the client so the client can send it on to the GC
char command[ 256 ];
Q_snprintf( command, Q_ARRAYSIZE( command ), "rfgc %s\n", pConnected->m_NetAdr.GetConnectionAddressString() );
g_pRunGameEngine->AddTextCommand( command );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Parse posted messages
//
//-----------------------------------------------------------------------------
void CFavoriteGames::OnCommand(const char *command)
{
if (!Q_stricmp(command, "AddServerByName"))
{
OnAddServerByName();
}
else if (!Q_stricmp(command, "AddCurrentServer" ))
{
OnAddCurrentServer();
}
else
{
BaseClass::OnCommand(command);
}
}
//-----------------------------------------------------------------------------
// Purpose: enables adding server
//-----------------------------------------------------------------------------
void CFavoriteGames::OnConnectToGame()
{
m_pAddCurrentServer->SetEnabled( true );
}
//-----------------------------------------------------------------------------
// Purpose: disables adding current server
//-----------------------------------------------------------------------------
void CFavoriteGames::OnDisconnectFromGame( void )
{
m_pAddCurrentServer->SetEnabled( false );
}

View File

@ -0,0 +1,55 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef FAVORITEGAMES_H
#define FAVORITEGAMES_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Favorite games list
//-----------------------------------------------------------------------------
class CFavoriteGames : public CBaseGamesPage
{
DECLARE_CLASS_SIMPLE( CFavoriteGames, CBaseGamesPage );
public:
CFavoriteGames(vgui::Panel *parent);
~CFavoriteGames();
// favorites list, loads/saves into keyvalues
void LoadFavoritesList();
// IGameList handlers
// returns true if the game list supports the specified ui elements
virtual bool SupportsItem(InterfaceItem_e item);
// called when the current refresh list is complete
virtual void RefreshComplete( HServerListRequest hReq, EMatchMakingServerResponse response );
// passed from main server browser window instead of messages
void OnConnectToGame();
void OnDisconnectFromGame( void );
void SetRefreshOnReload() { m_bRefreshOnListReload = true; }
private:
// context menu message handlers
MESSAGE_FUNC_INT( OnOpenContextMenu, "OpenContextMenu", itemID );
MESSAGE_FUNC( OnRemoveFromFavorites, "RemoveFromFavorites" );
MESSAGE_FUNC( OnAddServerByName, "AddServerByName" );
void OnAddCurrentServer( void );
void OnCommand(const char *command);
bool m_bRefreshOnListReload;
};
#endif // FAVORITEGAMES_H

View File

@ -0,0 +1,88 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "pch_serverbrowser.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CFriendsGames::CFriendsGames(vgui::Panel *parent) :
CBaseGamesPage(parent, "FriendsGames", eFriendsServer )
{
m_iServerRefreshCount = 0;
if ( !IsSteamGameServerBrowsingEnabled() )
{
m_pGameList->SetEmptyListText("#ServerBrowser_OfflineMode");
m_pConnect->SetEnabled( false );
m_pRefreshAll->SetEnabled( false );
m_pRefreshQuick->SetEnabled( false );
m_pAddServer->SetEnabled( false );
m_pFilter->SetEnabled( false );
}
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CFriendsGames::~CFriendsGames()
{
}
//-----------------------------------------------------------------------------
// Purpose: returns true if the game list supports the specified ui elements
//-----------------------------------------------------------------------------
bool CFriendsGames::SupportsItem(InterfaceItem_e item)
{
switch (item)
{
case FILTERS:
return true;
case GETNEWLIST:
default:
return false;
}
}
//-----------------------------------------------------------------------------
// Purpose: called when the current refresh list is complete
//-----------------------------------------------------------------------------
void CFriendsGames::RefreshComplete( HServerListRequest hReq, EMatchMakingServerResponse response )
{
SetRefreshing(false);
m_pGameList->SortList();
m_iServerRefreshCount = 0;
if ( IsSteamGameServerBrowsingEnabled() )
{
// set empty message
m_pGameList->SetEmptyListText("#ServerBrowser_NoFriendsServers");
}
BaseClass::RefreshComplete( hReq, response );
}
//-----------------------------------------------------------------------------
// Purpose: opens context menu (user right clicked on a server)
//-----------------------------------------------------------------------------
void CFriendsGames::OnOpenContextMenu(int itemID)
{
// get the server
int serverID = GetSelectedServerID();
if ( serverID == -1 )
return;
// Activate context menu
CServerContextMenu *menu = ServerBrowserDialog().GetContextMenu(GetActiveList());
menu->ShowMenu(this, serverID, true, true, true, true);
}

View File

@ -0,0 +1,39 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef FRIENDSGAMES_H
#define FRIENDSGAMES_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Favorite games list
//-----------------------------------------------------------------------------
class CFriendsGames : public CBaseGamesPage
{
DECLARE_CLASS_SIMPLE( CFriendsGames, CBaseGamesPage );
public:
CFriendsGames(vgui::Panel *parent);
~CFriendsGames();
// IGameList handlers
// returns true if the game list supports the specified ui elements
virtual bool SupportsItem(InterfaceItem_e item);
// called when the current refresh list is complete
virtual void RefreshComplete( HServerListRequest hReq, EMatchMakingServerResponse response );
private:
// context menu message handlers
MESSAGE_FUNC_INT( OnOpenContextMenu, "OpenContextMenu", itemID );
int m_iServerRefreshCount; // number of servers refreshed
};
#endif // FRIENDSGAMES_H

View File

@ -0,0 +1,136 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "pch_serverbrowser.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CHistoryGames::CHistoryGames(vgui::Panel *parent) :
CBaseGamesPage(parent, "HistoryGames", eHistoryServer )
{
m_bRefreshOnListReload = false;
m_pGameList->AddColumnHeader(10, "LastPlayed", "#ServerBrowser_LastPlayed", 100);
m_pGameList->SetSortFunc(10, LastPlayedCompare);
m_pGameList->SetSortColumn(10);
if ( !IsSteamGameServerBrowsingEnabled() )
{
m_pGameList->SetEmptyListText("#ServerBrowser_OfflineMode");
m_pConnect->SetEnabled( false );
m_pRefreshAll->SetEnabled( false );
m_pRefreshQuick->SetEnabled( false );
m_pAddServer->SetEnabled( false );
m_pFilter->SetEnabled( false );
}
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CHistoryGames::~CHistoryGames()
{
}
//-----------------------------------------------------------------------------
// Purpose: loads favorites list from disk
//-----------------------------------------------------------------------------
void CHistoryGames::LoadHistoryList()
{
if ( IsSteamGameServerBrowsingEnabled() )
{
// set empty message
m_pGameList->SetEmptyListText("#ServerBrowser_NoServersPlayed");
}
if ( m_bRefreshOnListReload )
{
m_bRefreshOnListReload = false;
StartRefresh();
}
}
//-----------------------------------------------------------------------------
// Purpose: returns true if the game list supports the specified ui elements
//-----------------------------------------------------------------------------
bool CHistoryGames::SupportsItem(InterfaceItem_e item)
{
switch (item)
{
case FILTERS:
return true;
case ADDSERVER:
case GETNEWLIST:
default:
return false;
}
}
//-----------------------------------------------------------------------------
// Purpose: called when the current refresh list is complete
//-----------------------------------------------------------------------------
void CHistoryGames::RefreshComplete( HServerListRequest hReq, EMatchMakingServerResponse response )
{
SetRefreshing(false);
m_pGameList->SetEmptyListText("#ServerBrowser_NoServersPlayed");
m_pGameList->SortList();
BaseClass::RefreshComplete( hReq, response );
}
//-----------------------------------------------------------------------------
// Purpose: opens context menu (user right clicked on a server)
//-----------------------------------------------------------------------------
void CHistoryGames::OnOpenContextMenu(int itemID)
{
CServerContextMenu *menu = ServerBrowserDialog().GetContextMenu(GetActiveList());
// get the server
int serverID = GetSelectedServerID();
if( serverID != -1 )
{
// Activate context menu
menu->ShowMenu(this, serverID, true, true, true, true);
menu->AddMenuItem("RemoveServer", "#ServerBrowser_RemoveServerFromHistory", new KeyValues("RemoveFromHistory"), this);
}
else
{
// no selected rows, so don't display default stuff in menu
menu->ShowMenu(this, (uint32)-1, false, false, false, false);
}
}
//-----------------------------------------------------------------------------
// Purpose: removes a server from the favorites
//-----------------------------------------------------------------------------
void CHistoryGames::OnRemoveFromHistory()
{
if ( !steamapicontext->SteamMatchmakingServers() || !steamapicontext->SteamMatchmaking() )
return;
// iterate the selection
for ( int i = m_pGameList->GetSelectedItemsCount() - 1; i >= 0; i-- )
{
int itemID = m_pGameList->GetSelectedItem( i );
int serverID = m_pGameList->GetItemData(itemID)->userData;
gameserveritem_t *pServer = steamapicontext->SteamMatchmakingServers()->GetServerDetails( m_hRequest, serverID );
if ( pServer )
steamapicontext->SteamMatchmaking()->RemoveFavoriteGame( pServer->m_nAppID, pServer->m_NetAdr.GetIP(), pServer->m_NetAdr.GetConnectionPort(), pServer->m_NetAdr.GetQueryPort(), k_unFavoriteFlagHistory );
}
UpdateStatus();
InvalidateLayout();
Repaint();
}

View File

@ -0,0 +1,46 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef HISTORYGAMES_H
#define HISTORYGAMES_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: History of all the servers joined
//-----------------------------------------------------------------------------
class CHistoryGames : public CBaseGamesPage
{
DECLARE_CLASS_SIMPLE( CHistoryGames, CBaseGamesPage );
public:
CHistoryGames(vgui::Panel *parent);
~CHistoryGames();
// favorites list, loads/saves into keyvalues
void LoadHistoryList();
// IGameList handlers
// returns true if the game list supports the specified ui elements
virtual bool SupportsItem(InterfaceItem_e item);
// called when the current refresh list is complete
virtual void RefreshComplete( HServerListRequest hReq, EMatchMakingServerResponse response );
void SetRefreshOnReload() { m_bRefreshOnListReload = true; }
private:
// context menu message handlers
MESSAGE_FUNC_INT( OnOpenContextMenu, "OpenContextMenu", itemID );
MESSAGE_FUNC( OnRemoveFromHistory, "RemoveFromHistory" );
bool m_bRefreshOnListReload;
};
#endif // HISTORYGAMES_H

View File

@ -0,0 +1,319 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "pch_serverbrowser.h"
using namespace vgui;
// How often to re-sort the server list
const float MINIMUM_SORT_TIME = 1.5f;
//-----------------------------------------------------------------------------
// Purpose: Constructor
// NOTE: m_Servers can not use more than 96 sockets, else it will
// cause internet explorer to Stop working under win98 SE!
//-----------------------------------------------------------------------------
CInternetGames::CInternetGames(vgui::Panel *parent, const char *panelName, EPageType eType ) :
CBaseGamesPage(parent, panelName, eType )
{
m_fLastSort = 0.0f;
m_bDirty = false;
m_bRequireUpdate = true;
m_bOfflineMode = !IsSteamGameServerBrowsingEnabled();
m_bAnyServersRetrievedFromMaster = false;
m_bNoServersListedOnMaster = false;
m_bAnyServersRespondedToQuery = false;
m_pLocationFilter->DeleteAllItems();
KeyValues *kv = new KeyValues("Regions");
if (kv->LoadFromFile( g_pFullFileSystem, "servers/Regions.vdf", NULL))
{
// iterate the list loading all the servers
for (KeyValues *srv = kv->GetFirstSubKey(); srv != NULL; srv = srv->GetNextKey())
{
struct regions_s region;
region.name = srv->GetString("text");
region.code = srv->GetInt("code");
KeyValues *regionKV = new KeyValues("region", "code", region.code);
m_pLocationFilter->AddItem( region.name.String(), regionKV );
regionKV->deleteThis();
m_Regions.AddToTail(region);
}
}
else
{
Assert(!("Could not load file servers/Regions.vdf; server browser will not function."));
}
kv->deleteThis();
LoadFilterSettings();
ivgui()->AddTickSignal( GetVPanel(), 250 );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CInternetGames::~CInternetGames()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CInternetGames::PerformLayout()
{
if ( !m_bOfflineMode && m_bRequireUpdate && ServerBrowserDialog().IsVisible() )
{
PostMessage( this, new KeyValues( "GetNewServerList" ), 0.1f );
m_bRequireUpdate = false;
}
if ( m_bOfflineMode )
{
m_pGameList->SetEmptyListText("#ServerBrowser_OfflineMode");
m_pConnect->SetEnabled( false );
m_pRefreshAll->SetEnabled( false );
m_pRefreshQuick->SetEnabled( false );
m_pAddServer->SetEnabled( false );
m_pFilter->SetEnabled( false );
}
BaseClass::PerformLayout();
m_pLocationFilter->SetEnabled(true);
}
//-----------------------------------------------------------------------------
// Purpose: Activates the page, starts refresh if needed
//-----------------------------------------------------------------------------
void CInternetGames::OnPageShow()
{
if ( m_pGameList->GetItemCount() == 0 && ServerBrowserDialog().IsVisible() )
BaseClass::OnPageShow();
// the "internet games" tab (unlike the other browser tabs)
// does not automatically start a query when the user
// navigates to this tab unless they have no servers listed.
}
//-----------------------------------------------------------------------------
// Purpose: Called every frame, maintains sockets and runs refreshes
//-----------------------------------------------------------------------------
void CInternetGames::OnTick()
{
if ( m_bOfflineMode )
{
BaseClass::OnTick();
return;
}
BaseClass::OnTick();
CheckRedoSort();
}
//-----------------------------------------------------------------------------
// Purpose: Handles incoming server refresh data
// updates the server browser with the refreshed information from the server itself
//-----------------------------------------------------------------------------
void CInternetGames::ServerResponded( HServerListRequest hReq, int iServer )
{
m_bDirty = true;
BaseClass::ServerResponded( hReq, iServer );
m_bAnyServersRespondedToQuery = true;
m_bAnyServersRetrievedFromMaster = true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CInternetGames::ServerFailedToRespond( HServerListRequest hReq, int iServer )
{
m_bDirty = true;
gameserveritem_t *pServer = steamapicontext->SteamMatchmakingServers()->GetServerDetails( hReq, iServer );
Assert( pServer );
if ( pServer->m_bHadSuccessfulResponse )
{
// if it's had a successful response in the past, leave it on
ServerResponded( hReq, iServer );
}
else
{
int iServerMap = m_mapServers.Find( iServer );
if ( iServerMap != m_mapServers.InvalidIndex() )
RemoveServer( m_mapServers[ iServerMap ] );
// we've never had a good response from this server, remove it from the list
m_iServerRefreshCount++;
}
}
//-----------------------------------------------------------------------------
// Purpose: Called when server refresh has been completed
//-----------------------------------------------------------------------------
void CInternetGames::RefreshComplete( HServerListRequest hReq, EMatchMakingServerResponse response )
{
SetRefreshing(false);
UpdateFilterSettings();
if ( response != eServerFailedToRespond )
{
if ( m_bAnyServersRespondedToQuery )
{
m_pGameList->SetEmptyListText( GetStringNoUnfilteredServers() );
}
else if ( response == eNoServersListedOnMasterServer )
{
m_pGameList->SetEmptyListText( GetStringNoUnfilteredServersOnMaster() );
}
else
{
m_pGameList->SetEmptyListText( GetStringNoServersResponded() );
}
}
else
{
m_pGameList->SetEmptyListText("#ServerBrowser_MasterServerNotResponsive");
}
// perform last sort
m_bDirty = false;
m_fLastSort = Plat_FloatTime();
if (IsVisible())
{
m_pGameList->SortList();
}
UpdateStatus();
BaseClass::RefreshComplete( hReq, response );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CInternetGames::GetNewServerList()
{
BaseClass::GetNewServerList();
UpdateStatus();
m_bRequireUpdate = false;
m_bAnyServersRetrievedFromMaster = false;
m_bAnyServersRespondedToQuery = false;
m_pGameList->DeleteAllItems();
}
//-----------------------------------------------------------------------------
// Purpose: returns true if the game list supports the specified ui elements
//-----------------------------------------------------------------------------
bool CInternetGames::SupportsItem(IGameList::InterfaceItem_e item)
{
switch (item)
{
case FILTERS:
case GETNEWLIST:
return true;
default:
return false;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CInternetGames::CheckRedoSort( void )
{
float fCurTime;
// No changes detected
if ( !m_bDirty )
return;
fCurTime = Plat_FloatTime();
// Not time yet
if ( fCurTime - m_fLastSort < MINIMUM_SORT_TIME)
return;
// postpone sort if mouse button is down
if ( input()->IsMouseDown(MOUSE_LEFT) || input()->IsMouseDown(MOUSE_RIGHT) )
{
// don't sort for at least another second
m_fLastSort = fCurTime - MINIMUM_SORT_TIME + 1.0f;
return;
}
// Reset timer
m_bDirty = false;
m_fLastSort = fCurTime;
// Force sort to occur now!
m_pGameList->SortList();
}
//-----------------------------------------------------------------------------
// Purpose: opens context menu (user right clicked on a server)
//-----------------------------------------------------------------------------
void CInternetGames::OnOpenContextMenu(int itemID)
{
// get the server
int serverID = GetSelectedServerID();
if ( serverID == -1 )
return;
// Activate context menu
CServerContextMenu *menu = ServerBrowserDialog().GetContextMenu(GetActiveList());
menu->ShowMenu(this, serverID, true, true, true, true);
}
//-----------------------------------------------------------------------------
// Purpose: refreshes a single server
//-----------------------------------------------------------------------------
void CInternetGames::OnRefreshServer(int serverID)
{
BaseClass::OnRefreshServer( serverID );
ServerBrowserDialog().UpdateStatusText("#ServerBrowser_GettingNewServerList");
}
//-----------------------------------------------------------------------------
// Purpose: get the region code selected in the ui
// Output: returns the region code the user wants to filter by
//-----------------------------------------------------------------------------
int CInternetGames::GetRegionCodeToFilter()
{
KeyValues *kv = m_pLocationFilter->GetActiveItemUserData();
if ( kv )
return kv->GetInt( "code" );
else
return 255;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CInternetGames::CheckTagFilter( gameserveritem_t &server )
{
// Servers without tags go in the official games, servers with tags go in custom games
bool bOfficialServer = !( server.m_szGameTags && server.m_szGameTags[0] );
if ( !bOfficialServer )
return false;
return true;
}

View File

@ -0,0 +1,83 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef INTERNETGAMES_H
#define INTERNETGAMES_H
#ifdef _WIN32
#pragma once
#endif
#include "BaseGamesPage.h"
//-----------------------------------------------------------------------------
// Purpose: Internet games list
//-----------------------------------------------------------------------------
class CInternetGames : public CBaseGamesPage
{
DECLARE_CLASS_SIMPLE( CInternetGames, CBaseGamesPage );
public:
CInternetGames( vgui::Panel *parent, const char *panelName = "InternetGames", EPageType eType = eInternetServer );
~CInternetGames();
// property page handlers
virtual void OnPageShow();
// returns true if the game list supports the specified ui elements
virtual bool SupportsItem(IGameList::InterfaceItem_e item);
// gets a new server list
MESSAGE_FUNC( GetNewServerList, "GetNewServerList" );
// serverlist refresh responses
virtual void ServerResponded( HServerListRequest hReq, int iServer );
virtual void ServerFailedToRespond( HServerListRequest hReq, int iServer );
virtual void RefreshComplete( HServerListRequest hReq, EMatchMakingServerResponse response );
MESSAGE_FUNC_INT( OnRefreshServer, "RefreshServer", serverID );
virtual int GetRegionCodeToFilter();
virtual bool CheckTagFilter( gameserveritem_t &server );
protected:
// vgui overrides
virtual void PerformLayout();
virtual void OnTick();
virtual const char *GetStringNoUnfilteredServers() { return "#ServerBrowser_NoInternetGames"; }
virtual const char *GetStringNoUnfilteredServersOnMaster() { return "#ServerBrowser_MasterServerHasNoServersListed"; }
virtual const char *GetStringNoServersResponded() { return "#ServerBrowser_NoInternetGamesResponded"; }
private:
// Called once per frame to see if sorting needs to occur again
void CheckRedoSort();
// Called once per frame to check re-send request to master server
void CheckRetryRequest( ESteamServerType serverType );
// opens context menu (user right clicked on a server)
MESSAGE_FUNC_INT( OnOpenContextMenu, "OpenContextMenu", itemID );
struct regions_s
{
CUtlSymbol name;
unsigned char code;
};
CUtlVector<struct regions_s> m_Regions; // list of the different regions you can query for
float m_fLastSort; // Time of last re-sort
bool m_bDirty; // Has the list been modified, thereby needing re-sort
bool m_bRequireUpdate; // checks whether we need an update upon opening
// error cases for if no servers are listed
bool m_bAnyServersRetrievedFromMaster;
bool m_bAnyServersRespondedToQuery;
bool m_bNoServersListedOnMaster;
bool m_bOfflineMode;
};
#endif // INTERNETGAMES_H

160
serverbrowser/LanGames.cpp Normal file
View File

@ -0,0 +1,160 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "pch_serverbrowser.h"
using namespace vgui;
const float BROADCAST_LIST_TIMEOUT = 0.4f;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CLanGames::CLanGames(vgui::Panel *parent, bool bAutoRefresh, const char *pCustomResFilename ) :
CBaseGamesPage(parent, "LanGames", eLANServer, pCustomResFilename)
{
m_iServerRefreshCount = 0;
m_bRequesting = false;
m_bAutoRefresh = bAutoRefresh;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CLanGames::~CLanGames()
{
}
//-----------------------------------------------------------------------------
// Purpose: Activates the page, starts refresh
//-----------------------------------------------------------------------------
void CLanGames::OnPageShow()
{
if ( m_bAutoRefresh )
StartRefresh();
}
//-----------------------------------------------------------------------------
// Purpose: Called every frame
//-----------------------------------------------------------------------------
void CLanGames::OnTick()
{
BaseClass::OnTick();
CheckRetryRequest();
}
//-----------------------------------------------------------------------------
// Purpose: returns true if the game list supports the specified ui elements
//-----------------------------------------------------------------------------
bool CLanGames::SupportsItem(InterfaceItem_e item)
{
switch (item)
{
case FILTERS:
return true;
case GETNEWLIST:
default:
return false;
}
}
//-----------------------------------------------------------------------------
// Purpose: starts the servers refreshing
//-----------------------------------------------------------------------------
void CLanGames::StartRefresh()
{
BaseClass::StartRefresh();
m_fRequestTime = Plat_FloatTime();
}
//-----------------------------------------------------------------------------
// Purpose: Control which button are visible.
//-----------------------------------------------------------------------------
void CLanGames::ManualShowButtons( bool bShowConnect, bool bShowRefreshAll, bool bShowFilter )
{
m_pConnect->SetVisible( bShowConnect );
m_pRefreshAll->SetVisible( bShowRefreshAll );
m_pFilter->SetVisible( bShowFilter );
}
//-----------------------------------------------------------------------------
// Purpose: stops current refresh/GetNewServerList()
//-----------------------------------------------------------------------------
void CLanGames::StopRefresh()
{
BaseClass::StopRefresh();
// clear update states
m_bRequesting = false;
}
//-----------------------------------------------------------------------------
// Purpose: Check to see if we've finished looking for local servers
//-----------------------------------------------------------------------------
void CLanGames::CheckRetryRequest()
{
if (!m_bRequesting)
return;
double curtime = Plat_FloatTime();
if (curtime - m_fRequestTime <= BROADCAST_LIST_TIMEOUT)
{
return;
}
// time has elapsed, finish up
m_bRequesting = false;
}
//-----------------------------------------------------------------------------
// Purpose: called when a server response has timed out, remove it
//-----------------------------------------------------------------------------
void CLanGames::ServerFailedToRespond( HServerListRequest hReq, int iServer )
{
int iServerMap = m_mapServers.Find( iServer );
if ( iServerMap != m_mapServers.InvalidIndex() )
RemoveServer( m_mapServers[ iServerMap ] );
}
//-----------------------------------------------------------------------------
// Purpose: called when the current refresh list is complete
//-----------------------------------------------------------------------------
void CLanGames::RefreshComplete( HServerListRequest hReq, EMatchMakingServerResponse response )
{
SetRefreshing( false );
m_pGameList->SortList();
m_iServerRefreshCount = 0;
m_pGameList->SetEmptyListText("#ServerBrowser_NoLanServers");
SetEmptyListText();
BaseClass::RefreshComplete( hReq, response );
}
void CLanGames::SetEmptyListText()
{
m_pGameList->SetEmptyListText("#ServerBrowser_NoLanServers");
}
//-----------------------------------------------------------------------------
// Purpose: opens context menu (user right clicked on a server)
//-----------------------------------------------------------------------------
void CLanGames::OnOpenContextMenu(int row)
{
int serverID = GetSelectedServerID();
if ( serverID == -1 )
return;
// Activate context menu
CServerContextMenu *menu = ServerBrowserDialog().GetContextMenu(GetActiveList());
menu->ShowMenu(this, serverID, true, true, true, false);
}

81
serverbrowser/LanGames.h Normal file
View File

@ -0,0 +1,81 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef LANGAMES_H
#define LANGAMES_H
#ifdef _WIN32
#pragma once
#endif
class CLanBroadcastMsgHandler;
//-----------------------------------------------------------------------------
// Purpose: Favorite games list
//-----------------------------------------------------------------------------
class CLanGames : public CBaseGamesPage
{
DECLARE_CLASS_SIMPLE( CLanGames, CBaseGamesPage );
public:
CLanGames(vgui::Panel *parent, bool bAutoRefresh=true, const char *pCustomResFilename=NULL);
~CLanGames();
// property page handlers
virtual void OnPageShow();
// IGameList handlers
// returns true if the game list supports the specified ui elements
virtual bool SupportsItem(InterfaceItem_e item);
// Control which button are visible.
void ManualShowButtons( bool bShowConnect, bool bShowRefreshAll, bool bShowFilter );
// If you pass NULL for pSpecificAddresses, it will broadcast on certain points.
// If you pass a non-null value, then it will send info queries directly to those ports.
void InternalGetNewServerList( CUtlVector<netadr_t> *pSpecificAddresses );
virtual void StartRefresh();
// stops current refresh/GetNewServerList()
virtual void StopRefresh();
// IServerRefreshResponse handlers
// called when a server response has timed out
virtual void ServerFailedToRespond( HServerListRequest hReq, int iServer );
// called when the current refresh list is complete
virtual void RefreshComplete( HServerListRequest hReq, EMatchMakingServerResponse response );
// Tell the game list what to put in there when there are no games found.
virtual void SetEmptyListText();
private:
// vgui message handlers
virtual void OnTick();
// lan timeout checking
virtual void CheckRetryRequest();
// context menu message handlers
MESSAGE_FUNC_INT( OnOpenContextMenu, "OpenContextMenu", itemID );
// number of servers refreshed
int m_iServerRefreshCount;
// true if we're broadcasting for servers
bool m_bRequesting;
// time at which we last broadcasted
double m_fRequestTime;
bool m_bAutoRefresh;
};
#endif // LANGAMES_H

125
serverbrowser/ModList.cpp Normal file
View File

@ -0,0 +1,125 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "pch_serverbrowser.h"
//-----------------------------------------------------------------------------
// Purpose: Singleton accessor
//-----------------------------------------------------------------------------
CModList &ModList()
{
static CModList s_ModList;
return s_ModList;
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CModList::CModList()
{
ParseSteamMods();
}
//-----------------------------------------------------------------------------
// Purpose: returns number of mods
//-----------------------------------------------------------------------------
int CModList::ModCount()
{
return m_ModList.Count();
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
const char *CModList::GetModName(int index)
{
return m_ModList[index].description;
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
const char *CModList::GetModDir(int index)
{
return m_ModList[index].gamedir;
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
const CGameID &CModList::GetAppID(int index) const
{
return m_ModList[index].m_GameID;
}
//-----------------------------------------------------------------------------
// Purpose: get the modlist index for this app id
//-----------------------------------------------------------------------------
int CModList::GetIndex( const CGameID &iAppID ) const
{
mod_t mod;
mod.m_GameID = iAppID;
return m_ModList.Find( mod );
}
//-----------------------------------------------------------------------------
// Purpose: returns the mod name for the associated gamedir
//-----------------------------------------------------------------------------
const char *CModList::GetModNameForModDir( const CGameID &gameID )
{
int iApp = GetIndex( gameID );
if ( iApp != m_ModList.InvalidIndex() )
{
return m_ModList[iApp].description;
}
if ( ServerBrowserDialog().GetActiveModName() )
{
return ServerBrowserDialog().GetActiveGameName();
}
return "";
}
//-----------------------------------------------------------------------------
// Purpose: sort the mod list in alphabetical order
//-----------------------------------------------------------------------------
int CModList::ModNameCompare( const mod_t *pLeft, const mod_t *pRight )
{
return ( Q_stricmp( pLeft->description, pRight->description ) );
}
//-----------------------------------------------------------------------------
// Purpose: gets list of steam games we can filter for
//-----------------------------------------------------------------------------
void CModList::ParseSteamMods()
{
}
//-----------------------------------------------------------------------------
// Purpose: load settings for an app
//-----------------------------------------------------------------------------
int CModList::LoadAppConfiguration( uint32 nAppID )
{
return -1;
}
//-----------------------------------------------------------------------------
// Purpose: add a vgui panel to message when the app list changes
//-----------------------------------------------------------------------------
void CModList::AddVGUIListener( vgui::VPANEL panel )
{
m_VGUIListeners.AddToTail( panel );
}

62
serverbrowser/ModList.h Normal file
View File

@ -0,0 +1,62 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef MODLIST_H
#define MODLIST_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Handles parsing of half-life directory for mod info
//-----------------------------------------------------------------------------
class CModList
{
public:
CModList();
int GetIndex( const CGameID &iAppID ) const;
void AddVGUIListener( vgui::VPANEL panel );
// returns number of mods
int ModCount();
// returns the full name of the mod, index valid in range [0, ModCount)
const char *GetModName( int index );
// returns mod directory string
const char *GetModDir( int index );
const CGameID &GetAppID( int index ) const;
// returns the mod name for the associated gamedir
const char *GetModNameForModDir( const CGameID &iAppID );
private:
struct mod_t
{
char description[64];
char gamedir[64];
CGameID m_GameID;
int m_InternalAppId;
bool operator==( const mod_t& rhs ) const { return rhs.m_GameID == m_GameID; }
};
static int ModNameCompare( const mod_t *pLeft, const mod_t *pRight );
void ParseInstalledMods();
void ParseSteamMods();
int LoadAppConfiguration( uint32 nAppID );
CUtlVector<mod_t> m_ModList;
CUtlVector<vgui::VPANEL> m_VGUIListeners;
};
// singleton accessor
extern CModList &ModList();
#endif // MODLIST_H

View File

@ -0,0 +1,317 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "pch_serverbrowser.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Invisible panel that forwards up mouse movement
//-----------------------------------------------------------------------------
class CMouseMessageForwardingPanel : public vgui::Panel
{
DECLARE_CLASS_SIMPLE( CMouseMessageForwardingPanel, vgui::Panel );
public:
CMouseMessageForwardingPanel( Panel *parent, const char *name );
virtual void PerformLayout( void );
virtual void OnMousePressed( vgui::MouseCode code );
virtual void OnMouseDoublePressed( vgui::MouseCode code );
virtual void OnMouseWheeled(int delta);
};
CMouseMessageForwardingPanel::CMouseMessageForwardingPanel( Panel *parent, const char *name ) : BaseClass( parent, name )
{
// don't draw an
SetPaintEnabled(false);
SetPaintBackgroundEnabled(false);
SetPaintBorderEnabled(false);
}
void CMouseMessageForwardingPanel::PerformLayout()
{
// fill out the whole area
int w, t;
GetParent()->GetSize(w, t);
SetBounds(0, 0, w, t);
}
void CMouseMessageForwardingPanel::OnMousePressed( vgui::MouseCode code )
{
if ( GetParent() )
{
GetParent()->OnMousePressed( code );
}
}
void CMouseMessageForwardingPanel::OnMouseDoublePressed( vgui::MouseCode code )
{
if ( GetParent() )
{
GetParent()->OnMouseDoublePressed( code );
}
}
void CMouseMessageForwardingPanel::OnMouseWheeled(int delta)
{
if ( GetParent() )
{
GetParent()->OnMouseWheeled( delta );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CQuickListPanel::CQuickListPanel( vgui::Panel* pParent, const char *pElementName ) : BaseClass( pParent, pElementName )
{
SetParent( pParent );
m_pListPanelParent = pParent;
CMouseMessageForwardingPanel *panel = new CMouseMessageForwardingPanel(this, NULL);
panel->SetZPos(3);
m_pLatencyImage = new ImagePanel( this, "latencyimage" );
m_pPlayerCountLabel = new Label( this, "playercount", "" );
m_pOtherServersLabel = new Label( this, "otherservercount", "" );
m_pServerNameLabel = new Label( this, "servername", "" );
m_pBGroundPanel = new Panel( this, "background" );
m_pMapImage = new ImagePanel( this, "mapimage" );
m_pGameTypeLabel = new Label( this, "gametype", "" );
m_pMapNameLabel = new Label( this, "mapname", "" );
m_pLatencyLabel = new Label( this, "latencytext", "" );
m_pReplayImage = new ImagePanel( this, "replayimage" );
const char *pPathID = "PLATFORM";
if ( g_pFullFileSystem->FileExists( "servers/QuickListPanel.res", "MOD" ) )
{
pPathID = "MOD";
}
LoadControlSettings( "servers/QuickListPanel.res", pPathID );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CQuickListPanel::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
if ( pScheme && m_pBGroundPanel )
{
m_pBGroundPanel->SetBgColor( pScheme->GetColor("QuickListBGDeselected", Color(255, 255, 255, 0 ) ) );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CQuickListPanel::SetRefreshing( void )
{
if ( m_pServerNameLabel )
{
m_pServerNameLabel->SetText( g_pVGuiLocalize->Find("#ServerBrowser_QuickListRefreshing") );
}
if ( m_pPlayerCountLabel )
{
m_pPlayerCountLabel->SetVisible( false );
}
if ( m_pOtherServersLabel )
{
m_pOtherServersLabel->SetVisible( false );
}
if ( m_pLatencyImage )
{
m_pLatencyImage->SetVisible( false );
}
if ( m_pReplayImage )
{
m_pReplayImage->SetVisible( false );
}
if ( m_pLatencyLabel )
{
m_pLatencyLabel->SetVisible( false );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CQuickListPanel::SetMapName( const char *pMapName )
{
Q_strncpy( m_szMapName, pMapName, sizeof( m_szMapName ) );
if ( m_pMapNameLabel )
{
m_pMapNameLabel->SetText( pMapName );
m_pMapNameLabel->SizeToContents();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CQuickListPanel::SetGameType( const char *pGameType )
{
if ( strlen ( pGameType ) == 0 )
{
m_pGameTypeLabel->SetVisible( false );
return;
}
char gametype[ 512 ];
Q_snprintf( gametype, sizeof( gametype ), "(%s)", pGameType );
m_pGameTypeLabel->SetText( gametype );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CQuickListPanel::SetServerInfo ( KeyValues *pKV, int iListID, int iTotalServers )
{
if ( pKV == NULL )
return;
m_iListID = iListID;
m_pServerNameLabel->SetText( pKV->GetString( "name", " " ) );
int iPing = pKV->GetInt( "ping", 0 );
if ( iPing <= 100 )
{
m_pLatencyImage->SetImage( "../vgui/icon_con_high.vmt" );
}
else if ( iPing <= 150 )
{
m_pLatencyImage->SetImage( "../vgui/icon_con_medium.vmt" );
}
else
{
m_pLatencyImage->SetImage( "../vgui/icon_con_low.vmt" );
}
m_pLatencyImage->SetVisible( false );
if ( GameSupportsReplay() )
{
if ( pKV->GetInt( "Replay", 0 ) > 0 )
{
m_pReplayImage->SetVisible( true );
}
}
char ping[ 512 ];
Q_snprintf( ping, sizeof( ping ), "%d ms", iPing );
m_pLatencyLabel->SetText( ping );
m_pLatencyLabel->SetVisible( true );
wchar_t players[ 512 ];
wchar_t playercount[16];
wchar_t *pwszPlayers = g_pVGuiLocalize->Find("#ServerBrowser_Players");
g_pVGuiLocalize->ConvertANSIToUnicode( pKV->GetString( "players", " " ), playercount, sizeof( playercount ) );
_snwprintf( players, ARRAYSIZE( players ), L"%ls %ls", playercount, pwszPlayers );
m_pPlayerCountLabel->SetText( players );
m_pPlayerCountLabel->SetVisible( true );
// Now setup the other server count
if ( iTotalServers == 2 )
{
m_pOtherServersLabel->SetText( g_pVGuiLocalize->Find("#ServerBrowser_QuickListOtherServer") );
m_pOtherServersLabel->SetVisible( true );
}
else if ( iTotalServers > 2 )
{
wchar_t *pwszServers = g_pVGuiLocalize->Find("#ServerBrowser_QuickListOtherServers");
_snwprintf( playercount, Q_ARRAYSIZE(playercount), L"%d", (iTotalServers-1) );
g_pVGuiLocalize->ConstructString( players, sizeof( players ), pwszServers, 1, playercount );
m_pOtherServersLabel->SetText( players );
m_pOtherServersLabel->SetVisible( true );
}
else
{
m_pOtherServersLabel->SetVisible( false );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CQuickListPanel::SetImage( const char *pMapName )
{
char path[ 512 ];
Q_snprintf( path, sizeof( path ), "materials/vgui/maps/menu_thumb_%s.vmt", pMapName );
char map[ 512 ];
Q_snprintf( map, sizeof( map ), "maps/%s.bsp", pMapName );
if ( g_pFullFileSystem->FileExists( map, "MOD" ) == false )
{
pMapName = "default_download";
}
else
{
if ( g_pFullFileSystem->FileExists( path, "MOD" ) == false )
{
pMapName = "default";
}
}
if ( m_pMapImage )
{
char imagename[ 512 ];
Q_snprintf( imagename, sizeof( imagename ), "..\\vgui\\maps\\menu_thumb_%s", pMapName );
m_pMapImage->SetImage ( imagename );
m_pMapImage->SetMouseInputEnabled( false );
}
}
void CQuickListPanel::OnMousePressed( vgui::MouseCode code )
{
if ( m_pListPanelParent )
{
vgui::PanelListPanel *pParent = dynamic_cast < vgui::PanelListPanel *> ( m_pListPanelParent );
if ( pParent )
{
pParent->SetSelectedPanel( this );
m_pListPanelParent->CallParentFunction( new KeyValues("ItemSelected", "itemID", -1 ) );
}
if ( code == MOUSE_RIGHT )
{
m_pListPanelParent->CallParentFunction( new KeyValues("OpenContextMenu", "itemID", -1 ) );
}
}
}
void CQuickListPanel::OnMouseDoublePressed( vgui::MouseCode code )
{
if ( code == MOUSE_RIGHT )
return;
// call the panel
OnMousePressed( code );
m_pListPanelParent->CallParentFunction( new KeyValues("ConnectToServer", "code", code) );
}

View File

@ -0,0 +1,83 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef QUICKLISTPANEL
#define QUICKLISTPANEL
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Spectator games list
//-----------------------------------------------------------------------------
class CQuickListPanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CQuickListPanel, vgui::EditablePanel );
public:
CQuickListPanel( vgui::Panel *parent, const char *panelName );
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
void SetMapName( const char *pMapName );
void SetImage( const char *pMapName );
void SetGameType( const char *pGameType );
const char *GetMapName( void ) { return m_szMapName; }
void SetRefreshing( void );
virtual void OnMousePressed( vgui::MouseCode code );
virtual void OnMouseDoublePressed( vgui::MouseCode code );
void SetServerInfo ( KeyValues *pKV, int iListID, int iTotalServers );
int GetListID( void ) { return m_iListID; }
MESSAGE_FUNC_INT( OnPanelSelected, "PanelSelected", state )
{
if ( state )
{
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
if ( pScheme && m_pBGroundPanel )
{
m_pBGroundPanel->SetBgColor( pScheme->GetColor("QuickListBGSelected", Color(255, 255, 255, 0 ) ) );
}
}
else
{
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
if ( pScheme && m_pBGroundPanel )
{
m_pBGroundPanel->SetBgColor( pScheme->GetColor("QuickListBGDeselected", Color(255, 255, 255, 0 ) ) );
}
}
PostMessage( GetParent()->GetVParent(), new KeyValues("PanelSelected") );
}
private:
char m_szMapName[128];
vgui::ImagePanel *m_pLatencyImage;
vgui::Label *m_pLatencyLabel;
vgui::Label *m_pPlayerCountLabel;
vgui::Label *m_pOtherServersLabel;
vgui::Label *m_pServerNameLabel;
vgui::Panel *m_pBGroundPanel;
vgui::ImagePanel *m_pMapImage;
vgui::Panel *m_pListPanelParent;
vgui::Label *m_pGameTypeLabel;
vgui::Label *m_pMapNameLabel;
vgui::ImagePanel *m_pReplayImage;
int m_iListID;
};
#endif // QUICKLISTPANEL

View File

@ -0,0 +1,489 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "pch_serverbrowser.h"
// expose the server browser interfaces
CServerBrowser g_ServerBrowserSingleton;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CServerBrowser, IServerBrowser, SERVERBROWSER_INTERFACE_VERSION, g_ServerBrowserSingleton);
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CServerBrowser, IVGuiModule, "VGuiModuleServerBrowser001", g_ServerBrowserSingleton); // the interface loaded by PlatformMenu.vdf
// singleton accessor
CServerBrowser &ServerBrowser()
{
return g_ServerBrowserSingleton;
}
IRunGameEngine *g_pRunGameEngine = NULL;
static CSteamAPIContext g_SteamAPIContext;
CSteamAPIContext *steamapicontext = &g_SteamAPIContext;
IEngineReplay *g_pEngineReplay = NULL;
ConVar sb_firstopentime( "sb_firstopentime", "0", FCVAR_DEVELOPMENTONLY, "Indicates the time the server browser was first opened." );
ConVar sb_numtimesopened( "sb_numtimesopened", "0", FCVAR_DEVELOPMENTONLY, "Indicates the number of times the server browser was opened this session." );
// the original author of this code felt strdup was not acceptible.
inline char *CloneString( const char *str )
{
char *cloneStr = new char [ strlen(str)+1 ];
strcpy( cloneStr, str );
return cloneStr;
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CServerBrowser::CServerBrowser()
{
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CServerBrowser::~CServerBrowser()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CServerBrowser::CreateDialog()
{
if (!m_hInternetDlg.Get())
{
m_hInternetDlg = new CServerBrowserDialog(NULL); // SetParent() call below fills this in
m_hInternetDlg->Initialize();
}
}
//-----------------------------------------------------------------------------
// Purpose: links to vgui and engine interfaces
//-----------------------------------------------------------------------------
bool CServerBrowser::Initialize(CreateInterfaceFn *factorylist, int factoryCount)
{
ConnectTier1Libraries( factorylist, factoryCount );
ConVar_Register();
ConnectTier2Libraries( factorylist, factoryCount );
ConnectTier3Libraries( factorylist, factoryCount );
g_pRunGameEngine = NULL;
for ( int i = 0; i < factoryCount; ++i )
{
if ( !g_pEngineReplay )
{
g_pEngineReplay = ( IEngineReplay * )factorylist[ i ]( ENGINE_REPLAY_INTERFACE_VERSION, NULL );
}
}
SteamAPI_InitSafe();
SteamAPI_SetTryCatchCallbacks( false ); // We don't use exceptions, so tell steam not to use try/catch in callback handlers
steamapicontext->Init();
for (int i = 0; i < factoryCount; i++)
{
if (!g_pRunGameEngine)
{
g_pRunGameEngine = (IRunGameEngine *)(factorylist[i])(RUNGAMEENGINE_INTERFACE_VERSION, NULL);
}
}
// load the vgui interfaces
#if defined( STEAM ) || defined( HL1 )
if ( !vgui::VGuiControls_Init("ServerBrowser", factorylist, factoryCount) )
#else
if ( !vgui::VGui_InitInterfacesList("ServerBrowser", factorylist, factoryCount) )
#endif
return false;
// load localization file
g_pVGuiLocalize->AddFile( "servers/serverbrowser_%language%.txt" );
return true;
}
//-----------------------------------------------------------------------------
// Purpose: links to other modules interfaces (tracker)
//-----------------------------------------------------------------------------
bool CServerBrowser::PostInitialize(CreateInterfaceFn *modules, int factoryCount)
{
// find the interfaces we need
for (int i = 0; i < factoryCount; i++)
{
if (!g_pRunGameEngine)
{
g_pRunGameEngine = (IRunGameEngine *)(modules[i])(RUNGAMEENGINE_INTERFACE_VERSION, NULL);
}
}
CreateDialog();
m_hInternetDlg->SetVisible(false);
return g_pRunGameEngine;
}
//-----------------------------------------------------------------------------
// Purpose: true if the user can't play a game due to VAC banning
//-----------------------------------------------------------------------------
bool CServerBrowser::IsVACBannedFromGame( int nAppID )
{
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Marks that the tool/game loading us intends to feed us workshop information
//-----------------------------------------------------------------------------
void CServerBrowser::SetWorkshopEnabled( bool bManaged )
{
m_bWorkshopEnabled = bManaged;
}
//-----------------------------------------------------------------------------
// Purpose: Add a mapname to our known user-subscribed workshop maps list
//-----------------------------------------------------------------------------
void CServerBrowser::AddWorkshopSubscribedMap( const char *pszMapName )
{
CUtlString strMap( pszMapName );
if ( !IsWorkshopSubscribedMap( strMap ) )
{
m_vecWorkshopSubscribedMaps.AddToTail( strMap );
}
}
//-----------------------------------------------------------------------------
// Purpose: remove a mapname to our known user-subscribed workshop maps list
//-----------------------------------------------------------------------------
void CServerBrowser::RemoveWorkshopSubscribedMap( const char *pszMapName )
{
m_vecWorkshopSubscribedMaps.FindAndFastRemove( CUtlString( pszMapName ) );
}
//-----------------------------------------------------------------------------
// Purpose: Well, is it?
//-----------------------------------------------------------------------------
bool CServerBrowser::IsWorkshopEnabled()
{
return m_bWorkshopEnabled;
}
//-----------------------------------------------------------------------------
// Purpose: Check if this map is in our subscribed list
//-----------------------------------------------------------------------------
bool CServerBrowser::IsWorkshopSubscribedMap( const char *pszMapName )
{
return m_vecWorkshopSubscribedMaps.HasElement( CUtlString( pszMapName ) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CServerBrowser::IsValid()
{
return ( g_pRunGameEngine );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CServerBrowser::Activate()
{
static bool firstTimeOpening = true;
if ( firstTimeOpening )
{
m_hInternetDlg->LoadUserData(); // reload the user data the first time the dialog is made visible, helps with the lag between module load and
// steamui getting Deactivate() call
firstTimeOpening = false;
}
int numTimesOpened = sb_numtimesopened.GetInt() + 1;
sb_numtimesopened.SetValue( numTimesOpened );
if ( numTimesOpened == 1 )
{
time_t aclock;
time( &aclock );
sb_firstopentime.SetValue( (int) aclock );
}
Open();
return true;
}
//-----------------------------------------------------------------------------
// Purpose: called when the server browser gets used in the game
//-----------------------------------------------------------------------------
void CServerBrowser::Deactivate()
{
if (m_hInternetDlg.Get())
{
m_hInternetDlg->SaveUserData();
}
}
//-----------------------------------------------------------------------------
// Purpose: called when the server browser is no longer being used in the game
//-----------------------------------------------------------------------------
void CServerBrowser::Reactivate()
{
if (m_hInternetDlg.Get())
{
m_hInternetDlg->LoadUserData();
if (m_hInternetDlg->IsVisible())
{
m_hInternetDlg->RefreshCurrentPage();
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CServerBrowser::Open()
{
m_hInternetDlg->Open();
}
//-----------------------------------------------------------------------------
// Purpose: returns direct handle to main server browser dialog
//-----------------------------------------------------------------------------
vgui::VPANEL CServerBrowser::GetPanel()
{
return m_hInternetDlg.Get() ? m_hInternetDlg->GetVPanel() : NULL;
}
//-----------------------------------------------------------------------------
// Purpose: sets the parent panel of the main module panel
//-----------------------------------------------------------------------------
void CServerBrowser::SetParent(vgui::VPANEL parent)
{
if (m_hInternetDlg.Get())
{
m_hInternetDlg->SetParent(parent);
}
}
//-----------------------------------------------------------------------------
// Purpose: Closes down the server browser for good
//-----------------------------------------------------------------------------
void CServerBrowser::Shutdown()
{
if (m_hInternetDlg.Get())
{
m_hInternetDlg->Close();
m_hInternetDlg->MarkForDeletion();
}
#if defined( STEAM )
vgui::VGuiControls_Shutdown();
#endif
DisconnectTier3Libraries();
DisconnectTier2Libraries();
ConVar_Unregister();
DisconnectTier1Libraries();
}
//-----------------------------------------------------------------------------
// Purpose: opens a game info dialog to watch the specified server; associated with the friend 'userName'
//-----------------------------------------------------------------------------
bool CServerBrowser::OpenGameInfoDialog( uint64 ulSteamIDFriend, const char *pszConnectCode )
{
#if !defined( _X360 ) // X360TBD: SteamFriends()
if ( m_hInternetDlg.Get() )
{
// activate an already-existing dialog
CDialogGameInfo *pDialogGameInfo = m_hInternetDlg->GetDialogGameInfoForFriend( ulSteamIDFriend );
if ( pDialogGameInfo )
{
pDialogGameInfo->Activate();
return true;
}
// none yet, create a new dialog
FriendGameInfo_t friendGameInfo;
if ( steamapicontext->SteamFriends()->GetFriendGamePlayed( ulSteamIDFriend, &friendGameInfo ) )
{
uint16 usConnPort = friendGameInfo.m_usGamePort;
if ( friendGameInfo.m_usQueryPort < QUERY_PORT_ERROR )
usConnPort = friendGameInfo.m_usQueryPort;
CDialogGameInfo *pDialogGameInfo = m_hInternetDlg->OpenGameInfoDialog( friendGameInfo.m_unGameIP, friendGameInfo.m_usGamePort, usConnPort, pszConnectCode );
pDialogGameInfo->SetFriend( ulSteamIDFriend );
return true;
}
}
#endif
return false;
}
//-----------------------------------------------------------------------------
// Purpose: joins a specified game - game info dialog will only be opened if the server is fully or passworded
//-----------------------------------------------------------------------------
bool CServerBrowser::JoinGame( uint64 ulSteamIDFriend, const char *pszConnectCode )
{
if ( OpenGameInfoDialog( ulSteamIDFriend, pszConnectCode ) )
{
CDialogGameInfo *pDialogGameInfo = m_hInternetDlg->GetDialogGameInfoForFriend( ulSteamIDFriend );
pDialogGameInfo->Connect();
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose: joins a game by IP/Port
//-----------------------------------------------------------------------------
bool CServerBrowser::JoinGame( uint32 unGameIP, uint16 usGamePort, const char *pszConnectCode )
{
m_hInternetDlg->JoinGame( unGameIP, usGamePort, pszConnectCode );
return true;
}
//-----------------------------------------------------------------------------
// Purpose: forces the game info dialog closed
//-----------------------------------------------------------------------------
void CServerBrowser::CloseGameInfoDialog( uint64 ulSteamIDFriend )
{
CDialogGameInfo *pDialogGameInfo = m_hInternetDlg->GetDialogGameInfoForFriend( ulSteamIDFriend );
if ( pDialogGameInfo )
{
pDialogGameInfo->Close();
}
}
//-----------------------------------------------------------------------------
// Purpose: closes all the game info dialogs
//-----------------------------------------------------------------------------
void CServerBrowser::CloseAllGameInfoDialogs()
{
if ( m_hInternetDlg.Get() )
{
m_hInternetDlg->CloseAllGameInfoDialogs();
}
}
CUtlVector< gametypes_t > g_GameTypes;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void LoadGameTypes( void )
{
if ( g_GameTypes.Count() > 0 )
return;
#define GAMETYPES_FILE "servers/ServerBrowserGameTypes.txt"
KeyValues * kv = new KeyValues( GAMETYPES_FILE );
if ( !kv->LoadFromFile( g_pFullFileSystem, GAMETYPES_FILE, "MOD" ) )
{
kv->deleteThis();
return;
}
g_GameTypes.RemoveAll();
for ( KeyValues *pData = kv->GetFirstSubKey(); pData != NULL; pData = pData->GetNextKey() )
{
gametypes_t gametype;
gametype.pPrefix = CloneString( pData->GetString( "prefix", "" ) );
gametype.pGametypeName = CloneString( pData->GetString( "name", "" ) );
g_GameTypes.AddToTail( gametype );
}
kv->deleteThis();
}
const char *GetGameTypeName( const char *pMapName )
{
LoadGameTypes();
for ( int i = 0; i < g_GameTypes.Count(); i++ )
{
int iLength = strlen( g_GameTypes[i].pPrefix );
if ( !Q_strncmp( pMapName, g_GameTypes[i].pPrefix, iLength ) )
{
return g_GameTypes[i].pGametypeName;
}
}
return "";
}
//-----------------------------------------------------------------------------
// Purpose of comments like these: none
//-----------------------------------------------------------------------------
const char *CServerBrowser::GetMapFriendlyNameAndGameType( const char *pszMapName, char *szFriendlyMapName, int cchFriendlyName )
{
// Make sure game types are loaded
LoadGameTypes();
// Scan list
const char *pszFriendlyGameTypeName = "";
for ( int i = 0; i < g_GameTypes.Count(); i++ )
{
int iLength = strlen( g_GameTypes[i].pPrefix );
if ( !Q_strnicmp( pszMapName, g_GameTypes[i].pPrefix, iLength ) )
{
pszMapName += iLength;
pszFriendlyGameTypeName = g_GameTypes[i].pGametypeName;
break;
}
}
// See how many characters from the name to copy.
// Start by assuming we'll copy the whole thing.
// (After any prefix we just skipped)
int l = V_strlen( pszMapName );
const char *pszFinal = Q_stristr( pszMapName, "_final" );
if ( pszFinal )
{
// truncate the _final (or _final1) part of the filename if it's at the end of the name
const char *pszNextChar = pszFinal + Q_strlen( "_final" );
if ( ( *pszNextChar == '\0' ) ||
( ( *pszNextChar == '1' ) && ( *(pszNextChar+1) == '\0' ) ) )
{
l = pszFinal - pszMapName;
}
}
// Safety check against buffer size
if ( l >= cchFriendlyName )
{
Assert( !"Map name too long for buffer!" );
l = cchFriendlyName-1;
}
// Copy friendly portion of name only
V_memcpy( szFriendlyMapName, pszMapName, l );
// It's like the Alamo. We never forget.
szFriendlyMapName[l] = '\0';
// Result should be the friendly game type name
return pszFriendlyGameTypeName;
}

View File

@ -0,0 +1,82 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef SERVERBROWSER_H
#define SERVERBROWSER_H
#ifdef _WIN32
#pragma once
#endif
class CServerBrowserDialog;
//-----------------------------------------------------------------------------
// Purpose: Handles the UI and pinging of a half-life game server list
//-----------------------------------------------------------------------------
class CServerBrowser : public IServerBrowser, public IVGuiModule
{
public:
CServerBrowser();
~CServerBrowser();
// IVGui module implementation
virtual bool Initialize(CreateInterfaceFn *factorylist, int numFactories);
virtual bool PostInitialize(CreateInterfaceFn *modules, int factoryCount);
virtual vgui::VPANEL GetPanel();
virtual bool Activate();
virtual bool IsValid();
virtual void Shutdown();
virtual void Deactivate();
virtual void Reactivate();
virtual void SetParent(vgui::VPANEL parent);
// IServerBrowser implementation
// joins a specified game - game info dialog will only be opened if the server is fully or passworded
virtual bool JoinGame( uint32 unGameIP, uint16 usGamePort, const char *pszConnectCode );
virtual bool JoinGame( uint64 ulSteamIDFriend, const char *pszConnectCode );
// opens a game info dialog to watch the specified server; associated with the friend 'userName'
virtual bool OpenGameInfoDialog( uint64 ulSteamIDFriend, const char *pszConnectCode );
// forces the game info dialog closed
virtual void CloseGameInfoDialog( uint64 ulSteamIDFriend );
// closes all the game info dialogs
virtual void CloseAllGameInfoDialogs();
virtual const char *GetMapFriendlyNameAndGameType( const char *pszMapName, char *szFriendlyMapName, int cchFriendlyName ) OVERRIDE;
// methods
virtual void CreateDialog();
virtual void Open();
// true if the user can't play a game
bool IsVACBannedFromGame( int nAppID );
// Enable filtering of workshop maps, requires the game/tool loading us to feed subscription data. This is a
// slightly ugly workaround to TF2 not yet having native workshop UI in quickplay, once that is in place this should
// either be stripped back out or expanded to be directly aware of the steam workshop without being managed.
virtual void SetWorkshopEnabled( bool bManaged ) OVERRIDE;
virtual void AddWorkshopSubscribedMap( const char *pszMapName ) OVERRIDE;
virtual void RemoveWorkshopSubscribedMap( const char *pszMapName ) OVERRIDE;
bool IsWorkshopEnabled();
bool IsWorkshopSubscribedMap( const char *pszMapName );
private:
vgui::DHANDLE<CServerBrowserDialog> m_hInternetDlg;
bool m_bWorkshopEnabled;
CUtlVector< CUtlString > m_vecWorkshopSubscribedMaps;
};
// singleton accessor
CServerBrowser &ServerBrowser();
class CSteamAPIContext;
extern CSteamAPIContext *steamapicontext;
#endif // SERVERBROWSER_H

View File

@ -0,0 +1,106 @@
//-----------------------------------------------------------------------------
// SERVERBROWSER.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$Macro SRCDIR ".."
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
$Configuration
{
$Compiler
{
$PreprocessorDefinitions "$BASE;VERSION_SAFE_STEAM_API_INTERFACES;SERVERBROWSER_EXPORTS;GAME_SRC;_USE_32BIT_TIME_T"
}
$Linker
{
$AdditionalDependencies "$BASE Advapi32.lib wsock32.lib Ws2_32.lib User32.lib" [$WIN32]
$AdditionalDependencies "$BASE Xonline.lib" [$X360]
$SystemLibraries "iconv" [$OSXALL]
}
}
$Project "ServerBrowser"
{
$Folder "Source Files"
{
$File "BaseGamesPage.cpp"
$File "BlacklistedServers.cpp"
$File "CustomGames.cpp"
$File "DialogAddServer.cpp"
$File "DialogGameInfo.cpp"
$File "DialogServerPassword.cpp"
$File "FavoriteGames.cpp"
$File "FriendsGames.cpp"
$File "HistoryGames.cpp"
$File "InternetGames.cpp"
$File "LanGames.cpp"
$File "ModList.cpp"
$File "ServerBrowser.cpp"
$File "ServerBrowserDialog.cpp"
$File "ServerContextMenu.cpp"
$File "ServerListCompare.cpp"
$File "SpectateGames.cpp"
$File "VACBannedConnRefusedDialog.cpp"
$File "VACBannedConnRefusedDialog.h"
$File "QuickListPanel.cpp"
$File "$SRCDIR\public\vgui_controls\vgui_controls.cpp"
{
$Configuration
{
$Compiler
{
}
}
}
$File "$SRCDIR\common\ServerBrowser\blacklisted_server_manager.cpp"
}
$Folder "Header Files"
{
$File "BaseGamesPage.h"
$File "BlacklistedServers.h"
$File "CustomGames.h"
$File "DialogAddServer.h"
$File "DialogGameInfo.h"
$File "DialogServerPassword.h"
$File "FavoriteGames.h"
$File "FriendsGames.h"
$File "HistoryGames.h"
$File "InternetGames.h"
$File "LanGames.h"
$File "ModList.h"
$File "ServerBrowser.h"
$File "ServerBrowserDialog.h"
$File "ServerContextMenu.h"
$File "ServerListCompare.h"
$File "SpectateGames.h"
$File "QuickListPanel.h"
$File "$SRCDIR\common\ServerBrowser\blacklisted_server_manager.h"
}
$Folder "Resource Files"
{
}
$Folder "Exposed interfaces"
{
$File "$SRCDIR\common\ServerBrowser\IServerBrowser.h"
}
$Folder "Link Libraries"
{
$ImpLib steam_api
$Lib tier2
$Lib tier3
$Lib vgui_controls
$Lib mathlib
}
}

View File

@ -0,0 +1,816 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include "pch_serverbrowser.h"
#if defined( _X360 )
#include "xbox/xbox_win32stubs.h"
#endif
#if defined( _WIN32 ) && !defined( _X360 )
#define WIN32_LEAN_AND_MEAN
#include <winsock.h>
#endif
#ifdef LINUX
#include <arpa/inet.h>
#endif
using namespace vgui;
ConVar sb_quick_list_bit_field( "sb_quick_list_bit_field", "-1" );
static CServerBrowserDialog *s_InternetDlg = NULL;
CServerBrowserDialog &ServerBrowserDialog()
{
return *CServerBrowserDialog::GetInstance();
}
// Returns a list of the ports that we hit when looking for
void GetMostCommonQueryPorts( CUtlVector<uint16> &ports )
{
for ( int i=0; i <= 5; i++ )
{
ports.AddToTail( 27015 + i );
ports.AddToTail( 26900 + i );
}
ports.AddToTail(4242); //RDKF
ports.AddToTail(27215); //Lost Planet
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CServerBrowserDialog::CServerBrowserDialog(vgui::Panel *parent) : Frame(parent, "CServerBrowserDialog")
{
s_InternetDlg = this;
m_szGameName[0] = 0;
m_szModDir[0] = 0;
m_pSavedData = NULL;
m_pFilterData = NULL;
m_pFavorites = NULL;
m_pBlacklist = NULL;
m_pHistory = NULL;
// Do this before LoadUserData() so it loads the blacklist file properly
m_pBlacklist = new CBlacklistedServers(this);
LoadUserData();
m_pInternetGames = new CCustomGames(this);
m_pFavorites = new CFavoriteGames(this);
m_pHistory = new CHistoryGames(this);
m_pSpectateGames = new CSpectateGames(this);
m_pLanGames = new CLanGames(this);
m_pFriendsGames = new CFriendsGames(this);
SetMinimumSize( 640, 384 );
SetSize( 640, 384 );
m_pGameList = m_pInternetGames;
m_pContextMenu = new CServerContextMenu(this);;
// property sheet
m_pTabPanel = new PropertySheet(this, "GameTabs");
m_pTabPanel->SetTabWidth(72);
m_pTabPanel->AddPage(m_pInternetGames, "#ServerBrowser_InternetTab");
m_pTabPanel->AddPage(m_pFavorites, "#ServerBrowser_FavoritesTab");
m_pTabPanel->AddPage(m_pHistory, "#ServerBrowser_HistoryTab");
m_pTabPanel->AddPage(m_pSpectateGames, "#ServerBrowser_SpectateTab");
m_pTabPanel->AddPage(m_pLanGames, "#ServerBrowser_LanTab");
m_pTabPanel->AddPage(m_pFriendsGames, "#ServerBrowser_FriendsTab");
if ( m_pBlacklist )
{
m_pTabPanel->AddPage(m_pBlacklist, "#ServerBrowser_BlacklistTab");
}
m_pTabPanel->AddActionSignalTarget(this);
m_pStatusLabel = new Label(this, "StatusLabel", "");
LoadControlSettingsAndUserConfig("Servers/DialogServerBrowser.res");
m_pStatusLabel->SetText("");
// load current tab
const char *gameList = m_pSavedData->GetString("GameList");
if (!Q_stricmp(gameList, "spectate"))
{
m_pTabPanel->SetActivePage(m_pSpectateGames);
}
else if (!Q_stricmp(gameList, "favorites"))
{
m_pTabPanel->SetActivePage(m_pFavorites);
}
else if (!Q_stricmp(gameList, "history"))
{
m_pTabPanel->SetActivePage(m_pHistory);
}
else if (!Q_stricmp(gameList, "lan"))
{
m_pTabPanel->SetActivePage(m_pLanGames);
}
else if (!Q_stricmp(gameList, "friends"))
{
m_pTabPanel->SetActivePage(m_pFriendsGames);
}
else if (!Q_stricmp(gameList, "blacklist"))
{
m_pTabPanel->SetActivePage(m_pBlacklist);
}
else
{
m_pTabPanel->SetActivePage(m_pInternetGames);
}
ivgui()->AddTickSignal( GetVPanel() );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CServerBrowserDialog::~CServerBrowserDialog()
{
delete m_pContextMenu;
SaveUserData();
if (m_pSavedData)
{
m_pSavedData->deleteThis();
}
}
//-----------------------------------------------------------------------------
// Purpose: Called once to set up
//-----------------------------------------------------------------------------
void CServerBrowserDialog::Initialize()
{
SetTitle("#ServerBrowser_Servers", true);
SetVisible(false);
}
//-----------------------------------------------------------------------------
// Purpose: returns a server in the list
//-----------------------------------------------------------------------------
gameserveritem_t *CServerBrowserDialog::GetServer( unsigned int serverID )
{
if (m_pGameList)
return m_pGameList->GetServer( serverID );
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Activates and gives the tab focus
//-----------------------------------------------------------------------------
void CServerBrowserDialog::Open()
{
BaseClass::Activate();
m_pTabPanel->RequestFocus();
MoveToCenterOfScreen();
}
//-----------------------------------------------------------------------------
// Purpose: Called every frame, updates animations for this module
//-----------------------------------------------------------------------------
void CServerBrowserDialog::OnTick()
{
BaseClass::OnTick();
vgui::GetAnimationController()->UpdateAnimations( system()->GetFrameTime() );
}
//-----------------------------------------------------------------------------
// Purpose: Loads filter settings from disk
//-----------------------------------------------------------------------------
void CServerBrowserDialog::LoadUserData()
{
// free any old filters
if (m_pSavedData)
{
m_pSavedData->deleteThis();
}
m_pSavedData = new KeyValues("Filters");
if (!m_pSavedData->LoadFromFile( g_pFullFileSystem, "ServerBrowser.vdf", "CONFIG"))
{
// doesn't matter if the file is not found, defaults will work successfully and file will be created on exit
}
KeyValues *filters = m_pSavedData->FindKey( "Filters", false );
if ( filters )
{
m_pFilterData = filters->MakeCopy();
m_pSavedData->RemoveSubKey( filters );
}
else
{
m_pFilterData = new KeyValues( "Filters" );
}
// reload all the page settings if necessary
if (m_pHistory)
{
// history
m_pHistory->LoadHistoryList();
if ( IsVisible() && m_pHistory->IsVisible() )
m_pHistory->StartRefresh();
}
if (m_pFavorites)
{
// favorites
m_pFavorites->LoadFavoritesList();
// filters
ReloadFilterSettings();
if ( IsVisible() && m_pFavorites->IsVisible() )
m_pFavorites->StartRefresh();
}
if ( m_pBlacklist )
{
m_pBlacklist->LoadBlacklistedList();
}
InvalidateLayout();
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CServerBrowserDialog::SaveUserData()
{
m_pSavedData->Clear();
m_pSavedData->LoadFromFile( g_pFullFileSystem, "ServerBrowser.vdf", "CONFIG");
// set the current tab
if (m_pGameList == m_pSpectateGames)
{
m_pSavedData->SetString("GameList", "spectate");
}
else if (m_pGameList == m_pFavorites)
{
m_pSavedData->SetString("GameList", "favorites");
}
else if (m_pGameList == m_pLanGames)
{
m_pSavedData->SetString("GameList", "lan");
}
else if (m_pGameList == m_pFriendsGames)
{
m_pSavedData->SetString("GameList", "friends");
}
else if (m_pGameList == m_pHistory)
{
m_pSavedData->SetString("GameList", "history");
}
else
{
m_pSavedData->SetString("GameList", "internet");
}
m_pSavedData->RemoveSubKey( m_pSavedData->FindKey( "Filters" ) ); // remove the saved subkey and add our subkey
m_pSavedData->AddSubKey( m_pFilterData->MakeCopy() );
m_pSavedData->SaveToFile( g_pFullFileSystem, "ServerBrowser.vdf", "CONFIG");
if ( m_pBlacklist )
{
m_pBlacklist->SaveBlacklistedList();
}
// save per-page config
SaveUserConfig();
}
//-----------------------------------------------------------------------------
// Purpose: refreshes the page currently visible
//-----------------------------------------------------------------------------
void CServerBrowserDialog::RefreshCurrentPage()
{
if (m_pGameList)
{
m_pGameList->StartRefresh();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CServerBrowserDialog::BlacklistsChanged()
{
m_pInternetGames->ApplyGameFilters();
}
//-----------------------------------------------------------------------------
// Purpose: Updates status test at bottom of window
//-----------------------------------------------------------------------------
void CServerBrowserDialog::UpdateStatusText(const char *fmt, ...)
{
if ( !m_pStatusLabel )
return;
if ( fmt && strlen(fmt) > 0 )
{
char str[ 1024 ];
va_list argptr;
va_start( argptr, fmt );
_vsnprintf( str, sizeof(str), fmt, argptr );
va_end( argptr );
m_pStatusLabel->SetText( str );
}
else
{
// clear
m_pStatusLabel->SetText( "" );
}
}
//-----------------------------------------------------------------------------
// Purpose: Updates status test at bottom of window
// Input : wchar_t* (unicode string) -
//-----------------------------------------------------------------------------
void CServerBrowserDialog::UpdateStatusText(wchar_t *unicode)
{
if ( !m_pStatusLabel )
return;
if ( unicode && wcslen(unicode) > 0 )
{
m_pStatusLabel->SetText( unicode );
}
else
{
// clear
m_pStatusLabel->SetText( "" );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CServerBrowserDialog::OnGameListChanged()
{
m_pGameList = dynamic_cast<IGameList *>(m_pTabPanel->GetActivePage());
UpdateStatusText("");
InvalidateLayout();
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: returns a pointer to a static instance of this dialog
//-----------------------------------------------------------------------------
CServerBrowserDialog *CServerBrowserDialog::GetInstance()
{
return s_InternetDlg;
}
//-----------------------------------------------------------------------------
// Purpose: Adds a server to the list of favorites
//-----------------------------------------------------------------------------
void CServerBrowserDialog::AddServerToFavorites(gameserveritem_t &server)
{
if ( steamapicontext->SteamMatchmaking() )
{
steamapicontext->SteamMatchmaking()->AddFavoriteGame(
server.m_nAppID,
server.m_NetAdr.GetIP(),
server.m_NetAdr.GetConnectionPort(),
server.m_NetAdr.GetQueryPort(),
k_unFavoriteFlagFavorite,
time( NULL ) );
if ( GameSupportsReplay() )
{
// send command to propagate to the client so the client can send it on to the GC
char command[ 256 ];
Q_snprintf( command, Q_ARRAYSIZE( command ), "rfgc %s\n", server.m_NetAdr.GetConnectionAddressString() );
g_pRunGameEngine->AddTextCommand( command );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Adds a server to our list of blacklisted servers
//-----------------------------------------------------------------------------
void CServerBrowserDialog::AddServerToBlacklist(gameserveritem_t &server)
{
if ( m_pBlacklist )
{
m_pBlacklist->AddServer( server );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CServerBrowserDialog::IsServerBlacklisted(gameserveritem_t &server)
{
if ( m_pBlacklist )
return m_pBlacklist->IsServerBlacklisted( server );
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CServerContextMenu *CServerBrowserDialog::GetContextMenu(vgui::Panel *pPanel)
{
// create a drop down for this object's states
if (m_pContextMenu)
delete m_pContextMenu;
m_pContextMenu = new CServerContextMenu(this);
m_pContextMenu->SetAutoDelete( false );
if (!pPanel)
{
m_pContextMenu->SetParent(this);
}
else
{
m_pContextMenu->SetParent(pPanel);
}
m_pContextMenu->SetVisible(false);
return m_pContextMenu;
}
//-----------------------------------------------------------------------------
// Purpose: begins the process of joining a server from a game list
// the game info dialog it opens will also update the game list
//-----------------------------------------------------------------------------
CDialogGameInfo *CServerBrowserDialog::JoinGame(IGameList *gameList, unsigned int serverIndex)
{
// open the game info dialog, then mark it to attempt to connect right away
CDialogGameInfo *gameDialog = OpenGameInfoDialog(gameList, serverIndex);
// set the dialog name to be the server name
gameDialog->Connect();
return gameDialog;
}
//-----------------------------------------------------------------------------
// Purpose: joins a game by a specified IP, not attached to any game list
//-----------------------------------------------------------------------------
CDialogGameInfo *CServerBrowserDialog::JoinGame(int serverIP, int serverPort, const char *pszConnectCode)
{
// open the game info dialog, then mark it to attempt to connect right away
CDialogGameInfo *gameDialog = OpenGameInfoDialog( serverIP, serverPort, serverPort, pszConnectCode );
// set the dialog name to be the server name
gameDialog->Connect();
return gameDialog;
}
//-----------------------------------------------------------------------------
// Purpose: opens a game info dialog from a game list
//-----------------------------------------------------------------------------
CDialogGameInfo *CServerBrowserDialog::OpenGameInfoDialog( IGameList *gameList, unsigned int serverIndex )
{
gameserveritem_t *pServer = gameList->GetServer( serverIndex );
if ( !pServer )
return NULL;
CDialogGameInfo *gameDialog = new CDialogGameInfo( NULL, pServer->m_NetAdr.GetIP(), pServer->m_NetAdr.GetQueryPort(), pServer->m_NetAdr.GetConnectionPort(), gameList->GetConnectCode() );
gameDialog->SetParent(GetVParent());
gameDialog->AddActionSignalTarget(this);
gameDialog->Run( pServer->GetName() );
int i = m_GameInfoDialogs.AddToTail();
m_GameInfoDialogs[i] = gameDialog;
return gameDialog;
}
//-----------------------------------------------------------------------------
// Purpose: opens a game info dialog by a specified IP, not attached to any game list
//-----------------------------------------------------------------------------
CDialogGameInfo *CServerBrowserDialog::OpenGameInfoDialog( int serverIP, uint16 connPort, uint16 queryPort, const char *pszConnectCode )
{
CDialogGameInfo *gameDialog = new CDialogGameInfo(NULL, serverIP, queryPort, connPort, pszConnectCode);
gameDialog->AddActionSignalTarget(this);
gameDialog->SetParent(GetVParent());
gameDialog->Run("");
int i = m_GameInfoDialogs.AddToTail();
m_GameInfoDialogs[i] = gameDialog;
return gameDialog;
}
//-----------------------------------------------------------------------------
// Purpose: closes all the game info dialogs
//-----------------------------------------------------------------------------
void CServerBrowserDialog::CloseAllGameInfoDialogs()
{
for (int i = 0; i < m_GameInfoDialogs.Count(); i++)
{
vgui::Panel *dlg = m_GameInfoDialogs[i];
if (dlg)
{
vgui::ivgui()->PostMessage(dlg->GetVPanel(), new KeyValues("Close"), NULL);
}
}
}
//-----------------------------------------------------------------------------
// Purpose: finds a dialog
//-----------------------------------------------------------------------------
CDialogGameInfo *CServerBrowserDialog::GetDialogGameInfoForFriend( uint64 ulSteamIDFriend )
{
FOR_EACH_VEC( m_GameInfoDialogs, i )
{
CDialogGameInfo *pDlg = m_GameInfoDialogs[i];
if ( pDlg && pDlg->GetAssociatedFriend() == ulSteamIDFriend )
{
return pDlg;
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: accessor to the filter save data
//-----------------------------------------------------------------------------
KeyValues *CServerBrowserDialog::GetFilterSaveData(const char *filterSet)
{
return m_pFilterData->FindKey(filterSet, true);
}
//-----------------------------------------------------------------------------
// Purpose: gets the name of the mod directory we're restricted to accessing, NULL if none
//-----------------------------------------------------------------------------
const char *CServerBrowserDialog::GetActiveModName()
{
return m_szModDir[0] ? m_szModDir : NULL;
}
//-----------------------------------------------------------------------------
// Purpose: gets the name of the mod directory we're restricted to accessing, NULL if none
//-----------------------------------------------------------------------------
const char *CServerBrowserDialog::GetActiveGameName()
{
return m_szGameName[0] ? m_szGameName : NULL;
}
//-----------------------------------------------------------------------------
// Purpose: return the app id to limit game queries to, set by Source/HL1 engines (NOT by filter settings, that is per page)
//-----------------------------------------------------------------------------
CGameID &CServerBrowserDialog::GetActiveAppID()
{
// !TEST! Un comment this to force a particular AppID
//m_iLimitAppID = CGameID( 440 );
return m_iLimitAppID;
}
//-----------------------------------------------------------------------------
// Purpose: receives a specified game is active, so no other game types can be displayed in server list
//-----------------------------------------------------------------------------
void CServerBrowserDialog::OnActiveGameName( KeyValues *pKV )
{
Q_strncpy(m_szModDir, pKV->GetString( "name" ), sizeof(m_szModDir));
Q_strncpy(m_szGameName, pKV->GetString( "game" ), sizeof(m_szGameName));
m_iLimitAppID = CGameID( pKV->GetUint64( "appid", 0 ) );
// reload filter settings (since they are no forced to be game specific)
ReloadFilterSettings();
}
//-----------------------------------------------------------------------------
// Purpose: resets all pages filter settings
//-----------------------------------------------------------------------------
void CServerBrowserDialog::ReloadFilterSettings()
{
m_pInternetGames->LoadFilterSettings();
m_pSpectateGames->LoadFilterSettings();
m_pFavorites->LoadFilterSettings();
m_pLanGames->LoadFilterSettings();
m_pFriendsGames->LoadFilterSettings();
m_pHistory->LoadFilterSettings();
}
//-----------------------------------------------------------------------------
// Purpose: Adds server to the history, saves as currently connected server
//-----------------------------------------------------------------------------
void CServerBrowserDialog::OnConnectToGame( KeyValues *pMessageValues )
{
int ip = pMessageValues->GetInt( "ip" );
int connectionPort = pMessageValues->GetInt( "connectionport" );
int queryPort = pMessageValues->GetInt( "queryport" );
if ( !ip || !queryPort )
return;
uint32 unIP = htonl( ip );
memset( &m_CurrentConnection, 0, sizeof(gameserveritem_t) );
m_CurrentConnection.m_NetAdr.SetIP( unIP );
m_CurrentConnection.m_NetAdr.SetQueryPort( queryPort );
m_CurrentConnection.m_NetAdr.SetConnectionPort( (unsigned short)connectionPort );
if (m_pHistory && steamapicontext->SteamMatchmaking() )
{
steamapicontext->SteamMatchmaking()->AddFavoriteGame( 0, unIP, connectionPort, queryPort, k_unFavoriteFlagHistory, time( NULL ) );
m_pHistory->SetRefreshOnReload();
}
// tell the game info dialogs, so they can cancel if we have connected
// to a server they were auto-retrying
for (int i = 0; i < m_GameInfoDialogs.Count(); i++)
{
vgui::Panel *dlg = m_GameInfoDialogs[i];
if (dlg)
{
KeyValues *kv = new KeyValues("ConnectedToGame", "ip", unIP, "connectionport", connectionPort);
kv->SetInt( "queryport", queryPort );
vgui::ivgui()->PostMessage(dlg->GetVPanel(), kv, NULL);
}
}
// forward to favorites
m_pFavorites->OnConnectToGame();
if ( m_pBlacklist )
{
m_pBlacklist->OnConnectToGame();
}
m_bCurrentlyConnected = true;
// Now we want to track which tabs have the quick list button checked
int iQuickListBitField = 0;
if ( m_pFriendsGames && m_pFriendsGames->IsQuickListButtonChecked() )
{
iQuickListBitField |= ( 1 << 0 );
}
if ( m_pLanGames && m_pLanGames->IsQuickListButtonChecked() )
{
iQuickListBitField |= ( 1 << 1 );
}
if ( m_pSpectateGames && m_pSpectateGames->IsQuickListButtonChecked() )
{
iQuickListBitField |= ( 1 << 2 );
}
if ( m_pHistory && m_pHistory->IsQuickListButtonChecked() )
{
iQuickListBitField |= ( 1 << 3 );
}
if ( m_pFavorites && m_pFavorites->IsQuickListButtonChecked() )
{
iQuickListBitField |= ( 1 << 4 );
}
if ( m_pInternetGames && m_pInternetGames->IsQuickListButtonChecked() )
{
iQuickListBitField |= ( 1 << 5 );
}
// Set the value so that the client.dll can use it for gamestats
sb_quick_list_bit_field.SetValue( iQuickListBitField );
// TF2 wants to close this dialog when the player connects to a game
if ( GameSupportsReplay() )
{
ConVarRef sb_close_browser_on_connect( "sb_close_browser_on_connect" );
if ( sb_close_browser_on_connect.IsValid() )
{
if ( sb_close_browser_on_connect.GetBool() == true )
{
OnClose();
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Clears currently connected server
//-----------------------------------------------------------------------------
void CServerBrowserDialog::OnDisconnectFromGame( void )
{
m_bCurrentlyConnected = false;
memset( &m_CurrentConnection, 0, sizeof(gameserveritem_t) );
// forward to favorites
m_pFavorites->OnDisconnectFromGame();
if ( m_pBlacklist )
{
m_pBlacklist->OnDisconnectFromGame();
}
}
//-----------------------------------------------------------------------------
// Purpose: Called when start start loading, so we can cease server browser activity
//-----------------------------------------------------------------------------
void CServerBrowserDialog::OnLoadingStarted( void )
{
m_pInternetGames->OnLoadingStarted();
m_pSpectateGames->OnLoadingStarted();
m_pFavorites->OnLoadingStarted();
m_pLanGames->OnLoadingStarted();
m_pFriendsGames->OnLoadingStarted();
m_pHistory->OnLoadingStarted();
}
//-----------------------------------------------------------------------------
// Purpose: Passes build mode activation down into the pages
//-----------------------------------------------------------------------------
void CServerBrowserDialog::ActivateBuildMode()
{
// no subpanel, no build mode
EditablePanel *panel = dynamic_cast<EditablePanel *>(m_pTabPanel->GetActivePage());
if (!panel)
return;
panel->ActivateBuildMode();
}
//-----------------------------------------------------------------------------
// Purpose: gets the default position and size on the screen to appear the first time
//-----------------------------------------------------------------------------
bool CServerBrowserDialog::GetDefaultScreenPosition(int &x, int &y, int &wide, int &tall)
{
int wx, wy, ww, wt;
surface()->GetWorkspaceBounds( wx, wy, ww, wt );
x = wx + (int)(ww * 0.05);
y = wy + (int)(wt * 0.4);
wide = (int)(ww * 0.5);
tall = (int)(wt * 0.55);
return true;
}
void CServerBrowserDialog::OnKeyCodePressed( vgui::KeyCode code )
{
// Handle close here, CBasePanel parent doesn't support "DialogClosing" command
ButtonCode_t nButtonCode = GetBaseButtonCode( code );
if ( nButtonCode == KEY_XBUTTON_B || nButtonCode == STEAMCONTROLLER_B )
{
OnCommand( "Close" );
return;
}
else if ( nButtonCode == KEY_XBUTTON_A || nButtonCode == STEAMCONTROLLER_A )
{
//OnOK( false );
//return;
}
else if ( nButtonCode == KEY_XBUTTON_UP ||
nButtonCode == KEY_XSTICK1_UP ||
nButtonCode == KEY_XSTICK2_UP ||
nButtonCode == STEAMCONTROLLER_DPAD_UP ||
nButtonCode == KEY_UP ||
nButtonCode == KEY_XBUTTON_DOWN ||
nButtonCode == KEY_XSTICK1_DOWN ||
nButtonCode == KEY_XSTICK2_DOWN ||
nButtonCode == STEAMCONTROLLER_DPAD_DOWN ||
nButtonCode == KEY_DOWN )
{
CBaseGamesPage *pGamesPage = dynamic_cast< CBaseGamesPage* >( m_pTabPanel->GetActivePage() );
if ( pGamesPage )
{
ListPanel *pListPanel = dynamic_cast< ListPanel * >( pGamesPage->GetActiveList() );
if ( pListPanel )
{
if ( pListPanel->GetSelectedItem( 0 ) == -1 )
{
pListPanel->SetSingleSelectedItem( pListPanel->GetItemIDFromRow( 0 ) );
pListPanel->RequestFocus();
return;
}
else if ( !pListPanel->HasFocus() )
{
pListPanel->RequestFocus();
return;
}
}
}
}
BaseClass::OnKeyCodePressed( code );
}

View File

@ -0,0 +1,159 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef SERVERBROWSERDIALOG_H
#define SERVERBROWSERDIALOG_H
#ifdef _WIN32
#pragma once
#endif
extern class IRunGameEngine *g_pRunGameEngine;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CServerBrowserDialog : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( CServerBrowserDialog, vgui::Frame );
public:
// Construction/destruction
CServerBrowserDialog( vgui::Panel *parent );
~CServerBrowserDialog( void );
void Initialize( void );
// displays the dialog, moves it into focus, updates if it has to
void Open( void );
// gets server info
gameserveritem_t *GetServer(unsigned int serverID);
// called every frame
virtual void OnTick();
// updates status text at bottom of window
void UpdateStatusText(PRINTF_FORMAT_STRING const char *format, ...);
// updates status text at bottom of window
void UpdateStatusText(wchar_t *unicode);
// context menu access
CServerContextMenu *GetContextMenu(vgui::Panel *pParent);
// returns a pointer to a static instance of this dialog
// valid for use only in sort functions
static CServerBrowserDialog *GetInstance();
// Adds a server to the list of favorites
void AddServerToFavorites(gameserveritem_t &server);
// Adds a server to our list of blacklisted servers
void AddServerToBlacklist(gameserveritem_t &server);
bool IsServerBlacklisted(gameserveritem_t &server);
// begins the process of joining a server from a game list
// the game info dialog it opens will also update the game list
CDialogGameInfo *JoinGame(IGameList *gameList, unsigned int serverIndex);
// joins a game by a specified IP, not attached to any game list
CDialogGameInfo *JoinGame(int serverIP, int serverPort, const char *pszConnectCode);
// opens a game info dialog from a game list
CDialogGameInfo *OpenGameInfoDialog(IGameList *gameList, unsigned int serverIndex);
// opens a game info dialog by a specified IP, not attached to any game list
CDialogGameInfo *OpenGameInfoDialog( int serverIP, uint16 connPort, uint16 queryPort, const char *pszConnectCode );
// closes all the game info dialogs
void CloseAllGameInfoDialogs();
CDialogGameInfo *GetDialogGameInfoForFriend( uint64 ulSteamIDFriend );
// accessor to the filter save data
KeyValues *GetFilterSaveData(const char *filterSet);
// gets the name of the mod directory we're restricted to accessing, NULL if none
const char *GetActiveModName();
CGameID &GetActiveAppID();
const char *GetActiveGameName();
// load/saves filter & favorites settings from disk
void LoadUserData();
void SaveUserData();
// forces the currently active page to refresh
void RefreshCurrentPage();
virtual gameserveritem_t *GetCurrentConnectedServer()
{
return &m_CurrentConnection;
}
void BlacklistsChanged();
CBlacklistedServers *GetBlacklistPage( void ) { return m_pBlacklist; }
private:
// current game list change
MESSAGE_FUNC( OnGameListChanged, "PageChanged" );
void ReloadFilterSettings();
// receives a specified game is active, so no other game types can be displayed in server list
MESSAGE_FUNC_PARAMS( OnActiveGameName, "ActiveGameName", name );
// notification that we connected / disconnected
MESSAGE_FUNC_PARAMS( OnConnectToGame, "ConnectedToGame", kv );
MESSAGE_FUNC( OnDisconnectFromGame, "DisconnectedFromGame" );
MESSAGE_FUNC( OnLoadingStarted, "LoadingStarted" );
virtual bool GetDefaultScreenPosition(int &x, int &y, int &wide, int &tall);
virtual void ActivateBuildMode();
void OnKeyCodePressed( vgui::KeyCode code );
private:
// list of all open game info dialogs
CUtlVector<vgui::DHANDLE<CDialogGameInfo> > m_GameInfoDialogs;
// pointer to current game list
IGameList *m_pGameList;
// Status text
vgui::Label *m_pStatusLabel;
// property sheet
vgui::PropertySheet *m_pTabPanel;
CFavoriteGames *m_pFavorites;
CBlacklistedServers *m_pBlacklist;
CHistoryGames *m_pHistory;
CInternetGames *m_pInternetGames;
CSpectateGames *m_pSpectateGames;
CLanGames *m_pLanGames;
CFriendsGames *m_pFriendsGames;
KeyValues *m_pSavedData;
KeyValues *m_pFilterData;
// context menu
CServerContextMenu *m_pContextMenu;
// active game
char m_szGameName[128];
char m_szModDir[128];
CGameID m_iLimitAppID;
// currently connected game
bool m_bCurrentlyConnected;
gameserveritem_t m_CurrentConnection;
};
// singleton accessor
extern CServerBrowserDialog &ServerBrowserDialog();
// Used by the LAN tab and the add server dialog when trying to find servers without having
// been given any ports to look for servers on.
void GetMostCommonQueryPorts( CUtlVector<uint16> &ports );
#endif // SERVERBROWSERDIALOG_H

View File

@ -0,0 +1,63 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "pch_serverbrowser.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CServerContextMenu::CServerContextMenu(Panel *parent) : Menu(parent, "ServerContextMenu")
{
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CServerContextMenu::~CServerContextMenu()
{
}
//-----------------------------------------------------------------------------
// Purpose: Activates the menu
//-----------------------------------------------------------------------------
void CServerContextMenu::ShowMenu(
Panel *target,
unsigned int serverID,
bool showConnect,
bool showViewGameInfo,
bool showRefresh,
bool showAddToFavorites )
{
if (showConnect)
{
AddMenuItem("ConnectToServer", "#ServerBrowser_ConnectToServer", new KeyValues("ConnectToServer", "serverID", serverID), target);
}
if (showViewGameInfo)
{
AddMenuItem("ViewGameInfo", "#ServerBrowser_ViewServerInfo", new KeyValues("ViewGameInfo", "serverID", serverID), target);
}
if (showRefresh)
{
AddMenuItem("RefreshServer", "#ServerBrowser_RefreshServer", new KeyValues("RefreshServer", "serverID", serverID), target);
}
if (showAddToFavorites)
{
AddMenuItem("AddToFavorites", "#ServerBrowser_AddServerToFavorites", new KeyValues("AddToFavorites", "serverID", serverID), target);
AddMenuItem("AddToBlacklist", "#ServerBrowser_AddServerToBlacklist", new KeyValues("AddToBlacklist", "serverID", serverID), target);
}
int x, y, gx, gy;
input()->GetCursorPos(x, y);
ipanel()->GetPos(surface()->GetEmbeddedPanel(), gx, gy);
SetPos(x - gx, y - gy);
SetVisible(true);
}

View File

@ -0,0 +1,34 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef SERVERCONTEXTMENU_H
#define SERVERCONTEXTMENU_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Basic right-click context menu for servers
//-----------------------------------------------------------------------------
class CServerContextMenu : public vgui::Menu
{
public:
CServerContextMenu(vgui::Panel *parent);
~CServerContextMenu();
// call this to Activate the menu
void ShowMenu(
vgui::Panel *target,
unsigned int serverID,
bool showConnect,
bool showViewGameInfo,
bool showRefresh,
bool showAddToFavorites);
};
#endif // SERVERCONTEXTMENU_H

View File

@ -0,0 +1,289 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "pch_serverbrowser.h"
bool IsReplayServer( gameserveritem_t &server );
//-----------------------------------------------------------------------------
// Purpose: List password column sort function
//-----------------------------------------------------------------------------
int __cdecl PasswordCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
gameserveritem_t *s1 = ServerBrowserDialog().GetServer(p1.userData);
gameserveritem_t *s2 = ServerBrowserDialog().GetServer(p2.userData);
if ( !s1 && s2 )
return -1;
if ( !s2 && s1 )
return 1;
if ( !s1 && !s2 )
return 0;
if ( s1->m_bPassword < s2->m_bPassword )
return 1;
else if ( s1->m_bPassword > s2->m_bPassword )
return -1;
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: list column sort function
//-----------------------------------------------------------------------------
int __cdecl BotsCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
gameserveritem_t *s1 = ServerBrowserDialog().GetServer(p1.userData);
gameserveritem_t *s2 = ServerBrowserDialog().GetServer(p2.userData);
if ( !s1 && s2 )
return -1;
if ( !s2 && s1 )
return 1;
if ( !s1 && !s2 )
return 0;
if ( s1->m_nBotPlayers < s2->m_nBotPlayers )
return 1;
else if ( s1->m_nBotPlayers > s2->m_nBotPlayers )
return -1;
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: list column sort function
//-----------------------------------------------------------------------------
int __cdecl SecureCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
gameserveritem_t *s1 = ServerBrowserDialog().GetServer(p1.userData);
gameserveritem_t *s2 = ServerBrowserDialog().GetServer(p2.userData);
if ( !s1 && s2 )
return -1;
if ( !s2 && s1 )
return 1;
if ( !s1 && !s2 )
return 0;
if ( s1->m_bSecure < s2->m_bSecure )
return 1;
else if ( s1->m_bSecure > s2->m_bSecure )
return -1;
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: list column sort function
//-----------------------------------------------------------------------------
int __cdecl IPAddressCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
gameserveritem_t *s1 = ServerBrowserDialog().GetServer(p1.userData);
gameserveritem_t *s2 = ServerBrowserDialog().GetServer(p2.userData);
if ( !s1 && s2 )
return -1;
if ( !s2 && s1 )
return 1;
if ( !s1 && !s2 )
return 0;
if ( s1->m_NetAdr < s2->m_NetAdr )
return -1;
else if ( s2->m_NetAdr < s1->m_NetAdr )
return 1;
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: Ping comparison function
//-----------------------------------------------------------------------------
int __cdecl PingCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
gameserveritem_t *s1 = ServerBrowserDialog().GetServer(p1.userData);
gameserveritem_t *s2 = ServerBrowserDialog().GetServer(p2.userData);
if ( !s1 && s2 )
return -1;
if ( !s2 && s1 )
return 1;
if ( !s1 && !s2 )
return 0;
int ping1 = s1->m_nPing;
int ping2 = s2->m_nPing;
if ( ping1 < ping2 )
return -1;
else if ( ping1 > ping2 )
return 1;
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: Map comparison function
//-----------------------------------------------------------------------------
int __cdecl MapCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
gameserveritem_t *s1 = ServerBrowserDialog().GetServer(p1.userData);
gameserveritem_t *s2 = ServerBrowserDialog().GetServer(p2.userData);
if ( !s1 && s2 )
return -1;
if ( !s2 && s1 )
return 1;
if ( !s1 && !s2 )
return 0;
return Q_stricmp( s1->m_szMap, s2->m_szMap );
}
//-----------------------------------------------------------------------------
// Purpose: Game dir comparison function
//-----------------------------------------------------------------------------
int __cdecl GameCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
gameserveritem_t *s1 = ServerBrowserDialog().GetServer(p1.userData);
gameserveritem_t *s2 = ServerBrowserDialog().GetServer(p2.userData);
if ( !s1 && s2 )
return -1;
if ( !s2 && s1 )
return 1;
if ( !s1 && !s2 )
return 0;
// make sure we haven't added the same server to the list twice
Assert( p1.userData != p2.userData );
return Q_stricmp( s1->m_szGameDescription, s2->m_szGameDescription );
}
//-----------------------------------------------------------------------------
// Purpose: Server name comparison function
//-----------------------------------------------------------------------------
int __cdecl ServerNameCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
gameserveritem_t *s1 = ServerBrowserDialog().GetServer(p1.userData);
gameserveritem_t *s2 = ServerBrowserDialog().GetServer(p2.userData);
if ( !s1 && s2 )
return -1;
if ( !s2 && s1 )
return 1;
if ( !s1 && !s2 )
return 0;
return Q_stricmp( s1->GetName(), s2->GetName() );
}
//-----------------------------------------------------------------------------
// Purpose: Player number comparison function
//-----------------------------------------------------------------------------
int __cdecl PlayersCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
gameserveritem_t *s1 = ServerBrowserDialog().GetServer(p1.userData);
gameserveritem_t *s2 = ServerBrowserDialog().GetServer(p2.userData);
if ( !s1 && s2 )
return -1;
if ( !s2 && s1 )
return 1;
if ( !s1 && !s2 )
return 0;
int s1p = max( 0, s1->m_nPlayers - s1->m_nBotPlayers );
int s1m = max( 0, s1->m_nMaxPlayers - s1->m_nBotPlayers );
int s2p = max( 0, s2->m_nPlayers - s2->m_nBotPlayers );
int s2m = max( 0, s2->m_nMaxPlayers - s2->m_nBotPlayers );
// compare number of players
if ( s1p > s2p )
return -1;
if ( s1p < s2p )
return 1;
// compare max players if number of current players is equal
if ( s1m > s2m )
return -1;
if ( s1m < s2m )
return 1;
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: Player number comparison function
//-----------------------------------------------------------------------------
int __cdecl LastPlayedCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
gameserveritem_t *s1 = ServerBrowserDialog().GetServer( p1.userData );
gameserveritem_t *s2 = ServerBrowserDialog().GetServer( p2.userData );
if ( !s1 && s2 )
return -1;
if ( !s2 && s1 )
return 1;
if ( !s1 && !s2 )
return 0;
// compare number of players
if ( s1->m_ulTimeLastPlayed > s2->m_ulTimeLastPlayed )
return -1;
if ( s1->m_ulTimeLastPlayed < s2->m_ulTimeLastPlayed )
return 1;
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: Tag comparison function
//-----------------------------------------------------------------------------
int __cdecl TagsCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
gameserveritem_t *s1 = ServerBrowserDialog().GetServer(p1.userData);
gameserveritem_t *s2 = ServerBrowserDialog().GetServer(p2.userData);
if ( !s1 && s2 )
return -1;
if ( !s2 && s1 )
return 1;
if ( !s1 && !s2 )
return 0;
return Q_stricmp( s1->m_szGameTags, s2->m_szGameTags );
}
//-----------------------------------------------------------------------------
// Purpose: Replay comparison function
//-----------------------------------------------------------------------------
int __cdecl ReplayCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2)
{
gameserveritem_t *s1 = ServerBrowserDialog().GetServer(p1.userData);
gameserveritem_t *s2 = ServerBrowserDialog().GetServer(p2.userData);
if ( !s1 && s2 )
return -1;
if ( !s2 && s1 )
return 1;
if ( !s1 && !s2 )
return 0;
bool s1_is_replay = IsReplayServer( *s1 );
bool s2_is_replay = IsReplayServer( *s2 );
if ( s1_is_replay < s2_is_replay )
return 1;
else if ( s1_is_replay > s2_is_replay )
return -1;
return 0;
}

View File

@ -0,0 +1,32 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef SERVERLISTCOMPARE_H
#define SERVERLISTCOMPARE_H
#ifdef _WIN32
#pragma once
#endif
using vgui::ListPanel;
using vgui::ListPanelItem;
// these functions are common to most server lists in sorts
int __cdecl PasswordCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2);
int __cdecl BotsCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2);
int __cdecl PingCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2);
int __cdecl PlayersCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2);
int __cdecl MapCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2);
int __cdecl GameCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2);
int __cdecl ServerNameCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2);
int __cdecl SecureCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2);
int __cdecl IPAddressCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2);
int __cdecl LastPlayedCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2);
int __cdecl TagsCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2);
int __cdecl ReplayCompare(ListPanel *pPanel, const ListPanelItem &p1, const ListPanelItem &p2);
#endif // SERVERLISTCOMPARE_H

View File

@ -0,0 +1,33 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "pch_serverbrowser.h"
CSpectateGames::CSpectateGames( vgui::Panel *parent )
: CInternetGames( parent, "SpectateGames", eSpectatorServer )
{
}
void CSpectateGames::GetNewServerList()
{
m_vecServerFilters.AddToTail( MatchMakingKeyValuePair_t( "proxy", "1" ) );
BaseClass::GetNewServerList();
}
void CSpectateGames::OnPageShow()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CSpectateGames::CheckTagFilter( gameserveritem_t &server )
{
return true;
}

View File

@ -0,0 +1,38 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef SPECTATEGAMES_H
#define SPECTATEGAMES_H
#ifdef _WIN32
#pragma once
#endif
#include "InternetGames.h"
//-----------------------------------------------------------------------------
// Purpose: Spectator games list
//-----------------------------------------------------------------------------
class CSpectateGames : public CInternetGames
{
public:
CSpectateGames(vgui::Panel *parent);
// property page handlers
virtual void OnPageShow();
virtual bool CheckTagFilter( gameserveritem_t &server );
protected:
// filters by spectator games
virtual void GetNewServerList();
private:
typedef CInternetGames BaseClass;
};
#endif // SPECTATEGAMES_H

View File

@ -0,0 +1,22 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "pch_serverbrowser.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CVACBannedConnRefusedDialog::CVACBannedConnRefusedDialog( VPANEL hVParent, const char *name ) : BaseClass( NULL, name )
{
SetParent( hVParent );
SetSize( 480, 220 );
SetSizeable( false );
LoadControlSettings( "servers/VACBannedConnRefusedDialog.res" );
MoveToCenterOfScreen();
}

View File

@ -0,0 +1,29 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef VACBANNEDCONNREFUSED_H
#define VACBANNEDCONNREFUSED_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Displays information about new VAC bans
//-----------------------------------------------------------------------------
class CVACBannedConnRefusedDialog : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( CVACBannedConnRefusedDialog, vgui::Frame );
public:
CVACBannedConnRefusedDialog( vgui::VPANEL hVParent, const char *name );
};
#endif // VACBANNEDCONNREFUSED_H

91
serverbrowser/igamelist.h Normal file
View File

@ -0,0 +1,91 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef IGAMELIST_H
#define IGAMELIST_H
#ifdef _WIN32
#pragma once
#endif
class gameserveritem_t;
#if defined( STEAM )
#include "steam2common.h"
#include "FindSteam2Servers.h"
#else
#include "steamcommon.h"
#include "FindSteamServers.h"
#endif
#include "netadr.h"
typedef enum
{
SERVERVERSION_SAME_VERSION = 0,
SERVERVERSION_SERVER_OLD,
SERVERVERSION_SERVER_NEWER
} SERVERVERSION;
struct serverdisplay_t
{
serverdisplay_t()
{
m_iListID = -1;
m_iServerID = -1;
m_bDoNotRefresh = true;
}
int m_iListID; // the VGUI2 list panel index for displaying this server
int m_iServerID; // the matchmaking interface index for this server
bool m_bDoNotRefresh;
bool operator==( const serverdisplay_t &rhs ) const { return rhs.m_iServerID == m_iServerID; }
};
//-----------------------------------------------------------------------------
// Purpose: Interface to accessing a game list
//-----------------------------------------------------------------------------
class IGameList
{
public:
enum InterfaceItem_e
{
FILTERS,
GETNEWLIST,
ADDSERVER,
ADDCURRENTSERVER,
};
// returns true if the game list supports the specified ui elements
virtual bool SupportsItem(InterfaceItem_e item) = 0;
// starts the servers refreshing
virtual void StartRefresh() = 0;
// gets a new server list
virtual void GetNewServerList() = 0;
// stops current refresh/GetNewServerList()
virtual void StopRefresh() = 0;
// returns true if the list is currently refreshing servers
virtual bool IsRefreshing() = 0;
// gets information about specified server
virtual gameserveritem_t *GetServer(unsigned int serverID) = 0;
// called when Connect button is pressed
virtual void OnBeginConnect() = 0;
// invalid server index
virtual int GetInvalidServerListID() = 0;
// Get code to use for tracking how people are connecting to servers
virtual const char *GetConnectCode() = 0;
};
#endif // IGAMELIST_H

View File

@ -0,0 +1,7 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "pch_serverbrowser.h"

View File

@ -0,0 +1,86 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include <winlite.h>
#undef CreateDialog
#ifdef WIN32
#include <direct.h>
#include <io.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include "vstdlib/pch_vstdlib.h"
#include "tier0/memdbgoff.h"
#include "vgui_controls/pch_vgui_controls.h"
#include "vgui_controls/Frame.h"
#include "tier0/memdbgon.h"
#include "tier3/tier3.h"
// steam3 API
//#include "steam/steam_querypackets.h"
#include "steam/steam_api.h"
#include "steam/isteamuser.h"
#include "steam/isteammatchmaking.h"
#include "steam/isteamfriends.h"
#include "ServerBrowser/IServerBrowser.h"
#include "IVguiModule.h"
#include "vgui_controls/Controls.h"
#include "netadr.h"
#include "filesystem.h"
#include "proto_oob.h"
#include "ModList.h"
#include "IRunGameEngine.h"
#include "OfflineMode.h"
// serverbrowser files
#include "igamelist.h"
#include "ServerListCompare.h"
#include "ServerBrowser.h"
#include "VACBannedConnRefusedDialog.h"
#include "DialogGameInfo.h"
#include "ServerContextMenu.h"
#include "DialogServerPassword.h"
#include "DialogAddServer.h"
// game list
#include "BaseGamesPage.h"
#include "BlacklistedServers.h"
#include "InternetGames.h"
#include "FavoriteGames.h"
#include "SpectateGames.h"
#include "LanGames.h"
#include "FriendsGames.h"
#include "HistoryGames.h"
#include "SpectateGames.h"
#include "CustomGames.h"
#include "ServerBrowserDialog.h"
#include "QuickListPanel.h"
#include "vgui_controls/PanelListPanel.h"
#include "replay/ienginereplay.h"
extern bool GameSupportsReplay();
extern bool IsReplayServer( gameserveritem_t &server );
#pragma warning( disable: 4355 ) // warning C4355: 'this' : used in base member initializer list
#if defined( STEAM )
#define IsSteam() true
#else
#define IsSteam() false
#endif
using namespace vgui;

15
serverbrowser/resource.h Normal file
View File

@ -0,0 +1,15 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by ServerBrowser.rc
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -0,0 +1,3 @@
LIBRARY serverbrowser_360.dll
EXPORTS
CreateInterface @1