WIP: Begin rewriting serverbrowser

This commit is contained in:
nillerusr
2023-01-29 19:26:04 +03:00
parent 548be38a0b
commit 41aa50e66e
27 changed files with 265 additions and 333 deletions

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_ullTimeBlacklistedAt > pSvr2->m_ullTimeBlacklistedAt )
return -1;
if ( pSvr1->m_ullTimeBlacklistedAt < pSvr2->m_ullTimeBlacklistedAt )
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" );
uint64 ullDate = pData->GetUint64( "date" );
if ( bResetTimes )
{
time_t today;
time( &today );
ullDate = (uint64)today;
}
const char *pszNetAddr = pData->GetString( "addr" );
if ( pszNetAddr && pszNetAddr[0] && pszName && pszName[0] )
{
blacklisted_server_t *blackServer = m_blackList.AddServer( pszName, pszNetAddr, ullDate );
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_ullTimeBlacklistedAt );
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,69 @@
//========= 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"
#include <time.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;
time_t 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,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,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