Add KoG tab in server browser

- As requested by qshar and KoG players
- Similar to DDNet tab
- Info fetched from servers-kog entry from https://info.ddnet.tw/info
- Also supports countries and types
- Doesn't inform whether map has been finished
- Generalized the code a bit but it's still ugly
- Depends on #1533, also shows KoG servers as official/verified
This commit is contained in:
def 2019-03-24 23:15:38 +01:00
parent 958778b441
commit bf576723a3
10 changed files with 271 additions and 168 deletions

View file

@ -490,15 +490,18 @@ CServerBrowser::CServerEntry *CServerBrowser::Add(const NETADDR &Addr)
} }
// check if it's an official server // check if it's an official server
for(int i = 0; i < m_NumDDNetCountries; i++) for(int Network = 0; Network < NUM_NETWORKS; Network++)
{ {
CDDNetCountry *pCntr = &m_aDDNetCountries[i]; for(int i = 0; i < m_aNetworks[Network].m_NumCountries; i++)
for(int j = 0; j < pCntr->m_NumServers; j++)
{ {
if(net_addr_comp(&Addr, &pCntr->m_aServers[j]) == 0) CNetworkCountry *pCntr = &m_aNetworks[Network].m_aCountries[i];
for(int j = 0; j < pCntr->m_NumServers; j++)
{ {
pEntry->m_Info.m_Official = true; if(net_addr_comp(&Addr, &pCntr->m_aServers[j]) == 0)
break; {
pEntry->m_Info.m_Official = true;
break;
}
} }
} }
} }
@ -561,6 +564,17 @@ void CServerBrowser::Set(const NETADDR &Addr, int Type, int Token, const CServer
QueueRequest(pEntry); QueueRequest(pEntry);
} }
} }
else if(Type == IServerBrowser::SET_KOG_ADD)
{
if(m_ServerlistType != IServerBrowser::TYPE_KOG)
return;
if(!Find(Addr))
{
pEntry = Add(Addr);
QueueRequest(pEntry);
}
}
else if(Type == IServerBrowser::SET_TOKEN) else if(Type == IServerBrowser::SET_TOKEN)
{ {
int BasicToken = Token; int BasicToken = Token;
@ -678,12 +692,12 @@ void CServerBrowser::Refresh(int Type)
else if(Type == IServerBrowser::TYPE_DDNET) else if(Type == IServerBrowser::TYPE_DDNET)
{ {
// remove unknown elements of exclude list // remove unknown elements of exclude list
DDNetCountryFilterClean(); CountryFilterClean(NETWORK_DDNET);
DDNetTypeFilterClean(); TypeFilterClean(NETWORK_DDNET);
for(int i = 0; i < m_NumDDNetCountries; i++) for(int i = 0; i < m_aNetworks[NETWORK_DDNET].m_NumCountries; i++)
{ {
CDDNetCountry *pCntr = &m_aDDNetCountries[i]; CNetworkCountry *pCntr = &m_aNetworks[NETWORK_DDNET].m_aCountries[i];
// check for filter // check for filter
if(DDNetFiltered(g_Config.m_BrFilterExcludeCountries, pCntr->m_aName)) if(DDNetFiltered(g_Config.m_BrFilterExcludeCountries, pCntr->m_aName))
@ -696,6 +710,27 @@ void CServerBrowser::Refresh(int Type)
} }
} }
} }
else if(Type == IServerBrowser::TYPE_KOG)
{
// remove unknown elements of exclude list
CountryFilterClean(NETWORK_KOG);
TypeFilterClean(NETWORK_KOG);
for(int i = 0; i < m_aNetworks[NETWORK_KOG].m_NumCountries; i++)
{
CNetworkCountry *pCntr = &m_aNetworks[NETWORK_KOG].m_aCountries[i];
// check for filter
if(DDNetFiltered(g_Config.m_BrFilterExcludeCountriesKoG, pCntr->m_aName))
continue;
for(int g = 0; g < pCntr->m_NumServers; g++)
{
if(!DDNetFiltered(g_Config.m_BrFilterExcludeTypesKoG, pCntr->m_aTypes[g]))
Set(pCntr->m_aServers[g], IServerBrowser::SET_KOG_ADD, -1, 0);
}
}
}
} }
void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) const void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) const
@ -1009,96 +1044,104 @@ void CServerBrowser::LoadDDNetServers()
if (!m_pDDNetInfo) if (!m_pDDNetInfo)
return; return;
// parse JSON
const json_value *pServers = json_object_get(m_pDDNetInfo, "servers");
if (!pServers || pServers->type != json_array)
return;
// reset servers / countries // reset servers / countries
m_NumDDNetCountries = 0; for (int Network = 0; Network < NUM_NETWORKS; Network++)
m_NumDDNetTypes = 0;
for (int i = 0; i < json_array_length(pServers) && m_NumDDNetCountries < MAX_DDNET_COUNTRIES; i++)
{ {
// pSrv - { name, flagId, servers } CNetwork *pNet = &m_aNetworks[Network];
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) // parse JSON
const json_value *pServers = json_object_get(m_pDDNetInfo, Network == NETWORK_DDNET ? "servers" : "servers-kog");
if (!pServers || pServers->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++)
{ {
dbg_msg("client_srvbrowse", "invalid attributes"); // pSrv - { name, flagId, servers }
continue; 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");
// build structure if (pSrv->type != json_object || pTypes->type != json_object || pName->type != json_string || pFlagID->type != json_integer)
CDDNetCountry *pCntr = &m_aDDNetCountries[m_NumDDNetCountries];
pCntr->Reset();
str_copy(pCntr->m_aName, json_string_get(pName), sizeof(pCntr->m_aName));
pCntr->m_FlagID = json_int_get(pFlagID);
// add country
for (unsigned int t = 0; t < pTypes->u.object.length; t++)
{
const char *pType = pTypes->u.object.values[t].name;
const json_value *pAddrs = pTypes->u.object.values[t].value;
if (pAddrs->type != json_array)
{ {
dbg_msg("client_srvbrowse", "invalid attributes"); dbg_msg("client_srvbrowse", "invalid attributes");
continue; continue;
} }
// add type // build structure
if(json_array_length(pAddrs) > 0 && m_NumDDNetTypes < MAX_DDNET_TYPES) CNetworkCountry *pCntr = &pNet->m_aCountries[pNet->m_NumCountries];
{
int Pos;
for(Pos = 0; Pos < m_NumDDNetTypes; Pos++)
{
if(!str_comp(m_aDDNetTypes[Pos], pType))
break;
}
if(Pos == m_NumDDNetTypes)
{
str_copy(m_aDDNetTypes[m_NumDDNetTypes], pType, sizeof(m_aDDNetTypes[m_NumDDNetTypes]));
m_NumDDNetTypes++;
}
}
// add addresses pCntr->Reset();
for (int g = 0; g < json_array_length(pAddrs); g++, pCntr->m_NumServers++)
str_copy(pCntr->m_aName, json_string_get(pName), sizeof(pCntr->m_aName));
pCntr->m_FlagID = json_int_get(pFlagID);
// add country
for (unsigned int t = 0; t < pTypes->u.object.length; t++)
{ {
const json_value *pAddr = json_array_get(pAddrs, g); const char *pType = pTypes->u.object.values[t].name;
if (pAddr->type != json_string) const json_value *pAddrs = pTypes->u.object.values[t].value;
if (pAddrs->type != json_array)
{ {
dbg_msg("client_srvbrowse", "invalid attributes"); dbg_msg("client_srvbrowse", "invalid attributes");
continue; 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, sizeof(pCntr->m_aTypes[pCntr->m_NumServers]));
}
}
m_NumDDNetCountries++; // add type
if(json_array_length(pAddrs) > 0 && pNet->m_NumTypes < MAX_TYPES)
{
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, sizeof(pNet->m_aTypes[pNet->m_NumTypes]));
pNet->m_NumTypes++;
}
}
// add addresses
for (int g = 0; g < json_array_length(pAddrs); g++, pCntr->m_NumServers++)
{
const json_value *pAddr = json_array_get(pAddrs, g);
if (pAddr->type != json_string)
{
dbg_msg("client_srvbrowse", "invalid attributes");
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, sizeof(pCntr->m_aTypes[pCntr->m_NumServers]));
}
}
pNet->m_NumCountries++;
}
} }
} }
void CServerBrowser::RecheckOfficial() void CServerBrowser::RecheckOfficial()
{ {
for(int i = 0; i < m_NumDDNetCountries; i++) for(int Network = 0; Network < NUM_NETWORKS; Network++)
{ {
CDDNetCountry *pCntr = &m_aDDNetCountries[i]; for(int i = 0; i < m_aNetworks[Network].m_NumCountries; i++)
for(int j = 0; j < pCntr->m_NumServers; j++)
{ {
CServerEntry *pEntry = Find(pCntr->m_aServers[j]); CNetworkCountry *pCntr = &m_aNetworks[Network].m_aCountries[i];
if(pEntry) for(int j = 0; j < pCntr->m_NumServers; j++)
{ {
pEntry->m_Info.m_Official = true; CServerEntry *pEntry = Find(pCntr->m_aServers[j]);
if(pEntry)
{
pEntry->m_Info.m_Official = true;
}
} }
} }
} }
@ -1265,15 +1308,39 @@ bool CServerBrowser::DDNetFiltered(char *pFilter, const char *pName)
return str_in_list(pFilter, ",", pName); // country not excluded return str_in_list(pFilter, ",", pName); // country not excluded
} }
void CServerBrowser::DDNetCountryFilterClean() void CServerBrowser::CountryFilterClean(int Network)
{ {
char *pExcludeCountries = Network == NETWORK_KOG ? g_Config.m_BrFilterExcludeCountriesKoG : g_Config.m_BrFilterExcludeCountries;
char aNewList[128]; char aNewList[128];
aNewList[0] = '\0'; aNewList[0] = '\0';
for(int i = 0; i < m_NumDDNetCountries; i++) for(int Network = 0; Network < NUM_NETWORKS; Network++)
{ {
const char *pName = m_aDDNetCountries[i].m_aName; for(int i = 0; i < m_aNetworks[Network].m_NumCountries; i++)
if(DDNetFiltered(g_Config.m_BrFilterExcludeCountries, pName)) {
const char *pName = m_aNetworks[Network].m_aCountries[i].m_aName;
if(DDNetFiltered(pExcludeCountries, pName))
{
char aBuf[128];
str_format(aBuf, sizeof(aBuf), ",%s", pName);
str_append(aNewList, aBuf, sizeof(aNewList));
}
}
}
str_copy(pExcludeCountries, aNewList, sizeof(g_Config.m_BrFilterExcludeCountries));
}
void CServerBrowser::TypeFilterClean(int Network)
{
char *pExcludeTypes = Network == NETWORK_KOG ? g_Config.m_BrFilterExcludeTypesKoG : g_Config.m_BrFilterExcludeTypes;
char aNewList[128];
aNewList[0] = '\0';
for(int i = 0; i < m_aNetworks[Network].m_NumTypes; i++)
{
const char *pName = m_aNetworks[Network].m_aTypes[i];
if(DDNetFiltered(pExcludeTypes, pName))
{ {
char aBuf[128]; char aBuf[128];
str_format(aBuf, sizeof(aBuf), ",%s", pName); str_format(aBuf, sizeof(aBuf), ",%s", pName);
@ -1281,24 +1348,5 @@ void CServerBrowser::DDNetCountryFilterClean()
} }
} }
str_copy(g_Config.m_BrFilterExcludeCountries, aNewList, sizeof(g_Config.m_BrFilterExcludeCountries)); str_copy(pExcludeTypes, aNewList, sizeof(g_Config.m_BrFilterExcludeTypes));
}
void CServerBrowser::DDNetTypeFilterClean()
{
char aNewList[128];
aNewList[0] = '\0';
for(int i = 0; i < m_NumDDNetTypes; i++)
{
const char *pName = m_aDDNetTypes[i];
if(DDNetFiltered(g_Config.m_BrFilterExcludeTypes, pName))
{
char aBuf[128];
str_format(aBuf, sizeof(aBuf), ",%s", pName);
str_append(aNewList, aBuf, sizeof(aNewList));
}
}
str_copy(g_Config.m_BrFilterExcludeTypes, aNewList, sizeof(g_Config.m_BrFilterExcludeTypes));
} }

