2016-07-11 11:14:58 -04:00
# include "STDInclude.hpp"
namespace Components
{
bool ServerList : : SortAsc = true ;
int ServerList : : SortKey = ServerList : : Column : : Ping ;
unsigned int ServerList : : CurrentServer = 0 ;
ServerList : : Container ServerList : : RefreshContainer ;
std : : vector < ServerList : : ServerInfo > ServerList : : OnlineList ;
std : : vector < ServerList : : ServerInfo > ServerList : : OfflineList ;
std : : vector < ServerList : : ServerInfo > ServerList : : FavouriteList ;
std : : vector < unsigned int > ServerList : : VisibleList ;
std : : vector < ServerList : : ServerInfo > * ServerList : : GetList ( )
{
if ( ServerList : : IsOnlineList ( ) )
{
return & ServerList : : OnlineList ;
}
else if ( ServerList : : IsOfflineList ( ) )
{
return & ServerList : : OfflineList ;
}
else if ( ServerList : : IsFavouriteList ( ) )
{
return & ServerList : : FavouriteList ;
}
return nullptr ;
}
bool ServerList : : IsFavouriteList ( )
{
2016-11-20 08:09:07 -05:00
return ( Dvar : : Var ( " ui_netSource " ) . get < int > ( ) = = 2 ) ;
2016-07-11 11:14:58 -04:00
}
bool ServerList : : IsOfflineList ( )
{
2016-11-20 08:09:07 -05:00
return ( Dvar : : Var ( " ui_netSource " ) . get < int > ( ) = = 0 ) ;
2016-07-11 11:14:58 -04:00
}
bool ServerList : : IsOnlineList ( )
{
2016-11-20 08:09:07 -05:00
return ( Dvar : : Var ( " ui_netSource " ) . get < int > ( ) = = 1 ) ;
2016-07-11 11:14:58 -04:00
}
unsigned int ServerList : : GetServerCount ( )
{
return ServerList : : VisibleList . size ( ) ;
}
const char * ServerList : : GetServerText ( unsigned int index , int column )
{
ServerList : : ServerInfo * info = ServerList : : GetServer ( index ) ;
if ( info )
{
return ServerList : : GetServerText ( info , column ) ;
}
return " " ;
}
const char * ServerList : : GetServerText ( ServerList : : ServerInfo * server , int column )
{
if ( ! server ) return " " ;
switch ( column )
{
case Column : : Password :
{
2016-11-20 08:09:07 -05:00
return ( server - > password ? " X " : " " ) ;
2016-07-11 11:14:58 -04:00
}
case Column : : Matchtype :
{
2016-11-20 08:09:07 -05:00
return ( ( server - > matchType = = 1 ) ? " P " : " M " ) ;
2016-07-11 11:14:58 -04:00
}
case Column : : Hostname :
{
2016-11-20 08:09:07 -05:00
return server - > hostname . data ( ) ;
2016-07-11 11:14:58 -04:00
}
case Column : : Mapname :
{
2016-11-20 08:09:07 -05:00
if ( server - > svRunning )
2016-08-14 11:01:01 -04:00
{
2016-11-20 08:09:07 -05:00
return Game : : UI_LocalizeMapName ( server - > mapname . data ( ) ) ;
2016-08-14 11:01:01 -04:00
}
else
{
2016-11-20 08:09:07 -05:00
return Utils : : String : : VA ( " ^3%s " , Game : : UI_LocalizeMapName ( server - > mapname . data ( ) ) ) ;
2016-08-14 11:01:01 -04:00
}
2016-07-11 11:14:58 -04:00
}
case Column : : Players :
{
2016-11-20 08:09:07 -05:00
return Utils : : String : : VA ( " %i (%i) " , server - > clients , server - > maxClients ) ;
2016-07-11 11:14:58 -04:00
}
case Column : : Gametype :
{
2016-11-20 08:09:07 -05:00
return Game : : UI_LocalizeGameType ( server - > gametype . data ( ) ) ;
2016-07-11 11:14:58 -04:00
}
case Column : : Mod :
{
2016-11-20 08:09:07 -05:00
if ( server - > mod ! = " " )
2016-07-11 11:14:58 -04:00
{
2016-11-20 08:09:07 -05:00
return ( server - > mod . data ( ) + 5 ) ;
2016-07-11 11:14:58 -04:00
}
return " " ;
}
case Column : : Ping :
{
2016-11-20 08:09:07 -05:00
return Utils : : String : : VA ( " %i " , server - > ping ) ;
2016-07-11 11:14:58 -04:00
}
}
return " " ;
}
void ServerList : : SelectServer ( unsigned int index )
{
ServerList : : CurrentServer = index ;
ServerList : : ServerInfo * info = ServerList : : GetCurrentServer ( ) ;
if ( info )
{
2016-11-20 08:09:07 -05:00
Dvar : : Var ( " ui_serverSelected " ) . set ( true ) ;
Dvar : : Var ( " ui_serverSelectedMap " ) . set ( info - > mapname ) ;
Dvar : : Var ( " ui_serverSelectedGametype " ) . set ( info - > gametype ) ;
2016-07-11 11:14:58 -04:00
}
else
{
2016-11-20 08:09:07 -05:00
Dvar : : Var ( " ui_serverSelected " ) . set ( false ) ;
2016-07-11 11:14:58 -04:00
}
}
void ServerList : : UpdateVisibleList ( )
{
auto list = ServerList : : GetList ( ) ;
if ( ! list ) return ;
std : : vector < ServerList : : ServerInfo > tempList ( * list ) ;
if ( tempList . empty ( ) )
{
ServerList : : Refresh ( ) ;
}
else
{
list - > clear ( ) ;
2016-11-20 08:09:07 -05:00
std : : lock_guard < std : : mutex > _ ( ServerList : : RefreshContainer . mutex ) ;
2016-07-11 11:14:58 -04:00
2016-11-20 08:09:07 -05:00
ServerList : : RefreshContainer . sendCount = 0 ;
ServerList : : RefreshContainer . sentCount = 0 ;
2016-07-11 11:14:58 -04:00
for ( auto server : tempList )
{
2016-11-20 08:09:07 -05:00
ServerList : : InsertRequest ( server . addr , false ) ;
2016-07-11 11:14:58 -04:00
}
}
}
void ServerList : : RefreshVisibleList ( )
{
2016-11-20 08:09:07 -05:00
Dvar : : Var ( " ui_serverSelected " ) . set ( false ) ;
2016-07-11 11:14:58 -04:00
ServerList : : VisibleList . clear ( ) ;
auto list = ServerList : : GetList ( ) ;
if ( ! list ) return ;
// Refresh entirely, if there is no entry in the list
if ( list - > empty ( ) )
{
ServerList : : Refresh ( ) ;
return ;
}
2016-11-20 08:09:07 -05:00
bool ui_browserShowFull = Dvar : : Var ( " ui_browserShowFull " ) . get < bool > ( ) ;
bool ui_browserShowEmpty = Dvar : : Var ( " ui_browserShowEmpty " ) . get < bool > ( ) ;
int ui_browserShowHardcore = Dvar : : Var ( " ui_browserKillcam " ) . get < int > ( ) ;
int ui_browserShowPassword = Dvar : : Var ( " ui_browserShowPassword " ) . get < int > ( ) ;
int ui_browserMod = Dvar : : Var ( " ui_browserMod " ) . get < int > ( ) ;
int ui_joinGametype = Dvar : : Var ( " ui_joinGametype " ) . get < int > ( ) ;
2016-07-11 11:14:58 -04:00
for ( unsigned int i = 0 ; i < list - > size ( ) ; + + i )
{
ServerList : : ServerInfo * info = & ( * list ) [ i ] ;
// Filter full servers
2016-11-20 08:09:07 -05:00
if ( ! ui_browserShowFull & & info - > clients > = info - > maxClients ) continue ;
2016-07-11 11:14:58 -04:00
// Filter empty servers
2016-11-20 08:09:07 -05:00
if ( ! ui_browserShowEmpty & & info - > clients < = 0 ) continue ;
2016-07-11 11:14:58 -04:00
// Filter hardcore servers
2016-11-20 08:09:07 -05:00
if ( ( ui_browserShowHardcore = = 0 & & info - > hardcore ) | | ( ui_browserShowHardcore = = 1 & & ! info - > hardcore ) ) continue ;
2016-07-11 11:14:58 -04:00
// Filter servers with password
2016-11-20 08:09:07 -05:00
if ( ( ui_browserShowPassword = = 0 & & info - > password ) | | ( ui_browserShowPassword = = 1 & & ! info - > password ) ) continue ;
2016-07-11 11:14:58 -04:00
// Don't show modded servers
2016-11-20 08:09:07 -05:00
if ( ( ui_browserMod = = 0 & & info - > mod . size ( ) ) | | ( ui_browserMod = = 1 & & ! info - > mod . size ( ) ) ) continue ;
2016-07-11 11:14:58 -04:00
// Filter by gametype
2016-11-20 08:09:07 -05:00
if ( ui_joinGametype > 0 & & ( ui_joinGametype - 1 ) < * Game : : gameTypeCount & & Game : : gameTypes [ ( ui_joinGametype - 1 ) ] . gameType ! = info - > gametype ) continue ;
2016-07-11 11:14:58 -04:00
ServerList : : VisibleList . push_back ( i ) ;
}
ServerList : : SortList ( ) ;
}
void ServerList : : Refresh ( )
{
2016-11-20 08:09:07 -05:00
Dvar : : Var ( " ui_serverSelected " ) . set ( false ) ;
2016-07-11 11:14:58 -04:00
Localization : : Set ( " MPUI_SERVERQUERIED " , " Sent requests: 0/0 " ) ;
// ServerList::OnlineList.clear();
// ServerList::OfflineList.clear();
// ServerList::FavouriteList.clear();
auto list = ServerList : : GetList ( ) ;
if ( list ) list - > clear ( ) ;
ServerList : : VisibleList . clear ( ) ;
2016-11-20 08:09:07 -05:00
ServerList : : RefreshContainer . mutex . lock ( ) ;
ServerList : : RefreshContainer . servers . clear ( ) ;
ServerList : : RefreshContainer . sendCount = 0 ;
ServerList : : RefreshContainer . sentCount = 0 ;
ServerList : : RefreshContainer . mutex . unlock ( ) ;
2016-07-11 11:14:58 -04:00
if ( ServerList : : IsOfflineList ( ) )
{
Discovery : : Perform ( ) ;
}
else if ( ServerList : : IsOnlineList ( ) )
{
# ifdef USE_LEGACY_SERVER_LIST
2016-11-20 08:09:07 -05:00
ServerList : : RefreshContainer . awatingList = true ;
ServerList : : RefreshContainer . awaitTime = Game : : Sys_Milliseconds ( ) ;
2016-07-11 11:14:58 -04:00
2016-11-20 08:09:07 -05:00
int masterPort = Dvar : : Var ( " masterPort " ) . get < int > ( ) ;
const char * masterServerName = Dvar : : Var ( " masterServerName " ) . get < const char * > ( ) ;
2016-07-11 11:14:58 -04:00
2016-11-20 08:09:07 -05:00
ServerList : : RefreshContainer . host = Network : : Address ( Utils : : String : : VA ( " %s:%u " , masterServerName , masterPort ) ) ;
2016-07-11 11:14:58 -04:00
Logger : : Print ( " Sending serverlist request to master: %s:%u \n " , masterServerName , masterPort ) ;
2016-11-20 08:09:07 -05:00
Network : : SendCommand ( ServerList : : RefreshContainer . host , " getservers " , Utils : : String : : VA ( " IW4 %i full empty " , PROTOCOL ) ) ;
2016-07-11 11:14:58 -04:00
//Network::SendCommand(ServerList::RefreshContainer.Host, "getservers", "0 full empty");
# else
Node : : SyncNodeList ( ) ;
# endif
}
else if ( ServerList : : IsFavouriteList ( ) )
{
ServerList : : LoadFavourties ( ) ;
}
}
void ServerList : : StoreFavourite ( std : : string server )
{
//json11::Json::parse()
std : : vector < std : : string > servers ;
if ( Utils : : IO : : FileExists ( " players/favourites.json " ) )
{
std : : string data = Utils : : IO : : ReadFile ( " players/favourites.json " ) ;
json11 : : Json object = json11 : : Json : : parse ( data , data ) ;
if ( ! object . is_array ( ) )
{
Logger : : Print ( " Favourites storage file is invalid! \n " ) ;
Game : : MessageBox ( " Favourites storage file is invalid! " , " Error " ) ;
return ;
}
auto storedServers = object . array_items ( ) ;
for ( unsigned int i = 0 ; i < storedServers . size ( ) ; + + i )
{
if ( ! storedServers [ i ] . is_string ( ) ) continue ;
if ( storedServers [ i ] . string_value ( ) = = server )
{
Game : : MessageBox ( " Server already marked as favourite. " , " Error " ) ;
return ;
}
servers . push_back ( storedServers [ i ] . string_value ( ) ) ;
}
}
servers . push_back ( server ) ;
json11 : : Json data = json11 : : Json ( servers ) ;
Utils : : IO : : WriteFile ( " players/favourites.json " , data . dump ( ) ) ;
Game : : MessageBox ( " Server added to favourites. " , " Success " ) ;
}
void ServerList : : LoadFavourties ( )
{
if ( ServerList : : IsFavouriteList ( ) & & Utils : : IO : : FileExists ( " players/favourites.json " ) )
{
auto list = ServerList : : GetList ( ) ;
if ( list ) list - > clear ( ) ;
std : : string data = Utils : : IO : : ReadFile ( " players/favourites.json " ) ;
json11 : : Json object = json11 : : Json : : parse ( data , data ) ;
if ( ! object . is_array ( ) )
{
Logger : : Print ( " Favourites storage file is invalid! \n " ) ;
Game : : MessageBox ( " Favourites storage file is invalid! " , " Error " ) ;
return ;
}
auto servers = object . array_items ( ) ;
for ( unsigned int i = 0 ; i < servers . size ( ) ; + + i )
{
if ( ! servers [ i ] . is_string ( ) ) continue ;
ServerList : : InsertRequest ( servers [ i ] . string_value ( ) , true ) ;
}
}
}
void ServerList : : InsertRequest ( Network : : Address address , bool acquireMutex )
{
2016-11-20 08:09:07 -05:00
if ( acquireMutex ) ServerList : : RefreshContainer . mutex . lock ( ) ;
2016-07-11 11:14:58 -04:00
ServerList : : Container : : ServerContainer container ;
2016-11-20 08:09:07 -05:00
container . sent = false ;
container . target = address ;
2016-07-11 11:14:58 -04:00
bool alreadyInserted = false ;
2016-11-20 08:09:07 -05:00
for ( auto & server : ServerList : : RefreshContainer . servers )
2016-07-11 11:14:58 -04:00
{
2016-11-20 08:09:07 -05:00
if ( server . target = = container . target )
2016-07-11 11:14:58 -04:00
{
alreadyInserted = true ;
break ;
}
}
if ( ! alreadyInserted )
{
2016-11-20 08:09:07 -05:00
ServerList : : RefreshContainer . servers . push_back ( container ) ;
2016-07-11 11:14:58 -04:00
auto list = ServerList : : GetList ( ) ;
if ( list )
{
for ( auto server : * list )
{
2016-11-20 08:09:07 -05:00
if ( server . addr = = container . target )
2016-07-11 11:14:58 -04:00
{
2016-11-20 08:09:07 -05:00
- - ServerList : : RefreshContainer . sendCount ;
- - ServerList : : RefreshContainer . sentCount ;
2016-07-11 11:14:58 -04:00
break ;
}
}
}
2016-11-20 08:09:07 -05:00
+ + ServerList : : RefreshContainer . sendCount ;
2016-07-11 11:14:58 -04:00
}
2016-11-20 08:09:07 -05:00
if ( acquireMutex ) ServerList : : RefreshContainer . mutex . unlock ( ) ;
2016-07-11 11:14:58 -04:00
}
void ServerList : : Insert ( Network : : Address address , Utils : : InfoString info )
{
2016-11-20 08:09:07 -05:00
std : : lock_guard < std : : mutex > _ ( ServerList : : RefreshContainer . mutex ) ;
2016-07-11 11:14:58 -04:00
2016-11-20 08:09:07 -05:00
for ( auto i = ServerList : : RefreshContainer . servers . begin ( ) ; i ! = ServerList : : RefreshContainer . servers . end ( ) ; )
2016-07-11 11:14:58 -04:00
{
// Our desired server
2016-11-20 08:09:07 -05:00
if ( i - > target = = address & & i - > sent )
2016-07-11 11:14:58 -04:00
{
// Challenge did not match
2016-11-20 08:09:07 -05:00
if ( i - > challenge ! = info . get ( " challenge " ) )
2016-07-11 11:14:58 -04:00
{
// Shall we remove the server from the queue?
// Better not, it might send a second response with the correct challenge.
// This might happen when users refresh twice (or more often) in a short period of time
break ;
}
ServerInfo server ;
2016-11-20 08:09:07 -05:00
server . hostname = info . get ( " hostname " ) ;
server . mapname = info . get ( " mapname " ) ;
server . gametype = info . get ( " gametype " ) ;
server . shortversion = info . get ( " shortversion " ) ;
server . mod = info . get ( " fs_game " ) ;
server . matchType = atoi ( info . get ( " matchtype " ) . data ( ) ) ;
server . clients = atoi ( info . get ( " clients " ) . data ( ) ) ;
server . securityLevel = atoi ( info . get ( " securityLevel " ) . data ( ) ) ;
server . maxClients = atoi ( info . get ( " sv_maxclients " ) . data ( ) ) ;
server . password = ( atoi ( info . get ( " isPrivate " ) . data ( ) ) ! = 0 ) ;
server . hardcore = ( atoi ( info . get ( " hc " ) . data ( ) ) ! = 0 ) ;
server . svRunning = ( atoi ( info . get ( " sv_running " ) . data ( ) ) ! = 0 ) ;
server . ping = ( Game : : Sys_Milliseconds ( ) - i - > sendTime ) ;
server . addr = address ;
2016-07-11 11:14:58 -04:00
// Remove server from queue
2016-11-20 08:09:07 -05:00
i = ServerList : : RefreshContainer . servers . erase ( i ) ;
2016-07-11 11:14:58 -04:00
// Check if already inserted and remove
auto list = ServerList : : GetList ( ) ;
if ( ! list ) return ;
unsigned int k = 0 ;
for ( auto j = list - > begin ( ) ; j ! = list - > end ( ) ; + + k )
{
2016-11-20 08:09:07 -05:00
if ( j - > addr = = address )
2016-07-11 11:14:58 -04:00
{
j = list - > erase ( j ) ;
}
else
{
+ + j ;
}
}
// Also remove from visible list
for ( auto j = ServerList : : VisibleList . begin ( ) ; j ! = ServerList : : VisibleList . end ( ) ; )
{
if ( * j = = k )
{
j = ServerList : : VisibleList . erase ( j ) ;
}
else
{
+ + j ;
}
}
2016-11-20 08:09:07 -05:00
if ( info . get ( " gamename " ) = = " IW4 "
& & server . matchType
2016-07-11 11:14:58 -04:00
# ifndef DEBUG
2016-11-20 08:09:07 -05:00
& & server . shortversion = = SHORTVERSION
2016-07-11 11:14:58 -04:00
# endif
)
{
auto lList = ServerList : : GetList ( ) ;
if ( lList )
{
lList - > push_back ( server ) ;
ServerList : : RefreshVisibleList ( ) ;
}
}
break ;
}
else
{
+ + i ;
}
}
}
ServerList : : ServerInfo * ServerList : : GetCurrentServer ( )
{
return ServerList : : GetServer ( ServerList : : CurrentServer ) ;
}
void ServerList : : SortList ( )
{
qsort ( ServerList : : VisibleList . data ( ) , ServerList : : VisibleList . size ( ) , sizeof ( int ) , [ ] ( const void * first , const void * second )
{
const unsigned int server1 = * static_cast < const unsigned int * > ( first ) ;
const unsigned int server2 = * static_cast < const unsigned int * > ( second ) ;
ServerInfo * info1 = nullptr ;
ServerInfo * info2 = nullptr ;
auto list = ServerList : : GetList ( ) ;
if ( ! list ) return 0 ;
if ( list - > size ( ) > server1 ) info1 = & ( * list ) [ server1 ] ;
if ( list - > size ( ) > server2 ) info2 = & ( * list ) [ server2 ] ;
if ( ! info1 ) return 1 ;
if ( ! info2 ) return - 1 ;
// Numerical comparisons
if ( ServerList : : SortKey = = ServerList : : Column : : Ping )
{
2016-11-20 08:09:07 -05:00
return ( ( info1 - > ping - info2 - > ping ) * ( ServerList : : SortAsc ? 1 : - 1 ) ) ;
2016-07-11 11:14:58 -04:00
}
else if ( ServerList : : SortKey = = ServerList : : Column : : Players )
{
2016-11-20 08:09:07 -05:00
return ( ( info1 - > clients - info2 - > clients ) * ( ServerList : : SortAsc ? 1 : - 1 ) ) ;
2016-07-11 11:14:58 -04:00
}
std : : string text1 = Colors : : Strip ( ServerList : : GetServerText ( info1 , ServerList : : SortKey ) ) ;
std : : string text2 = Colors : : Strip ( ServerList : : GetServerText ( info2 , ServerList : : SortKey ) ) ;
// ASCII-based comparison
return ( text1 . compare ( text2 ) * ( ServerList : : SortAsc ? 1 : - 1 ) ) ;
} ) ;
}
ServerList : : ServerInfo * ServerList : : GetServer ( unsigned int index )
{
if ( ServerList : : VisibleList . size ( ) > index )
{
auto list = ServerList : : GetList ( ) ;
if ( ! list ) return nullptr ;
if ( list - > size ( ) > ServerList : : VisibleList [ index ] )
{
return & ( * list ) [ ServerList : : VisibleList [ index ] ] ;
}
}
return nullptr ;
}
void ServerList : : Frame ( )
{
2016-11-20 08:09:07 -05:00
// This is bad practice and might even cause undefined behaviour!
if ( ! ServerList : : RefreshContainer . mutex . try_lock ( ) ) return ;
2016-07-11 11:14:58 -04:00
2016-11-20 08:09:07 -05:00
if ( ServerList : : RefreshContainer . awatingList )
2016-07-11 11:14:58 -04:00
{
// Check if we haven't got a response within 10 seconds
2016-11-20 08:09:07 -05:00
if ( Game : : Sys_Milliseconds ( ) - ServerList : : RefreshContainer . awaitTime > 5000 )
2016-07-11 11:14:58 -04:00
{
2016-11-20 08:09:07 -05:00
ServerList : : RefreshContainer . awatingList = false ;
2016-07-11 11:14:58 -04:00
2016-11-20 08:09:07 -05:00
Logger : : Print ( " We haven't received a response from the master within %d seconds! \n " , ( Game : : Sys_Milliseconds ( ) - ServerList : : RefreshContainer . awaitTime ) / 1000 ) ;
2016-07-11 11:14:58 -04:00
}
}
// Send requests to 10 servers each frame
int SendServers = 10 ;
2016-11-20 08:09:07 -05:00
for ( unsigned int i = 0 ; i < ServerList : : RefreshContainer . servers . size ( ) ; + + i )
2016-07-11 11:14:58 -04:00
{
2016-11-20 08:09:07 -05:00
ServerList : : Container : : ServerContainer * server = & ServerList : : RefreshContainer . servers [ i ] ;
if ( server - > sent ) continue ;
2016-07-11 11:14:58 -04:00
// Found server we can send a request to
2016-11-20 08:09:07 -05:00
server - > sent = true ;
2016-07-11 11:14:58 -04:00
SendServers - - ;
2016-11-20 08:09:07 -05:00
server - > sendTime = Game : : Sys_Milliseconds ( ) ;
server - > challenge = fmt : : sprintf ( " %X " , Utils : : Cryptography : : Rand : : GenerateInt ( ) ) ;
2016-07-11 11:14:58 -04:00
2016-11-20 08:09:07 -05:00
+ + ServerList : : RefreshContainer . sentCount ;
2016-07-11 11:14:58 -04:00
2016-11-20 08:09:07 -05:00
Network : : SendCommand ( server - > target , " getinfo " , server - > challenge ) ;
2016-07-11 11:14:58 -04:00
// Display in the menu, like in COD4
2016-11-20 08:09:07 -05:00
Localization : : Set ( " MPUI_SERVERQUERIED " , fmt : : sprintf ( " Sent requests: %d/%d " , ServerList : : RefreshContainer . sentCount , ServerList : : RefreshContainer . sendCount ) ) ;
2016-07-11 11:14:58 -04:00
if ( SendServers < = 0 ) break ;
}
2016-11-20 08:09:07 -05:00
ServerList : : RefreshContainer . mutex . unlock ( ) ;
2016-07-11 11:14:58 -04:00
}
void ServerList : : UpdateSource ( )
{
Dvar : : Var netSource ( " ui_netSource " ) ;
2016-11-20 08:09:07 -05:00
int source = netSource . get < int > ( ) ;
2016-07-11 11:14:58 -04:00
2016-11-20 08:09:07 -05:00
if ( + + source > netSource . get < Game : : dvar_t * > ( ) - > max . i )
2016-07-11 11:14:58 -04:00
{
source = 0 ;
}
2016-11-20 08:09:07 -05:00
netSource . set ( source ) ;
2016-07-11 11:14:58 -04:00
ServerList : : RefreshVisibleList ( ) ;
}
void ServerList : : UpdateGameType ( )
{
Dvar : : Var joinGametype ( " ui_joinGametype " ) ;
2016-11-20 08:09:07 -05:00
int gametype = joinGametype . get < int > ( ) ;
2016-07-11 11:14:58 -04:00
if ( + + gametype > * Game : : gameTypeCount )
{
gametype = 0 ;
}
2016-11-20 08:09:07 -05:00
joinGametype . set ( gametype ) ;
2016-07-11 11:14:58 -04:00
ServerList : : RefreshVisibleList ( ) ;
}
ServerList : : ServerList ( )
{
ServerList : : OnlineList . clear ( ) ;
ServerList : : VisibleList . clear ( ) ;
Dvar : : OnInit ( [ ] ( )
{
Dvar : : Register < bool > ( " ui_serverSelected " , false , Game : : dvar_flag : : DVAR_FLAG_NONE , " Whether a server has been selected in the serverlist " ) ;
Dvar : : Register < const char * > ( " ui_serverSelectedMap " , " mp_afghan " , Game : : dvar_flag : : DVAR_FLAG_NONE , " Map of the selected server " ) ;
} ) ;
Localization : : Set ( " MPUI_SERVERQUERIED " , " Sent requests: 0/0 " ) ;
Network : : Handle ( " getServersResponse " , [ ] ( Network : : Address address , std : : string data )
{
2016-11-20 08:09:07 -05:00
if ( ServerList : : RefreshContainer . host ! = address ) return ; // Only parse from host we sent to
2016-07-11 11:14:58 -04:00
2016-11-20 08:09:07 -05:00
ServerList : : RefreshContainer . awatingList = false ;
2016-07-11 11:14:58 -04:00
2016-11-20 08:09:07 -05:00
std : : lock_guard < std : : mutex > _ ( ServerList : : RefreshContainer . mutex ) ;
2016-07-11 11:14:58 -04:00
int offset = 0 ;
2016-11-20 08:09:07 -05:00
int count = ServerList : : RefreshContainer . servers . size ( ) ;
2016-07-11 11:14:58 -04:00
ServerList : : MasterEntry * entry = nullptr ;
// Find first entry
do
{
entry = reinterpret_cast < ServerList : : MasterEntry * > ( const_cast < char * > ( data . data ( ) ) + offset + + ) ;
}
while ( ! entry - > HasSeparator ( ) & & ! entry - > IsEndToken ( ) ) ;
for ( int i = 0 ; ! entry [ i ] . IsEndToken ( ) & & entry [ i ] . HasSeparator ( ) ; + + i )
{
Network : : Address serverAddr = address ;
2016-11-20 08:09:07 -05:00
serverAddr . setIP ( entry [ i ] . ip ) ;
serverAddr . setPort ( ntohs ( entry [ i ] . port ) ) ;
serverAddr . setType ( Game : : NA_IP ) ;
2016-07-11 11:14:58 -04:00
ServerList : : InsertRequest ( serverAddr , false ) ;
}
2016-11-20 08:09:07 -05:00
Logger : : Print ( " Parsed %d servers from master \n " , ServerList : : RefreshContainer . servers . size ( ) - count ) ;
2016-07-11 11:14:58 -04:00
} ) ;
// Set default masterServerName + port and save it
# ifdef USE_LEGACY_SERVER_LIST
Utils : : Hook : : Set < char * > ( 0x60AD92 , " localhost " ) ;
Utils : : Hook : : Set < BYTE > ( 0x60AD90 , Game : : dvar_flag : : DVAR_FLAG_SAVED ) ; // masterServerName
Utils : : Hook : : Set < BYTE > ( 0x60ADC6 , Game : : dvar_flag : : DVAR_FLAG_SAVED ) ; // masterPort
# endif
// Add server list feeder
UIFeeder : : Add ( 2.0f , ServerList : : GetServerCount , ServerList : : GetServerText , ServerList : : SelectServer ) ;
// Add required UIScripts
UIScript : : Add ( " UpdateFilter " , ServerList : : RefreshVisibleList ) ;
UIScript : : Add ( " RefreshFilter " , ServerList : : UpdateVisibleList ) ;
UIScript : : Add ( " RefreshServers " , ServerList : : Refresh ) ;
UIScript : : Add ( " JoinServer " , [ ] ( )
{
ServerList : : ServerInfo * info = ServerList : : GetServer ( ServerList : : CurrentServer ) ;
if ( info )
{
2016-11-20 08:09:07 -05:00
Party : : Connect ( info - > addr ) ;
2016-07-11 11:14:58 -04:00
}
} ) ;
UIScript : : Add ( " ServerSort " , [ ] ( UIScript : : Token token )
{
2016-11-20 08:09:07 -05:00
int key = token . get < int > ( ) ;
2016-07-11 11:14:58 -04:00
if ( ServerList : : SortKey = = key )
{
ServerList : : SortAsc = ! ServerList : : SortAsc ;
}
else
{
ServerList : : SortKey = key ;
ServerList : : SortAsc = true ;
}
Logger : : Print ( " Sorting server list by token: %d \n " , ServerList : : SortKey ) ;
ServerList : : SortList ( ) ;
} ) ;
UIScript : : Add ( " CreateListFavorite " , [ ] ( )
{
ServerList : : ServerInfo * info = ServerList : : GetCurrentServer ( ) ;
if ( info )
{
2016-11-20 08:09:07 -05:00
ServerList : : StoreFavourite ( info - > addr . getString ( ) ) ;
2016-07-11 11:14:58 -04:00
}
} ) ;
UIScript : : Add ( " CreateFavorite " , [ ] ( )
{
2016-11-20 08:09:07 -05:00
ServerList : : StoreFavourite ( Dvar : : Var ( " ui_favoriteAddress " ) . get < std : : string > ( ) ) ;
2016-07-11 11:14:58 -04:00
} ) ;
UIScript : : Add ( " CreateCurrentServerFavorite " , [ ] ( )
{
2016-11-20 08:09:07 -05:00
if ( Dvar : : Var ( " cl_ingame " ) . get < bool > ( ) )
2016-07-11 11:14:58 -04:00
{
2016-11-20 08:09:07 -05:00
std : : string addressText = Network : : Address ( * Game : : connectedHost ) . getString ( ) ;
2016-07-11 11:14:58 -04:00
if ( addressText ! = " 0.0.0.0:0 " & & addressText ! = " loopback " )
{
ServerList : : StoreFavourite ( addressText ) ;
}
}
} ) ;
// Add required ownerDraws
UIScript : : AddOwnerDraw ( 220 , ServerList : : UpdateSource ) ;
UIScript : : AddOwnerDraw ( 253 , ServerList : : UpdateGameType ) ;
// Add frame callback
Renderer : : OnFrame ( ServerList : : Frame ) ;
2016-08-08 12:59:02 -04:00
// This is placed here in case the anticheat has been disabled!
# ifndef DEBUG
2016-11-05 07:56:12 -04:00
Renderer : : OnFrame ( AntiCheat : : ReadIntegrityCheck ) ;
2016-08-08 12:59:02 -04:00
# endif
2016-07-11 11:14:58 -04:00
}
ServerList : : ~ ServerList ( )
{
ServerList : : OnlineList . clear ( ) ;
ServerList : : OfflineList . clear ( ) ;
ServerList : : FavouriteList . clear ( ) ;
ServerList : : VisibleList . clear ( ) ;
2016-11-20 08:09:07 -05:00
ServerList : : RefreshContainer . mutex . lock ( ) ;
ServerList : : RefreshContainer . awatingList = false ;
ServerList : : RefreshContainer . servers . clear ( ) ;
ServerList : : RefreshContainer . mutex . unlock ( ) ;
2016-07-11 11:14:58 -04:00
}
}