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:
Robert Müller 2023-09-17 13:31:41 +02:00
parent 2973eee036
commit ce65d57f2e
5 changed files with 219 additions and 194 deletions

View file

@ -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());
}
}

View file

@ -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;

View file

@ -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;
};

View file

@ -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;

View file

@ -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);