View file

@ -25,9 +25,8 @@ public:
CServerEntry *m_pNextReq; CServerEntry *m_pNextReq;
}; };
class CDDNetCountry struct CNetworkCountry
{ {
public:
enum enum
{ {
MAX_SERVERS = 1024 MAX_SERVERS = 1024
@ -53,10 +52,20 @@ public:
enum enum
{ {
MAX_FAVORITES=2048, MAX_FAVORITES=2048,
MAX_DDNET_COUNTRIES=16, MAX_COUNTRIES=16,
MAX_DDNET_TYPES=32, MAX_TYPES=32,
}; };
struct CNetwork
{
CNetworkCountry m_aCountries[MAX_COUNTRIES];
int m_NumCountries;
char m_aTypes[MAX_TYPES][32];
int m_NumTypes;
};
CServerBrowser(); CServerBrowser();
virtual ~CServerBrowser(); virtual ~CServerBrowser();
@ -91,18 +100,18 @@ public:
void LoadDDNetInfoJson(); void LoadDDNetInfoJson();
const json_value *LoadDDNetInfo(); const json_value *LoadDDNetInfo();
int HasRank(const char *pMap); int HasRank(const char *pMap);
int NumDDNetCountries() { return m_NumDDNetCountries; }; int NumCountries(int Network) { return m_aNetworks[Network].m_NumCountries; };
int GetDDNetCountryFlag(int Index) { return m_aDDNetCountries[Index].m_FlagID; }; int GetCountryFlag(int Network, int Index) { return m_aNetworks[Network].m_aCountries[Index].m_FlagID; };
const char *GetDDNetCountryName(int Index) { return m_aDDNetCountries[Index].m_aName; }; const char *GetCountryName(int Network, int Index) { return m_aNetworks[Network].m_aCountries[Index].m_aName; };
int NumDDNetTypes() { return m_NumDDNetTypes; }; int NumTypes(int Network) { return m_aNetworks[Network].m_NumTypes; };
const char *GetDDNetType(int Index) { return m_aDDNetTypes[Index]; }; const char *GetType(int Network, int Index) { return m_aNetworks[Network].m_aTypes[Index]; };
void DDNetFilterAdd(char *pFilter, const char *pName); void DDNetFilterAdd(char *pFilter, const char *pName);
void DDNetFilterRem(char *pFilter, const char *pName); void DDNetFilterRem(char *pFilter, const char *pName);
bool DDNetFiltered(char *pFilter, const char *pName); bool DDNetFiltered(char *pFilter, const char *pName);
void DDNetCountryFilterClean(); void CountryFilterClean(int Network);
void DDNetTypeFilterClean(); void TypeFilterClean(int Network);
// //
void Update(bool ForceResort); void Update(bool ForceResort);
@ -130,11 +139,7 @@ private:
NETADDR m_aFavoriteServers[MAX_FAVORITES]; NETADDR m_aFavoriteServers[MAX_FAVORITES];
int m_NumFavoriteServers; int m_NumFavoriteServers;
CDDNetCountry m_aDDNetCountries[MAX_DDNET_COUNTRIES]; CNetwork m_aNetworks[NUM_NETWORKS];
int m_NumDDNetCountries;
char m_aDDNetTypes[MAX_DDNET_TYPES][32];
int m_NumDDNetTypes;
json_value *m_pDDNetInfo; json_value *m_pDDNetInfo;

View file

@ -103,11 +103,17 @@ public:
TYPE_LAN = 2, TYPE_LAN = 2,
TYPE_FAVORITES = 3, TYPE_FAVORITES = 3,
TYPE_DDNET = 4, TYPE_DDNET = 4,
TYPE_KOG = 5,
SET_MASTER_ADD=1, SET_MASTER_ADD=1,
SET_FAV_ADD, SET_FAV_ADD,
SET_DDNET_ADD, SET_DDNET_ADD,
SET_TOKEN SET_KOG_ADD,
SET_TOKEN,
NETWORK_DDNET=0,
NETWORK_KOG=1,
NUM_NETWORKS,
}; };
virtual void Refresh(int Type) = 0; virtual void Refresh(int Type) = 0;
@ -127,18 +133,18 @@ public:
virtual void AddFavorite(const NETADDR &Addr) = 0; virtual void AddFavorite(const NETADDR &Addr) = 0;
virtual void RemoveFavorite(const NETADDR &Addr) = 0; virtual void RemoveFavorite(const NETADDR &Addr) = 0;
virtual int NumDDNetCountries() = 0; virtual int NumCountries(int Network) = 0;
virtual int GetDDNetCountryFlag(int Index) = 0; virtual int GetCountryFlag(int Network, int Index) = 0;
virtual const char *GetDDNetCountryName(int Index) = 0; virtual const char *GetCountryName(int Network, int Index) = 0;
virtual int NumDDNetTypes() = 0; virtual int NumTypes(int Network) = 0;
virtual const char *GetDDNetType(int Index) = 0; virtual const char *GetType(int Network, int Index) = 0;
virtual void DDNetFilterAdd(char *pFilter, const char *pName) = 0; virtual void DDNetFilterAdd(char *pFilter, const char *pName) = 0;
virtual void DDNetFilterRem(char *pFilter, const char *pName) = 0; virtual void DDNetFilterRem(char *pFilter, const char *pName) = 0;
virtual bool DDNetFiltered(char *pFilter, const char *pName) = 0; virtual bool DDNetFiltered(char *pFilter, const char *pName) = 0;
virtual void DDNetCountryFilterClean() = 0; virtual void CountryFilterClean(int Network) = 0;
virtual void DDNetTypeFilterClean() = 0; virtual void TypeFilterClean(int Network) = 0;
virtual int GetCurrentType() = 0; virtual int GetCurrentType() = 0;
}; };

