//========= 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; }