Files
funnygame/external/steamworks/steamworksexample/ServerBrowser.cpp
2025-07-13 15:47:42 +03:00

203 lines
8.1 KiB
C++

//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class for handling finding servers, getting their details, and displaying
// them inside the game
//
// $NoKeywords: $
//=============================================================================
#include "stdafx.h"
#include "ServerBrowser.h"
#include "ServerBrowserMenu.h"
//-----------------------------------------------------------------------------
// Purpose: Constructor -- initialize from steam gameserveritem_t
//-----------------------------------------------------------------------------
CGameServer::CGameServer( gameserveritem_t *pGameServerItem )
{
m_unIPAddress = pGameServerItem->m_NetAdr.GetIP();
m_nConnectionPort = pGameServerItem->m_NetAdr.GetConnectionPort();
m_nPing = pGameServerItem->m_nPing;
strncpy_safe( m_szMap, pGameServerItem->m_szMap, ARRAYSIZE( m_szMap ) );
strncpy_safe( m_szGameDescription, pGameServerItem->m_szGameDescription, ARRAYSIZE( m_szGameDescription ) );
m_nPlayers = pGameServerItem->m_nPlayers;
m_nMaxPlayers = pGameServerItem->m_nMaxPlayers;
m_nBotPlayers = pGameServerItem->m_nBotPlayers;
m_bPassword = pGameServerItem->m_bPassword;
m_bSecure = pGameServerItem->m_bSecure;
m_nServerVersion = pGameServerItem->m_nServerVersion;
strncpy_safe( m_szServerName, pGameServerItem->GetName(), ARRAYSIZE( m_szServerName ) );
sprintf_safe( m_szServerString, "%s (%i/%i) at %s ping(%d)", pGameServerItem->GetName(), pGameServerItem->m_nPlayers, pGameServerItem->m_nMaxPlayers, pGameServerItem->m_NetAdr.GetConnectionAddressString(), pGameServerItem->m_nPing );
m_steamID = pGameServerItem->m_steamID;
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CServerBrowser::CServerBrowser( IGameEngine *pGameEngine )
{
m_pMenu = new CServerBrowserMenu( pGameEngine );
m_pGameEngine = pGameEngine;
m_nServers = 0;
m_bRequestingServers = false;
m_hServerListRequest = NULL;
m_pMenu->Rebuild( m_ListGameServers, m_bRequestingServers );
m_pMenu->SetHeading( "Internet Server browser" );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CServerBrowser::~CServerBrowser()
{
if ( m_hServerListRequest )
{
SteamMatchmakingServers()->ReleaseRequest( m_hServerListRequest );
m_hServerListRequest = NULL;
}
if ( m_pMenu )
delete m_pMenu;
// ...
}
//-----------------------------------------------------------------------------
// Purpose: Initiate a refresh of internet servers
//-----------------------------------------------------------------------------
void CServerBrowser::RefreshInternetServers()
{
// If we are still finishing the previous refresh, then ignore this new request
if ( m_bRequestingServers )
return;
// If another request is outstanding, make sure we release it properly
if ( m_hServerListRequest )
{
SteamMatchmakingServers()->ReleaseRequest( m_hServerListRequest );
m_hServerListRequest = NULL;
}
OutputDebugString( "Refreshing internet servers\n" );
// Track that we are now in a refresh, what type of refresh, and reset our server count
m_bRequestingServers = true;
m_nServers = 0;
m_ListGameServers.clear();
m_pMenu->SetHeading( "Internet Server browser" );
m_pMenu->Rebuild( m_ListGameServers, m_bRequestingServers );
Steamworks_TestSecret();
// Allocate some filters, there are some common pre-defined values that can be used:
//
// "gamedir" -- this is used to specify mods inside or a single product/appid
// "secure" -- this is used to specify whether anti-cheat is enabled for a server
// "gametype" -- this is used to specify game type and is set to whatever your game server code sets
MatchMakingKeyValuePair_t pFilters[2];
MatchMakingKeyValuePair_t *pFilter = pFilters;
strncpy_safe( pFilters[ 0 ].m_szKey, "gamedir", sizeof(pFilters[ 0 ].m_szKey) );
strncpy_safe( pFilters[ 0 ].m_szValue, "spacewar", sizeof(pFilters[ 0 ].m_szValue) );
strncpy_safe( pFilters[ 1 ].m_szKey, "secure", sizeof(pFilters[ 1 ].m_szKey) );
strncpy_safe( pFilters[ 1 ].m_szValue, "1", sizeof(pFilters[ 1 ].m_szValue) );
//strncpy_safe( pFilters[ 2 ].m_szKey, "gametype", sizeof(pFilters[ 1 ].m_szValue) );
//strncpy_safe( pFilters[ 2 ].m_szValue, "dm", sizeof(pFilters[ 1 ].m_szValue) );
// bugbug jmccaskey - passing just the appid without filters results in getting all servers rather than
// servers filtered by appid alone. So, we'll use the filters to filter the results better.
m_hServerListRequest = SteamMatchmakingServers()->RequestInternetServerList( SteamUtils()->GetAppID(), &pFilter, ARRAYSIZE(pFilters), this );
}
//-----------------------------------------------------------------------------
// Purpose: Initiate a refresh of LAN servers
//-----------------------------------------------------------------------------
void CServerBrowser::RefreshLANServers()
{
// If we are still finishing the previous refresh, then ignore this new request
if ( m_bRequestingServers )
return;
// If another request is outstanding, make sure we release it properly
if ( m_hServerListRequest )
{
SteamMatchmakingServers()->ReleaseRequest( m_hServerListRequest );
m_hServerListRequest = NULL;
}
OutputDebugString( "Refreshing LAN servers\n" );
// Track that we are now in a refresh, what type of refresh, and reset our server count
m_bRequestingServers = true;
m_nServers = 0;
m_ListGameServers.clear();
m_pMenu->SetHeading( "LAN Server browser" );
m_pMenu->Rebuild( m_ListGameServers, m_bRequestingServers );
// LAN refresh doesn't accept filters like internet above does
m_hServerListRequest = SteamMatchmakingServers()->RequestLANServerList( SteamUtils()->GetAppID(), this );
}
//-----------------------------------------------------------------------------
// Purpose: Callback from Steam telling us about a server that has responded
//-----------------------------------------------------------------------------
void CServerBrowser::ServerResponded( HServerListRequest hReq, int iServer )
{
// Assert( hReq == m_hServerListRequest );
gameserveritem_t *pServer = SteamMatchmakingServers()->GetServerDetails( hReq, iServer );
if ( pServer )
{
// Filter out servers that don't match our appid here (might get these in LAN calls since we can't put more filters on it)
if ( pServer->m_nAppID == SteamUtils()->GetAppID() )
{
m_ListGameServers.push_back( CGameServer( pServer ) );
m_nServers++;
}
}
// Rebuild menu
m_pMenu->Rebuild( m_ListGameServers, m_bRequestingServers );
}
//-----------------------------------------------------------------------------
// Purpose: Callback from Steam telling us about a server that has failed to respond
//-----------------------------------------------------------------------------
void CServerBrowser::ServerFailedToRespond( HServerListRequest hReq, int iServer )
{
// Assert( hReq == m_hServerListRequest );
// bugbug jmccaskey - why would we ever need this? Remove servers from our list I guess?
}
//-----------------------------------------------------------------------------
// Purpose: Callback from Steam telling us a refresh is complete
//-----------------------------------------------------------------------------
void CServerBrowser::RefreshComplete( HServerListRequest hReq, EMatchMakingServerResponse response )
{
// Assert( hReq == m_hServerListRequest );
// Doesn't really matter to us whether the response tells us the refresh succeeded or failed,
// we just track whether we are done refreshing or not
m_bRequestingServers = false;
}
//-----------------------------------------------------------------------------
// Purpose: Run a server browser frame (does stuff like checking KB input to change state)
//-----------------------------------------------------------------------------
void CServerBrowser::RunFrame()
{
m_pMenu->RunFrame();
}