2017-01-16 11:42:50 -05: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 ( )
{
return ( Dvar : : Var ( " ui_netSource " ) . get < int > ( ) = = 2 ) ;
}
bool ServerList : : IsOfflineList ( )
{
return ( Dvar : : Var ( " ui_netSource " ) . get < int > ( ) = = 0 ) ;
}
bool ServerList : : IsOnlineList ( )
{
2017-02-25 09:32:15 -05:00
return ( Monitor : : IsEnabled ( ) | | Dvar : : Var ( " ui_netSource " ) . get < int > ( ) = = 1 ) ;
2017-01-16 11:42:50 -05: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 )
{
2017-01-21 16:14:23 -05:00
return ServerList : : GetServerInfoText ( info , column ) ;
2017-01-16 11:42:50 -05:00
}
return " " ;
}
2017-01-21 16:14:23 -05:00
const char * ServerList : : GetServerInfoText ( ServerList : : ServerInfo * server , int column )
2017-01-16 11:42:50 -05:00
{
if ( ! server ) return " " ;
switch ( column )
{
case Column : : Password :
{
return ( server - > password ? " X " : " " ) ;
}
case Column : : Matchtype :
{
return ( ( server - > matchType = = 1 ) ? " P " : " M " ) ;
}
case Column : : Hostname :
{
return server - > hostname . data ( ) ;
}
case Column : : Mapname :
{
if ( server - > svRunning )
{
2017-01-29 12:27:11 -05:00
if ( ! Maps : : CheckMapInstalled ( server - > mapname . data ( ) ) )
{
return Utils : : String : : VA ( " ^1%s " , Game : : UI_LocalizeMapName ( server - > mapname . data ( ) ) ) ;
}
2017-01-16 11:42:50 -05:00
return Game : : UI_LocalizeMapName ( server - > mapname . data ( ) ) ;
}
else
{
return Utils : : String : : VA ( " ^3%s " , Game : : UI_LocalizeMapName ( server - > mapname . data ( ) ) ) ;
}
}
case Column : : Players :
{
return Utils : : String : : VA ( " %i (%i) " , server - > clients , server - > maxClients ) ;
}
case Column : : Gametype :
{
return Game : : UI_LocalizeGameType ( server - > gametype . data ( ) ) ;
}
case Column : : Mod :
{
if ( server - > mod ! = " " )
{
return ( server - > mod . data ( ) + 5 ) ;
}
return " " ;
}
case Column : : Ping :
{
2017-02-11 12:29:44 -05:00
if ( server - > ping < 75 ) // Below this is a good ping
{
return Utils : : String : : VA ( " ^2%i " , server - > ping ) ;
}
else if ( server - > ping < 150 ) // Below this is a medium ping
{
return Utils : : String : : VA ( " ^3%i " , server - > ping ) ;
}
else
{
return Utils : : String : : VA ( " ^1%i " , server - > ping ) ;
}
2017-01-16 11:42:50 -05:00
}
2017-01-20 16:41:03 -05:00
default :
{
break ;
} ;
2017-01-16 11:42:50 -05:00
}
return " " ;
}
void ServerList : : SelectServer ( unsigned int index )
{
ServerList : : CurrentServer = index ;
ServerList : : ServerInfo * info = ServerList : : GetCurrentServer ( ) ;
if ( info )
{
Dvar : : Var ( " ui_serverSelected " ) . set ( true ) ;
Dvar : : Var ( " ui_serverSelectedMap " ) . set ( info - > mapname ) ;
Dvar : : Var ( " ui_serverSelectedGametype " ) . set ( info - > gametype ) ;
}
else
{
Dvar : : Var ( " ui_serverSelected " ) . set ( false ) ;
}
}
void ServerList : : UpdateVisibleList ( UIScript : : Token )
{
auto list = ServerList : : GetList ( ) ;
if ( ! list ) return ;
std : : vector < ServerList : : ServerInfo > tempList ( * list ) ;
if ( tempList . empty ( ) )
{
ServerList : : Refresh ( UIScript : : Token ( ) ) ;
}
else
{
list - > clear ( ) ;
2017-02-28 13:58:03 -05:00
std : : lock_guard < std : : recursive_mutex > _ ( ServerList : : RefreshContainer . mutex ) ;
2017-01-16 11:42:50 -05:00
ServerList : : RefreshContainer . sendCount = 0 ;
ServerList : : RefreshContainer . sentCount = 0 ;
2017-05-30 14:31:00 -04:00
for ( auto & server : tempList )
2017-01-16 11:42:50 -05:00
{
2017-02-28 13:58:03 -05:00
ServerList : : InsertRequest ( server . addr ) ;
2017-01-16 11:42:50 -05:00
}
}
}
void ServerList : : RefreshVisibleList ( UIScript : : Token )
{
Dvar : : Var ( " ui_serverSelected " ) . set ( false ) ;
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 ( UIScript : : Token ( ) ) ;
return ;
}
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 > ( ) ;
for ( unsigned int i = 0 ; i < list - > size ( ) ; + + i )
{
ServerList : : ServerInfo * info = & ( * list ) [ i ] ;
// Filter full servers
if ( ! ui_browserShowFull & & info - > clients > = info - > maxClients ) continue ;
// Filter empty servers
if ( ! ui_browserShowEmpty & & info - > clients < = 0 ) continue ;
// Filter hardcore servers
if ( ( ui_browserShowHardcore = = 0 & & info - > hardcore ) | | ( ui_browserShowHardcore = = 1 & & ! info - > hardcore ) ) continue ;
// Filter servers with password
if ( ( ui_browserShowPassword = = 0 & & info - > password ) | | ( ui_browserShowPassword = = 1 & & ! info - > password ) ) continue ;
// Don't show modded servers
if ( ( ui_browserMod = = 0 & & info - > mod . size ( ) ) | | ( ui_browserMod = = 1 & & ! info - > mod . size ( ) ) ) continue ;
// Filter by gametype
if ( ui_joinGametype > 0 & & ( ui_joinGametype - 1 ) < * Game : : gameTypeCount & & Game : : gameTypes [ ( ui_joinGametype - 1 ) ] . gameType ! = info - > gametype ) continue ;
ServerList : : VisibleList . push_back ( i ) ;
}
ServerList : : SortList ( ) ;
}
void ServerList : : Refresh ( UIScript : : Token )
{
Dvar : : Var ( " ui_serverSelected " ) . set ( false ) ;
2017-03-10 20:11:32 -05:00
//Localization::Set("MPUI_SERVERQUERIED", "Sent requests: 0/0");
2017-01-16 11:42:50 -05:00
// ServerList::OnlineList.clear();
// ServerList::OfflineList.clear();
// ServerList::FavouriteList.clear();
auto list = ServerList : : GetList ( ) ;
if ( list ) list - > clear ( ) ;
ServerList : : VisibleList . clear ( ) ;
2017-05-30 14:31:00 -04:00
{
std : : lock_guard < std : : recursive_mutex > _ ( ServerList : : RefreshContainer . mutex ) ;
ServerList : : RefreshContainer . servers . clear ( ) ;
ServerList : : RefreshContainer . sendCount = 0 ;
ServerList : : RefreshContainer . sentCount = 0 ;
}
2017-01-16 11:42:50 -05:00
if ( ServerList : : IsOfflineList ( ) )
{
Discovery : : Perform ( ) ;
}
else if ( ServerList : : IsOnlineList ( ) )
{
# ifdef USE_LEGACY_SERVER_LIST
ServerList : : RefreshContainer . awatingList = true ;
ServerList : : RefreshContainer . awaitTime = Game : : Sys_Milliseconds ( ) ;
int masterPort = Dvar : : Var ( " masterPort " ) . get < int > ( ) ;
const char * masterServerName = Dvar : : Var ( " masterServerName " ) . get < const char * > ( ) ;
ServerList : : RefreshContainer . host = Network : : Address ( Utils : : String : : VA ( " %s:%u " , masterServerName , masterPort ) ) ;
Logger : : Print ( " Sending serverlist request to master: %s:%u \n " , masterServerName , masterPort ) ;
Network : : SendCommand ( ServerList : : RefreshContainer . host , " getservers " , Utils : : String : : VA ( " IW4 %i full empty " , PROTOCOL ) ) ;
//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 " ) ;
2017-02-06 15:09:41 -05:00
Game : : ShowMessageBox ( " Favourites storage file is invalid! " , " Error " ) ;
2017-01-16 11:42:50 -05:00
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 )
{
2017-02-06 15:09:41 -05:00
Game : : ShowMessageBox ( " Server already marked as favourite. " , " Error " ) ;
2017-01-16 11:42:50 -05:00
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 ( ) ) ;
2017-02-06 15:09:41 -05:00
Game : : ShowMessageBox ( " Server added to favourites. " , " Success " ) ;
2017-01-16 11:42:50 -05:00
}
2017-01-18 17:35:33 -05:00
void ServerList : : RemoveFavourite ( std : : string server )
{
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 " ) ;
2017-02-06 15:09:41 -05:00
Game : : ShowMessageBox ( " Favourites storage file is invalid! " , " Error " ) ;
2017-01-18 17:35:33 -05:00
return ;
}
for ( auto & storedServer : object . array_items ( ) )
{
if ( storedServer . is_string ( ) & & storedServer . string_value ( ) ! = server )
{
servers . push_back ( storedServer . string_value ( ) ) ;
}
}
}
json11 : : Json data = json11 : : Json ( servers ) ;
Utils : : IO : : WriteFile ( " players/favourites.json " , data . dump ( ) ) ;
auto list = ServerList : : GetList ( ) ;
if ( list ) list - > clear ( ) ;
ServerList : : RefreshVisibleList ( UIScript : : Token ( ) ) ;
2017-02-06 15:09:41 -05:00
Game : : ShowMessageBox ( " Server removed from favourites. " , " Success " ) ;
2017-01-18 17:35:33 -05:00
}
2017-01-16 11:42:50 -05:00
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 " ) ;
2017-02-06 15:09:41 -05:00
Game : : ShowMessageBox ( " Favourites storage file is invalid! " , " Error " ) ;
2017-01-16 11:42:50 -05:00
return ;
}
auto servers = object . array_items ( ) ;
for ( unsigned int i = 0 ; i < servers . size ( ) ; + + i )
{
if ( ! servers [ i ] . is_string ( ) ) continue ;
2017-02-28 13:58:03 -05:00
ServerList : : InsertRequest ( servers [ i ] . string_value ( ) ) ;
2017-01-16 11:42:50 -05:00
}
}
}
2017-02-28 13:58:03 -05:00
void ServerList : : InsertRequest ( Network : : Address address )
2017-01-16 11:42:50 -05:00
{
2017-02-28 13:58:03 -05:00
std : : lock_guard < std : : recursive_mutex > _ ( ServerList : : RefreshContainer . mutex ) ;
2017-01-16 11:42:50 -05:00
ServerList : : Container : : ServerContainer container ;
container . sent = false ;
container . target = address ;
bool alreadyInserted = false ;
for ( auto & server : ServerList : : RefreshContainer . servers )
{
if ( server . target = = container . target )
{
alreadyInserted = true ;
break ;
}
}
if ( ! alreadyInserted )
{
ServerList : : RefreshContainer . servers . push_back ( container ) ;
auto list = ServerList : : GetList ( ) ;
if ( list )
{
2017-05-30 14:31:00 -04:00
for ( auto & server : * list )
2017-01-16 11:42:50 -05:00
{
if ( server . addr = = container . target )
{
- - ServerList : : RefreshContainer . sendCount ;
- - ServerList : : RefreshContainer . sentCount ;
break ;
}
}
}
+ + ServerList : : RefreshContainer . sendCount ;
}
}
void ServerList : : Insert ( Network : : Address address , Utils : : InfoString info )
{
2017-02-28 13:58:03 -05:00
std : : lock_guard < std : : recursive_mutex > _ ( ServerList : : RefreshContainer . mutex ) ;
2017-01-16 11:42:50 -05:00
for ( auto i = ServerList : : RefreshContainer . servers . begin ( ) ; i ! = ServerList : : RefreshContainer . servers . end ( ) ; )
{
// Our desired server
if ( i - > target = = address & & i - > sent )
{
// Challenge did not match
if ( i - > challenge ! = info . get ( " challenge " ) )
{
// 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 ;
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 ;
// Remove server from queue
i = ServerList : : RefreshContainer . servers . erase ( i ) ;
// 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 )
{
if ( j - > addr = = address )
{
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 ;
}
}
if ( info . get ( " gamename " ) = = " IW4 "
& & server . matchType
2017-02-15 04:15:35 -05:00
# if !defined(DEBUG) && defined(VERSION_FILTER)
2017-02-15 08:11:36 -05:00
& & ServerList : : CompareVersion ( server . shortversion , SHORTVERSION )
2017-01-16 11:42:50 -05:00
# endif
)
{
auto lList = ServerList : : GetList ( ) ;
if ( lList )
{
lList - > push_back ( server ) ;
ServerList : : RefreshVisibleList ( UIScript : : Token ( ) ) ;
}
}
break ;
}
else
{
+ + i ;
}
}
}
2017-02-15 08:11:36 -05:00
bool ServerList : : CompareVersion ( std : : string version1 , std : : string version2 )
{
std : : vector < std : : string > subVersions1 = Utils : : String : : Explode ( version1 , ' . ' ) ;
std : : vector < std : : string > subVersions2 = Utils : : String : : Explode ( version2 , ' . ' ) ;
while ( subVersions1 . size ( ) > = 3 ) subVersions1 . pop_back ( ) ;
while ( subVersions2 . size ( ) > = 3 ) subVersions2 . pop_back ( ) ;
if ( subVersions1 . size ( ) ! = subVersions2 . size ( ) ) return false ;
for ( unsigned int i = 0 ; i < subVersions1 . size ( ) ; + + i )
{
if ( atoi ( subVersions1 [ i ] . data ( ) ) ! = atoi ( subVersions2 [ i ] . data ( ) ) )
{
return false ;
}
}
return true ;
}
2017-01-16 11:42:50 -05:00
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 )
{
return ( ( info1 - > ping - info2 - > ping ) * ( ServerList : : SortAsc ? 1 : - 1 ) ) ;
}
else if ( ServerList : : SortKey = = ServerList : : Column : : Players )
{
return ( ( info1 - > clients - info2 - > clients ) * ( ServerList : : SortAsc ? 1 : - 1 ) ) ;
}
2017-01-21 16:14:23 -05:00
std : : string text1 = Colors : : Strip ( ServerList : : GetServerInfoText ( info1 , ServerList : : SortKey ) ) ;
std : : string text2 = Colors : : Strip ( ServerList : : GetServerInfoText ( info2 , ServerList : : SortKey ) ) ;
2017-01-16 11:42:50 -05:00
// 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 ( )
{
2017-05-30 14:31:00 -04:00
std : : lock_guard < std : : recursive_mutex > _ ( ServerList : : RefreshContainer . mutex ) ;
2017-01-16 11:42:50 -05:00
if ( ServerList : : RefreshContainer . awatingList )
{
// Check if we haven't got a response within 10 seconds
if ( Game : : Sys_Milliseconds ( ) - ServerList : : RefreshContainer . awaitTime > 5000 )
{
ServerList : : RefreshContainer . awatingList = false ;
Logger : : Print ( " We haven't received a response from the master within %d seconds! \n " , ( Game : : Sys_Milliseconds ( ) - ServerList : : RefreshContainer . awaitTime ) / 1000 ) ;
}
}
// Send requests to 10 servers each frame
int SendServers = 10 ;
for ( unsigned int i = 0 ; i < ServerList : : RefreshContainer . servers . size ( ) ; + + i )
{
ServerList : : Container : : ServerContainer * server = & ServerList : : RefreshContainer . servers [ i ] ;
if ( server - > sent ) continue ;
// Found server we can send a request to
server - > sent = true ;
SendServers - - ;
server - > sendTime = Game : : Sys_Milliseconds ( ) ;
2017-01-19 12:14:30 -05:00
server - > challenge = Utils : : Cryptography : : Rand : : GenerateChallenge ( ) ;
2017-01-16 11:42:50 -05:00
+ + ServerList : : RefreshContainer . sentCount ;
Network : : SendCommand ( server - > target , " getinfo " , server - > challenge ) ;
// Display in the menu, like in COD4
2017-02-26 09:27:02 -05:00
//Localization::Set("MPUI_SERVERQUERIED", Utils::String::VA("Sent requests: %d/%d", ServerList::RefreshContainer.sentCount, ServerList::RefreshContainer.sendCount));
2017-01-16 11:42:50 -05:00
if ( SendServers < = 0 ) break ;
}
2017-02-26 09:27:02 -05:00
ServerList : : UpdateVisibleInfo ( ) ;
2017-01-16 11:42:50 -05:00
}
void ServerList : : UpdateSource ( )
{
Dvar : : Var netSource ( " ui_netSource " ) ;
int source = netSource . get < int > ( ) ;
if ( + + source > netSource . get < Game : : dvar_t * > ( ) - > max . i )
{
source = 0 ;
}
netSource . set ( source ) ;
ServerList : : RefreshVisibleList ( UIScript : : Token ( ) ) ;
}
void ServerList : : UpdateGameType ( )
{
Dvar : : Var joinGametype ( " ui_joinGametype " ) ;
int gametype = joinGametype . get < int > ( ) ;
if ( + + gametype > * Game : : gameTypeCount )
{
gametype = 0 ;
}
joinGametype . set ( gametype ) ;
ServerList : : RefreshVisibleList ( UIScript : : Token ( ) ) ;
}
2017-02-26 09:27:02 -05:00
void ServerList : : UpdateVisibleInfo ( )
{
static int servers = 0 ;
static int players = 0 ;
auto list = ServerList : : GetList ( ) ;
if ( list )
{
int newSevers = list - > size ( ) ;
int newPlayers = 0 ;
for ( unsigned int i = 0 ; i < list - > size ( ) ; + + i )
{
newPlayers + = list - > at ( i ) . clients ;
}
if ( newSevers ! = servers | | newPlayers ! = players )
{
servers = newSevers ;
players = newPlayers ;
Localization : : Set ( " MPUI_SERVERQUERIED " , Utils : : String : : VA ( " Servers: %i \n Players: %i " , servers , players ) ) ;
}
}
}
2017-01-16 11:42:50 -05:00
ServerList : : ServerList ( )
{
ServerList : : OnlineList . clear ( ) ;
2017-02-26 09:27:02 -05:00
ServerList : : OfflineList . clear ( ) ;
ServerList : : FavouriteList . clear ( ) ;
2017-01-16 11:42:50 -05:00
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 " ) ;
} ) ;
2017-03-24 13:28:03 -04:00
// Fix ui_netsource dvar
Utils : : Hook : : Nop ( 0x4CDEEC , 5 ) ; // Don't reset the netsource when gametypes aren't loaded
Dvar : : Register < int > ( " ui_netSource " , 1 , 0 , 2 , Game : : DVAR_FLAG_SAVED , reinterpret_cast < const char * > ( 0x6D9F08 ) ) ;
2017-02-26 09:27:02 -05:00
//Localization::Set("MPUI_SERVERQUERIED", "Sent requests: 0/0");
Localization : : Set ( " MPUI_SERVERQUERIED " , " Servers: 0 \n Players: 0 " ) ;
2017-01-16 11:42:50 -05:00
Network : : Handle ( " getServersResponse " , [ ] ( Network : : Address address , std : : string data )
{
if ( ServerList : : RefreshContainer . host ! = address ) return ; // Only parse from host we sent to
ServerList : : RefreshContainer . awatingList = false ;
2017-02-28 13:58:03 -05:00
std : : lock_guard < std : : recursive_mutex > _ ( ServerList : : RefreshContainer . mutex ) ;
2017-01-16 11:42:50 -05:00
int offset = 0 ;
int count = ServerList : : RefreshContainer . servers . size ( ) ;
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 ;
serverAddr . setIP ( entry [ i ] . ip ) ;
serverAddr . setPort ( ntohs ( entry [ i ] . port ) ) ;
serverAddr . setType ( Game : : NA_IP ) ;
2017-02-28 13:58:03 -05:00
ServerList : : InsertRequest ( serverAddr ) ;
2017-01-16 11:42:50 -05:00
}
Logger : : Print ( " Parsed %d servers from master \n " , ServerList : : RefreshContainer . servers . size ( ) - count ) ;
} ) ;
// Set default masterServerName + port and save it
# ifdef USE_LEGACY_SERVER_LIST
2017-03-24 15:31:59 -04:00
Utils : : Hook : : Set < char * > ( 0x60AD92 , " 127.0.0.1 " ) ;
2017-01-16 11:42:50 -05:00
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 " , [ ] ( UIScript : : Token )
{
ServerList : : ServerInfo * info = ServerList : : GetServer ( ServerList : : CurrentServer ) ;
if ( info )
{
Party : : Connect ( info - > addr ) ;
}
} ) ;
UIScript : : Add ( " ServerSort " , [ ] ( UIScript : : Token token )
{
int key = token . get < int > ( ) ;
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 " , [ ] ( UIScript : : Token )
{
ServerList : : ServerInfo * info = ServerList : : GetCurrentServer ( ) ;
if ( info )
{
ServerList : : StoreFavourite ( info - > addr . getString ( ) ) ;
}
} ) ;
UIScript : : Add ( " CreateFavorite " , [ ] ( UIScript : : Token )
{
ServerList : : StoreFavourite ( Dvar : : Var ( " ui_favoriteAddress " ) . get < std : : string > ( ) ) ;
} ) ;
UIScript : : Add ( " CreateCurrentServerFavorite " , [ ] ( UIScript : : Token )
{
2017-01-18 17:35:33 -05:00
if ( Game : : CL_IsCgameInitialized ( ) )
2017-01-16 11:42:50 -05:00
{
std : : string addressText = Network : : Address ( * Game : : connectedHost ) . getString ( ) ;
if ( addressText ! = " 0.0.0.0:0 " & & addressText ! = " loopback " )
{
ServerList : : StoreFavourite ( addressText ) ;
}
}
} ) ;
2017-01-18 17:35:33 -05:00
UIScript : : Add ( " DeleteFavorite " , [ ] ( UIScript : : Token )
{
ServerList : : ServerInfo * info = ServerList : : GetCurrentServer ( ) ;
if ( info )
{
ServerList : : RemoveFavourite ( info - > addr . getString ( ) ) ;
} ;
} ) ;
2017-01-16 11:42:50 -05:00
2017-01-28 07:31:43 -05:00
Command : : Add ( " playerCount " , [ ] ( Command : : Params * )
{
int count = 0 ;
for ( auto server : ServerList : : OnlineList )
{
count + = server . clients ;
}
Logger : : Print ( " There are %d players playing. \n " , count ) ;
} ) ;
2017-01-16 11:42:50 -05:00
// Add required ownerDraws
UIScript : : AddOwnerDraw ( 220 , ServerList : : UpdateSource ) ;
UIScript : : AddOwnerDraw ( 253 , ServerList : : UpdateGameType ) ;
// Add frame callback
Renderer : : OnFrame ( ServerList : : Frame ) ;
// This is placed here in case the anticheat has been disabled!
2017-01-26 14:41:39 -05:00
# if !defined(DEBUG) && !defined(DISABLE_ANTICHEAT) && defined(PROCTECT_PROCESS)
2017-01-16 11:42:50 -05:00
Renderer : : OnFrame ( AntiCheat : : ReadIntegrityCheck ) ;
# endif
}
ServerList : : ~ ServerList ( )
{
ServerList : : OnlineList . clear ( ) ;
ServerList : : OfflineList . clear ( ) ;
ServerList : : FavouriteList . clear ( ) ;
ServerList : : VisibleList . clear ( ) ;
2017-05-30 14:31:00 -04:00
{
std : : lock_guard < std : : recursive_mutex > _ ( ServerList : : RefreshContainer . mutex ) ;
ServerList : : RefreshContainer . awatingList = false ;
ServerList : : RefreshContainer . servers . clear ( ) ;
}
2017-01-16 11:42:50 -05:00
}
}