Show if user has rank on map in browser (+filter)

UI implementation by timakro
This commit is contained in:
def 2017-08-30 21:34:01 +02:00
parent e480b651e7
commit 16f3ddc5a7
10 changed files with 144 additions and 12 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 B

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -263,7 +263,7 @@ container.pickups.Add(Pickup("ninja", 90, 90))
set_particles = SpriteSet("particles", image_particles, 8, 8)
set_game = SpriteSet("game", image_game, 32, 16)
set_tee = SpriteSet("tee", image_null, 8, 4)
set_browseicons = SpriteSet("browseicons", image_browseicons, 4, 1)
set_browseicons = SpriteSet("browseicons", image_browseicons, 6, 1)
set_emoticons = SpriteSet("emoticons", image_emoticons, 4, 4)
set_speedup_arrow = SpriteSet("speedup_arrow", image_speedup_arrow, 1, 1)
set_demobuttons = SpriteSet("demobuttons", image_demobuttons, 5, 1)
@ -395,6 +395,8 @@ container.sprites.Add(Sprite("question", set_emoticons, 3, 3, 1, 1))
container.sprites.Add(Sprite("browse_lock", set_browseicons, 0,0,1,1))
container.sprites.Add(Sprite("browse_heart", set_browseicons, 1,0,1,1))
container.sprites.Add(Sprite("browse_unpure", set_browseicons, 3,0,1,1))
container.sprites.Add(Sprite("browse_norank", set_browseicons, 4,0,1,1))
container.sprites.Add(Sprite("browse_rank", set_browseicons, 5,0,1,1))
container.sprites.Add(Sprite("speedup_arrow", set_speedup_arrow, 0,0,1,1))

View file

@ -190,6 +190,7 @@ public:
virtual void DemoSlice(const char *pDstPath, CLIENTFUNC_FILTER pfnFilter, void *pUser) = 0;
virtual void RequestDDNetSrvList() = 0;
virtual void RequestDDNetRanks() = 0;
virtual bool EditorHasUnsavedData() = 0;
virtual void GenerateTimeoutSeed() = 0;

View file