View file

@ -53,9 +53,12 @@ MACRO_CONFIG_INT(BrFilterPureMap, br_filter_pure_map, 0, 0, 1, CFGFLAG_SAVE|CFGF
MACRO_CONFIG_INT(BrFilterCompatversion, br_filter_compatversion, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out non-compatible servers in browser") MACRO_CONFIG_INT(BrFilterCompatversion, br_filter_compatversion, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out non-compatible servers in browser")
MACRO_CONFIG_INT(BrFilterUnfinishedMap, br_filter_unfinished_map, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Show only servers with unfinished maps") MACRO_CONFIG_INT(BrFilterUnfinishedMap, br_filter_unfinished_map, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Show only servers with unfinished maps")
MACRO_CONFIG_STR(BrFilterExcludeCountries, br_filter_exclude_countries, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out ddnet servers by country") MACRO_CONFIG_STR(BrFilterExcludeCountries, br_filter_exclude_countries, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out DDNet servers by country")
MACRO_CONFIG_STR(BrFilterExcludeTypes, br_filter_exclude_types, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out ddnet servers by type (mod)") MACRO_CONFIG_STR(BrFilterExcludeTypes, br_filter_exclude_types, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out DDNet servers by type (mod)")
MACRO_CONFIG_INT(BrIndicateFinished, br_indicate_finished, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Show whether you have finished a DDNet map (transmits your player name to info.ddnet.tw)") MACRO_CONFIG_INT(BrIndicateFinished, br_indicate_finished, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Show whether you have finished a DDNet map (transmits your player name to info.ddnet.tw/info)")
MACRO_CONFIG_STR(BrFilterExcludeCountriesKoG, br_filter_exclude_countries_kog, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out kog servers by country")
MACRO_CONFIG_STR(BrFilterExcludeTypesKoG, br_filter_exclude_types_kog, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out kog servers by type (mod)")
MACRO_CONFIG_INT(BrSort, br_sort, 4, 0, 256, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sorting column in server browser") MACRO_CONFIG_INT(BrSort, br_sort, 4, 0, 256, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sorting column in server browser")
MACRO_CONFIG_INT(BrSortOrder, br_sort_order, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sorting order in server browser") MACRO_CONFIG_INT(BrSortOrder, br_sort_order, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sorting order in server browser")

View file

@ -735,9 +735,9 @@ int CMenus::RenderMenubar(CUIRect r)
m_DoubleClickIndex = -1; m_DoubleClickIndex = -1;
} }
Box.VSplitLeft(100.0f, &Button, &Box); Box.VSplitLeft(80.0f, &Button, &Box);
static int s_DDNetButton=0; static int s_DDNetButton=0;
if(DoButton_MenuTab(&s_DDNetButton, Localize("DDNet"), m_ActivePage==PAGE_DDNET, &Button, CUI::CORNER_TR)) if(DoButton_MenuTab(&s_DDNetButton, "DDNet", m_ActivePage==PAGE_DDNET, &Button, 0))
{ {
if(ServerBrowser()->GetCurrentType() != IServerBrowser::TYPE_DDNET) if(ServerBrowser()->GetCurrentType() != IServerBrowser::TYPE_DDNET)
{ {
@ -748,6 +748,19 @@ int CMenus::RenderMenubar(CUIRect r)
m_DoubleClickIndex = -1; m_DoubleClickIndex = -1;
} }
Box.VSplitLeft(60.0f, &Button, &Box);
static int s_KoGButton=0;
if(DoButton_MenuTab(&s_KoGButton, "KoG", m_ActivePage==PAGE_KOG, &Button, CUI::CORNER_TR))
{
if(ServerBrowser()->GetCurrentType() != IServerBrowser::TYPE_KOG)
{
Client()->RequestDDNetInfo();
ServerBrowser()->Refresh(IServerBrowser::TYPE_KOG);
}
NewPage = PAGE_KOG;
m_DoubleClickIndex = -1;
}
Box.VSplitLeft(10.0f, 0, &Box); Box.VSplitLeft(10.0f, 0, &Box);
Box.VSplitLeft(100.0f, &Button, &Box); Box.VSplitLeft(100.0f, &Button, &Box);
static int s_DemosButton=0; static int s_DemosButton=0;
@ -894,7 +907,7 @@ void CMenus::RenderLoading()
void CMenus::RenderNews(CUIRect MainView) void CMenus::RenderNews(CUIRect MainView)
{ {
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
MainView.HSplitTop(15.0f, 0, &MainView); MainView.HSplitTop(15.0f, 0, &MainView);
MainView.VSplitLeft(15.0f, 0, &MainView); MainView.VSplitLeft(15.0f, 0, &MainView);
@ -973,6 +986,8 @@ int CMenus::Render()
ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES); ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES);
else if(g_Config.m_UiPage == PAGE_DDNET) else if(g_Config.m_UiPage == PAGE_DDNET)
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET); ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
else if(g_Config.m_UiPage == PAGE_KOG)
ServerBrowser()->Refresh(IServerBrowser::TYPE_KOG);
} }
if(Client()->State() == IClient::STATE_ONLINE) if(Client()->State() == IClient::STATE_ONLINE)
@ -1049,11 +1064,12 @@ int CMenus::Render()
RenderServerbrowser(MainView); RenderServerbrowser(MainView);
else if(g_Config.m_UiPage == PAGE_DDNET) else if(g_Config.m_UiPage == PAGE_DDNET)
RenderServerbrowser(MainView); RenderServerbrowser(MainView);
else if(g_Config.m_UiPage == PAGE_KOG)
RenderServerbrowser(MainView);
else if(g_Config.m_UiPage == PAGE_SETTINGS) else if(g_Config.m_UiPage == PAGE_SETTINGS)
RenderSettings(MainView); RenderSettings(MainView);
// do tab bar // do tab bar
TabBar.VMargin(20.0f, &TabBar);
RenderMenubar(TabBar); RenderMenubar(TabBar);
} }
else else

