mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Support dynamic list of "communities" in engine serverbrowser
Replace existing hard-coded support for two "networks" with support for a dynamic list of "communities" which are indexed by a string-ID, though right now the DDNet and KoG communities are still hard-coded. The communities now also support an arbitrary number of associated countries, types and servers. This is a refactoring to prepare for getting the list of communities dynamically from the server and removing the DDNet and KoG tabs from the serverbrowser.
This commit is contained in:
parent
2973eee036
commit
ce65d57f2e
|
@ -678,21 +678,25 @@ CServerBrowser::CServerEntry *CServerBrowser::Add(const NETADDR *pAddrs, int Num
|
|||
|
||||
// check if it's an official server
|
||||
bool Official = false;
|
||||
for(const auto &Network : m_aNetworks)
|
||||
for(const auto &Community : Communities())
|
||||
{
|
||||
for(int j = 0; !Official && j < Network.m_NumCountries; j++)
|
||||
for(const auto &Country : Community.Countries())
|
||||
{
|
||||
const CNetworkCountry *pCntr = &Network.m_aCountries[j];
|
||||
for(int k = 0; !Official && k < pCntr->m_NumServers; k++)
|
||||
for(const auto &Server : Country.Servers())
|
||||
{
|
||||
for(int l = 0; !Official && l < NumAddrs; l++)
|
||||
for(int l = 0; l < NumAddrs; l++)
|
||||
{
|
||||
if(pAddrs[l] == pCntr->m_aServers[k])
|
||||
if(pAddrs[l] == Server.Address())
|
||||
{
|
||||
Official = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(Official)
|
||||
break;
|
||||
}
|
||||
if(Official)
|
||||
break;
|
||||
}
|
||||
if(Official)
|
||||
break;
|
||||
|
@ -949,18 +953,18 @@ void CServerBrowser::UpdateFromHttp()
|
|||
}
|
||||
else
|
||||
{
|
||||
int Network;
|
||||
int CommunityIndex;
|
||||
char *pExcludeCountries;
|
||||
char *pExcludeTypes;
|
||||
switch(m_ServerlistType)
|
||||
{
|
||||
case IServerBrowser::TYPE_DDNET:
|
||||
Network = NETWORK_DDNET;
|
||||
CommunityIndex = NETWORK_DDNET;
|
||||
pExcludeCountries = g_Config.m_BrFilterExcludeCountries;
|
||||
pExcludeTypes = g_Config.m_BrFilterExcludeTypes;
|
||||
break;
|
||||
case IServerBrowser::TYPE_KOG:
|
||||
Network = NETWORK_KOG;
|
||||
CommunityIndex = NETWORK_KOG;
|
||||
pExcludeCountries = g_Config.m_BrFilterExcludeCountriesKoG;
|
||||
pExcludeTypes = g_Config.m_BrFilterExcludeTypesKoG;
|
||||
break;
|
||||
|
@ -968,33 +972,22 @@ void CServerBrowser::UpdateFromHttp()
|
|||
dbg_assert(false, "invalid network");
|
||||
return;
|
||||
}
|
||||
// remove unknown elements of exclude list
|
||||
CountryFilterClean(Network);
|
||||
TypeFilterClean(Network);
|
||||
// remove unknown elements from exclude lists
|
||||
CountryFilterClean(CommunityIndex);
|
||||
TypeFilterClean(CommunityIndex);
|
||||
|
||||
int MaxServers = 0;
|
||||
for(int i = 0; i < m_aNetworks[Network].m_NumCountries; i++)
|
||||
const CCommunity &Community = Communities()[CommunityIndex];
|
||||
for(const auto &Country : Community.Countries())
|
||||
{
|
||||
CNetworkCountry *pCntr = &m_aNetworks[Network].m_aCountries[i];
|
||||
MaxServers = maximum(MaxServers, pCntr->m_NumServers);
|
||||
}
|
||||
// check for filter
|
||||
if(DDNetFiltered(pExcludeCountries, Country.Name()))
|
||||
continue;
|
||||
|
||||
for(int g = 0; g < MaxServers; g++)
|
||||
{
|
||||
for(int i = 0; i < m_aNetworks[Network].m_NumCountries; i++)
|
||||
for(const auto &Server : Country.Servers())
|
||||
{
|
||||
CNetworkCountry *pCntr = &m_aNetworks[Network].m_aCountries[i];
|
||||
|
||||
// check for filter
|
||||
if(DDNetFiltered(pExcludeCountries, pCntr->m_aName))
|
||||
if(DDNetFiltered(pExcludeTypes, Server.TypeName()))
|
||||
continue;
|
||||
|
||||
if(g >= pCntr->m_NumServers)
|
||||
continue;
|
||||
|
||||
if(DDNetFiltered(pExcludeTypes, pCntr->m_aTypes[g]))
|
||||
continue;
|
||||
WantedAddrs.insert(pCntr->m_aServers[g]);
|
||||
WantedAddrs.insert(Server.Address());
|
||||
}
|
||||
}
|
||||
Want = [&](const NETADDR *pAddrs, int NumAddrs) -> bool {
|
||||
|
@ -1180,103 +1173,92 @@ void CServerBrowser::Update()
|
|||
|
||||
void CServerBrowser::LoadDDNetServers()
|
||||
{
|
||||
// parse communities (hard-coded for now)
|
||||
m_vCommunities.clear();
|
||||
m_vCommunities.emplace_back(COMMUNITY_DDNET, "DDNet", "servers");
|
||||
m_vCommunities.emplace_back("kog", "KoG", "servers-kog");
|
||||
|
||||
if(!m_pDDNetInfo)
|
||||
return;
|
||||
|
||||
// reset servers / countries
|
||||
for(int Network = 0; Network < NUM_NETWORKS; Network++)
|
||||
// parse servers for each community
|
||||
for(auto &Community : m_vCommunities)
|
||||
{
|
||||
CNetwork *pNet = &m_aNetworks[Network];
|
||||
|
||||
// parse JSON
|
||||
const json_value *pServers = json_object_get(m_pDDNetInfo, Network == NETWORK_DDNET ? "servers" : "servers-kog");
|
||||
|
||||
if(!pServers || pServers->type != json_array)
|
||||
const json_value &Servers = (*m_pDDNetInfo)[Community.JsonServersKey()];
|
||||
if(Servers.type != json_array)
|
||||
return;
|
||||
|
||||
pNet->m_NumCountries = 0;
|
||||
pNet->m_NumTypes = 0;
|
||||
|
||||
for(int i = 0; i < json_array_length(pServers) && pNet->m_NumCountries < MAX_COUNTRIES; i++)
|
||||
for(unsigned ServerIndex = 0; ServerIndex < Servers.u.array.length; ++ServerIndex)
|
||||
{
|
||||
// pSrv - { name, flagId, servers }
|
||||
const json_value *pSrv = json_array_get(pServers, i);
|
||||
const json_value *pTypes = json_object_get(pSrv, "servers");
|
||||
const json_value *pName = json_object_get(pSrv, "name");
|
||||
const json_value *pFlagID = json_object_get(pSrv, "flagId");
|
||||
|
||||
if(pSrv->type != json_object || pTypes->type != json_object || pName->type != json_string || pFlagID->type != json_integer)
|
||||
// pServer - { name, flagId, servers }
|
||||
const json_value &Server = *Servers.u.array.values[ServerIndex];
|
||||
if(Server.type != json_object)
|
||||
{
|
||||
dbg_msg("serverbrowser", "invalid attributes");
|
||||
dbg_msg("serverbrowser", "invalid attributes (ServerIndex=%u)", ServerIndex);
|
||||
continue;
|
||||
}
|
||||
|
||||
// build structure
|
||||
CNetworkCountry *pCntr = &pNet->m_aCountries[pNet->m_NumCountries];
|
||||
|
||||
pCntr->Reset();
|
||||
|
||||
str_copy(pCntr->m_aName, json_string_get(pName));
|
||||
pCntr->m_FlagID = json_int_get(pFlagID);
|
||||
|
||||
// add country
|
||||
for(unsigned int t = 0; t < pTypes->u.object.length; t++)
|
||||
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)
|
||||
{
|
||||
const char *pType = pTypes->u.object.values[t].name;
|
||||
const json_value *pAddrs = pTypes->u.object.values[t].value;
|
||||
dbg_msg("serverbrowser", "invalid attributes (ServerIndex=%u)", ServerIndex);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(pAddrs->type != json_array)
|
||||
Community.m_vCountries.emplace_back(Name.u.string.ptr, FlagId.u.integer);
|
||||
CCommunityCountry *pCountry = &Community.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)
|
||||
{
|
||||
dbg_msg("serverbrowser", "invalid attributes");
|
||||
dbg_msg("serverbrowser", "invalid attributes (ServerIndex=%u, TypeIndex=%u)", ServerIndex, TypeIndex);
|
||||
continue;
|
||||
}
|
||||
if(Addresses.u.array.length == 0)
|
||||
continue;
|
||||
|
||||
// add type
|
||||
if(json_array_length(pAddrs) > 0 && pNet->m_NumTypes < MAX_TYPES)
|
||||
const char *pTypeName = Types.u.object.values[TypeIndex].name;
|
||||
|
||||
// add type if it doesn't exist already
|
||||
const auto CommunityType = std::find_if(Community.m_vTypes.begin(), Community.m_vTypes.end(), [pTypeName](const auto &Elem) {
|
||||
return str_comp(Elem.Name(), pTypeName) == 0;
|
||||
});
|
||||
if(CommunityType == Community.m_vTypes.end())
|
||||
{
|
||||
int Pos;
|
||||
for(Pos = 0; Pos < pNet->m_NumTypes; Pos++)
|
||||
{
|
||||
if(!str_comp(pNet->m_aTypes[Pos], pType))
|
||||
break;
|
||||
}
|
||||
if(Pos == pNet->m_NumTypes)
|
||||
{
|
||||
str_copy(pNet->m_aTypes[pNet->m_NumTypes], pType);
|
||||
pNet->m_NumTypes++;
|
||||
}
|
||||
Community.m_vTypes.emplace_back(pTypeName);
|
||||
}
|
||||
|
||||
// add addresses
|
||||
for(int g = 0; g < json_array_length(pAddrs); g++, pCntr->m_NumServers++)
|
||||
for(unsigned AddressIndex = 0; AddressIndex < Addresses.u.array.length; ++AddressIndex)
|
||||
{
|
||||
const json_value *pAddr = json_array_get(pAddrs, g);
|
||||
if(pAddr->type != json_string)
|
||||
const json_value &Address = *Addresses.u.array.values[AddressIndex];
|
||||
if(Address.type != json_string)
|
||||
{
|
||||
dbg_msg("serverbrowser", "invalid attributes");
|
||||
dbg_msg("serverbrowser", "invalid attributes (ServerIndex=%u, TypeIndex=%u, AddressIndex=%u)", ServerIndex, TypeIndex, AddressIndex);
|
||||
continue;
|
||||
}
|
||||
const char *pStr = json_string_get(pAddr);
|
||||
net_addr_from_str(&pCntr->m_aServers[pCntr->m_NumServers], pStr);
|
||||
str_copy(pCntr->m_aTypes[pCntr->m_NumServers], pType);
|
||||
NETADDR NetAddr;
|
||||
net_addr_from_str(&NetAddr, Address.u.string.ptr);
|
||||
pCountry->m_vServers.emplace_back(NetAddr, pTypeName);
|
||||
}
|
||||
}
|
||||
|
||||
pNet->m_NumCountries++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CServerBrowser::RecheckOfficial()
|
||||
{
|
||||
for(auto &Network : m_aNetworks)
|
||||
for(const auto &Community : Communities())
|
||||
{
|
||||
for(int i = 0; i < Network.m_NumCountries; i++)
|
||||
for(const auto &Country : Community.Countries())
|
||||
{
|
||||
CNetworkCountry *pCntr = &Network.m_aCountries[i];
|
||||
for(int j = 0; j < pCntr->m_NumServers; j++)
|
||||
for(const auto &Server : Country.Servers())
|
||||
{
|
||||
CServerEntry *pEntry = Find(pCntr->m_aServers[j]);
|
||||
CServerEntry *pEntry = Find(Server.Address());
|
||||
if(pEntry)
|
||||
{
|
||||
pEntry->m_Info.m_Official = true;
|
||||
|
@ -1356,16 +1338,17 @@ const char *CServerBrowser::GetTutorialServer()
|
|||
g_Config.m_UiPage = CMenus::PAGE_DDNET;
|
||||
Refresh(IServerBrowser::TYPE_DDNET);
|
||||
|
||||
CNetwork *pNetwork = &m_aNetworks[NETWORK_DDNET];
|
||||
const CCommunity *pCommunity = Community(COMMUNITY_DDNET);
|
||||
if(pCommunity == nullptr)
|
||||
return nullptr;
|
||||
|
||||
const char *pBestAddr = nullptr;
|
||||
int BestLatency = std::numeric_limits<int>::max();
|
||||
|
||||
for(int i = 0; i < pNetwork->m_NumCountries; i++)
|
||||
for(const auto &Country : pCommunity->Countries())
|
||||
{
|
||||
CNetworkCountry *pCntr = &pNetwork->m_aCountries[i];
|
||||
for(int j = 0; j < pCntr->m_NumServers; j++)
|
||||
for(const auto &Server : Country.Servers())
|
||||
{
|
||||
CServerEntry *pEntry = Find(pCntr->m_aServers[j]);
|
||||
CServerEntry *pEntry = Find(Server.Address());
|
||||
if(!pEntry)
|
||||
continue;
|
||||
if(str_find(pEntry->m_Info.m_aName, "(Tutorial)") == 0)
|
||||
|
@ -1412,14 +1395,26 @@ int CServerBrowser::LoadingProgression() const
|
|||
return 100.0f * Loaded / Servers;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void CServerBrowser::DDNetFilterAdd(char *pFilter, int FilterSize, const char *pName) const
|
||||
{
|
||||
if(DDNetFiltered(pFilter, pName))
|
||||
return;
|
||||
|
||||
char aBuf[128];
|
||||
str_format(aBuf, sizeof(aBuf), ",%s", pName);
|
||||
str_append(pFilter, aBuf, FilterSize);
|
||||
str_append(pFilter, ",", FilterSize);
|
||||
str_append(pFilter, pName, FilterSize);
|
||||
}
|
||||
|
||||
void CServerBrowser::DDNetFilterRem(char *pFilter, int FilterSize, const char *pName) const
|
||||
|
@ -1438,34 +1433,31 @@ void CServerBrowser::DDNetFilterRem(char *pFilter, int FilterSize, const char *p
|
|||
{
|
||||
if(str_comp_nocase(pName, aToken) != 0)
|
||||
{
|
||||
char aBuf2[128];
|
||||
str_format(aBuf2, sizeof(aBuf2), ",%s", aToken);
|
||||
str_append(pFilter, aBuf2, FilterSize);
|
||||
str_append(pFilter, ",", FilterSize);
|
||||
str_append(pFilter, aToken, FilterSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CServerBrowser::DDNetFiltered(const char *pFilter, const char *pName) const
|
||||
{
|
||||
return str_in_list(pFilter, ",", pName); // country not excluded
|
||||
return str_in_list(pFilter, ",", pName); // element not excluded
|
||||
}
|
||||
|
||||
void CServerBrowser::CountryFilterClean(int Network)
|
||||
void CServerBrowser::CountryFilterClean(int CommunityIndex)
|
||||
{
|
||||
char *pExcludeCountries = Network == NETWORK_KOG ? g_Config.m_BrFilterExcludeCountriesKoG : g_Config.m_BrFilterExcludeCountries;
|
||||
char aNewList[128];
|
||||
char *pExcludeCountries = CommunityIndex == NETWORK_DDNET ? g_Config.m_BrFilterExcludeCountries : g_Config.m_BrFilterExcludeCountriesKoG;
|
||||
char aNewList[sizeof(g_Config.m_BrFilterExcludeCountries)];
|
||||
aNewList[0] = '\0';
|
||||
|
||||
for(auto &Net : m_aNetworks)
|
||||
for(const auto &Community : Communities())
|
||||
{
|
||||
for(int i = 0; i < Net.m_NumCountries; i++)
|
||||
for(const auto &Country : Community.Countries())
|
||||
{
|
||||
const char *pName = Net.m_aCountries[i].m_aName;
|
||||
if(DDNetFiltered(pExcludeCountries, pName))
|
||||
if(DDNetFiltered(pExcludeCountries, Country.Name()))
|
||||
{
|
||||
char aBuf[128];
|
||||
str_format(aBuf, sizeof(aBuf), ",%s", pName);
|
||||
str_append(aNewList, aBuf);
|
||||
str_append(aNewList, ",");
|
||||
str_append(aNewList, Country.Name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1473,20 +1465,19 @@ void CServerBrowser::CountryFilterClean(int Network)
|
|||
str_copy(pExcludeCountries, aNewList, sizeof(g_Config.m_BrFilterExcludeCountries));
|
||||
}
|
||||
|
||||
void CServerBrowser::TypeFilterClean(int Network)
|
||||
void CServerBrowser::TypeFilterClean(int CommunityIndex)
|
||||
{
|
||||
char *pExcludeTypes = Network == NETWORK_KOG ? g_Config.m_BrFilterExcludeTypesKoG : g_Config.m_BrFilterExcludeTypes;
|
||||
char aNewList[128];
|
||||
char *pExcludeTypes = CommunityIndex == NETWORK_DDNET ? g_Config.m_BrFilterExcludeTypes : g_Config.m_BrFilterExcludeTypesKoG;
|
||||
char aNewList[sizeof(g_Config.m_BrFilterExcludeTypes)];
|
||||
aNewList[0] = '\0';
|
||||
|
||||
for(int i = 0; i < m_aNetworks[Network].m_NumTypes; i++)
|
||||
const CCommunity &Community = Communities()[CommunityIndex];
|
||||
for(const auto &Type : Community.Types())
|
||||
{
|
||||
const char *pName = m_aNetworks[Network].m_aTypes[i];
|
||||
if(DDNetFiltered(pExcludeTypes, pName))
|
||||
if(DDNetFiltered(pExcludeTypes, Type.Name()))
|
||||
{
|
||||
char aBuf[128];
|
||||
str_format(aBuf, sizeof(aBuf), ",%s", pName);
|
||||
str_append(aNewList, aBuf);
|
||||
str_append(aNewList, ",");
|
||||
str_append(aNewList, Type.Name());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,43 +38,6 @@ public:
|
|||
CServerEntry *m_pNextReq;
|
||||
};
|
||||
|
||||
struct CNetworkCountry
|
||||
{
|
||||
enum
|
||||
{
|
||||
MAX_SERVERS = 1024
|
||||
};
|
||||
|
||||
char m_aName[256];
|
||||
int m_FlagID;
|
||||
NETADDR m_aServers[MAX_SERVERS];
|
||||
char m_aTypes[MAX_SERVERS][32];
|
||||
int m_NumServers;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_NumServers = 0;
|
||||
m_FlagID = -1;
|
||||
m_aName[0] = '\0';
|
||||
};
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_FAVORITES = 2048,
|
||||
MAX_COUNTRIES = 32,
|
||||
MAX_TYPES = 32,
|
||||
};
|
||||
|
||||
struct CNetwork
|
||||
{
|
||||
CNetworkCountry m_aCountries[MAX_COUNTRIES];
|
||||
int m_NumCountries;
|
||||
|
||||
char m_aTypes[MAX_TYPES][32];
|
||||
int m_NumTypes;
|
||||
};
|
||||
|
||||
CServerBrowser();
|
||||
virtual ~CServerBrowser();
|
||||
|
||||
|
@ -107,18 +70,15 @@ public:
|
|||
void LoadDDNetInfoJson();
|
||||
const json_value *LoadDDNetInfo();
|
||||
int HasRank(const char *pMap);
|
||||
int NumCountries(int Network) override { return m_aNetworks[Network].m_NumCountries; }
|
||||
int GetCountryFlag(int Network, int Index) override { return m_aNetworks[Network].m_aCountries[Index].m_FlagID; }
|
||||
const char *GetCountryName(int Network, int Index) override { return m_aNetworks[Network].m_aCountries[Index].m_aName; }
|
||||
|
||||
int NumTypes(int Network) override { return m_aNetworks[Network].m_NumTypes; }
|
||||
const char *GetType(int Network, int Index) override { return m_aNetworks[Network].m_aTypes[Index]; }
|
||||
const std::vector<CCommunity> &Communities() const override;
|
||||
const CCommunity *Community(const char *pCommunityId) const override;
|
||||
|
||||
void DDNetFilterAdd(char *pFilter, int FilterSize, const char *pName) const override;
|
||||
void DDNetFilterRem(char *pFilter, int FilterSize, const char *pName) const override;
|
||||
bool DDNetFiltered(const char *pFilter, const char *pName) const override;
|
||||
void CountryFilterClean(int Network) override;
|
||||
void TypeFilterClean(int Network) override;
|
||||
void CountryFilterClean(int CommunityIndex) override;
|
||||
void TypeFilterClean(int CommunityIndex) override;
|
||||
|
||||
//
|
||||
void Update();
|
||||
|
@ -155,7 +115,7 @@ private:
|
|||
int *m_pSortedServerlist;
|
||||
std::unordered_map<NETADDR, int> m_ByAddr;
|
||||
|
||||
CNetwork m_aNetworks[NUM_NETWORKS];
|
||||
std::vector<CCommunity> m_vCommunities;
|
||||
int m_OwnLocation = CServerInfo::LOC_UNKNOWN;
|
||||
|
||||
json_value *m_pDDNetInfo;
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include "kernel.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define DDNET_INFO "ddnet-info.json"
|
||||
|
||||
class CUIElement;
|
||||
|
@ -99,6 +101,80 @@ public:
|
|||
void InfoToString(char *pBuffer, int BufferSize) const;
|
||||
};
|
||||
|
||||
class CCommunityCountryServer
|
||||
{
|
||||
NETADDR m_Address;
|
||||
char m_aTypeName[32];
|
||||
|
||||
public:
|
||||
CCommunityCountryServer(NETADDR Address, const char *pTypeName) :
|
||||
m_Address(Address)
|
||||
{
|
||||
str_copy(m_aTypeName, pTypeName);
|
||||
}
|
||||
|
||||
NETADDR Address() const { return m_Address; }
|
||||
const char *TypeName() const { return m_aTypeName; }
|
||||
};
|
||||
|
||||
class CCommunityCountry
|
||||
{
|
||||
friend class CServerBrowser;
|
||||
|
||||
char m_aName[256];
|
||||
int m_FlagId;
|
||||
std::vector<CCommunityCountryServer> m_vServers;
|
||||
|
||||
public:
|
||||
CCommunityCountry(const char *pName, int FlagId) :
|
||||
m_FlagId(FlagId)
|
||||
{
|
||||
str_copy(m_aName, pName);
|
||||
}
|
||||
|
||||
const char *Name() const { return m_aName; }
|
||||
int FlagId() const { return m_FlagId; }
|
||||
const std::vector<CCommunityCountryServer> &Servers() const { return m_vServers; }
|
||||
};
|
||||
|
||||
class CCommunityType
|
||||
{
|
||||
char m_aName[32];
|
||||
|
||||
public:
|
||||
CCommunityType(const char *pName)
|
||||
{
|
||||
str_copy(m_aName, pName);
|
||||
}
|
||||
|
||||
const char *Name() const { return m_aName; }
|
||||
};
|
||||
|
||||
class CCommunity
|
||||
{
|
||||
friend class CServerBrowser;
|
||||
|
||||
char m_aId[32];
|
||||
char m_aName[64];
|
||||
char m_aJsonServersKey[32];
|
||||
std::vector<CCommunityCountry> m_vCountries;
|
||||
std::vector<CCommunityType> m_vTypes;
|
||||
|
||||
public:
|
||||
CCommunity(const char *pId, const char *pName, const char *pJsonServersKey)
|
||||
{
|
||||
str_copy(m_aId, pId);
|
||||
str_copy(m_aName, pName);
|
||||
str_copy(m_aJsonServersKey, pJsonServersKey);
|
||||
}
|
||||
|
||||
const char *Id() const { return m_aId; }
|
||||
const char *Name() const { return m_aName; }
|
||||
const char *JsonServersKey() const { return m_aJsonServersKey; }
|
||||
const std::vector<CCommunityCountry> &Countries() const { return m_vCountries; }
|
||||
const std::vector<CCommunityType> &Types() const { return m_vTypes; }
|
||||
};
|
||||
|
||||
class IServerBrowser : public IInterface
|
||||
{
|
||||
MACRO_INTERFACE("serverbrowser", 0)
|
||||
|
@ -129,11 +205,14 @@ public:
|
|||
TYPE_DDNET = 4,
|
||||
TYPE_KOG = 5,
|
||||
|
||||
// TODO: remove integer community index and used string IDs instead
|
||||
NETWORK_DDNET = 0,
|
||||
NETWORK_KOG = 1,
|
||||
NUM_NETWORKS,
|
||||
};
|
||||
|
||||
static constexpr const char *COMMUNITY_DDNET = "ddnet";
|
||||
|
||||
static constexpr const char *SEARCH_EXCLUDE_TOKEN = ";";
|
||||
|
||||
virtual void Refresh(int Type) = 0;
|
||||
|
@ -149,18 +228,14 @@ public:
|
|||
virtual int NumSortedServers() const = 0;
|
||||
virtual const CServerInfo *SortedGet(int Index) const = 0;
|
||||
|
||||
virtual int NumCountries(int Network) = 0;
|
||||
virtual int GetCountryFlag(int Network, int Index) = 0;
|
||||
virtual const char *GetCountryName(int Network, int Index) = 0;
|
||||
|
||||
virtual int NumTypes(int Network) = 0;
|
||||
virtual const char *GetType(int Network, int Index) = 0;
|
||||
virtual const std::vector<CCommunity> &Communities() const = 0;
|
||||
virtual const CCommunity *Community(const char *pCommunityId) const = 0;
|
||||
|
||||
virtual void DDNetFilterAdd(char *pFilter, int FilterSize, const char *pName) const = 0;
|
||||
virtual void DDNetFilterRem(char *pFilter, int FilterSize, const char *pName) const = 0;
|
||||
virtual bool DDNetFiltered(const char *pFilter, const char *pName) const = 0;
|
||||
virtual void CountryFilterClean(int Network) = 0;
|
||||
virtual void TypeFilterClean(int Network) = 0;
|
||||
virtual void CountryFilterClean(int CommunityIndex) = 0;
|
||||
virtual void TypeFilterClean(int CommunityIndex) = 0;
|
||||
virtual int GetCurrentType() = 0;
|
||||
virtual const char *GetTutorialServer() = 0;
|
||||
};
|
||||
|
|
|
@ -464,8 +464,8 @@ protected:
|
|||
CScrollRegion &ScrollRegion, std::vector<unsigned char> &vItemIds,
|
||||
const std::function<const char *(int ItemIndex)> &GetItemName,
|
||||
const std::function<void(int ItemIndex, CUIRect Item, const void *pItemId, bool Active)> &RenderItem);
|
||||
void RenderServerbrowserCountriesFilter(CUIRect View, int Network);
|
||||
void RenderServerbrowserTypesFilter(CUIRect View, int Network);
|
||||
void RenderServerbrowserCountriesFilter(CUIRect View, const CCommunity &Community);
|
||||
void RenderServerbrowserTypesFilter(CUIRect View, const CCommunity &Community);
|
||||
struct SPopupCountrySelectionContext
|
||||
{
|
||||
CMenus *m_pMenus;
|
||||
|
|
|
@ -722,7 +722,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
|
|||
const ColorRGBA ColorActive = ColorRGBA(0.0f, 0.0f, 0.0f, 0.3f);
|
||||
const ColorRGBA ColorInactive = ColorRGBA(0.0f, 0.0f, 0.0f, 0.15f);
|
||||
|
||||
const int Network = g_Config.m_UiPage == PAGE_DDNET ? IServerBrowser::NETWORK_DDNET : IServerBrowser::NETWORK_KOG;
|
||||
const CCommunity &Community = ServerBrowser()->Communities()[g_Config.m_UiPage == PAGE_DDNET ? IServerBrowser::NETWORK_DDNET : IServerBrowser::NETWORK_KOG];
|
||||
|
||||
CUIRect TabContents, CountriesTab, TypesTab;
|
||||
View.HSplitTop(6.0f, nullptr, &View);
|
||||
|
@ -752,11 +752,11 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
|
|||
|
||||
if(s_ActiveTab == FILTERTAB_COUNTRIES)
|
||||
{
|
||||
RenderServerbrowserCountriesFilter(TabContents, Network);
|
||||
RenderServerbrowserCountriesFilter(TabContents, Community);
|
||||
}
|
||||
else if(s_ActiveTab == FILTERTAB_TYPES)
|
||||
{
|
||||
RenderServerbrowserTypesFilter(TabContents, Network);
|
||||
RenderServerbrowserTypesFilter(TabContents, Community);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -883,11 +883,11 @@ void CMenus::RenderServerbrowserDDNetFilter(CUIRect View,
|
|||
ScrollRegion.End();
|
||||
}
|
||||
|
||||
void CMenus::RenderServerbrowserCountriesFilter(CUIRect View, int Network)
|
||||
void CMenus::RenderServerbrowserCountriesFilter(CUIRect View, const CCommunity &Community)
|
||||
{
|
||||
char *pFilterExcludeCountries = Network == IServerBrowser::NETWORK_DDNET ? g_Config.m_BrFilterExcludeCountries : g_Config.m_BrFilterExcludeCountriesKoG;
|
||||
const int FilterExcludeCountriesSize = Network == IServerBrowser::NETWORK_DDNET ? sizeof(g_Config.m_BrFilterExcludeCountries) : sizeof(g_Config.m_BrFilterExcludeCountriesKoG);
|
||||
const int MaxEntries = ServerBrowser()->NumCountries(Network);
|
||||
char *pFilterExcludeCountries = str_comp(Community.Id(), IServerBrowser::COMMUNITY_DDNET) == 0 ? g_Config.m_BrFilterExcludeCountries : g_Config.m_BrFilterExcludeCountriesKoG;
|
||||
const int FilterExcludeCountriesSize = str_comp(Community.Id(), IServerBrowser::COMMUNITY_DDNET) == 0 ? sizeof(g_Config.m_BrFilterExcludeCountries) : sizeof(g_Config.m_BrFilterExcludeCountriesKoG);
|
||||
const int MaxEntries = Community.Countries().size();
|
||||
const int EntriesPerRow = MaxEntries > 8 ? 5 : 4;
|
||||
|
||||
static CScrollRegion s_ScrollRegion;
|
||||
|
@ -897,25 +897,24 @@ void CMenus::RenderServerbrowserCountriesFilter(CUIRect View, int Network)
|
|||
const float Spacing = 2.0f;
|
||||
|
||||
const auto &&GetItemName = [&](int ItemIndex) {
|
||||
return ServerBrowser()->GetCountryName(Network, ItemIndex);
|
||||
return Community.Countries()[ItemIndex].Name();
|
||||
};
|
||||
const auto &&RenderItem = [&](int ItemIndex, CUIRect Item, const void *pItemId, bool Active) {
|
||||
Item.Margin(Spacing, &Item);
|
||||
const float OldWidth = Item.w;
|
||||
Item.w = Item.h * 2.0f;
|
||||
Item.x += (OldWidth - Item.w) / 2.0f;
|
||||
const int FlagID = ServerBrowser()->GetCountryFlag(Network, ItemIndex);
|
||||
m_pClient->m_CountryFlags.Render(FlagID, ColorRGBA(1.0f, 1.0f, 1.0f, (Active ? 0.9f : 0.2f) + (UI()->HotItem() == pItemId ? 0.1f : 0.0f)), Item.x, Item.y, Item.w, Item.h);
|
||||
m_pClient->m_CountryFlags.Render(Community.Countries()[ItemIndex].FlagId(), ColorRGBA(1.0f, 1.0f, 1.0f, (Active ? 0.9f : 0.2f) + (UI()->HotItem() == pItemId ? 0.1f : 0.0f)), Item.x, Item.y, Item.w, Item.h);
|
||||
};
|
||||
|
||||
RenderServerbrowserDDNetFilter(View, pFilterExcludeCountries, FilterExcludeCountriesSize, ItemHeight + 2.0f * Spacing, MaxEntries, EntriesPerRow, s_ScrollRegion, s_vItemIds, GetItemName, RenderItem);
|
||||
}
|
||||
|
||||
void CMenus::RenderServerbrowserTypesFilter(CUIRect View, int Network)
|
||||
void CMenus::RenderServerbrowserTypesFilter(CUIRect View, const CCommunity &Community)
|
||||
{
|
||||
char *pFilterExcludeTypes = Network == IServerBrowser::NETWORK_DDNET ? g_Config.m_BrFilterExcludeTypes : g_Config.m_BrFilterExcludeTypesKoG;
|
||||
const int FilterExcludeTypesSize = Network == IServerBrowser::NETWORK_DDNET ? sizeof(g_Config.m_BrFilterExcludeTypes) : sizeof(g_Config.m_BrFilterExcludeTypesKoG);
|
||||
const int MaxEntries = ServerBrowser()->NumTypes(Network);
|
||||
char *pFilterExcludeTypes = str_comp(Community.Id(), IServerBrowser::COMMUNITY_DDNET) == 0 ? g_Config.m_BrFilterExcludeTypes : g_Config.m_BrFilterExcludeTypesKoG;
|
||||
const int FilterExcludeTypesSize = str_comp(Community.Id(), IServerBrowser::COMMUNITY_DDNET) == 0 ? sizeof(g_Config.m_BrFilterExcludeTypes) : sizeof(g_Config.m_BrFilterExcludeTypesKoG);
|
||||
const int MaxEntries = Community.Types().size();
|
||||
const int EntriesPerRow = 3;
|
||||
|
||||
static CScrollRegion s_ScrollRegion;
|
||||
|
@ -925,7 +924,7 @@ void CMenus::RenderServerbrowserTypesFilter(CUIRect View, int Network)
|
|||
const float Spacing = 2.0f;
|
||||
|
||||
const auto &&GetItemName = [&](int ItemIndex) {
|
||||
return ServerBrowser()->GetType(Network, ItemIndex);
|
||||
return Community.Types()[ItemIndex].Name();
|
||||
};
|
||||
const auto &&RenderItem = [&](int ItemIndex, CUIRect Item, const void *pItemId, bool Active) {
|
||||
Item.Margin(Spacing, &Item);
|
||||
|
|
Loading…
Reference in a new issue