2020-04-22 16:56:21 +00:00
//========= 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 ;
2023-01-29 16:26:04 +00:00
IServersInfo * g_pServersInfo = NULL ;
2020-04-22 16:56:21 +00:00
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 ) ;
2023-01-29 16:26:04 +00:00
if ( ! g_pServersInfo )
g_pServersInfo = ( IServersInfo * ) factorylist [ i ] ( SERVERLIST_INTERFACE_VERSION , NULL ) ;
2020-04-22 16:56:21 +00:00
}
2023-01-29 16:26:04 +00:00
2020-04-22 16:56:21 +00:00
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 )
{
2023-01-29 16:26:04 +00:00
#if 0
2020-04-22 16:56:21 +00:00
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 )
{
2023-01-29 16:26:04 +00:00
/* if ( OpenGameInfoDialog( ulSteamIDFriend, pszConnectCode ) )
2020-04-22 16:56:21 +00:00
{
CDialogGameInfo * pDialogGameInfo = m_hInternetDlg - > GetDialogGameInfoForFriend ( ulSteamIDFriend ) ;
pDialogGameInfo - > Connect ( ) ;
2023-01-29 16:26:04 +00:00
} */
2020-04-22 16:56:21 +00:00
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 )
{
2023-01-29 16:26:04 +00:00
#if 0
2020-04-22 16:56:21 +00:00
CDialogGameInfo * pDialogGameInfo = m_hInternetDlg - > GetDialogGameInfoForFriend ( ulSteamIDFriend ) ;
if ( pDialogGameInfo )
{
pDialogGameInfo - > Close ( ) ;
}
2023-01-29 16:26:04 +00:00
# endif
2020-04-22 16:56:21 +00:00
}
//-----------------------------------------------------------------------------
// 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 ;
}