View file

@ -337,6 +337,7 @@ public:
PAGE_LAN, PAGE_LAN,
PAGE_FAVORITES, PAGE_FAVORITES,
PAGE_DDNET, PAGE_DDNET,
PAGE_KOG,
PAGE_DEMOS, PAGE_DEMOS,
PAGE_SETTINGS, PAGE_SETTINGS,
PAGE_SYSTEM, PAGE_SYSTEM,

View file

@ -675,7 +675,11 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
{ {
g_Config.m_BrFilterUnfinishedMap = 0; g_Config.m_BrFilterUnfinishedMap = 0;
} }
}
if(g_Config.m_UiPage == PAGE_DDNET || g_Config.m_UiPage == PAGE_KOG)
{
int Network = g_Config.m_UiPage == PAGE_DDNET ? IServerBrowser::NETWORK_DDNET : IServerBrowser::NETWORK_KOG;
// add more space // add more space
ServerFilter.HSplitTop(10.0f, 0, &ServerFilter); ServerFilter.HSplitTop(10.0f, 0, &ServerFilter);
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter); ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
@ -701,8 +705,9 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
if(s_ActivePage == 1) if(s_ActivePage == 1)
{ {
int MaxTypes = ServerBrowser()->NumDDNetTypes(); char *pFilterExcludeTypes = Network == IServerBrowser::NETWORK_DDNET ? g_Config.m_BrFilterExcludeTypes : g_Config.m_BrFilterExcludeTypesKoG;
int NumTypes = ServerBrowser()->NumDDNetTypes(); int MaxTypes = ServerBrowser()->NumTypes(Network);
int NumTypes = ServerBrowser()->NumTypes(Network);
int PerLine = 3; int PerLine = 3;
ServerFilter.HSplitTop(4.0f, 0, &ServerFilter); ServerFilter.HSplitTop(4.0f, 0, &ServerFilter);
@ -723,8 +728,8 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
for(int i = 0; i < PerLine && NumTypes > 0; i++, NumTypes--) for(int i = 0; i < PerLine && NumTypes > 0; i++, NumTypes--)
{ {
int TypeIndex = MaxTypes - NumTypes; int TypeIndex = MaxTypes - NumTypes;
const char *pName = ServerBrowser()->GetDDNetType(TypeIndex); const char *pName = ServerBrowser()->GetType(Network, TypeIndex);
bool Active = !ServerBrowser()->DDNetFiltered(g_Config.m_BrFilterExcludeTypes, pName); bool Active = !ServerBrowser()->DDNetFiltered(pFilterExcludeTypes, pName);
vec2 Pos = vec2(TypesRect.x+TypesRect.w*((i+0.5f)/(float)PerLine), TypesRect.y); vec2 Pos = vec2(TypesRect.x+TypesRect.w*((i+0.5f)/(float)PerLine), TypesRect.y);
@ -744,28 +749,28 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
{ {
// left click to toggle flag filter // left click to toggle flag filter
if(Active) if(Active)
ServerBrowser()->DDNetFilterAdd(g_Config.m_BrFilterExcludeTypes, pName); ServerBrowser()->DDNetFilterAdd(pFilterExcludeTypes, pName);
else else
ServerBrowser()->DDNetFilterRem(g_Config.m_BrFilterExcludeTypes, pName); ServerBrowser()->DDNetFilterRem(pFilterExcludeTypes, pName);
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET); ServerBrowser()->Refresh(ServerBrowser()->GetCurrentType());
} }
else if(Button == 2) else if(Button == 2)
{ {
// right click to exclusively activate one // right click to exclusively activate one
g_Config.m_BrFilterExcludeTypes[0] = '\0'; pFilterExcludeTypes[0] = '\0';
for(int j = 0; j < MaxTypes; ++j) for(int j = 0; j < MaxTypes; ++j)
{ {
if(j != TypeIndex) if(j != TypeIndex)
ServerBrowser()->DDNetFilterAdd(g_Config.m_BrFilterExcludeTypes, ServerBrowser()->GetDDNetType(j)); ServerBrowser()->DDNetFilterAdd(pFilterExcludeTypes, ServerBrowser()->GetType(Network, j));
} }
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET); ServerBrowser()->Refresh(ServerBrowser()->GetCurrentType());
} }
else if(Button == 3) else if(Button == 3)
{ {
// middle click to reset (re-enable all) // middle click to reset (re-enable all)
g_Config.m_BrFilterExcludeTypes[0] = '\0'; pFilterExcludeTypes[0] = '\0';
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET); ServerBrowser()->Refresh(ServerBrowser()->GetCurrentType());
} }
vec4 Color(1.0f, 1.0f, 1.0f, 1.0f); vec4 Color(1.0f, 1.0f, 1.0f, 1.0f);
@ -780,6 +785,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
} }
else else
{ {
char *pFilterExcludeCountries = Network == IServerBrowser::NETWORK_DDNET ? g_Config.m_BrFilterExcludeCountries : g_Config.m_BrFilterExcludeCountriesKoG;
ServerFilter.HSplitTop(17.0f, &ServerFilter, &ServerFilter); ServerFilter.HSplitTop(17.0f, &ServerFilter, &ServerFilter);
vec4 Color(1.0f, 1.0f, 1.0f, 1.0f); vec4 Color(1.0f, 1.0f, 1.0f, 1.0f);
@ -787,8 +793,8 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
const float FlagWidth = 40.0f; const float FlagWidth = 40.0f;
const float FlagHeight = 20.0f; const float FlagHeight = 20.0f;
int MaxFlags = ServerBrowser()->NumDDNetCountries(); int MaxFlags = ServerBrowser()->NumCountries(Network);
int NumFlags = ServerBrowser()->NumDDNetCountries(); int NumFlags = ServerBrowser()->NumCountries(Network);
int PerLine = MaxFlags > 9 ? 4 : 3; int PerLine = MaxFlags > 9 ? 4 : 3;
CUIRect FlagsRect; CUIRect FlagsRect;
@ -802,9 +808,9 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
for(int i = 0; i < PerLine && NumFlags > 0; i++, NumFlags--) for(int i = 0; i < PerLine && NumFlags > 0; i++, NumFlags--)
{ {
int CountryIndex = MaxFlags - NumFlags; int CountryIndex = MaxFlags - NumFlags;
const char *pName = ServerBrowser()->GetDDNetCountryName(CountryIndex); const char *pName = ServerBrowser()->GetCountryName(Network, CountryIndex);
bool Active = !ServerBrowser()->DDNetFiltered(g_Config.m_BrFilterExcludeCountries, pName); bool Active = !ServerBrowser()->DDNetFiltered(pFilterExcludeCountries, pName);
int FlagID = ServerBrowser()->GetDDNetCountryFlag(CountryIndex); int FlagID = ServerBrowser()->GetCountryFlag(Network, CountryIndex);
vec2 Pos = vec2(FlagsRect.x+FlagsRect.w*((i+0.5f)/(float)PerLine), FlagsRect.y); vec2 Pos = vec2(FlagsRect.x+FlagsRect.w*((i+0.5f)/(float)PerLine), FlagsRect.y);
@ -825,28 +831,28 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
{ {
// left click to toggle flag filter // left click to toggle flag filter
if(Active) if(Active)
ServerBrowser()->DDNetFilterAdd(g_Config.m_BrFilterExcludeCountries, pName); ServerBrowser()->DDNetFilterAdd(pFilterExcludeCountries, pName);
else else
ServerBrowser()->DDNetFilterRem(g_Config.m_BrFilterExcludeCountries, pName); ServerBrowser()->DDNetFilterRem(pFilterExcludeCountries, pName);
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET); ServerBrowser()->Refresh(ServerBrowser()->GetCurrentType());
} }
else if(Button == 2) else if(Button == 2)
{ {
// right click to exclusively activate one // right click to exclusively activate one
g_Config.m_BrFilterExcludeCountries[0] = '\0'; pFilterExcludeCountries[0] = '\0';
for(int j = 0; j < MaxFlags; ++j) for(int j = 0; j < MaxFlags; ++j)
{ {
if(j != CountryIndex) if(j != CountryIndex)
ServerBrowser()->DDNetFilterAdd(g_Config.m_BrFilterExcludeCountries, ServerBrowser()->GetDDNetCountryName(j)); ServerBrowser()->DDNetFilterAdd(pFilterExcludeCountries, ServerBrowser()->GetCountryName(Network, j));
} }
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET); ServerBrowser()->Refresh(ServerBrowser()->GetCurrentType());
} }
else if(Button == 3) else if(Button == 3)
{ {
// middle click to reset (re-enable all) // middle click to reset (re-enable all)
g_Config.m_BrFilterExcludeCountries[0] = '\0'; pFilterExcludeCountries[0] = '\0';
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET); ServerBrowser()->Refresh(ServerBrowser()->GetCurrentType());
} }
vec4 Color(1.0f, 1.0f, 1.0f, 1.0f); vec4 Color(1.0f, 1.0f, 1.0f, 1.0f);
@ -1240,7 +1246,7 @@ void CMenus::RenderServerbrowser(CUIRect MainView)
CUIRect ServerList, ToolBox, StatusBox, TabBar; CUIRect ServerList, ToolBox, StatusBox, TabBar;
// background // background
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
MainView.Margin(10.0f, &MainView); MainView.Margin(10.0f, &MainView);
// create server list, status box, tab bar and tool box area // create server list, status box, tab bar and tool box area
@ -1414,6 +1420,12 @@ void CMenus::RenderServerbrowser(CUIRect MainView)
Client()->RequestDDNetInfo(); Client()->RequestDDNetInfo();
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET); ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
} }
else if(g_Config.m_UiPage == PAGE_KOG)
{
// start a new serverlist request
Client()->RequestDDNetInfo();
ServerBrowser()->Refresh(IServerBrowser::TYPE_KOG);
}
m_DoubleClickIndex = -1; m_DoubleClickIndex = -1;
} }