@ -321,6 +321,7 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta)
m_MapdownloadCrc = 0;
m_MapdownloadAmount = -1;
m_MapdownloadTotalsize = -1;
m_pDDNetRanksTask = NULL;
m_CurrentServerInfoRequestTime = -1;
@ -1170,6 +1171,7 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket)
m_NetClient[g_Config.m_ClDummy].Send(&Packet);
RequestDDNetSrvList();
RequestDDNetRanks();
// request the map version list now
mem_zero(&Packet, sizeof(Packet));
@ -1408,6 +1410,8 @@ void CClient::ProcessServerInfo(int RawType, NETADDR *pFrom, const void *pData,
GET_INT(Info.m_MaxPlayers);
GET_INT(Info.m_NumClients);
GET_INT(Info.m_MaxClients);
if(Info.m_aMap[0])
Info.m_HasRank = m_ServerBrowser.HasRank(Info.m_aMap);
// don't add invalid info to the server browser list
if(Info.m_NumClients < 0 || Info.m_MaxClients < 0 ||
@ -1542,6 +1546,7 @@ void CClient::ProcessServerInfo(int RawType, NETADDR *pFrom, const void *pData,
}
}
}
#undef GET_STRING
#undef GET_INT
}
@ -2256,6 +2261,22 @@ void CClient::FinishMapDownload()
}
}
void CClient::ResetDDNetRanks()
{
if(m_pDDNetRanksTask)
{
m_pDDNetRanksTask->Abort();
delete m_pDDNetRanksTask;
m_pDDNetRanksTask = NULL;
}
}
void CClient::FinishDDNetRanks()
{
ResetDDNetRanks();
m_ServerBrowser.LoadDDNetRanks();
}
void CClient::PumpNetwork()
{
for(int i=0; i<3; i++)
@ -2548,6 +2569,7 @@ void CClient::Update()
// pump the network
PumpNetwork();
if(m_pMapdownloadTask)
{
if(m_pMapdownloadTask->State() == CFetchTask::STATE_DONE)
@ -2565,6 +2587,21 @@ void CClient::Update()
}
}
if(m_pDDNetRanksTask)
{
if(m_pDDNetRanksTask->State() == CFetchTask::STATE_DONE)
FinishDDNetRanks();
else if(m_pDDNetRanksTask->State() == CFetchTask::STATE_ERROR)
{
dbg_msg("ddnet-ranks", "download failed");
ResetDDNetRanks();
}
else if(m_pDDNetRanksTask->State() == CFetchTask::STATE_ABORTED)
{
delete m_pDDNetRanksTask;
m_pDDNetRanksTask = NULL;
}
}
// update the maser server registry
MasterServer()->Update();
@ -3735,6 +3772,18 @@ void CClient::RequestDDNetSrvList()
m_NetClient[g_Config.m_ClDummy].Send(&Packet);
}
void CClient::RequestDDNetRanks()
{
char aUrl[256];
char aEscaped[128];
Fetcher()->Escape(aEscaped, sizeof(aEscaped), g_Config.m_PlayerName);
str_format(aUrl, sizeof(aUrl), "https://ddnet.tw/players/?json=%s", aEscaped);
m_pDDNetRanksTask = new CFetchTask(true, /*UseDDNetCA*/ false);
Fetcher()->QueueAdd(m_pDDNetRanksTask, aUrl, "ddnet-ranks.json", IStorage::TYPE_SAVE);
}
int CClient::GetPredictionTime()
{
int64 Now = time_get();

View file

@ -135,6 +135,7 @@ class CClient : public IClient, public CDemoPlayer::IListener
int m_MapdownloadCrc;
int m_MapdownloadAmount;
int m_MapdownloadTotalsize;
CFetchTask *m_pDDNetRanksTask;
// time
CSmoothTime m_GameTime[2];
@ -298,6 +299,8 @@ public:
void ResetMapDownload();
void FinishMapDownload();
void ResetDDNetRanks();
void FinishDDNetRanks();
virtual CFetchTask *MapDownloadTask() { return m_pMapdownloadTask; }
virtual const char *MapDownloadName() { return m_aMapdownloadName; }
@ -392,6 +395,7 @@ public:
virtual void DemoSlice(const char *pDstPath, CLIENTFUNC_FILTER pfnFilter, void *pUser);
void RequestDDNetSrvList();
void RequestDDNetRanks();
bool EditorHasUnsavedData() { return m_pEditor->HasUnsavedData(); }
virtual IFriends* Foes() {return &m_Foes; }

View file

@ -62,6 +62,8 @@ CServerBrowser::CServerBrowser()
m_ServerlistType = 0;
m_BroadcastTime = 0;
m_BroadcastExtraToken = -1;
m_pDDNetRanks = 0;
}
void CServerBrowser::SetBaseInfo(class CNetClient *pClient, const char *pNetVersion)
@ -189,6 +191,8 @@ void CServerBrowser::Filter()
Filtered = 1;
else if(!g_Config.m_BrFilterGametypeStrict && g_Config.m_BrFilterGametype[0] && !str_find_nocase(m_ppServerlist[i]->m_Info.m_aGameType, g_Config.m_BrFilterGametype))
Filtered = 1;
else if(g_Config.m_BrFilterUnfinishedMap && m_ppServerlist[i]->m_Info.m_HasRank != 0)
Filtered = 1;
else
{
if(g_Config.m_BrFilterCountry)
@ -292,8 +296,9 @@ int CServerBrowser::SortHash() const
i |= g_Config.m_BrFilterPure<<11;
i |= g_Config.m_BrFilterPureMap<<12;
i |= g_Config.m_BrFilterGametypeStrict<<13;
i |= g_Config.m_BrFilterCountry<<14;
i |= g_Config.m_BrFilterPing<<15;
i |= g_Config.m_BrFilterUnfinishedMap<<14;
i |= g_Config.m_BrFilterCountry<<15;
i |= g_Config.m_BrFilterPing<<16;
return i;
}
@ -411,6 +416,7 @@ CServerBrowser::CServerEntry *CServerBrowser::Add(const NETADDR &Addr)
pEntry->m_Info.m_NetAddr = Addr;
pEntry->m_Info.m_Latency = 999;
pEntry->m_Info.m_HasRank = -1;
net_addr_str(&Addr, pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aAddress), true);
str_copy(pEntry->m_Info.m_aName, pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aName));
@ -581,7 +587,8 @@ void CServerBrowser::Refresh(int Type)
}
else if(Type == IServerBrowser::TYPE_DDNET)
{
LoadDDNet();
LoadDDNetServers();
LoadDDNetRanks();
// remove unknown elements of exclude list
DDNetCountryFilterClean();
@ -911,7 +918,7 @@ void CServerBrowser::RemoveFavorite(const NETADDR &Addr)
}
}
void CServerBrowser::LoadDDNet()
void CServerBrowser::LoadDDNetServers()
{
// reset servers / countries
m_NumDDNetCountries = 0;
@ -926,7 +933,6 @@ void CServerBrowser::LoadDDNet()
char aBuf[4096*4];
mem_zero(aBuf, sizeof(aBuf));
io_read(File, aBuf, sizeof(aBuf));
io_close(File);
@ -997,6 +1003,52 @@ void CServerBrowser::LoadDDNet()
json_value_free(pCountries);
}
void CServerBrowser::LoadDDNetRanks()
{
// load ddnet ranks list
IStorage *pStorage = Kernel()->RequestInterface<IStorage>();
IOHANDLE File = pStorage->OpenFile("ddnet-ranks.json", IOFLAG_READ, IStorage::TYPE_ALL);
if(!File)
return;
const int Length = io_length(File);
char *pBuf = (char *)mem_alloc(Length, 1);
pBuf[0] = '\0';
io_read(File, pBuf, Length);
io_close(File);
m_pDDNetRanks = json_parse(pBuf, Length);
mem_free(pBuf);
for(int i = 0; i < m_NumServers; i++)
{
if(m_ppServerlist[i]->m_Info.m_aMap[0])
m_ppServerlist[i]->m_Info.m_HasRank = HasRank(m_ppServerlist[i]->m_Info.m_aMap);
}
}
int CServerBrowser::HasRank(const char *pMap)
{
if(m_ServerlistType != IServerBrowser::TYPE_DDNET)
return -1;
if(!m_pDDNetRanks)
return -1;
for (int i = 0; i < json_array_length(m_pDDNetRanks); i++)
{
const json_value *pJson = json_array_get(m_pDDNetRanks, i);
const char *pStr = json_string_get(pJson);
if(str_comp(pMap, pStr) == 0)
return 1;
}
return 0;
}
bool CServerBrowser::IsRefreshing() const
{
return m_pFirstReqServer != 0;

View file

@ -4,6 +4,7 @@
#define ENGINE_CLIENT_SERVERBROWSER_H
#include <engine/serverbrowser.h>
#include <engine/external/json-parser/json.h>
class CServerBrowser : public IServerBrowser
{
@ -73,7 +74,9 @@ public:
void AddFavorite(const NETADDR &Addr);
void RemoveFavorite(const NETADDR &Addr);
void LoadDDNet();
void LoadDDNetServers();
void LoadDDNetRanks();
int HasRank(const char *pMap);
int NumDDNetCountries() { return m_NumDDNetCountries; };
int GetDDNetCountryFlag(int Index) { return m_aDDNetCountries[Index].m_FlagID; };
const char *GetDDNetCountryName(int Index) { return m_aDDNetCountries[Index].m_aName; };
@ -118,6 +121,7 @@ private:
char m_aDDNetTypes[MAX_DDNET_TYPES][32];
int m_NumDDNetTypes;
json_value *m_pDDNetRanks;
CServerEntry *m_aServerlistIp[256]; // ip hash list

View file

@ -47,6 +47,7 @@ public:
int m_Flags;
int m_Favorite;
int m_Latency; // in ms
int m_HasRank;
char m_aGameType[16];
char m_aName[64];
char m_aMap[32];

View file

@ -58,6 +58,7 @@ MACRO_CONFIG_STR(BrFilterServerAddress, br_filter_serveraddress, 128, "", CFGFLA
MACRO_CONFIG_INT(BrFilterPure, br_filter_pure, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out non-standard servers in browser")
MACRO_CONFIG_INT(BrFilterPureMap, br_filter_pure_map, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out non-standard maps 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_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)")

View file

@ -67,7 +67,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
{COL_FLAG_FAV, -1, " ", -1, 14.0f, 0, {0}, {0}},
{COL_NAME, IServerBrowser::SORT_NAME, "Name", 0, 50.0f, 0, {0}, {0}}, // Localize - these strings are localized within CLocConstString
{COL_GAMETYPE, IServerBrowser::SORT_GAMETYPE, "Type", 1, 50.0f, 0, {0}, {0}},
{COL_MAP, IServerBrowser::SORT_MAP, "Map", 1, 100.0f + (Headers.w - 480) / 8, 0, {0}, {0}},
{COL_MAP, IServerBrowser::SORT_MAP, "Map", 1, 120.0f + (Headers.w - 480) / 8, 0, {0}, {0}},
{COL_PLAYERS, IServerBrowser::SORT_NUMPLAYERS, "Players", 1, 60.0f, 0, {0}, {0}},
{-1, -1, " ", 1, 10.0f, 0, {0}, {0}},
{COL_PING, IServerBrowser::SORT_PING, "Ping", 1, 40.0f, FIXED, {0}, {0}},
@ -363,6 +363,18 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
}
else if(ID == COL_MAP)
{
if(g_Config.m_UiPage == PAGE_DDNET)
{
CUIRect Icon;
Button.VMargin(4.0f, &Button);
Button.VSplitLeft(Button.h, &Icon, &Button);
Icon.Margin(2.0f, &Icon);
if(pItem->m_HasRank == 0)
DoButton_Icon(IMAGE_BROWSEICONS, SPRITE_BROWSE_NORANK, &Icon);
else if(pItem->m_HasRank == 1)
DoButton_Icon(IMAGE_BROWSEICONS, SPRITE_BROWSE_RANK, &Icon);
}
CTextCursor Cursor;
TextRender()->SetCursor(&Cursor, Button.x, Button.y, 12.0f * UI()->Scale(), TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Button.w;
@ -582,19 +594,19 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
g_Config.m_BrFilterPw ^= 1;
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if (DoButton_CheckBox((char *)&g_Config.m_BrFilterCompatversion, Localize("Compatible version"), g_Config.m_BrFilterCompatversion, &Button))
if (DoButton_CheckBox(&g_Config.m_BrFilterCompatversion, Localize("Compatible version"), g_Config.m_BrFilterCompatversion, &Button))
g_Config.m_BrFilterCompatversion ^= 1;
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if (DoButton_CheckBox((char *)&g_Config.m_BrFilterPure, Localize("Standard gametype"), g_Config.m_BrFilterPure, &Button))
if (DoButton_CheckBox(&g_Config.m_BrFilterPure, Localize("Standard gametype"), g_Config.m_BrFilterPure, &Button))
g_Config.m_BrFilterPure ^= 1;
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if (DoButton_CheckBox((char *)&g_Config.m_BrFilterPureMap, Localize("Standard map"), g_Config.m_BrFilterPureMap, &Button))
if (DoButton_CheckBox(&g_Config.m_BrFilterPureMap, Localize("Standard map"), g_Config.m_BrFilterPureMap, &Button))
g_Config.m_BrFilterPureMap ^= 1;
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if (DoButton_CheckBox((char *)&g_Config.m_BrFilterGametypeStrict, Localize("Strict gametype filter"), g_Config.m_BrFilterGametypeStrict, &Button))
if (DoButton_CheckBox(&g_Config.m_BrFilterGametypeStrict, Localize("Strict gametype filter"), g_Config.m_BrFilterGametypeStrict, &Button))
g_Config.m_BrFilterGametypeStrict ^= 1;
ServerFilter.HSplitTop(5.0f, 0, &ServerFilter);
@ -658,6 +670,10 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
// ddnet country filters
if(g_Config.m_UiPage == PAGE_DDNET)
{
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if (DoButton_CheckBox(&g_Config.m_BrFilterUnfinishedMap, Localize("Unfinished map"), g_Config.m_BrFilterUnfinishedMap, &Button))
g_Config.m_BrFilterUnfinishedMap ^= 1;
// add more space
ServerFilter.HSplitTop(10.0f, 0, &ServerFilter);
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
@ -821,6 +837,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
g_Config.m_BrFilterPing = 999;
g_Config.m_BrFilterGametype[0] = 0;
g_Config.m_BrFilterGametypeStrict = 0;
g_Config.m_BrFilterUnfinishedMap = 0;
g_Config.m_BrFilterServerAddress[0] = 0;
g_Config.m_BrFilterPure = 0;
g_Config.m_BrFilterPureMap = 0;
@ -1347,6 +1364,7 @@ void CMenus::RenderServerbrowser(CUIRect MainView)
{
// start a new serverlist request
Client()->RequestDDNetSrvList();
Client()->RequestDDNetRanks();
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
}
m_DoubleClickIndex = -1;