2010-11-20 10:37:14 +00:00
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
2021-04-17 14:05:24 +00:00
# include "serverbrowser.h"
# include "serverbrowser_http.h"
# include "serverbrowser_ping_cache.h"
2018-07-11 20:46:04 +00:00
# include <algorithm>
2022-02-14 23:22:52 +00:00
# include <climits>
2022-05-23 18:16:18 +00:00
# include <unordered_set>
2022-01-02 03:27:29 +00:00
# include <vector>
2010-05-29 07:25:38 +00:00
2019-04-06 00:46:56 +00:00
# include <base/hash_ctxt.h>
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
# include <base/log.h>
2010-05-29 07:25:38 +00:00
# include <base/system.h>
2011-03-23 12:06:35 +00:00
2010-05-29 07:25:38 +00:00
# include <engine/shared/config.h>
2020-01-01 19:07:04 +00:00
# include <engine/shared/json.h>
Add HTTP masterserver registering and HTTP masterserver
Registering
-----------
The idea is that game servers push their server info to the
masterservers every 15 seconds or when the server info changes, but not
more than once per second.
The game servers do not support the old registering protocol anymore,
the backward compatibility is handled by the masterserver.
The register call is a HTTP POST to a URL like
`https://master1.ddnet.tw/ddnet/15/register` and looks like this:
```json
POST /ddnet/15/register HTTP/1.1
Address: tw-0.6+udp://connecting-address.invalid:8303
Secret: 81fa3955-6f83-4290-818d-31c0906b1118
Challenge-Secret: 81fa3955-6f83-4290-818d-31c0906b1118:tw0.6/ipv6
Info-Serial: 0
{
"max_clients": 64,
"max_players": 64,
"passworded": false,
"game_type": "TestDDraceNetwork",
"name": "My DDNet server",
"map": {
"name": "dm1",
"sha256": "0b0c481d77519c32fbe85624ef16ec0fa9991aec7367ad538bd280f28d8c26cf",
"size": 5805
},
"version": "0.6.4, 16.0.3",
"clients": []
}
```
The `Address` header declares that the server wants to register itself as
a `tw-0.6+udp` server, i.e. a server speaking a Teeworlds-0.6-compatible
protocol.
The free-form `Secret` header is used as a server identity, the server
list will be deduplicated via this secret.
The free-form `Challenge-Secret` is sent back via UDP for a port forward
check. This might have security implications as the masterserver can be
asked to send a UDP packet containing some user-controlled bytes. This
is somewhat mitigated by the fact that it can only go to an
attacker-controlled IP address.
The `Info-Serial` header is an integer field that should increase each
time the server info (in the body) changes. The masterserver uses that
field to ensure that it doesn't use old server infos.
The body is a free-form JSON object set by the game server. It should
contain certain keys in the correct form to be accepted by clients. The
body is optional if the masterserver already confirmed the reception of
the info with the given `Info-Serial`.
Not shown in this payload is the `Connless-Token` header that is used
for Teeworlds 0.7 style communication.
Also not shown is the `Challenge-Token` that should be included once the
server receives the challenge token via UDP.
The masterserver responds with a `200 OK` with a body like this:
```
{"status":"success"}
```
The `status` field can be `success` if the server was successfully
registered on the masterserver, `need_challenge` if the masterserver
wants the correct `Challenge-Token` header before the register process
is successful, `need_info` if the server sent an empty body but the
masterserver doesn't actually know the server info.
It can also be `error` if the request was malformed, only in this case
an HTTP status code except `200 OK` is sent.
Synchronization
---------------
The masterserver keeps state and outputs JSON files every second.
```json
{
"servers": [
{
"addresses": [
"tw-0.6+udp://127.0.0.1:8303",
"tw-0.6+udp://[::1]:8303"
],
"info_serial": 0,
"info": {
"max_clients": 64,
"max_players": 64,
"passworded": false,
"game_type": "TestDDraceNetwork",
"name": "My DDNet server",
"map": {
"name": "dm1",
"sha256": "0b0c481d77519c32fbe85624ef16ec0fa9991aec7367ad538bd280f28d8c26cf",
"size": 5805
},
"version": "0.6.4, 16.0.3",
"clients": []
}
}
]
}
```
`servers.json` (or configured by `--out`) is a server list that is
compatible with DDNet 15.5+ clients. It is a JSON object containing a
single key `servers` with a list of game servers. Each game server is
represented by a JSON object with an `addresses` key containing a list
of all known addresses of the server and an `info` key containing the
free-form server info sent by the game server. The free-form `info` JSON
object re-encoded by the master server and thus canonicalized and
stripped of any whitespace characters outside strings.
```json
{
"kind": "mastersrv",
"now": 1816002,
"secrets": {
"tw-0.6+udp://127.0.0.1:8303": {
"ping_time": 1811999,
"secret": "42d8f991-f2fa-46e5-a9ae-ebcc93846feb"
},
"tw-0.6+udp://[::1]:8303": {
"ping_time": 1811999,
"secret": "42d8f991-f2fa-46e5-a9ae-ebcc93846feb"
}
},
"servers": {
"42d8f991-f2fa-46e5-a9ae-ebcc93846feb": {
"info_serial": 0,
"info": {
"max_clients": 64,
"max_players": 64,
"passworded": false,
"game_type": "TestDDraceNetwork",
"name": "My DDNet server",
"map": {
"name": "dm1",
"sha256": "0b0c481d77519c32fbe85624ef16ec0fa9991aec7367ad538bd280f28d8c26cf",
"size": 5805
},
"version": "0.6.4, 16.0.3",
"clients": []
}
}
}
}
```
`--write-dump` outputs a JSON file compatible with `--read-dump-dir`,
this can be used to synchronize servers across different masterservers.
`--read-dump-dir` is also used to ingest servers from the backward
compatibility layer that pings each server for their server info using
the old protocol.
The `kind` field describe that this is `mastersrv` output and not from a
`backcompat`. This is used for prioritizing `mastersrv` information over
`backcompat` information.
The `now` field contains an integer describing the current time in
milliseconds relative an unspecified epoch that is fixed for each JSON
file. This is done instead of using the current time as the epoch for
better compression of non-changing data.
`secrets` is a map from each server address and to a JSON object
containing the last ping time (`ping_time`) in milliseconds relative to
the same epoch as before, and the server secret (`secret`) that is used
to unify server infos from different addresses of the same logical
server.
`servers` is a map from the aforementioned `secret`s to the
corresponding `info_serial` and `info`.
```json
[
"tw-0.6+udp://127.0.0.1:8303",
"tw-0.6+udp://[::1]:8303"
]
```
`--write-addresses` outputs a JSON file containing all addresses
corresponding to servers that are registered to HTTP masterservers. It
does not contain the servers that are obtained via backward
compatibility measures.
This file can be used by an old-style masterserver to also list
new-style servers without the game servers having to register there.
An implementation of this can be found at
https://github.com/heinrich5991/teeworlds/tree/mastersrv_6_backcompat
for Teeworlds 0.5/0.6 masterservers and at
https://github.com/heinrich5991/teeworlds/tree/mastersrv_7_backcompat
for Teeworlds 0.7 masterservers.
All these JSON files can be sent over the network in an efficient way
using https://github.com/heinrich5991/twmaster-collect. It establishes a
zstd-compressed TCP connection authenticated by a string token that is
sent in plain-text. It watches the specified file and transmits it every
time it changes. Due to the zstd-compression, the data sent over the
network is similar to the size of a diff.
Implementation
--------------
The masterserver implementation was done in Rust.
The current gameserver register implementation doesn't support more than
one masterserver for registering.
2022-05-19 20:03:17 +00:00
# include <engine/shared/masterserver.h>
2011-03-23 12:06:35 +00:00
# include <engine/shared/network.h>
# include <engine/shared/protocol.h>
2018-07-11 20:46:04 +00:00
# include <engine/shared/serverinfo.h>
2010-05-29 07:25:38 +00:00
2011-03-23 12:06:35 +00:00
# include <engine/console.h>
2018-07-11 20:46:04 +00:00
# include <engine/engine.h>
2022-05-23 18:16:18 +00:00
# include <engine/favorites.h>
2011-03-23 12:06:35 +00:00
# include <engine/friends.h>
2014-09-13 14:36:25 +00:00
# include <engine/storage.h>
2010-05-29 07:25:38 +00:00
2022-12-05 21:16:01 +00:00
class CSortWrap
2010-05-29 07:25:38 +00:00
{
typedef bool ( CServerBrowser : : * SortFunc ) ( int , int ) const ;
SortFunc m_pfnSort ;
CServerBrowser * m_pThis ;
2020-09-26 19:41:58 +00:00
2010-05-29 07:25:38 +00:00
public :
2022-12-05 21:16:01 +00:00
CSortWrap ( CServerBrowser * pServer , SortFunc Func ) :
2022-06-30 22:36:32 +00:00
m_pfnSort ( Func ) , m_pThis ( pServer ) { }
2011-11-29 21:34:47 +00:00
bool operator ( ) ( int a , int b ) { return ( g_Config . m_BrSortOrder ? ( m_pThis - > * m_pfnSort ) ( b , a ) : ( m_pThis - > * m_pfnSort ) ( a , b ) ) ; }
2010-05-29 07:25:38 +00:00
} ;
2022-12-23 22:23:44 +00:00
bool matchesPart ( const char * a , const char * b )
{
return str_utf8_find_nocase ( a , b ) ! = nullptr ;
}
bool matchesExactly ( const char * a , const char * b )
{
return str_comp ( a , & b [ 1 ] ) = = 0 ;
}
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
CServerBrowser : : CServerBrowser ( ) :
m_CommunitiesFilter ( g_Config . m_BrFilterExcludeCommunities , sizeof ( g_Config . m_BrFilterExcludeCommunities ) ) ,
m_CountriesFilter ( g_Config . m_BrFilterExcludeCountries , sizeof ( g_Config . m_BrFilterExcludeCountries ) ) ,
m_TypesFilter ( g_Config . m_BrFilterExcludeTypes , sizeof ( g_Config . m_BrFilterExcludeTypes ) )
2010-05-29 07:25:38 +00:00
{
2022-12-05 21:26:56 +00:00
m_ppServerlist = nullptr ;
m_pSortedServerlist = nullptr ;
2010-05-29 07:25:38 +00:00
2022-12-05 21:26:56 +00:00
m_pFirstReqServer = nullptr ; // request list
m_pLastReqServer = nullptr ;
2010-05-29 07:25:38 +00:00
m_NumRequests = 0 ;
2022-12-05 22:00:35 +00:00
m_NeedResort = false ;
2023-09-30 10:20:04 +00:00
m_Sorthash = 0 ;
2022-12-05 22:00:35 +00:00
2010-05-29 07:25:38 +00:00
m_NumSortedServers = 0 ;
m_NumSortedServersCapacity = 0 ;
2023-10-01 18:17:55 +00:00
m_NumSortedPlayers = 0 ;
2010-05-29 07:25:38 +00:00
m_NumServers = 0 ;
m_NumServerCapacity = 0 ;
m_ServerlistType = 0 ;
m_BroadcastTime = 0 ;
2017-10-14 19:58:23 +00:00
secure_random_fill ( m_aTokenSeed , sizeof ( m_aTokenSeed ) ) ;
2017-08-30 19:34:01 +00:00
2022-12-05 21:26:56 +00:00
m_pDDNetInfo = nullptr ;
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
m_DDNetInfoUpdateTime = 0 ;
2017-09-03 15:36:51 +00:00
}
CServerBrowser : : ~ CServerBrowser ( )
{
2022-03-01 22:19:49 +00:00
free ( m_ppServerlist ) ;
free ( m_pSortedServerlist ) ;
json_value_free ( m_pDDNetInfo ) ;
2018-07-11 20:46:04 +00:00
delete m_pHttp ;
m_pHttp = nullptr ;
2021-04-17 14:05:24 +00:00
delete m_pPingCache ;
m_pPingCache = nullptr ;
2010-05-29 07:25:38 +00:00
}
void CServerBrowser : : SetBaseInfo ( class CNetClient * pClient , const char * pNetVersion )
{
m_pNetClient = pClient ;
2022-07-09 16:14:56 +00:00
str_copy ( m_aNetVersion , pNetVersion ) ;
2010-08-17 22:06:00 +00:00
m_pConsole = Kernel ( ) - > RequestInterface < IConsole > ( ) ;
2023-09-30 10:26:21 +00:00
m_pConfigManager = Kernel ( ) - > RequestInterface < IConfigManager > ( ) ;
2018-07-11 20:46:04 +00:00
m_pEngine = Kernel ( ) - > RequestInterface < IEngine > ( ) ;
2022-05-23 18:16:18 +00:00
m_pFavorites = Kernel ( ) - > RequestInterface < IFavorites > ( ) ;
2011-03-23 12:06:35 +00:00
m_pFriends = Kernel ( ) - > RequestInterface < IFriends > ( ) ;
2021-04-17 14:05:24 +00:00
m_pStorage = Kernel ( ) - > RequestInterface < IStorage > ( ) ;
m_pPingCache = CreateServerBrowserPingCache ( m_pConsole , m_pStorage ) ;
2021-04-21 14:54:42 +00:00
RegisterCommands ( ) ;
}
2021-06-02 22:27:00 +00:00
void CServerBrowser : : OnInit ( )
{
m_pHttp = CreateServerBrowserHttp ( m_pEngine , m_pConsole , m_pStorage , g_Config . m_BrCachedBestServerinfoUrl ) ;
}
2021-04-21 14:54:42 +00:00
void CServerBrowser : : RegisterCommands ( )
{
m_pConsole - > Register ( " leak_ip_address_to_all_servers " , " " , CFGFLAG_CLIENT , Con_LeakIpAddress , this , " Leaks your IP address to all servers by pinging each of them, also acquiring the latency in the process " ) ;
}
void CServerBrowser : : Con_LeakIpAddress ( IConsole : : IResult * pResult , void * pUserData )
{
CServerBrowser * pThis = ( CServerBrowser * ) pUserData ;
2022-05-23 18:16:18 +00:00
// We only consider the first address of every server.
2022-06-15 17:34:41 +00:00
std : : vector < int > vSortedServers ;
2021-04-21 14:54:42 +00:00
// Sort servers by IP address, ignoring port.
class CAddrComparer
{
public :
CServerBrowser * m_pThis ;
bool operator ( ) ( int i , int j )
{
2022-05-23 18:16:18 +00:00
NETADDR Addr1 = m_pThis - > m_ppServerlist [ i ] - > m_Info . m_aAddresses [ 0 ] ;
NETADDR Addr2 = m_pThis - > m_ppServerlist [ j ] - > m_Info . m_aAddresses [ 0 ] ;
2021-04-21 14:54:42 +00:00
Addr1 . port = 0 ;
Addr2 . port = 0 ;
return net_addr_comp ( & Addr1 , & Addr2 ) < 0 ;
}
} ;
2022-06-15 17:34:41 +00:00
vSortedServers . reserve ( pThis - > m_NumServers ) ;
2021-04-21 14:54:42 +00:00
for ( int i = 0 ; i < pThis - > m_NumServers ; i + + )
{
2022-06-15 17:34:41 +00:00
vSortedServers . push_back ( i ) ;
2021-04-21 14:54:42 +00:00
}
2022-06-15 17:34:41 +00:00
std : : sort ( vSortedServers . begin ( ) , vSortedServers . end ( ) , CAddrComparer { pThis } ) ;
2021-04-21 14:54:42 +00:00
// Group the servers into those with same IP address (but differing
// port).
NETADDR Addr ;
int Start = - 1 ;
2022-06-15 17:34:41 +00:00
for ( int i = 0 ; i < = ( int ) vSortedServers . size ( ) ; i + + )
2021-04-21 14:54:42 +00:00
{
NETADDR NextAddr ;
2022-06-15 17:34:41 +00:00
if ( i < ( int ) vSortedServers . size ( ) )
2021-04-21 14:54:42 +00:00
{
2022-05-23 18:16:18 +00:00
NextAddr = pThis - > m_ppServerlist [ vSortedServers [ i ] ] - > m_Info . m_aAddresses [ 0 ] ;
2021-04-21 14:54:42 +00:00
NextAddr . port = 0 ;
}
2022-06-15 17:34:41 +00:00
bool New = Start = = - 1 | | i = = ( int ) vSortedServers . size ( ) | | net_addr_comp ( & Addr , & NextAddr ) ! = 0 ;
2021-04-21 14:54:42 +00:00
if ( Start ! = - 1 & & New )
{
int Chosen = Start + secure_rand_below ( i - Start ) ;
2022-06-15 17:34:41 +00:00
CServerEntry * pChosen = pThis - > m_ppServerlist [ vSortedServers [ Chosen ] ] ;
2021-04-21 14:54:42 +00:00
pChosen - > m_RequestIgnoreInfo = true ;
pThis - > QueueRequest ( pChosen ) ;
char aAddr [ NETADDR_MAXSTRSIZE ] ;
2022-05-23 18:16:18 +00:00
net_addr_str ( & pChosen - > m_Info . m_aAddresses [ 0 ] , aAddr , sizeof ( aAddr ) , true ) ;
2022-12-05 21:43:04 +00:00
dbg_msg ( " serverbrowser " , " queuing ping request for %s " , aAddr ) ;
2021-04-21 14:54:42 +00:00
}
2022-06-15 17:34:41 +00:00
if ( i < ( int ) vSortedServers . size ( ) & & New )
2021-04-21 14:54:42 +00:00
{
Start = i ;
Addr = NextAddr ;
}
}
2010-05-29 07:25:38 +00:00
}
2023-09-30 10:24:12 +00:00
int CServerBrowser : : Players ( const CServerInfo & Item ) const
{
return g_Config . m_BrFilterSpectators ? Item . m_NumPlayers : Item . m_NumClients ;
}
int CServerBrowser : : Max ( const CServerInfo & Item ) const
{
return g_Config . m_BrFilterSpectators ? Item . m_MaxPlayers : Item . m_MaxClients ;
}
2010-05-29 07:25:38 +00:00
const CServerInfo * CServerBrowser : : SortedGet ( int Index ) const
{
if ( Index < 0 | | Index > = m_NumSortedServers )
2022-12-05 21:26:56 +00:00
return nullptr ;
2010-05-29 07:25:38 +00:00
return & m_ppServerlist [ m_pSortedServerlist [ Index ] ] - > m_Info ;
}
2017-10-14 19:58:23 +00:00
int CServerBrowser : : GenerateToken ( const NETADDR & Addr ) const
{
2019-04-06 00:47:00 +00:00
SHA256_CTX Sha256 ;
sha256_init ( & Sha256 ) ;
sha256_update ( & Sha256 , m_aTokenSeed , sizeof ( m_aTokenSeed ) ) ;
sha256_update ( & Sha256 , ( unsigned char * ) & Addr , sizeof ( Addr ) ) ;
SHA256_DIGEST Digest = sha256_finish ( & Sha256 ) ;
2019-04-06 00:46:56 +00:00
return ( Digest . data [ 0 ] < < 16 ) | ( Digest . data [ 1 ] < < 8 ) | Digest . data [ 2 ] ;
2017-10-14 19:58:23 +00:00
}
int CServerBrowser : : GetBasicToken ( int Token )
{
return Token & 0xff ;
}
int CServerBrowser : : GetExtraToken ( int Token )
{
return Token > > 8 ;
}
2010-05-29 07:25:38 +00:00
bool CServerBrowser : : SortCompareName ( int Index1 , int Index2 ) const
{
2022-06-30 22:36:32 +00:00
CServerEntry * pIndex1 = m_ppServerlist [ Index1 ] ;
CServerEntry * pIndex2 = m_ppServerlist [ Index2 ] ;
2010-08-12 17:29:59 +00:00
// make sure empty entries are listed last
2022-06-30 22:36:32 +00:00
return ( pIndex1 - > m_GotInfo & & pIndex2 - > m_GotInfo ) | | ( ! pIndex1 - > m_GotInfo & & ! pIndex2 - > m_GotInfo ) ? str_comp ( pIndex1 - > m_Info . m_aName , pIndex2 - > m_Info . m_aName ) < 0 :
pIndex1 - > m_GotInfo ! = 0 ;
2010-05-29 07:25:38 +00:00
}
bool CServerBrowser : : SortCompareMap ( int Index1 , int Index2 ) const
{
2022-06-30 22:36:32 +00:00
CServerEntry * pIndex1 = m_ppServerlist [ Index1 ] ;
CServerEntry * pIndex2 = m_ppServerlist [ Index2 ] ;
return str_comp ( pIndex1 - > m_Info . m_aMap , pIndex2 - > m_Info . m_aMap ) < 0 ;
2010-05-29 07:25:38 +00:00
}
bool CServerBrowser : : SortComparePing ( int Index1 , int Index2 ) const
{
2022-06-30 22:36:32 +00:00
CServerEntry * pIndex1 = m_ppServerlist [ Index1 ] ;
CServerEntry * pIndex2 = m_ppServerlist [ Index2 ] ;
return pIndex1 - > m_Info . m_Latency < pIndex2 - > m_Info . m_Latency ;
2010-05-29 07:25:38 +00:00
}
bool CServerBrowser : : SortCompareGametype ( int Index1 , int Index2 ) const
{
2022-06-30 22:36:32 +00:00
CServerEntry * pIndex1 = m_ppServerlist [ Index1 ] ;
CServerEntry * pIndex2 = m_ppServerlist [ Index2 ] ;
return str_comp ( pIndex1 - > m_Info . m_aGameType , pIndex2 - > m_Info . m_aGameType ) < 0 ;
2010-05-29 07:25:38 +00:00
}
bool CServerBrowser : : SortCompareNumPlayers ( int Index1 , int Index2 ) const
{
2022-06-30 22:36:32 +00:00
CServerEntry * pIndex1 = m_ppServerlist [ Index1 ] ;
CServerEntry * pIndex2 = m_ppServerlist [ Index2 ] ;
return pIndex1 - > m_Info . m_NumFilteredPlayers > pIndex2 - > m_Info . m_NumFilteredPlayers ;
2010-05-29 07:25:38 +00:00
}
2011-03-20 14:33:49 +00:00
bool CServerBrowser : : SortCompareNumClients ( int Index1 , int Index2 ) const
{
2022-06-30 22:36:32 +00:00
CServerEntry * pIndex1 = m_ppServerlist [ Index1 ] ;
CServerEntry * pIndex2 = m_ppServerlist [ Index2 ] ;
return pIndex1 - > m_Info . m_NumClients > pIndex2 - > m_Info . m_NumClients ;
2011-03-20 14:33:49 +00:00
}
2020-08-24 21:23:37 +00:00
bool CServerBrowser : : SortCompareNumPlayersAndPing ( int Index1 , int Index2 ) const
{
2022-06-30 22:36:32 +00:00
CServerEntry * pIndex1 = m_ppServerlist [ Index1 ] ;
CServerEntry * pIndex2 = m_ppServerlist [ Index2 ] ;
2020-08-24 21:23:37 +00:00
2022-06-30 22:36:32 +00:00
if ( pIndex1 - > m_Info . m_NumFilteredPlayers = = pIndex2 - > m_Info . m_NumFilteredPlayers )
return pIndex1 - > m_Info . m_Latency > pIndex2 - > m_Info . m_Latency ;
else if ( pIndex1 - > m_Info . m_NumFilteredPlayers = = 0 | | pIndex2 - > m_Info . m_NumFilteredPlayers = = 0 | | pIndex1 - > m_Info . m_Latency / 100 = = pIndex2 - > m_Info . m_Latency / 100 )
return pIndex1 - > m_Info . m_NumFilteredPlayers < pIndex2 - > m_Info . m_NumFilteredPlayers ;
2020-08-24 21:23:37 +00:00
else
2022-06-30 22:36:32 +00:00
return pIndex1 - > m_Info . m_Latency > pIndex2 - > m_Info . m_Latency ;
2020-08-24 21:23:37 +00:00
}
2010-05-29 07:25:38 +00:00
void CServerBrowser : : Filter ( )
{
m_NumSortedServers = 0 ;
2023-10-01 18:17:55 +00:00
m_NumSortedPlayers = 0 ;
2010-05-29 07:25:38 +00:00
// allocate the sorted list
if ( m_NumSortedServersCapacity < m_NumServers )
{
2022-03-01 22:19:49 +00:00
free ( m_pSortedServerlist ) ;
2010-05-29 07:25:38 +00:00
m_NumSortedServersCapacity = m_NumServers ;
2018-04-09 09:56:39 +00:00
m_pSortedServerlist = ( int * ) calloc ( m_NumSortedServersCapacity , sizeof ( int ) ) ;
2010-05-29 07:25:38 +00:00
}
// filter the servers
2022-12-05 21:14:14 +00:00
for ( int i = 0 ; i < m_NumServers ; i + + )
2010-05-29 07:25:38 +00:00
{
2023-09-30 10:41:01 +00:00
CServerInfo & Info = m_ppServerlist [ i ] - > m_Info ;
2022-12-05 21:30:09 +00:00
bool Filtered = false ;
2010-05-29 07:25:38 +00:00
2023-09-30 10:41:01 +00:00
if ( g_Config . m_BrFilterEmpty & & Info . m_NumFilteredPlayers = = 0 )
2022-12-05 21:30:09 +00:00
Filtered = true ;
2023-09-30 10:41:01 +00:00
else if ( g_Config . m_BrFilterFull & & Players ( Info ) = = Max ( Info ) )
2022-12-05 21:30:09 +00:00
Filtered = true ;
2023-09-30 10:41:01 +00:00
else if ( g_Config . m_BrFilterPw & & Info . m_Flags & SERVER_FLAG_PASSWORD )
2022-12-05 21:30:09 +00:00
Filtered = true ;
2023-09-30 10:41:01 +00:00
else if ( g_Config . m_BrFilterServerAddress [ 0 ] & & ! str_find_nocase ( Info . m_aAddress , g_Config . m_BrFilterServerAddress ) )
2022-12-05 21:30:09 +00:00
Filtered = true ;
2023-09-30 10:41:01 +00:00
else if ( g_Config . m_BrFilterGametypeStrict & & g_Config . m_BrFilterGametype [ 0 ] & & str_comp_nocase ( Info . m_aGameType , g_Config . m_BrFilterGametype ) )
2022-12-05 21:30:09 +00:00
Filtered = true ;
2023-09-30 10:41:01 +00:00
else if ( ! g_Config . m_BrFilterGametypeStrict & & g_Config . m_BrFilterGametype [ 0 ] & & ! str_utf8_find_nocase ( Info . m_aGameType , g_Config . m_BrFilterGametype ) )
2022-12-05 21:30:09 +00:00
Filtered = true ;
2023-09-30 10:41:01 +00:00
else if ( g_Config . m_BrFilterUnfinishedMap & & Info . m_HasRank = = CServerInfo : : RANK_RANKED )
2022-12-05 21:30:09 +00:00
Filtered = true ;
2011-06-29 20:27:32 +00:00
else
2011-06-26 15:10:13 +00:00
{
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
if ( m_ServerlistType = = IServerBrowser : : TYPE_INTERNET | | m_ServerlistType = = IServerBrowser : : TYPE_FAVORITES )
{
Filtered = CommunitiesFilter ( ) . Filtered ( Info . m_aCommunityId ) ;
Filtered = Filtered | | CountriesFilter ( ) . Filtered ( Info . m_aCommunityCountry ) ;
Filtered = Filtered | | TypesFilter ( ) . Filtered ( Info . m_aCommunityType ) ;
}
if ( ! Filtered & & g_Config . m_BrFilterCountry )
2011-06-26 15:10:13 +00:00
{
2022-12-05 21:30:09 +00:00
Filtered = true ;
2011-06-29 20:27:32 +00:00
// match against player country
2023-09-30 10:41:01 +00:00
for ( int p = 0 ; p < minimum ( Info . m_NumClients , ( int ) MAX_CLIENTS ) ; p + + )
2011-06-29 20:27:32 +00:00
{
2023-09-30 10:41:01 +00:00
if ( Info . m_aClients [ p ] . m_Country = = g_Config . m_BrFilterCountryIndex )
2011-06-29 20:27:32 +00:00
{
2022-12-05 21:30:09 +00:00
Filtered = false ;
2011-06-29 20:27:32 +00:00
break ;
}
}
2011-06-26 15:10:13 +00:00
}
2011-03-18 18:03:13 +00:00
2022-09-25 12:37:24 +00:00
if ( ! Filtered & & g_Config . m_BrFilterString [ 0 ] ! = ' \0 ' )
2011-06-26 15:10:13 +00:00
{
2023-09-30 10:41:01 +00:00
Info . m_QuickSearchHit = 0 ;
2011-06-29 20:27:32 +00:00
2022-09-25 12:37:24 +00:00
const char * pStr = g_Config . m_BrFilterString ;
char aFilterStr [ sizeof ( g_Config . m_BrFilterString ) ] ;
while ( ( pStr = str_next_token ( pStr , IServerBrowser : : SEARCH_EXCLUDE_TOKEN , aFilterStr , sizeof ( aFilterStr ) ) ) )
2011-03-23 12:06:35 +00:00
{
2022-09-25 12:37:24 +00:00
if ( aFilterStr [ 0 ] = = ' \0 ' )
{
continue ;
}
2022-12-23 22:23:44 +00:00
auto MatchesFn = matchesPart ;
const int FilterLen = str_length ( aFilterStr ) ;
if ( aFilterStr [ 0 ] = = ' " ' & & aFilterStr [ FilterLen - 1 ] = = ' " ' )
{
aFilterStr [ FilterLen - 1 ] = ' \0 ' ;
MatchesFn = matchesExactly ;
}
2016-08-02 20:16:02 +00:00
2022-09-25 12:37:24 +00:00
// match against server name
2023-09-30 10:41:01 +00:00
if ( MatchesFn ( Info . m_aName , aFilterStr ) )
2016-08-02 20:16:02 +00:00
{
2023-09-30 10:41:01 +00:00
Info . m_QuickSearchHit | = IServerBrowser : : QUICK_SERVERNAME ;
2016-08-02 20:16:02 +00:00
}
2011-06-29 20:27:32 +00:00
2022-09-25 12:37:24 +00:00
// match against players
2023-09-30 10:41:01 +00:00
for ( int p = 0 ; p < minimum ( Info . m_NumClients , ( int ) MAX_CLIENTS ) ; p + + )
2022-09-25 12:37:24 +00:00
{
2023-09-30 10:41:01 +00:00
if ( MatchesFn ( Info . m_aClients [ p ] . m_aName , aFilterStr ) | |
MatchesFn ( Info . m_aClients [ p ] . m_aClan , aFilterStr ) )
2022-09-25 12:37:24 +00:00
{
2022-12-23 14:59:44 +00:00
if ( g_Config . m_BrFilterConnectingPlayers & &
2023-09-30 10:41:01 +00:00
str_comp ( Info . m_aClients [ p ] . m_aName , " (connecting) " ) = = 0 & &
Info . m_aClients [ p ] . m_aClan [ 0 ] = = ' \0 ' )
2022-12-23 14:59:44 +00:00
{
continue ;
}
2023-09-30 10:41:01 +00:00
Info . m_QuickSearchHit | = IServerBrowser : : QUICK_PLAYER ;
2022-09-25 12:37:24 +00:00
break ;
}
}
// match against map
2023-09-30 10:41:01 +00:00
if ( MatchesFn ( Info . m_aMap , aFilterStr ) )
2022-09-25 12:37:24 +00:00
{
2023-09-30 10:41:01 +00:00
Info . m_QuickSearchHit | = IServerBrowser : : QUICK_MAPNAME ;
2022-09-25 12:37:24 +00:00
}
2016-08-02 20:16:02 +00:00
}
2016-08-06 22:52:00 +00:00
2023-09-30 10:41:01 +00:00
if ( ! Info . m_QuickSearchHit )
2022-12-05 21:30:09 +00:00
Filtered = true ;
2011-06-29 20:27:32 +00:00
}
2014-12-10 03:49:16 +00:00
2022-09-25 12:37:24 +00:00
if ( ! Filtered & & g_Config . m_BrExcludeString [ 0 ] ! = ' \0 ' )
2014-12-10 03:49:16 +00:00
{
2022-09-25 12:37:24 +00:00
const char * pStr = g_Config . m_BrExcludeString ;
char aExcludeStr [ sizeof ( g_Config . m_BrExcludeString ) ] ;
while ( ( pStr = str_next_token ( pStr , IServerBrowser : : SEARCH_EXCLUDE_TOKEN , aExcludeStr , sizeof ( aExcludeStr ) ) ) )
2014-12-10 03:49:16 +00:00
{
2022-09-25 12:37:24 +00:00
if ( aExcludeStr [ 0 ] = = ' \0 ' )
{
continue ;
}
2022-12-23 22:23:44 +00:00
auto MatchesFn = matchesPart ;
const int FilterLen = str_length ( aExcludeStr ) ;
if ( aExcludeStr [ 0 ] = = ' " ' & & aExcludeStr [ FilterLen - 1 ] = = ' " ' )
{
aExcludeStr [ FilterLen - 1 ] = ' \0 ' ;
MatchesFn = matchesExactly ;
}
2014-12-10 03:49:16 +00:00
2022-09-25 12:37:24 +00:00
// match against server name
2023-09-30 10:41:01 +00:00
if ( MatchesFn ( Info . m_aName , aExcludeStr ) )
2022-09-25 12:37:24 +00:00
{
2022-12-05 21:30:09 +00:00
Filtered = true ;
2022-09-25 12:37:24 +00:00
break ;
}
2019-03-05 09:46:29 +00:00
2022-09-25 12:37:24 +00:00
// match against map
2023-09-30 10:41:01 +00:00
if ( MatchesFn ( Info . m_aMap , aExcludeStr ) )
2022-09-25 12:37:24 +00:00
{
2022-12-05 21:30:09 +00:00
Filtered = true ;
2022-09-25 12:37:24 +00:00
break ;
}
2016-08-06 22:52:00 +00:00
2022-09-25 12:37:24 +00:00
// match against gametype
2023-09-30 10:41:01 +00:00
if ( MatchesFn ( Info . m_aGameType , aExcludeStr ) )
2022-09-25 12:37:24 +00:00
{
2022-12-05 21:30:09 +00:00
Filtered = true ;
2022-09-25 12:37:24 +00:00
break ;
}
}
2014-12-10 03:49:16 +00:00
}
2010-05-29 07:25:38 +00:00
}
2022-12-05 21:30:09 +00:00
if ( ! Filtered )
2011-06-26 15:10:13 +00:00
{
2023-09-30 10:57:10 +00:00
UpdateServerFriends ( & Info ) ;
2011-06-26 15:10:13 +00:00
2023-09-30 10:41:01 +00:00
if ( ! g_Config . m_BrFilterFriends | | Info . m_FriendState ! = IFriends : : FRIEND_NO )
2023-10-01 18:17:55 +00:00
{
m_NumSortedPlayers + = Info . m_NumFilteredPlayers ;
2011-06-26 15:10:13 +00:00
m_pSortedServerlist [ m_NumSortedServers + + ] = i ;
2023-10-01 18:17:55 +00:00
}
2011-06-26 15:10:13 +00:00
}
2010-05-29 07:25:38 +00:00
}
}
int CServerBrowser : : SortHash ( ) const
{
2020-09-26 19:33:36 +00:00
int i = g_Config . m_BrSort & 0xff ;
i | = g_Config . m_BrFilterEmpty < < 4 ;
i | = g_Config . m_BrFilterFull < < 5 ;
i | = g_Config . m_BrFilterSpectators < < 6 ;
i | = g_Config . m_BrFilterFriends < < 7 ;
i | = g_Config . m_BrFilterPw < < 8 ;
i | = g_Config . m_BrSortOrder < < 9 ;
i | = g_Config . m_BrFilterGametypeStrict < < 12 ;
i | = g_Config . m_BrFilterUnfinishedMap < < 13 ;
i | = g_Config . m_BrFilterCountry < < 14 ;
i | = g_Config . m_BrFilterConnectingPlayers < < 15 ;
2010-05-29 07:25:38 +00:00
return i ;
}
void CServerBrowser : : Sort ( )
{
2023-09-30 10:48:02 +00:00
// update number of filtered players
2022-12-05 21:14:14 +00:00
for ( int i = 0 ; i < m_NumServers ; i + + )
2018-10-29 21:03:57 +00:00
{
2023-09-30 10:48:02 +00:00
UpdateServerFilteredPlayers ( & m_ppServerlist [ i ] - > m_Info ) ;
2018-10-29 21:03:57 +00:00
}
2010-05-29 07:25:38 +00:00
// create filtered list
Filter ( ) ;
// sort
2020-09-26 19:41:58 +00:00
if ( g_Config . m_BrSortOrder = = 2 & & ( g_Config . m_BrSort = = IServerBrowser : : SORT_NUMPLAYERS | | g_Config . m_BrSort = = IServerBrowser : : SORT_PING ) )
2022-12-05 21:16:01 +00:00
std : : stable_sort ( m_pSortedServerlist , m_pSortedServerlist + m_NumSortedServers , CSortWrap ( this , & CServerBrowser : : SortCompareNumPlayersAndPing ) ) ;
2020-08-24 21:23:37 +00:00
else if ( g_Config . m_BrSort = = IServerBrowser : : SORT_NAME )
2022-12-05 21:16:01 +00:00
std : : stable_sort ( m_pSortedServerlist , m_pSortedServerlist + m_NumSortedServers , CSortWrap ( this , & CServerBrowser : : SortCompareName ) ) ;
2010-05-29 07:25:38 +00:00
else if ( g_Config . m_BrSort = = IServerBrowser : : SORT_PING )
2022-12-05 21:16:01 +00:00
std : : stable_sort ( m_pSortedServerlist , m_pSortedServerlist + m_NumSortedServers , CSortWrap ( this , & CServerBrowser : : SortComparePing ) ) ;
2010-05-29 07:25:38 +00:00
else if ( g_Config . m_BrSort = = IServerBrowser : : SORT_MAP )
2022-12-05 21:16:01 +00:00
std : : stable_sort ( m_pSortedServerlist , m_pSortedServerlist + m_NumSortedServers , CSortWrap ( this , & CServerBrowser : : SortCompareMap ) ) ;
2010-05-29 07:25:38 +00:00
else if ( g_Config . m_BrSort = = IServerBrowser : : SORT_NUMPLAYERS )
2022-12-05 21:16:01 +00:00
std : : stable_sort ( m_pSortedServerlist , m_pSortedServerlist + m_NumSortedServers , CSortWrap ( this , & CServerBrowser : : SortCompareNumPlayers ) ) ;
2010-05-29 07:25:38 +00:00
else if ( g_Config . m_BrSort = = IServerBrowser : : SORT_GAMETYPE )
2022-12-05 21:16:01 +00:00
std : : stable_sort ( m_pSortedServerlist , m_pSortedServerlist + m_NumSortedServers , CSortWrap ( this , & CServerBrowser : : SortCompareGametype ) ) ;
2010-05-29 07:25:38 +00:00
m_Sorthash = SortHash ( ) ;
}
void CServerBrowser : : RemoveRequest ( CServerEntry * pEntry )
{
if ( pEntry - > m_pPrevReq | | pEntry - > m_pNextReq | | m_pFirstReqServer = = pEntry )
{
if ( pEntry - > m_pPrevReq )
pEntry - > m_pPrevReq - > m_pNextReq = pEntry - > m_pNextReq ;
else
m_pFirstReqServer = pEntry - > m_pNextReq ;
if ( pEntry - > m_pNextReq )
pEntry - > m_pNextReq - > m_pPrevReq = pEntry - > m_pPrevReq ;
else
m_pLastReqServer = pEntry - > m_pPrevReq ;
2022-12-05 21:26:56 +00:00
pEntry - > m_pPrevReq = nullptr ;
pEntry - > m_pNextReq = nullptr ;
2010-05-29 07:25:38 +00:00
m_NumRequests - - ;
}
}
CServerBrowser : : CServerEntry * CServerBrowser : : Find ( const NETADDR & Addr )
{
2022-05-23 18:16:18 +00:00
auto Entry = m_ByAddr . find ( Addr ) ;
if ( Entry = = m_ByAddr . end ( ) )
2010-05-29 07:25:38 +00:00
{
2022-05-23 18:16:18 +00:00
return nullptr ;
2010-05-29 07:25:38 +00:00
}
2022-05-23 18:16:18 +00:00
return m_ppServerlist [ Entry - > second ] ;
2010-05-29 07:25:38 +00:00
}
void CServerBrowser : : QueueRequest ( CServerEntry * pEntry )
{
// add it to the list of servers that we should request info from
pEntry - > m_pPrevReq = m_pLastReqServer ;
if ( m_pLastReqServer )
m_pLastReqServer - > m_pNextReq = pEntry ;
else
m_pFirstReqServer = pEntry ;
m_pLastReqServer = pEntry ;
2022-12-05 21:26:56 +00:00
pEntry - > m_pNextReq = nullptr ;
2010-05-29 07:25:38 +00:00
m_NumRequests + + ;
}
2022-05-23 18:16:18 +00:00
void ServerBrowserFormatAddresses ( char * pBuffer , int BufferSize , NETADDR * pAddrs , int NumAddrs )
{
for ( int i = 0 ; i < NumAddrs ; i + + )
{
if ( i ! = 0 )
{
if ( BufferSize < = 1 )
{
return ;
}
pBuffer [ 0 ] = ' , ' ;
2022-12-05 21:26:56 +00:00
pBuffer [ 1 ] = ' \0 ' ;
2022-05-23 18:16:18 +00:00
pBuffer + = 1 ;
BufferSize - = 1 ;
}
if ( BufferSize < = 1 )
{
return ;
}
net_addr_str ( & pAddrs [ i ] , pBuffer , BufferSize , true ) ;
int Length = str_length ( pBuffer ) ;
pBuffer + = Length ;
BufferSize - = Length ;
}
}
2010-05-29 07:25:38 +00:00
void CServerBrowser : : SetInfo ( CServerEntry * pEntry , const CServerInfo & Info )
{
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
const CServerInfo TmpInfo = pEntry - > m_Info ;
2010-05-29 07:25:38 +00:00
pEntry - > m_Info = Info ;
2022-07-31 20:43:43 +00:00
pEntry - > m_Info . m_Favorite = TmpInfo . m_Favorite ;
pEntry - > m_Info . m_FavoriteAllowPing = TmpInfo . m_FavoriteAllowPing ;
mem_copy ( pEntry - > m_Info . m_aAddresses , TmpInfo . m_aAddresses , sizeof ( pEntry - > m_Info . m_aAddresses ) ) ;
pEntry - > m_Info . m_NumAddresses = TmpInfo . m_NumAddresses ;
2022-05-23 18:16:18 +00:00
ServerBrowserFormatAddresses ( pEntry - > m_Info . m_aAddress , sizeof ( pEntry - > m_Info . m_aAddress ) , pEntry - > m_Info . m_aAddresses , pEntry - > m_Info . m_NumAddresses ) ;
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
UpdateServerCommunity ( & pEntry - > m_Info ) ;
UpdateServerRank ( & pEntry - > m_Info ) ;
2010-05-29 07:25:38 +00:00
2023-05-22 15:22:52 +00:00
if ( pEntry - > m_Info . m_ClientScoreKind = = CServerInfo : : CLIENT_SCORE_KIND_UNSPECIFIED )
{
if ( ( str_find_nocase ( pEntry - > m_Info . m_aGameType , " race " ) | | str_find_nocase ( pEntry - > m_Info . m_aGameType , " fastcap " ) ) & & g_Config . m_ClDDRaceScoreBoard )
{
pEntry - > m_Info . m_ClientScoreKind = CServerInfo : : CLIENT_SCORE_KIND_TIME_BACKCOMPAT ;
}
else
{
pEntry - > m_Info . m_ClientScoreKind = CServerInfo : : CLIENT_SCORE_KIND_POINTS ;
}
}
2021-05-12 16:04:49 +00:00
class CPlayerScoreNameLess
{
2023-05-25 23:38:11 +00:00
const int ScoreKind ;
2023-05-22 11:00:06 +00:00
2021-05-12 16:04:49 +00:00
public :
2023-05-22 11:00:06 +00:00
CPlayerScoreNameLess ( int ClientScoreKind ) :
ScoreKind ( ClientScoreKind )
{
}
2021-05-12 16:04:49 +00:00
bool operator ( ) ( const CServerInfo : : CClient & p0 , const CServerInfo : : CClient & p1 )
{
2023-05-25 23:38:11 +00:00
// Sort players before non players
2021-05-12 16:04:49 +00:00
if ( p0 . m_Player & & ! p1 . m_Player )
return true ;
if ( ! p0 . m_Player & & p1 . m_Player )
return false ;
int Score0 = p0 . m_Score ;
int Score1 = p1 . m_Score ;
2023-05-22 11:00:06 +00:00
2023-05-25 23:38:11 +00:00
if ( ScoreKind = = CServerInfo : : CLIENT_SCORE_KIND_TIME | | ScoreKind = = CServerInfo : : CLIENT_SCORE_KIND_TIME_BACKCOMPAT )
2023-05-22 11:00:06 +00:00
{
2023-05-25 23:38:11 +00:00
// Sort unfinished (-9999) and still connecting players (-1) after others
if ( Score0 < 0 & & Score1 > = 0 )
return false ;
if ( Score0 > = 0 & & Score1 < 0 )
return true ;
2023-05-22 11:00:06 +00:00
}
2021-05-12 16:04:49 +00:00
2023-05-25 23:38:11 +00:00
if ( Score0 ! = Score1 )
{
// Handle the sign change introduced with CLIENT_SCORE_KIND_TIME
if ( ScoreKind = = CServerInfo : : CLIENT_SCORE_KIND_TIME )
return Score0 < Score1 ;
else
return Score0 > Score1 ;
2023-05-22 14:32:48 +00:00
}
2023-05-22 11:00:06 +00:00
2021-05-12 16:04:49 +00:00
return str_comp_nocase ( p0 . m_aName , p1 . m_aName ) < 0 ;
}
} ;
2023-05-22 11:00:06 +00:00
std : : sort ( pEntry - > m_Info . m_aClients , pEntry - > m_Info . m_aClients + Info . m_NumReceivedClients , CPlayerScoreNameLess ( pEntry - > m_Info . m_ClientScoreKind ) ) ;
2021-05-12 16:04:49 +00:00
2010-05-29 07:25:38 +00:00
pEntry - > m_GotInfo = 1 ;
}
2021-04-21 14:54:42 +00:00
void CServerBrowser : : SetLatency ( NETADDR Addr , int Latency )
{
2022-05-23 18:16:18 +00:00
m_pPingCache - > CachePing ( Addr , Latency ) ;
2021-04-21 14:54:42 +00:00
Addr . port = 0 ;
2022-05-23 18:16:18 +00:00
for ( int i = 0 ; i < m_NumServers ; i + + )
2021-04-21 14:54:42 +00:00
{
2022-05-23 18:16:18 +00:00
if ( ! m_ppServerlist [ i ] - > m_GotInfo )
2021-04-21 14:54:42 +00:00
{
2022-05-23 18:16:18 +00:00
continue ;
}
bool Found = false ;
for ( int j = 0 ; j < m_ppServerlist [ i ] - > m_Info . m_NumAddresses ; j + + )
{
NETADDR Other = m_ppServerlist [ i ] - > m_Info . m_aAddresses [ j ] ;
Other . port = 0 ;
if ( Addr = = Other )
{
Found = true ;
break ;
}
}
if ( ! Found )
{
continue ;
}
int Ping = m_pPingCache - > GetPing ( m_ppServerlist [ i ] - > m_Info . m_aAddresses , m_ppServerlist [ i ] - > m_Info . m_NumAddresses ) ;
if ( Ping = = - 1 )
{
continue ;
2021-04-21 14:54:42 +00:00
}
2022-05-23 18:16:18 +00:00
m_ppServerlist [ i ] - > m_Info . m_Latency = Ping ;
m_ppServerlist [ i ] - > m_Info . m_LatencyIsEstimated = false ;
2021-04-21 14:54:42 +00:00
}
}
2022-05-23 18:16:18 +00:00
CServerBrowser : : CServerEntry * CServerBrowser : : Add ( const NETADDR * pAddrs , int NumAddrs )
2010-05-29 07:25:38 +00:00
{
// create new pEntry
2022-12-05 21:14:14 +00:00
CServerEntry * pEntry = ( CServerEntry * ) m_ServerlistHeap . Allocate ( sizeof ( CServerEntry ) ) ;
2010-05-29 07:25:38 +00:00
mem_zero ( pEntry , sizeof ( CServerEntry ) ) ;
// set the info
2022-05-23 18:16:18 +00:00
mem_copy ( pEntry - > m_Info . m_aAddresses , pAddrs , NumAddrs * sizeof ( pAddrs [ 0 ] ) ) ;
pEntry - > m_Info . m_NumAddresses = NumAddrs ;
2010-05-29 07:25:38 +00:00
pEntry - > m_Info . m_Latency = 999 ;
2023-09-30 10:39:30 +00:00
pEntry - > m_Info . m_HasRank = CServerInfo : : RANK_UNAVAILABLE ;
2022-05-23 18:16:18 +00:00
ServerBrowserFormatAddresses ( pEntry - > m_Info . m_aAddress , sizeof ( pEntry - > m_Info . m_aAddress ) , pEntry - > m_Info . m_aAddresses , pEntry - > m_Info . m_NumAddresses ) ;
str_copy ( pEntry - > m_Info . m_aName , pEntry - > m_Info . m_aAddress , sizeof ( pEntry - > m_Info . m_aName ) ) ;
2010-05-29 07:25:38 +00:00
// check if it's a favorite
2022-05-23 18:16:18 +00:00
pEntry - > m_Info . m_Favorite = m_pFavorites - > IsFavorite ( pEntry - > m_Info . m_aAddresses , pEntry - > m_Info . m_NumAddresses ) ;
pEntry - > m_Info . m_FavoriteAllowPing = m_pFavorites - > IsPingAllowed ( pEntry - > m_Info . m_aAddresses , pEntry - > m_Info . m_NumAddresses ) ;
2019-03-19 06:46:48 +00:00
2022-05-23 18:16:18 +00:00
for ( int i = 0 ; i < NumAddrs ; i + + )
{
m_ByAddr [ pAddrs [ i ] ] = m_NumServers ;
}
2010-05-29 07:25:38 +00:00
if ( m_NumServers = = m_NumServerCapacity )
{
CServerEntry * * ppNewlist ;
m_NumServerCapacity + = 100 ;
2020-11-04 18:12:45 +00:00
ppNewlist = ( CServerEntry * * ) calloc ( m_NumServerCapacity , sizeof ( CServerEntry * ) ) ; // NOLINT(bugprone-sizeof-expression)
2020-10-10 10:17:40 +00:00
if ( m_NumServers > 0 )
2020-11-04 18:12:45 +00:00
mem_copy ( ppNewlist , m_ppServerlist , m_NumServers * sizeof ( CServerEntry * ) ) ; // NOLINT(bugprone-sizeof-expression)
2018-04-09 09:56:39 +00:00
free ( m_ppServerlist ) ;
2010-05-29 07:25:38 +00:00
m_ppServerlist = ppNewlist ;
}
// add to list
m_ppServerlist [ m_NumServers ] = pEntry ;
pEntry - > m_Info . m_ServerIndex = m_NumServers ;
m_NumServers + + ;
return pEntry ;
}
2022-05-23 18:16:18 +00:00
void CServerBrowser : : OnServerInfoUpdate ( const NETADDR & Addr , int Token , const CServerInfo * pInfo )
2010-05-29 07:25:38 +00:00
{
2022-05-23 18:16:18 +00:00
int BasicToken = Token ;
int ExtraToken = 0 ;
if ( pInfo - > m_Type = = SERVERINFO_EXTENDED )
2010-05-29 07:25:38 +00:00
{
2022-05-23 18:16:18 +00:00
BasicToken = Token & 0xff ;
ExtraToken = Token > > 8 ;
2010-05-29 07:25:38 +00:00
}
2022-05-23 18:16:18 +00:00
CServerEntry * pEntry = Find ( Addr ) ;
2014-09-13 14:36:25 +00:00
2022-05-23 18:16:18 +00:00
if ( m_ServerlistType = = IServerBrowser : : TYPE_LAN )
{
NETADDR Broadcast ;
mem_zero ( & Broadcast , sizeof ( Broadcast ) ) ;
Broadcast . type = m_pNetClient - > NetType ( ) | NETTYPE_LINK_BROADCAST ;
int TokenBC = GenerateToken ( Broadcast ) ;
bool Drop = false ;
Drop = Drop | | BasicToken ! = GetBasicToken ( TokenBC ) ;
Drop = Drop | | ( pInfo - > m_Type = = SERVERINFO_EXTENDED & & ExtraToken ! = GetExtraToken ( TokenBC ) ) ;
if ( Drop )
2014-09-13 14:36:25 +00:00
{
2022-05-23 18:16:18 +00:00
return ;
2014-09-13 14:36:25 +00:00
}
2022-05-23 18:16:18 +00:00
if ( ! pEntry )
pEntry = Add ( & Addr , 1 ) ;
2014-09-13 14:36:25 +00:00
}
2022-05-23 18:16:18 +00:00
else
2019-03-24 22:15:38 +00:00
{
2022-05-23 18:16:18 +00:00
if ( ! pEntry )
{
2019-03-24 22:15:38 +00:00
return ;
2022-05-23 18:16:18 +00:00
}
int TokenAddr = GenerateToken ( Addr ) ;
bool Drop = false ;
Drop = Drop | | BasicToken ! = GetBasicToken ( TokenAddr ) ;
Drop = Drop | | ( pInfo - > m_Type = = SERVERINFO_EXTENDED & & ExtraToken ! = GetExtraToken ( TokenAddr ) ) ;
if ( Drop )
2019-03-24 22:15:38 +00:00
{
2022-05-23 18:16:18 +00:00
return ;
2019-03-24 22:15:38 +00:00
}
}
2022-05-23 18:16:18 +00:00
if ( m_ServerlistType = = IServerBrowser : : TYPE_LAN )
2018-07-11 20:46:04 +00:00
{
2022-05-23 18:16:18 +00:00
SetInfo ( pEntry , * pInfo ) ;
pEntry - > m_Info . m_Latency = minimum ( static_cast < int > ( ( time_get ( ) - m_BroadcastTime ) * 1000 / time_freq ( ) ) , 999 ) ;
2018-07-11 20:46:04 +00:00
}
2022-05-23 18:16:18 +00:00
else if ( pEntry - > m_RequestTime > 0 )
2010-05-29 07:25:38 +00:00
{
2022-05-23 18:16:18 +00:00
if ( ! pEntry - > m_RequestIgnoreInfo )
2017-03-29 10:56:13 +00:00
{
2022-05-23 18:16:18 +00:00
SetInfo ( pEntry , * pInfo ) ;
2017-03-29 10:56:13 +00:00
}
2022-05-23 18:16:18 +00:00
int Latency = minimum ( static_cast < int > ( ( time_get ( ) - pEntry - > m_RequestTime ) * 1000 / time_freq ( ) ) , 999 ) ;
if ( ! pEntry - > m_RequestIgnoreInfo )
2020-09-02 23:51:33 +00:00
{
2022-05-23 18:16:18 +00:00
pEntry - > m_Info . m_Latency = Latency ;
2020-09-02 23:51:33 +00:00
}
else
2017-03-29 10:56:13 +00:00
{
2022-05-23 18:16:18 +00:00
char aAddr [ NETADDR_MAXSTRSIZE ] ;
net_addr_str ( & Addr , aAddr , sizeof ( aAddr ) , true ) ;
2022-12-05 21:43:04 +00:00
dbg_msg ( " serverbrowser " , " received ping response from %s " , aAddr ) ;
2022-05-23 18:16:18 +00:00
SetLatency ( Addr , Latency ) ;
2017-03-29 10:56:13 +00:00
}
2022-05-23 18:16:18 +00:00
pEntry - > m_RequestTime = - 1 ; // Request has been answered
2010-05-29 07:25:38 +00:00
}
2022-05-23 18:16:18 +00:00
RemoveRequest ( pEntry ) ;
2022-12-05 22:00:35 +00:00
RequestResort ( ) ;
2010-05-29 07:25:38 +00:00
}
void CServerBrowser : : Refresh ( int Type )
{
2021-07-08 17:18:01 +00:00
bool ServerListTypeChanged = m_ServerlistType ! = Type ;
int OldServerListType = m_ServerlistType ;
2010-05-29 07:25:38 +00:00
m_ServerlistType = Type ;
2020-09-03 00:03:22 +00:00
secure_random_fill ( m_aTokenSeed , sizeof ( m_aTokenSeed ) ) ;
2010-05-29 07:25:38 +00:00
2021-07-08 17:18:01 +00:00
if ( Type = = IServerBrowser : : TYPE_LAN | | ( ServerListTypeChanged & & OldServerListType = = IServerBrowser : : TYPE_LAN ) )
CleanUp ( ) ;
2010-05-29 07:25:38 +00:00
if ( Type = = IServerBrowser : : TYPE_LAN )
{
2022-06-30 22:36:32 +00:00
unsigned char aBuffer [ sizeof ( SERVERBROWSE_GETINFO ) + 1 ] ;
2010-05-29 07:25:38 +00:00
CNetChunk Packet ;
2011-03-28 18:11:28 +00:00
/* do the broadcast version */
2010-05-29 07:25:38 +00:00
Packet . m_ClientID = - 1 ;
mem_zero ( & Packet , sizeof ( Packet ) ) ;
2020-09-26 19:41:58 +00:00
Packet . m_Address . type = m_pNetClient - > NetType ( ) | NETTYPE_LINK_BROADCAST ;
Packet . m_Flags = NETSENDFLAG_CONNLESS | NETSENDFLAG_EXTENDED ;
2022-06-30 22:36:32 +00:00
Packet . m_DataSize = sizeof ( aBuffer ) ;
Packet . m_pData = aBuffer ;
2017-03-29 10:56:13 +00:00
mem_zero ( & Packet . m_aExtraData , sizeof ( Packet . m_aExtraData ) ) ;
2017-10-14 19:58:23 +00:00
int Token = GenerateToken ( Packet . m_Address ) ;
2022-06-30 22:36:32 +00:00
mem_copy ( aBuffer , SERVERBROWSE_GETINFO , sizeof ( SERVERBROWSE_GETINFO ) ) ;
aBuffer [ sizeof ( SERVERBROWSE_GETINFO ) ] = GetBasicToken ( Token ) ;
2017-10-14 19:58:23 +00:00
Packet . m_aExtraData [ 0 ] = GetExtraToken ( Token ) > > 8 ;
Packet . m_aExtraData [ 1 ] = GetExtraToken ( Token ) & 0xff ;
2010-05-29 07:25:38 +00:00
m_BroadcastTime = time_get ( ) ;
2022-12-05 21:14:14 +00:00
for ( int i = 8303 ; i < = 8310 ; i + + )
2010-05-29 07:25:38 +00:00
{
Packet . m_Address . port = i ;
m_pNetClient - > Send ( & Packet ) ;
}
if ( g_Config . m_Debug )
2022-12-05 21:43:04 +00:00
m_pConsole - > Print ( IConsole : : OUTPUT_LEVEL_DEBUG , " serverbrowser " , " broadcasting for servers " ) ;
2010-05-29 07:25:38 +00:00
}
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
else if ( Type = = IServerBrowser : : TYPE_FAVORITES | | Type = = IServerBrowser : : TYPE_INTERNET )
2019-03-24 22:15:38 +00:00
{
2018-07-11 20:46:04 +00:00
m_pHttp - > Refresh ( ) ;
2021-04-21 14:54:42 +00:00
m_pPingCache - > Load ( ) ;
2018-07-11 20:46:04 +00:00
m_RefreshingHttp = true ;
2021-07-08 17:18:01 +00:00
if ( ServerListTypeChanged & & m_pHttp - > NumServers ( ) > 0 )
{
CleanUp ( ) ;
UpdateFromHttp ( ) ;
Sort ( ) ;
}
2019-03-24 22:15:38 +00:00
}
2010-05-29 07:25:38 +00:00
}
2021-06-09 15:29:06 +00:00
void CServerBrowser : : RequestImpl ( const NETADDR & Addr , CServerEntry * pEntry , int * pBasicToken , int * pToken , bool RandomToken ) const
2010-05-29 07:25:38 +00:00
{
if ( g_Config . m_Debug )
{
2011-03-30 10:08:33 +00:00
char aAddrStr [ NETADDR_MAXSTRSIZE ] ;
2011-12-29 22:36:53 +00:00
net_addr_str ( & Addr , aAddrStr , sizeof ( aAddrStr ) , true ) ;
2010-08-17 22:06:00 +00:00
char aBuf [ 256 ] ;
2020-09-26 19:41:58 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " requesting server info from %s " , aAddrStr ) ;
2022-12-05 21:43:04 +00:00
m_pConsole - > Print ( IConsole : : OUTPUT_LEVEL_DEBUG , " serverbrowser " , aBuf ) ;
2010-05-29 07:25:38 +00:00
}
2017-10-14 19:58:23 +00:00
int Token = GenerateToken ( Addr ) ;
2021-06-09 15:29:06 +00:00
if ( RandomToken )
{
int AvoidBasicToken = GetBasicToken ( Token ) ;
do
{
secure_random_fill ( & Token , sizeof ( Token ) ) ;
Token & = 0xffffff ;
} while ( GetBasicToken ( Token ) = = AvoidBasicToken ) ;
}
2021-04-23 21:12:16 +00:00
if ( pToken )
{
* pToken = Token ;
}
if ( pBasicToken )
{
* pBasicToken = GetBasicToken ( Token ) ;
}
2017-10-14 19:58:23 +00:00
2022-12-05 21:14:14 +00:00
unsigned char aBuffer [ sizeof ( SERVERBROWSE_GETINFO ) + 1 ] ;
2022-06-30 22:36:32 +00:00
mem_copy ( aBuffer , SERVERBROWSE_GETINFO , sizeof ( SERVERBROWSE_GETINFO ) ) ;
aBuffer [ sizeof ( SERVERBROWSE_GETINFO ) ] = GetBasicToken ( Token ) ;
2010-05-29 07:25:38 +00:00
2022-12-05 21:14:14 +00:00
CNetChunk Packet ;
2010-05-29 07:25:38 +00:00
Packet . m_ClientID = - 1 ;
Packet . m_Address = Addr ;
2020-09-26 19:41:58 +00:00
Packet . m_Flags = NETSENDFLAG_CONNLESS | NETSENDFLAG_EXTENDED ;
2022-06-30 22:36:32 +00:00
Packet . m_DataSize = sizeof ( aBuffer ) ;
Packet . m_pData = aBuffer ;
2017-03-29 10:56:13 +00:00
mem_zero ( & Packet . m_aExtraData , sizeof ( Packet . m_aExtraData ) ) ;
2017-10-14 19:58:23 +00:00
Packet . m_aExtraData [ 0 ] = GetExtraToken ( Token ) > > 8 ;
Packet . m_aExtraData [ 1 ] = GetExtraToken ( Token ) & 0xff ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
m_pNetClient - > Send ( & Packet ) ;
if ( pEntry )
pEntry - > m_RequestTime = time_get ( ) ;
}
2021-06-09 15:29:06 +00:00
void CServerBrowser : : RequestCurrentServer ( const NETADDR & Addr ) const
{
RequestImpl ( Addr , nullptr , nullptr , nullptr , false ) ;
}
void CServerBrowser : : RequestCurrentServerWithRandomToken ( const NETADDR & Addr , int * pBasicToken , int * pToken ) const
2021-04-23 21:12:16 +00:00
{
2021-06-09 15:29:06 +00:00
RequestImpl ( Addr , nullptr , pBasicToken , pToken , true ) ;
2021-04-23 21:12:16 +00:00
}
void CServerBrowser : : SetCurrentServerPing ( const NETADDR & Addr , int Ping )
2010-05-29 07:25:38 +00:00
{
2021-08-20 15:16:18 +00:00
SetLatency ( Addr , minimum ( Ping , 999 ) ) ;
2010-05-29 07:25:38 +00:00
}
2018-07-11 20:46:04 +00:00
void CServerBrowser : : UpdateFromHttp ( )
2015-07-09 00:08:14 +00:00
{
2021-04-24 16:06:42 +00:00
int OwnLocation ;
if ( str_comp ( g_Config . m_BrLocation , " auto " ) = = 0 )
{
OwnLocation = m_OwnLocation ;
}
else
{
if ( CServerInfo : : ParseLocation ( & OwnLocation , g_Config . m_BrLocation ) )
{
char aBuf [ 64 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " cannot parse br_location: '%s' " , g_Config . m_BrLocation ) ;
2022-12-05 21:43:04 +00:00
m_pConsole - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " serverbrowser " , aBuf ) ;
2021-04-24 16:06:42 +00:00
}
}
2021-04-21 14:54:42 +00:00
2018-07-11 20:46:04 +00:00
int NumServers = m_pHttp - > NumServers ( ) ;
int NumLegacyServers = m_pHttp - > NumLegacyServers ( ) ;
2022-05-23 18:16:18 +00:00
std : : function < bool ( const NETADDR * , int ) > Want = [ ] ( const NETADDR * pAddrs , int NumAddrs ) { return true ; } ;
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
if ( m_ServerlistType = = IServerBrowser : : TYPE_FAVORITES )
2010-05-29 07:25:38 +00:00
{
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
Want = [ & ] ( const NETADDR * pAddrs , int NumAddrs ) - > bool { return m_pFavorites - > IsFavorite ( pAddrs , NumAddrs ) ! = TRISTATE : : NONE ; } ;
2022-05-23 18:16:18 +00:00
}
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
2022-05-23 18:16:18 +00:00
for ( int i = 0 ; i < NumServers ; i + + )
{
CServerInfo Info = m_pHttp - > Server ( i ) ;
if ( ! Want ( Info . m_aAddresses , Info . m_NumAddresses ) )
2013-12-31 02:18:37 +00:00
{
2022-05-23 18:16:18 +00:00
continue ;
2013-12-31 02:18:37 +00:00
}
2022-05-23 18:16:18 +00:00
int Ping = m_pPingCache - > GetPing ( Info . m_aAddresses , Info . m_NumAddresses ) ;
Info . m_LatencyIsEstimated = Ping = = - 1 ;
if ( Info . m_LatencyIsEstimated )
2018-07-11 20:46:04 +00:00
{
2022-05-23 18:16:18 +00:00
Info . m_Latency = CServerInfo : : EstimateLatency ( OwnLocation , Info . m_Location ) ;
2018-07-11 20:46:04 +00:00
}
2022-05-23 18:16:18 +00:00
else
2018-07-11 20:46:04 +00:00
{
2022-05-23 18:16:18 +00:00
Info . m_Latency = Ping ;
}
CServerEntry * pEntry = Add ( Info . m_aAddresses , Info . m_NumAddresses ) ;
SetInfo ( pEntry , Info ) ;
pEntry - > m_RequestIgnoreInfo = true ;
}
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
2022-05-23 18:16:18 +00:00
for ( int i = 0 ; i < NumLegacyServers ; i + + )
{
NETADDR Addr = m_pHttp - > LegacyServer ( i ) ;
if ( ! Want ( & Addr , 1 ) )
2020-09-26 19:41:58 +00:00
{
2022-05-23 18:16:18 +00:00
continue ;
}
QueueRequest ( Add ( & Addr , 1 ) ) ;
}
2018-07-11 20:46:04 +00:00
2022-05-23 18:16:18 +00:00
if ( m_ServerlistType = = IServerBrowser : : TYPE_FAVORITES )
{
const IFavorites : : CEntry * pFavorites ;
int NumFavorites ;
m_pFavorites - > AllEntries ( & pFavorites , & NumFavorites ) ;
for ( int i = 0 ; i < NumFavorites ; i + + )
2018-07-11 20:46:04 +00:00
{
2022-05-23 18:16:18 +00:00
bool Found = false ;
for ( int j = 0 ; j < pFavorites [ i ] . m_NumAddrs ; j + + )
2018-07-11 20:46:04 +00:00
{
2022-05-23 18:16:18 +00:00
if ( Find ( pFavorites [ i ] . m_aAddrs [ j ] ) )
2018-07-11 20:46:04 +00:00
{
2022-05-23 18:16:18 +00:00
Found = true ;
break ;
2018-07-11 20:46:04 +00:00
}
}
2022-05-23 18:16:18 +00:00
if ( Found )
2015-07-09 00:08:14 +00:00
{
2018-07-11 20:46:04 +00:00
continue ;
2014-01-03 15:14:41 +00:00
}
2022-05-23 18:16:18 +00:00
// (Also add favorites we're not allowed to ping.)
CServerEntry * pEntry = Add ( pFavorites [ i ] . m_aAddrs , pFavorites [ i ] . m_NumAddrs ) ;
if ( pFavorites - > m_AllowPing )
2021-05-12 19:06:08 +00:00
{
2022-05-23 18:16:18 +00:00
QueueRequest ( pEntry ) ;
2021-05-12 19:06:08 +00:00
}
}
2014-01-03 15:14:41 +00:00
}
2022-05-23 18:16:18 +00:00
2022-12-05 22:00:35 +00:00
RequestResort ( ) ;
2018-07-11 20:46:04 +00:00
}
2021-07-08 17:18:01 +00:00
void CServerBrowser : : CleanUp ( )
{
// clear out everything
m_ServerlistHeap . Reset ( ) ;
m_NumServers = 0 ;
m_NumSortedServers = 0 ;
2023-10-01 18:17:55 +00:00
m_NumSortedPlayers = 0 ;
2022-05-23 18:16:18 +00:00
m_ByAddr . clear ( ) ;
2022-12-05 21:26:56 +00:00
m_pFirstReqServer = nullptr ;
m_pLastReqServer = nullptr ;
2021-07-08 17:18:01 +00:00
m_NumRequests = 0 ;
m_CurrentMaxRequests = g_Config . m_BrMaxRequests ;
}
2022-12-05 22:00:35 +00:00
void CServerBrowser : : Update ( )
2018-07-11 20:46:04 +00:00
{
2021-06-23 05:05:49 +00:00
int64_t Timeout = time_freq ( ) ;
int64_t Now = time_get ( ) ;
2018-07-11 20:46:04 +00:00
2021-05-13 00:46:28 +00:00
const char * pHttpBestUrl ;
if ( ! m_pHttp - > GetBestUrl ( & pHttpBestUrl ) & & pHttpBestUrl ! = m_pHttpPrevBestUrl )
{
2022-07-09 16:14:56 +00:00
str_copy ( g_Config . m_BrCachedBestServerinfoUrl , pHttpBestUrl ) ;
2021-05-13 00:46:28 +00:00
m_pHttpPrevBestUrl = pHttpBestUrl ;
}
2018-07-11 20:46:04 +00:00
m_pHttp - > Update ( ) ;
if ( m_ServerlistType ! = TYPE_LAN & & m_RefreshingHttp & & ! m_pHttp - > IsRefreshing ( ) )
2010-05-29 07:25:38 +00:00
{
2018-07-11 20:46:04 +00:00
m_RefreshingHttp = false ;
2021-07-08 17:18:01 +00:00
CleanUp ( ) ;
2018-07-11 20:46:04 +00:00
UpdateFromHttp ( ) ;
// TODO: move this somewhere else
2021-07-08 17:18:01 +00:00
Sort ( ) ;
2018-07-11 20:46:04 +00:00
return ;
2010-05-29 07:25:38 +00:00
}
2018-07-11 20:46:04 +00:00
CServerEntry * pEntry = m_pFirstReqServer ;
int Count = 0 ;
2022-02-14 23:12:52 +00:00
while ( true )
2010-05-29 07:25:38 +00:00
{
if ( ! pEntry ) // no more entries
break ;
2020-09-26 19:41:58 +00:00
if ( pEntry - > m_RequestTime & & pEntry - > m_RequestTime + Timeout < Now )
2013-12-31 01:34:33 +00:00
{
pEntry = pEntry - > m_pNextReq ;
continue ;
}
2020-09-17 15:41:13 +00:00
// no more than 10 concurrent requests
2013-12-31 01:34:33 +00:00
if ( Count = = m_CurrentMaxRequests )
2010-05-29 07:25:38 +00:00
break ;
if ( pEntry - > m_RequestTime = = 0 )
2014-01-08 05:15:56 +00:00
{
2022-10-11 12:35:15 +00:00
RequestImpl ( pEntry - > m_Info . m_aAddresses [ 0 ] , pEntry , nullptr , nullptr , false ) ;
2014-01-08 05:15:56 +00:00
}
2010-05-29 07:25:38 +00:00
Count + + ;
pEntry = pEntry - > m_pNextReq ;
}
2015-07-09 00:08:14 +00:00
2013-12-31 01:34:33 +00:00
if ( m_pFirstReqServer & & Count = = 0 & & m_CurrentMaxRequests > 1 ) //NO More current Server Requests
{
//reset old ones
pEntry = m_pFirstReqServer ;
2022-02-14 23:12:52 +00:00
while ( true )
2013-12-31 01:34:33 +00:00
{
if ( ! pEntry ) // no more entries
break ;
2015-07-09 00:08:14 +00:00
pEntry - > m_RequestTime = 0 ;
pEntry = pEntry - > m_pNextReq ;
2013-12-31 01:34:33 +00:00
}
2015-07-09 00:08:14 +00:00
2013-12-31 01:34:33 +00:00
//update max-requests
2020-09-26 19:41:58 +00:00
m_CurrentMaxRequests = m_CurrentMaxRequests / 2 ;
2013-12-31 02:18:37 +00:00
if ( m_CurrentMaxRequests < 1 )
m_CurrentMaxRequests = 1 ;
2013-12-31 01:34:33 +00:00
}
else if ( Count = = 0 & & m_CurrentMaxRequests = = 1 ) //we reached the limit, just release all left requests. IF a server sends us a packet, a new request will be added automatically, so we can delete all
2015-07-09 00:08:14 +00:00
{
2013-12-31 01:34:33 +00:00
pEntry = m_pFirstReqServer ;
2022-02-14 23:12:52 +00:00
while ( true )
2013-12-31 01:34:33 +00:00
{
if ( ! pEntry ) // no more entries
2015-07-09 00:08:14 +00:00
break ;
2018-07-11 20:46:04 +00:00
CServerEntry * pNext = pEntry - > m_pNextReq ;
2020-09-26 19:41:58 +00:00
RemoveRequest ( pEntry ) ; //release request
2013-12-31 01:34:33 +00:00
pEntry = pNext ;
2014-01-03 15:14:41 +00:00
}
}
2015-07-09 00:08:14 +00:00
2010-05-29 07:25:38 +00:00
// check if we need to resort
2022-12-05 22:00:35 +00:00
if ( m_Sorthash ! = SortHash ( ) | | m_NeedResort )
2020-12-22 10:13:51 +00:00
{
2022-05-23 18:16:18 +00:00
for ( int i = 0 ; i < m_NumServers ; i + + )
{
CServerInfo * pInfo = & m_ppServerlist [ i ] - > m_Info ;
pInfo - > m_Favorite = m_pFavorites - > IsFavorite ( pInfo - > m_aAddresses , pInfo - > m_NumAddresses ) ;
pInfo - > m_FavoriteAllowPing = m_pFavorites - > IsPingAllowed ( pInfo - > m_aAddresses , pInfo - > m_NumAddresses ) ;
}
2010-05-29 07:25:38 +00:00
Sort ( ) ;
2022-12-05 22:00:35 +00:00
m_NeedResort = false ;
2020-12-22 10:13:51 +00:00
}
2010-05-29 07:25:38 +00:00
}
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
const json_value * CServerBrowser : : LoadDDNetInfo ( )
{
LoadDDNetInfoJson ( ) ;
LoadDDNetLocation ( ) ;
LoadDDNetServers ( ) ;
for ( int i = 0 ; i < m_NumServers ; i + + )
{
UpdateServerCommunity ( & m_ppServerlist [ i ] - > m_Info ) ;
UpdateServerRank ( & m_ppServerlist [ i ] - > m_Info ) ;
}
m_DDNetInfoUpdateTime = time_get ( ) ;
return m_pDDNetInfo ;
}
void CServerBrowser : : LoadDDNetInfoJson ( )
{
void * pBuf ;
unsigned Length ;
if ( ! m_pStorage - > ReadFile ( DDNET_INFO_FILE , IStorage : : TYPE_SAVE , & pBuf , & Length ) )
return ;
json_value_free ( m_pDDNetInfo ) ;
json_settings JsonSettings { } ;
char aError [ 256 ] ;
m_pDDNetInfo = json_parse_ex ( & JsonSettings , static_cast < json_char * > ( pBuf ) , Length , aError ) ;
free ( pBuf ) ;
if ( m_pDDNetInfo = = nullptr )
{
log_error ( " serverbrowser " , " invalid info json: '%s' " , aError ) ;
}
else if ( m_pDDNetInfo - > type ! = json_object )
{
log_error ( " serverbrowser " , " invalid info root " ) ;
json_value_free ( m_pDDNetInfo ) ;
m_pDDNetInfo = nullptr ;
}
}
void CServerBrowser : : LoadDDNetLocation ( )
{
m_OwnLocation = CServerInfo : : LOC_UNKNOWN ;
if ( m_pDDNetInfo )
{
const json_value & Location = ( * m_pDDNetInfo ) [ " location " ] ;
if ( Location . type ! = json_string | | CServerInfo : : ParseLocation ( & m_OwnLocation , Location ) )
{
log_error ( " serverbrowser " , " invalid location " ) ;
}
}
}
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
bool CServerBrowser : : ParseCommunityServers ( CCommunity * pCommunity , const json_value & Servers )
{
for ( unsigned ServerIndex = 0 ; ServerIndex < Servers . u . array . length ; + + ServerIndex )
{
// pServer - { name, flagId, servers }
const json_value & Server = Servers [ ServerIndex ] ;
if ( Server . type ! = json_object )
{
log_error ( " serverbrowser " , " invalid server (ServerIndex=%u) " , ServerIndex ) ;
return false ;
}
const json_value & Name = Server [ " name " ] ;
const json_value & FlagId = Server [ " flagId " ] ;
const json_value & Types = Server [ " servers " ] ;
if ( Name . type ! = json_string | | FlagId . type ! = json_integer | | Types . type ! = json_object )
{
log_error ( " serverbrowser " , " invalid server attribute (ServerIndex=%u) " , ServerIndex ) ;
return false ;
}
if ( Types . u . object . length = = 0 )
continue ;
pCommunity - > m_vCountries . emplace_back ( Name . u . string . ptr , FlagId . u . integer ) ;
CCommunityCountry * pCountry = & pCommunity - > m_vCountries . back ( ) ;
for ( unsigned TypeIndex = 0 ; TypeIndex < Types . u . object . length ; + + TypeIndex )
{
const json_value & Addresses = * Types . u . object . values [ TypeIndex ] . value ;
if ( Addresses . type ! = json_array )
{
log_error ( " serverbrowser " , " invalid addresses (ServerIndex=%u, TypeIndex=%u) " , ServerIndex , TypeIndex ) ;
return false ;
}
if ( Addresses . u . array . length = = 0 )
continue ;
const char * pTypeName = Types . u . object . values [ TypeIndex ] . name ;
// add type if it doesn't exist already
const auto CommunityType = std : : find_if ( pCommunity - > m_vTypes . begin ( ) , pCommunity - > m_vTypes . end ( ) , [ pTypeName ] ( const auto & Elem ) {
return str_comp ( Elem . Name ( ) , pTypeName ) = = 0 ;
} ) ;
if ( CommunityType = = pCommunity - > m_vTypes . end ( ) )
{
pCommunity - > m_vTypes . emplace_back ( pTypeName ) ;
}
// add addresses
for ( unsigned AddressIndex = 0 ; AddressIndex < Addresses . u . array . length ; + + AddressIndex )
{
const json_value & Address = Addresses [ AddressIndex ] ;
if ( Address . type ! = json_string )
{
log_error ( " serverbrowser " , " invalid address (ServerIndex=%u, TypeIndex=%u, AddressIndex=%u) " , ServerIndex , TypeIndex , AddressIndex ) ;
return false ;
}
NETADDR NetAddr ;
if ( net_addr_from_str ( & NetAddr , Address . u . string . ptr ) )
{
log_error ( " serverbrowser " , " invalid address (ServerIndex=%u, TypeIndex=%u, AddressIndex=%u) " , ServerIndex , TypeIndex , AddressIndex ) ;
continue ;
}
pCountry - > m_vServers . emplace_back ( NetAddr , pTypeName ) ;
}
}
}
return true ;
}
bool CServerBrowser : : ParseCommunityFinishes ( CCommunity * pCommunity , const json_value & Finishes )
{
for ( unsigned FinishIndex = 0 ; FinishIndex < Finishes . u . array . length ; + + FinishIndex )
{
const json_value & Finish = Finishes [ FinishIndex ] ;
if ( Finish . type ! = json_string )
{
log_error ( " serverbrowser " , " invalid rank (FinishIndex=%u) " , FinishIndex ) ;
return false ;
}
pCommunity - > m_FinishedMaps . emplace ( ( const char * ) Finish ) ;
}
return true ;
}
2017-08-30 19:34:01 +00:00
void CServerBrowser : : LoadDDNetServers ( )
2014-09-13 14:36:25 +00:00
{
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
// Parse communities
2023-09-17 11:31:41 +00:00
m_vCommunities . clear ( ) ;
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
m_CommunityServersByAddr . clear ( ) ;
2023-09-17 11:31:41 +00:00
2020-09-26 19:41:58 +00:00
if ( ! m_pDDNetInfo )
2017-09-03 15:36:51 +00:00
return ;
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
const json_value & Communities = ( * m_pDDNetInfo ) [ " communities " ] ;
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
if ( Communities . type ! = json_array )
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
return ;
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
for ( unsigned CommunityIndex = 0 ; CommunityIndex < Communities . u . array . length ; + + CommunityIndex )
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
{
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
const json_value & Community = Communities [ CommunityIndex ] ;
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
if ( Community . type ! = json_object )
{
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
log_error ( " serverbrowser " , " invalid community (CommunityIndex=%d) " , ( int ) CommunityIndex ) ;
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
continue ;
}
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
const json_value & Id = Community [ " id " ] ;
if ( Id . type ! = json_string )
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
{
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
log_error ( " serverbrowser " , " invalid community id (CommunityIndex=%d) " , ( int ) CommunityIndex ) ;
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
continue ;
}
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
const json_value & Icon = Community [ " icon " ] ;
const json_value & IconSha256 = Icon [ " sha256 " ] ;
const json_value & IconUrl = Icon [ " url " ] ;
const json_value & Name = Community [ " name " ] ;
const json_value * pFinishes = & Icon [ " finishes " ] ;
const json_value * pServers = & Icon [ " servers " ] ;
if ( pFinishes - > type = = json_none )
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
{
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
if ( str_comp ( Id , COMMUNITY_DDNET ) = = 0 )
{
pFinishes = & ( * m_pDDNetInfo ) [ " maps " ] ;
}
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
}
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
// Backward compatibility.
if ( pServers - > type = = json_none )
{
if ( str_comp ( Id , COMMUNITY_DDNET ) = = 0 )
{
pServers = & ( * m_pDDNetInfo ) [ " servers " ] ;
}
else if ( str_comp ( Id , " kog " ) = = 0 )
{
pServers = & ( * m_pDDNetInfo ) [ " servers-kog " ] ;
}
}
if ( false | |
Icon . type ! = json_object | |
IconSha256 . type ! = json_string | |
IconUrl . type ! = json_string | |
Name . type ! = json_string | |
( pFinishes - > type ! = json_array & & pFinishes - > type ! = json_none ) | |
pServers - > type ! = json_array )
{
log_error ( " serverbrowser " , " invalid community attribute (CommunityId=%s) " , ( const char * ) Id ) ;
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
continue ;
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
}
SHA256_DIGEST ParsedIconSha256 ;
if ( sha256_from_str ( & ParsedIconSha256 , IconSha256 ) ! = 0 )
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
{
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
log_error ( " serverbrowser " , " invalid community icon sha256 (CommunityId=%s) " , ( const char * ) Id ) ;
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
continue ;
}
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
CCommunity NewCommunity ( Id , Name , ParsedIconSha256 , IconUrl ) ;
if ( ParseCommunityServers ( & NewCommunity , * pServers ) )
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
{
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
log_error ( " serverbrowser " , " invalid community servers (CommunityId=%s) " , NewCommunity . Id ( ) ) ;
continue ;
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
}
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
NewCommunity . m_HasFinishes = pFinishes - > type = = json_array ;
if ( NewCommunity . m_HasFinishes & & ParseCommunityFinishes ( & NewCommunity , * pFinishes ) )
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
{
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
log_error ( " serverbrowser " , " invalid community finishes (CommunityId=%s) " , NewCommunity . Id ( ) ) ;
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
continue ;
}
2014-09-13 14:36:25 +00:00
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
for ( const auto & Country : NewCommunity . Countries ( ) )
2014-09-13 14:36:25 +00:00
{
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
for ( const auto & Server : Country . Servers ( ) )
2023-09-17 11:31:41 +00:00
{
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
m_CommunityServersByAddr . emplace ( Server . Address ( ) , CCommunityServer ( NewCommunity . Id ( ) , Country . Name ( ) , Server . TypeName ( ) ) ) ;
2017-09-03 15:36:51 +00:00
}
2019-03-24 22:15:38 +00:00
}
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
m_vCommunities . push_back ( std : : move ( NewCommunity ) ) ;
2017-09-03 15:36:51 +00:00
}
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
// Add default none community
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
m_vCommunities . emplace_back ( COMMUNITY_NONE , " None " , SHA256_ZEROED , " " ) ;
2017-09-03 15:36:51 +00:00
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
// Remove unknown elements from exclude lists
CleanFilters ( ) ;
2017-08-30 19:34:01 +00:00
}
2023-09-30 10:48:02 +00:00
void CServerBrowser : : UpdateServerFilteredPlayers ( CServerInfo * pInfo ) const
{
pInfo - > m_NumFilteredPlayers = g_Config . m_BrFilterSpectators ? pInfo - > m_NumPlayers : pInfo - > m_NumClients ;
if ( g_Config . m_BrFilterConnectingPlayers )
{
for ( const auto & Client : pInfo - > m_aClients )
{
if ( ( ! g_Config . m_BrFilterSpectators | | Client . m_Player ) & & str_comp ( Client . m_aName , " (connecting) " ) = = 0 & & Client . m_aClan [ 0 ] = = ' \0 ' )
pInfo - > m_NumFilteredPlayers - - ;
}
}
}
2023-09-30 10:57:10 +00:00
void CServerBrowser : : UpdateServerFriends ( CServerInfo * pInfo ) const
{
pInfo - > m_FriendState = IFriends : : FRIEND_NO ;
pInfo - > m_FriendNum = 0 ;
for ( int ClientIndex = 0 ; ClientIndex < minimum ( pInfo - > m_NumReceivedClients , ( int ) MAX_CLIENTS ) ; ClientIndex + + )
{
pInfo - > m_aClients [ ClientIndex ] . m_FriendState = m_pFriends - > GetFriendState ( pInfo - > m_aClients [ ClientIndex ] . m_aName , pInfo - > m_aClients [ ClientIndex ] . m_aClan ) ;
pInfo - > m_FriendState = maximum ( pInfo - > m_FriendState , pInfo - > m_aClients [ ClientIndex ] . m_FriendState ) ;
if ( pInfo - > m_aClients [ ClientIndex ] . m_FriendState ! = IFriends : : FRIEND_NO )
pInfo - > m_FriendNum + + ;
}
}
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
void CServerBrowser : : UpdateServerCommunity ( CServerInfo * pInfo ) const
{
for ( int AddressIndex = 0 ; AddressIndex < pInfo - > m_NumAddresses ; AddressIndex + + )
{
const auto Community = m_CommunityServersByAddr . find ( pInfo - > m_aAddresses [ AddressIndex ] ) ;
if ( Community ! = m_CommunityServersByAddr . end ( ) )
{
str_copy ( pInfo - > m_aCommunityId , Community - > second . CommunityId ( ) ) ;
str_copy ( pInfo - > m_aCommunityCountry , Community - > second . CountryName ( ) ) ;
str_copy ( pInfo - > m_aCommunityType , Community - > second . TypeName ( ) ) ;
return ;
}
}
str_copy ( pInfo - > m_aCommunityId , COMMUNITY_NONE ) ;
str_copy ( pInfo - > m_aCommunityCountry , " " ) ;
str_copy ( pInfo - > m_aCommunityType , " " ) ;
}
void CServerBrowser : : UpdateServerRank ( CServerInfo * pInfo ) const
{
const CCommunity * pCommunity = Community ( pInfo - > m_aCommunityId ) ;
pInfo - > m_HasRank = pCommunity = = nullptr ? CServerInfo : : RANK_UNAVAILABLE : pCommunity - > HasRank ( pInfo - > m_aMap ) ;
}
2022-02-21 00:04:49 +00:00
const char * CServerBrowser : : GetTutorialServer ( )
{
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
// Use internet tab as default after joining tutorial, also makes sure Find() actually works.
2022-03-24 15:14:54 +00:00
// Note that when no server info has been loaded yet, this will not return a result immediately.
2023-09-30 10:26:21 +00:00
m_pConfigManager - > Reset ( " ui_page " ) ;
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
Refresh ( IServerBrowser : : TYPE_INTERNET ) ;
2022-03-24 15:14:54 +00:00
2023-09-17 11:31:41 +00:00
const CCommunity * pCommunity = Community ( COMMUNITY_DDNET ) ;
if ( pCommunity = = nullptr )
return nullptr ;
2022-02-21 00:04:49 +00:00
const char * pBestAddr = nullptr ;
int BestLatency = std : : numeric_limits < int > : : max ( ) ;
2023-09-17 11:31:41 +00:00
for ( const auto & Country : pCommunity - > Countries ( ) )
2022-02-21 00:04:49 +00:00
{
2023-09-17 11:31:41 +00:00
for ( const auto & Server : Country . Servers ( ) )
2022-02-21 00:04:49 +00:00
{
2023-09-17 11:31:41 +00:00
CServerEntry * pEntry = Find ( Server . Address ( ) ) ;
2022-02-21 00:04:49 +00:00
if ( ! pEntry )
continue ;
if ( str_find ( pEntry - > m_Info . m_aName , " (Tutorial) " ) = = 0 )
continue ;
if ( pEntry - > m_Info . m_NumPlayers > pEntry - > m_Info . m_MaxPlayers - 10 )
continue ;
if ( pEntry - > m_Info . m_Latency > = BestLatency )
continue ;
BestLatency = pEntry - > m_Info . m_Latency ;
pBestAddr = pEntry - > m_Info . m_aAddress ;
}
}
return pBestAddr ;
}
2010-11-17 11:43:24 +00:00
bool CServerBrowser : : IsRefreshing ( ) const
{
2022-12-05 21:26:56 +00:00
return m_pFirstReqServer ! = nullptr ;
2010-11-17 11:43:24 +00:00
}
2010-05-29 07:25:38 +00:00
2018-07-11 20:46:04 +00:00
bool CServerBrowser : : IsGettingServerlist ( ) const
2010-05-29 07:25:38 +00:00
{
2018-07-11 20:46:04 +00:00
return m_pHttp - > IsRefreshing ( ) ;
2010-05-29 07:25:38 +00:00
}
2010-10-30 16:56:57 +00:00
int CServerBrowser : : LoadingProgression ( ) const
{
if ( m_NumServers = = 0 )
return 0 ;
2011-04-13 18:37:12 +00:00
2010-10-30 16:56:57 +00:00
int Servers = m_NumServers ;
2020-09-26 19:41:58 +00:00
int Loaded = m_NumServers - m_NumRequests ;
return 100.0f * Loaded / Servers ;
2010-10-30 16:56:57 +00:00
}
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
CServerInfo : : ERankState CCommunity : : HasRank ( const char * pMap ) const
{
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
if ( ! HasRanks ( ) )
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
return CServerInfo : : RANK_UNAVAILABLE ;
const CCommunityMap Needle ( pMap ) ;
Add icon URL, remove `servers-key`/`ranks-key` from community JSON
Previously:
```json
{
"ddnet": {
"name": "DDraceNetwork",
"servers-key": "servers",
"ranks-key": "maps",
"icon-sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b"
}
}
```
Now:
```json
[
{
"id": "ddnet",
"name": "DDraceNetwork",
"icon": {
"sha256": "162313eeb954e34495ad03066fee1418ed3c963e76cc83dff993e1c7856c742b",
"url": "https://info.ddnet.org/icons/ddnet.png"
},
"ranks": [
…
],
"servers": {
…
}
}
]
```
Special case `ddnet` to look for the `servers`, `maps` in the top-level
and `kog` to look for `servers-kog` in the top-level.
2023-11-18 20:52:51 +00:00
return m_FinishedMaps . count ( Needle ) = = 0 ? CServerInfo : : RANK_UNRANKED : CServerInfo : : RANK_RANKED ;
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
}
2023-09-17 11:31:41 +00:00
const std : : vector < CCommunity > & CServerBrowser : : Communities ( ) const
{
return m_vCommunities ;
}
const CCommunity * CServerBrowser : : Community ( const char * pCommunityId ) const
{
const auto Community = std : : find_if ( Communities ( ) . begin ( ) , Communities ( ) . end ( ) , [ pCommunityId ] ( const auto & Elem ) {
return str_comp ( Elem . Id ( ) , pCommunityId ) = = 0 ;
} ) ;
return Community = = Communities ( ) . end ( ) ? nullptr : & ( * Community ) ;
}
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
std : : vector < const CCommunity * > CServerBrowser : : SelectedCommunities ( ) const
{
std : : vector < const CCommunity * > vpSelected ;
for ( const auto & Community : Communities ( ) )
{
if ( ! CommunitiesFilter ( ) . Filtered ( Community . Id ( ) ) )
{
vpSelected . push_back ( & Community ) ;
}
}
return vpSelected ;
}
void CFilterList : : Add ( const char * pElement )
2014-09-19 21:52:09 +00:00
{
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
if ( Filtered ( pElement ) )
2014-09-19 21:52:09 +00:00
return ;
2015-07-09 00:08:14 +00:00
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
if ( m_pFilter [ 0 ] ! = ' \0 ' )
str_append ( m_pFilter , " , " , m_FilterSize ) ;
str_append ( m_pFilter , pElement , m_FilterSize ) ;
2014-09-19 21:52:09 +00:00
}
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
void CFilterList : : Remove ( const char * pElement )
2014-09-19 21:52:09 +00:00
{
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
if ( ! Filtered ( pElement ) )
2014-09-19 21:52:09 +00:00
return ;
// rewrite exclude/filter list
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
char aBuf [ 512 ] ;
2014-09-19 21:52:09 +00:00
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
str_copy ( aBuf , m_pFilter ) ;
m_pFilter [ 0 ] = ' \0 ' ;
2014-09-19 21:52:09 +00:00
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
char aToken [ 512 ] ;
2022-06-30 22:36:32 +00:00
for ( const char * pTok = aBuf ; ( pTok = str_next_token ( pTok , " , " , aToken , sizeof ( aToken ) ) ) ; )
2014-09-19 21:52:09 +00:00
{
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
if ( str_comp_nocase ( pElement , aToken ) ! = 0 )
2014-09-19 21:52:09 +00:00
{
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
if ( m_pFilter [ 0 ] ! = ' \0 ' )
str_append ( m_pFilter , " , " , m_FilterSize ) ;
str_append ( m_pFilter , aToken , m_FilterSize ) ;
2014-09-19 21:52:09 +00:00
}
2019-03-11 11:39:54 +00:00
}
2014-09-19 21:52:09 +00:00
}
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
void CFilterList : : Clear ( )
{
m_pFilter [ 0 ] = ' \0 ' ;
}
bool CFilterList : : Filtered ( const char * pElement ) const
2014-09-19 21:52:09 +00:00
{
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
// If the needle is not defined, we exclude it if there is any other
// exclusion, i.e. we only show those elements when the filter is empty.
if ( pElement [ 0 ] = = ' \0 ' )
return ! Empty ( ) ;
// Special case: "*element" means anything except that element is excluded.
// Necessary because the default filter cannot exclude unknown elements,
// but we want to select only the DDNet community by default.
if ( m_pFilter [ 0 ] = = ' * ' )
return str_comp ( m_pFilter + 1 , pElement ) ! = 0 ;
// Comma separated list of excluded elements.
return str_in_list ( m_pFilter , " , " , pElement ) ;
2014-09-19 21:52:09 +00:00
}
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
bool CFilterList : : Empty ( ) const
2014-09-19 21:52:09 +00:00
{
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
return m_pFilter [ 0 ] = = ' \0 ' ;
}
void CFilterList : : Clean ( const std : : vector < const char * > & vpAllowedElements )
{
char aNewList [ 512 ] ;
2016-05-19 13:54:52 +00:00
aNewList [ 0 ] = ' \0 ' ;
2015-07-09 00:08:14 +00:00
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
for ( const char * pElement : vpAllowedElements )
2014-09-19 21:52:09 +00:00
{
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
if ( Filtered ( pElement ) )
2014-09-19 21:52:09 +00:00
{
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
if ( aNewList [ 0 ] ! = ' \0 ' )
2023-09-17 11:31:41 +00:00
str_append ( aNewList , " , " ) ;
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
str_append ( aNewList , pElement ) ;
2014-09-19 21:52:09 +00:00
}
}
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
str_copy ( m_pFilter , aNewList , m_FilterSize ) ;
2014-09-19 21:52:09 +00:00
}
2014-12-14 15:45:18 +00:00
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
void CServerBrowser : : CleanFilters ( )
2014-12-14 15:45:18 +00:00
{
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
CommunitiesFilterClean ( ) ;
CountriesFilterClean ( ) ;
TypesFilterClean ( ) ;
}
2015-07-09 00:08:14 +00:00
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
void CServerBrowser : : CommunitiesFilterClean ( )
{
std : : vector < const char * > vpCommunityNames ;
for ( const auto & Community : Communities ( ) )
vpCommunityNames . push_back ( Community . Id ( ) ) ;
m_CommunitiesFilter . Clean ( vpCommunityNames ) ;
}
2014-12-14 15:45:18 +00:00
Add community server filter and icons, remove DDNet and KoG tabs
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes #5654.
2023-08-28 20:08:51 +00:00
void CServerBrowser : : CountriesFilterClean ( )
{
std : : vector < const char * > vpCountryNames ;
for ( const auto & Community : Communities ( ) )
for ( const auto & Country : Community . Countries ( ) )
vpCountryNames . push_back ( Country . Name ( ) ) ;
m_CountriesFilter . Clean ( vpCountryNames ) ;
}
void CServerBrowser : : TypesFilterClean ( )
{
std : : vector < const char * > vpTypeNames ;
for ( const auto & Community : Communities ( ) )
for ( const auto & Type : Community . Types ( ) )
vpTypeNames . push_back ( Type . Name ( ) ) ;
m_TypesFilter . Clean ( vpTypeNames ) ;
2014-12-14 15:45:18 +00:00
}
2018-07-11 20:46:04 +00:00
2022-10-09 11:43:10 +00:00
bool CServerBrowser : : IsRegistered ( const NETADDR & Addr )
{
const int NumServers = m_pHttp - > NumServers ( ) ;
for ( int i = 0 ; i < NumServers ; i + + )
{
const CServerInfo Info = m_pHttp - > Server ( i ) ;
for ( int j = 0 ; j < Info . m_NumAddresses ; j + + )
{
if ( net_addr_comp ( & Info . m_aAddresses [ j ] , & Addr ) = = 0 )
{
return true ;
}
}
}
const int NumLegacyServers = m_pHttp - > NumLegacyServers ( ) ;
for ( int i = 0 ; i < NumLegacyServers ; i + + )
{
if ( net_addr_comp ( & m_pHttp - > LegacyServer ( i ) , & Addr ) = = 0 )
{
return true ;
}
}
return false ;
}
2018-07-11 20:46:04 +00:00
int CServerInfo : : EstimateLatency ( int Loc1 , int Loc2 )
{
if ( Loc1 = = LOC_UNKNOWN | | Loc2 = = LOC_UNKNOWN )
{
return 999 ;
}
if ( Loc1 ! = Loc2 )
{
2021-05-27 19:45:12 +00:00
return 199 ;
2018-07-11 20:46:04 +00:00
}
2021-05-27 19:45:12 +00:00
return 99 ;
2018-07-11 20:46:04 +00:00
}
2023-01-06 20:14:26 +00:00
2018-07-11 20:46:04 +00:00
bool CServerInfo : : ParseLocation ( int * pResult , const char * pString )
{
* pResult = LOC_UNKNOWN ;
int Length = str_length ( pString ) ;
if ( Length < 2 )
{
return true ;
}
// ISO continent code. Allow antarctica, but treat it as unknown.
2023-09-17 11:30:45 +00:00
static const char s_apLocations [ NUM_LOCS ] [ 6 ] = {
2018-07-11 20:46:04 +00:00
" an " , // LOC_UNKNOWN
" af " , // LOC_AFRICA
" as " , // LOC_ASIA
" oc " , // LOC_AUSTRALIA
" eu " , // LOC_EUROPE
" na " , // LOC_NORTH_AMERICA
" sa " , // LOC_SOUTH_AMERICA
2021-04-24 13:48:27 +00:00
" as:cn " , // LOC_CHINA
2018-07-11 20:46:04 +00:00
} ;
2022-06-30 22:36:32 +00:00
for ( int i = std : : size ( s_apLocations ) - 1 ; i > = 0 ; i - - )
2018-07-11 20:46:04 +00:00
{
2022-06-30 22:36:32 +00:00
if ( str_startswith ( pString , s_apLocations [ i ] ) )
2018-07-11 20:46:04 +00:00
{
* pResult = i ;
return false ;
}
}
return true ;
}
2023-01-06 20:14:26 +00:00
void CServerInfo : : InfoToString ( char * pBuffer , int BufferSize ) const
{
str_format (
pBuffer ,
BufferSize ,
" %s \n "
" Address: ddnet://%s \n "
" My IGN: %s \n " ,
m_aName ,
m_aAddress ,
g_Config . m_PlayerName ) ;
}