View file

@ -793,7 +793,7 @@ void CMenus::RenderDemoList(CUIRect MainView)
} }
// render background // render background
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
MainView.Margin(10.0f, &MainView); MainView.Margin(10.0f, &MainView);
CUIRect ButtonBar, RefreshRect, FetchRect, PlayRect, DeleteRect, RenameRect, LabelRect, ListBox; CUIRect ButtonBar, RefreshRect, FetchRect, PlayRect, DeleteRect, RenameRect, LabelRect, ListBox;

View file

@ -39,7 +39,7 @@ void CMenus::RenderGame(CUIRect MainView)
#else #else
MainView.HSplitTop(45.0f, &ButtonBar, &MainView); MainView.HSplitTop(45.0f, &ButtonBar, &MainView);
#endif #endif
RenderTools()->DrawUIRect(&ButtonBar, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); RenderTools()->DrawUIRect(&ButtonBar, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
// button bar // button bar
ButtonBar.HSplitTop(10.0f, 0, &ButtonBar); ButtonBar.HSplitTop(10.0f, 0, &ButtonBar);
@ -157,7 +157,7 @@ void CMenus::RenderGame(CUIRect MainView)
void CMenus::RenderPlayers(CUIRect MainView) void CMenus::RenderPlayers(CUIRect MainView)
{ {
CUIRect Button, Button2, ButtonBar, Options, Player; CUIRect Button, Button2, ButtonBar, Options, Player;
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
// player options // player options
MainView.Margin(10.0f, &Options); MainView.Margin(10.0f, &Options);
@ -351,7 +351,7 @@ void CMenus::RenderServerInfo(CUIRect MainView)
Client()->GetServerInfo(&CurrentServerInfo); Client()->GetServerInfo(&CurrentServerInfo);
// render background // render background
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
CUIRect View, ServerInfo, GameInfo, Motd; CUIRect View, ServerInfo, GameInfo, Motd;
@ -564,7 +564,7 @@ void CMenus::RenderServerControl(CUIRect MainView)
#else #else
MainView.HSplitTop(20.0f, &Bottom, &MainView); MainView.HSplitTop(20.0f, &Bottom, &MainView);
#endif #endif
RenderTools()->DrawUIRect(&Bottom, ms_ColorTabbarActive, CUI::CORNER_T, 10.0f); RenderTools()->DrawUIRect(&Bottom, ms_ColorTabbarActive, 0, 10.0f);
#if defined(__ANDROID__) #if defined(__ANDROID__)
MainView.HSplitTop(50.0f, &TabBar, &MainView); MainView.HSplitTop(50.0f, &TabBar, &MainView);
#else #else
@ -768,7 +768,7 @@ void CMenus::RenderInGameNetwork(CUIRect MainView)
int Page = g_Config.m_UiPage; int Page = g_Config.m_UiPage;
int NewPage = -1; int NewPage = -1;
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
Box.HSplitTop(5.0f, &MainView, &MainView); Box.HSplitTop(5.0f, &MainView, &MainView);
Box.HSplitTop(24.0f, &Box, &MainView); Box.HSplitTop(24.0f, &Box, &MainView);
@ -798,19 +798,31 @@ void CMenus::RenderInGameNetwork(CUIRect MainView)
{ {
if(Page != PAGE_FAVORITES) if(Page != PAGE_FAVORITES)
ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES); ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES);
NewPage = PAGE_FAVORITES; NewPage = PAGE_FAVORITES;
} }
Box.VSplitLeft(110.0f, &Button, &Box); Box.VSplitLeft(110.0f, &Button, &Box);
static int s_DDNetButton=0; static int s_DDNetButton=0;
if(DoButton_MenuTab(&s_DDNetButton, Localize("DDNet"), Page==PAGE_DDNET, &Button, CUI::CORNER_BR) || Page < PAGE_INTERNET || Page > PAGE_DDNET) if(DoButton_MenuTab(&s_DDNetButton, "DDNet", Page==PAGE_DDNET, &Button, 0) || Page < PAGE_INTERNET || Page > PAGE_KOG)
{ {
if(Page != PAGE_DDNET) if(Page != PAGE_DDNET)
{ {
Client()->RequestDDNetInfo(); Client()->RequestDDNetInfo();
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET); ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
} }
NewPage = PAGE_DDNET; NewPage = PAGE_DDNET;
}
Box.VSplitLeft(110.0f, &Button, &Box);
static int s_KoGButton=0;
if(DoButton_MenuTab(&s_KoGButton, "KoG", Page==PAGE_KOG, &Button, CUI::CORNER_BR))
{
if(Page != PAGE_KOG)
{
Client()->RequestDDNetInfo();
ServerBrowser()->Refresh(IServerBrowser::TYPE_KOG);
}
NewPage = PAGE_KOG;
} }
if(NewPage != -1) if(NewPage != -1)
@ -903,7 +915,7 @@ void CMenus::DeleteGhostItem(int Index)
void CMenus::RenderGhost(CUIRect MainView) void CMenus::RenderGhost(CUIRect MainView)
{ {
// render background // render background
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B|CUI::CORNER_TL, 10.0f); RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
MainView.HSplitTop(10.0f, 0, &MainView); MainView.HSplitTop(10.0f, 0, &MainView);
MainView.HSplitBottom(5.0f, &MainView, 0); MainView.HSplitBottom(5.0f, &MainView, 0);

View file

@ -1374,11 +1374,11 @@ void CMenus::RenderSettings(CUIRect MainView)
// render background // render background
CUIRect Temp, TabBar, RestartWarning; CUIRect Temp, TabBar, RestartWarning;
MainView.VSplitRight(120.0f, &MainView, &TabBar); MainView.VSplitRight(120.0f, &MainView, &TabBar);
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B|CUI::CORNER_TL, 10.0f); RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
MainView.Margin(10.0f, &MainView); MainView.Margin(10.0f, &MainView);
MainView.HSplitBottom(15.0f, &MainView, &RestartWarning); MainView.HSplitBottom(15.0f, &MainView, &RestartWarning);
TabBar.HSplitTop(50.0f, &Temp, &TabBar); TabBar.HSplitTop(50.0f, &Temp, &TabBar);
RenderTools()->DrawUIRect(&Temp, ms_ColorTabbarActive, CUI::CORNER_R, 10.0f); RenderTools()->DrawUIRect(&Temp, ms_ColorTabbarActive, CUI::CORNER_BR, 10.0f);
MainView.HSplitTop(10.0f, 0, &MainView); MainView.HSplitTop(10.0f, 0, &MainView);