mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Allow multiple addresses per server in the serverbrowser
Support is incomplete for `leak_ip_address_to_all_servers` (will only ping the first address of each server) and for the `leak_ip` setting (which will also only ping the first address of each server).
This commit is contained in:
parent
2e34cf4d4b
commit
6600024f24
|
@ -1706,6 +1706,7 @@ set_src(BASE GLOB_RECURSE src/base
|
|||
system.cpp
|
||||
system.h
|
||||
tl/threading.h
|
||||
types.h
|
||||
unicode/confusables.cpp
|
||||
unicode/confusables.h
|
||||
unicode/confusables_data.h
|
||||
|
@ -1723,6 +1724,7 @@ set_src(ENGINE_INTERFACE GLOB src/engine
|
|||
discord.h
|
||||
editor.h
|
||||
engine.h
|
||||
favorites.h
|
||||
friends.h
|
||||
ghost.h
|
||||
graphics.h
|
||||
|
@ -1963,6 +1965,7 @@ if(CLIENT)
|
|||
demoedit.cpp
|
||||
demoedit.h
|
||||
discord.cpp
|
||||
favorites.cpp
|
||||
friends.cpp
|
||||
friends.h
|
||||
ghost.cpp
|
||||
|
|
11
src/base/types.h
Normal file
11
src/base/types.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef BASE_TYPES_H
|
||||
#define BASE_TYPES_H
|
||||
|
||||
enum class TRISTATE
|
||||
{
|
||||
NONE,
|
||||
SOME,
|
||||
ALL,
|
||||
};
|
||||
|
||||
#endif // BASE_TYPES_H
|
|
@ -22,6 +22,7 @@
|
|||
#include <engine/discord.h>
|
||||
#include <engine/editor.h>
|
||||
#include <engine/engine.h>
|
||||
#include <engine/favorites.h>
|
||||
#include <engine/graphics.h>
|
||||
#include <engine/input.h>
|
||||
#include <engine/keys.h>
|
||||
|
@ -1519,7 +1520,7 @@ void CClient::ProcessServerInfo(int RawType, NETADDR *pFrom, const void *pData,
|
|||
{
|
||||
if(!DuplicatedPacket && (!pEntry || !pEntry->m_GotInfo || SavedType >= pEntry->m_Info.m_Type))
|
||||
{
|
||||
m_ServerBrowser.Set(*pFrom, IServerBrowser::SET_TOKEN, Token, &Info);
|
||||
m_ServerBrowser.OnServerInfoUpdate(*pFrom, Token, &Info);
|
||||
}
|
||||
|
||||
// Player info is irrelevant for the client (while connected),
|
||||
|
@ -1535,7 +1536,8 @@ void CClient::ProcessServerInfo(int RawType, NETADDR *pFrom, const void *pData,
|
|||
if(SavedType >= m_CurrentServerInfo.m_Type)
|
||||
{
|
||||
mem_copy(&m_CurrentServerInfo, &Info, sizeof(m_CurrentServerInfo));
|
||||
m_CurrentServerInfo.m_NetAddr = m_ServerAddress;
|
||||
m_CurrentServerInfo.m_NumAddresses = 1;
|
||||
m_CurrentServerInfo.m_aAddresses[0] = m_ServerAddress;
|
||||
m_CurrentServerInfoRequestTime = -1;
|
||||
}
|
||||
|
||||
|
@ -2954,6 +2956,7 @@ void CClient::InitInterfaces()
|
|||
// fetch interfaces
|
||||
m_pEngine = Kernel()->RequestInterface<IEngine>();
|
||||
m_pEditor = Kernel()->RequestInterface<IEditor>();
|
||||
m_pFavorites = Kernel()->RequestInterface<IFavorites>();
|
||||
//m_pGraphics = Kernel()->RequestInterface<IEngineGraphics>();
|
||||
m_pSound = Kernel()->RequestInterface<IEngineSound>();
|
||||
m_pGameClient = Kernel()->RequestInterface<IGameClient>();
|
||||
|
@ -2978,6 +2981,7 @@ void CClient::InitInterfaces()
|
|||
m_Updater.Init();
|
||||
#endif
|
||||
|
||||
m_pConfigManager->RegisterCallback(IFavorites::ConfigSaveCallback, m_pFavorites);
|
||||
m_Friends.Init();
|
||||
m_Foes.Init(true);
|
||||
|
||||
|
@ -3672,6 +3676,41 @@ void CClient::Con_RconLogin(IConsole::IResult *pResult, void *pUserData)
|
|||
pSelf->RconAuth(pResult->GetString(0), pResult->GetString(1));
|
||||
}
|
||||
|
||||
void CClient::Con_BeginFavoriteGroup(IConsole::IResult *pResult, void *pUserData)
|
||||
{
|
||||
CClient *pSelf = (CClient *)pUserData;
|
||||
if(pSelf->m_FavoritesGroup)
|
||||
{
|
||||
log_error("client", "opening favorites group while there is already one, discarding old one");
|
||||
for(int i = 0; i < pSelf->m_FavoritesGroupNum; i++)
|
||||
{
|
||||
char aAddr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&pSelf->m_aFavoritesGroupAddresses[i], aAddr, sizeof(aAddr), true);
|
||||
log_warn("client", "discarding %s", aAddr);
|
||||
}
|
||||
}
|
||||
pSelf->m_FavoritesGroup = true;
|
||||
pSelf->m_FavoritesGroupAllowPing = false;
|
||||
pSelf->m_FavoritesGroupNum = 0;
|
||||
}
|
||||
|
||||
void CClient::Con_EndFavoriteGroup(IConsole::IResult *pResult, void *pUserData)
|
||||
{
|
||||
CClient *pSelf = (CClient *)pUserData;
|
||||
if(!pSelf->m_FavoritesGroup)
|
||||
{
|
||||
log_error("client", "closing favorites group while there is none, ignoring");
|
||||
return;
|
||||
}
|
||||
log_info("client", "adding group of %d favorites", pSelf->m_FavoritesGroupNum);
|
||||
pSelf->m_pFavorites->Add(pSelf->m_aFavoritesGroupAddresses, pSelf->m_FavoritesGroupNum);
|
||||
if(pSelf->m_FavoritesGroupAllowPing)
|
||||
{
|
||||
pSelf->m_pFavorites->AllowPing(pSelf->m_aFavoritesGroupAddresses, pSelf->m_FavoritesGroupNum, true);
|
||||
}
|
||||
pSelf->m_FavoritesGroup = false;
|
||||
}
|
||||
|
||||
void CClient::Con_AddFavorite(IConsole::IResult *pResult, void *pUserData)
|
||||
{
|
||||
CClient *pSelf = (CClient *)pUserData;
|
||||
|
@ -3683,10 +3722,29 @@ void CClient::Con_AddFavorite(IConsole::IResult *pResult, void *pUserData)
|
|||
pSelf->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf);
|
||||
return;
|
||||
}
|
||||
pSelf->m_ServerBrowser.AddFavorite(Addr);
|
||||
if(pResult->NumArguments() > 1 && str_find(pResult->GetString(1), "allow_ping"))
|
||||
bool AllowPing = pResult->NumArguments() > 1 && str_find(pResult->GetString(1), "allow_ping");
|
||||
char aAddr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&Addr, aAddr, sizeof(aAddr), true);
|
||||
if(pSelf->m_FavoritesGroup)
|
||||
{
|
||||
pSelf->m_ServerBrowser.FavoriteAllowPing(Addr, true);
|
||||
if(pSelf->m_FavoritesGroupNum == (int)std::size(pSelf->m_aFavoritesGroupAddresses))
|
||||
{
|
||||
log_error("client", "discarding %s because groups can have at most a size of %d", aAddr, pSelf->m_FavoritesGroupNum);
|
||||
return;
|
||||
}
|
||||
log_info("client", "adding %s to favorites group", aAddr);
|
||||
pSelf->m_aFavoritesGroupAddresses[pSelf->m_FavoritesGroupNum] = Addr;
|
||||
pSelf->m_FavoritesGroupAllowPing = pSelf->m_FavoritesGroupAllowPing || AllowPing;
|
||||
pSelf->m_FavoritesGroupNum += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_info("client", "adding %s to favorites", aAddr);
|
||||
pSelf->m_pFavorites->Add(&Addr, 1);
|
||||
if(AllowPing)
|
||||
{
|
||||
pSelf->m_pFavorites->AllowPing(&Addr, 1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3695,7 +3753,7 @@ void CClient::Con_RemoveFavorite(IConsole::IResult *pResult, void *pUserData)
|
|||
CClient *pSelf = (CClient *)pUserData;
|
||||
NETADDR Addr;
|
||||
if(net_addr_from_str(&Addr, pResult->GetString(0)) == 0)
|
||||
pSelf->m_ServerBrowser.RemoveFavorite(Addr);
|
||||
pSelf->m_pFavorites->Remove(&Addr, 1);
|
||||
}
|
||||
|
||||
void CClient::DemoSliceBegin()
|
||||
|
@ -4383,6 +4441,8 @@ void CClient::RegisterCommands()
|
|||
m_pConsole->Register("record", "?r[file]", CFGFLAG_CLIENT, Con_Record, this, "Record to the file");
|
||||
m_pConsole->Register("stoprecord", "", CFGFLAG_CLIENT, Con_StopRecord, this, "Stop recording");
|
||||
m_pConsole->Register("add_demomarker", "", CFGFLAG_CLIENT, Con_AddDemoMarker, this, "Add demo timeline marker");
|
||||
m_pConsole->Register("begin_favorite_group", "", CFGFLAG_CLIENT, Con_BeginFavoriteGroup, this, "Use this before `add_favorite` to group favorites. End with `end_favorite_group`");
|
||||
m_pConsole->Register("end_favorite_group", "", CFGFLAG_CLIENT, Con_EndFavoriteGroup, this, "Use this after `add_favorite` to group favorites. Start with `begin_favorite_group`");
|
||||
m_pConsole->Register("add_favorite", "s[host|ip] ?s['allow_ping']", CFGFLAG_CLIENT, Con_AddFavorite, this, "Add a server as a favorite");
|
||||
m_pConsole->Register("remove_favorite", "r[host|ip]", CFGFLAG_CLIENT, Con_RemoveFavorite, this, "Remove a server from favorites");
|
||||
m_pConsole->Register("demo_slice_start", "", CFGFLAG_CLIENT, Con_DemoSliceBegin, this, "");
|
||||
|
@ -4403,6 +4463,9 @@ void CClient::RegisterCommands()
|
|||
m_pConsole->Chain("br_filter_string", ConchainServerBrowserUpdate, this);
|
||||
m_pConsole->Chain("br_filter_gametype", ConchainServerBrowserUpdate, this);
|
||||
m_pConsole->Chain("br_filter_serveraddress", ConchainServerBrowserUpdate, this);
|
||||
m_pConsole->Chain("add_favorite", ConchainServerBrowserUpdate, this);
|
||||
m_pConsole->Chain("remove_favorite", ConchainServerBrowserUpdate, this);
|
||||
m_pConsole->Chain("end_favorite_group", ConchainServerBrowserUpdate, this);
|
||||
|
||||
m_pConsole->Chain("gfx_screen", ConchainWindowScreen, this);
|
||||
m_pConsole->Chain("gfx_fullscreen", ConchainFullscreen, this);
|
||||
|
@ -4567,6 +4630,7 @@ int main(int argc, const char **argv)
|
|||
RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IMap *>(pEngineMap), false);
|
||||
|
||||
RegisterFail = RegisterFail || !pKernel->RegisterInterface(CreateEditor(), false);
|
||||
RegisterFail = RegisterFail || !pKernel->RegisterInterface(CreateFavorites().release());
|
||||
RegisterFail = RegisterFail || !pKernel->RegisterInterface(CreateGameClient());
|
||||
RegisterFail = RegisterFail || !pKernel->RegisterInterface(pStorage);
|
||||
RegisterFail = RegisterFail || !pKernel->RegisterInterface(pDiscord);
|
||||
|
|
|
@ -110,6 +110,7 @@ class CClient : public IClient, public CDemoPlayer::IListener
|
|||
IEngineInput *m_pInput;
|
||||
IEngineGraphics *m_pGraphics;
|
||||
IEngineSound *m_pSound;
|
||||
IFavorites *m_pFavorites;
|
||||
IGameClient *m_pGameClient;
|
||||
IEngineMap *m_pMap;
|
||||
IConfigManager *m_pConfigManager;
|
||||
|
@ -291,6 +292,12 @@ class CClient : public IClient, public CDemoPlayer::IListener
|
|||
int m_OwnExecutableSize = 0;
|
||||
IOHANDLE m_OwnExecutable;
|
||||
|
||||
// favorite command handling
|
||||
bool m_FavoritesGroup = false;
|
||||
bool m_FavoritesGroupAllowPing = false;
|
||||
int m_FavoritesGroupNum = 0;
|
||||
NETADDR m_aFavoritesGroupAddresses[MAX_SERVER_ADDRESSES];
|
||||
|
||||
void UpdateDemoIntraTimers();
|
||||
int MaxLatencyTicks() const;
|
||||
int PredictionMargin() const;
|
||||
|
@ -446,6 +453,8 @@ public:
|
|||
static void Con_Rcon(IConsole::IResult *pResult, void *pUserData);
|
||||
static void Con_RconAuth(IConsole::IResult *pResult, void *pUserData);
|
||||
static void Con_RconLogin(IConsole::IResult *pResult, void *pUserData);
|
||||
static void Con_BeginFavoriteGroup(IConsole::IResult *pResult, void *pUserData);
|
||||
static void Con_EndFavoriteGroup(IConsole::IResult *pResult, void *pUserData);
|
||||
static void Con_AddFavorite(IConsole::IResult *pResult, void *pUserData);
|
||||
static void Con_RemoveFavorite(IConsole::IResult *pResult, void *pUserData);
|
||||
static void Con_Play(IConsole::IResult *pResult, void *pUserData);
|
||||
|
|
249
src/engine/client/favorites.cpp
Normal file
249
src/engine/client/favorites.cpp
Normal file
|
@ -0,0 +1,249 @@
|
|||
#include <engine/favorites.h>
|
||||
#include <engine/shared/config.h>
|
||||
#include <engine/shared/protocol.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
class CFavorites : public IFavorites
|
||||
{
|
||||
protected:
|
||||
void OnConfigSave(IConfigManager *pConfigManager) override;
|
||||
|
||||
public:
|
||||
TRISTATE IsFavorite(const NETADDR *pAddrs, int NumAddrs) const override;
|
||||
TRISTATE IsPingAllowed(const NETADDR *pAddrs, int NumAddrs) const override;
|
||||
void Add(const NETADDR *pAddrs, int NumAddrs) override;
|
||||
void AllowPing(const NETADDR *pAddrs, int NumAddrs, bool AllowPing) override;
|
||||
void Remove(const NETADDR *pAddrs, int NumAddrs) override;
|
||||
void AllEntries(const CEntry **ppEntries, int *pNumEntries) override;
|
||||
|
||||
private:
|
||||
std::vector<CEntry> m_aEntries;
|
||||
std::unordered_map<NETADDR, int> m_ByAddr;
|
||||
|
||||
CEntry *Entry(const NETADDR &Addr);
|
||||
const CEntry *Entry(const NETADDR &Addr) const;
|
||||
// `pEntry` must come from the `m_aEntries` vector.
|
||||
void RemoveEntry(CEntry *pEntry);
|
||||
};
|
||||
|
||||
void CFavorites::OnConfigSave(IConfigManager *pConfigManager)
|
||||
{
|
||||
for(const auto &Entry : m_aEntries)
|
||||
{
|
||||
if(Entry.m_NumAddrs > 1)
|
||||
{
|
||||
pConfigManager->WriteLine("begin_favorite_group");
|
||||
}
|
||||
for(int i = 0; i < Entry.m_NumAddrs; i++)
|
||||
{
|
||||
char aAddr[NETADDR_MAXSTRSIZE];
|
||||
char aBuffer[128];
|
||||
net_addr_str(&Entry.m_aAddrs[i], aAddr, sizeof(aAddr), true);
|
||||
if(!Entry.m_AllowPing)
|
||||
{
|
||||
str_format(aBuffer, sizeof(aBuffer), "add_favorite %s", aAddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add quotes to the first parameter for backward
|
||||
// compatibility with versions that took a `r` console
|
||||
// parameter.
|
||||
str_format(aBuffer, sizeof(aBuffer), "add_favorite \"%s\" allow_ping", aAddr);
|
||||
}
|
||||
pConfigManager->WriteLine(aBuffer);
|
||||
}
|
||||
if(Entry.m_NumAddrs > 1)
|
||||
{
|
||||
pConfigManager->WriteLine("end_favorite_group");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TRISTATE CFavorites::IsFavorite(const NETADDR *pAddrs, int NumAddrs) const
|
||||
{
|
||||
bool All = true;
|
||||
bool None = true;
|
||||
for(int i = 0; i < NumAddrs && (All || None); i++)
|
||||
{
|
||||
const CEntry *pEntry = Entry(pAddrs[i]);
|
||||
if(pEntry)
|
||||
{
|
||||
None = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
All = false;
|
||||
}
|
||||
}
|
||||
// Return ALL if no addresses were passed.
|
||||
if(All)
|
||||
{
|
||||
return TRISTATE::ALL;
|
||||
}
|
||||
else if(None)
|
||||
{
|
||||
return TRISTATE::NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TRISTATE::SOME;
|
||||
}
|
||||
}
|
||||
|
||||
TRISTATE CFavorites::IsPingAllowed(const NETADDR *pAddrs, int NumAddrs) const
|
||||
{
|
||||
bool All = true;
|
||||
bool None = true;
|
||||
for(int i = 0; i < NumAddrs && (All || None); i++)
|
||||
{
|
||||
const CEntry *pEntry = Entry(pAddrs[i]);
|
||||
if(pEntry == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(pEntry->m_AllowPing)
|
||||
{
|
||||
None = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
All = false;
|
||||
}
|
||||
}
|
||||
// Return ALL if no addresses were passed.
|
||||
if(All)
|
||||
{
|
||||
return TRISTATE::ALL;
|
||||
}
|
||||
else if(None)
|
||||
{
|
||||
return TRISTATE::NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TRISTATE::SOME;
|
||||
}
|
||||
}
|
||||
|
||||
void CFavorites::Add(const NETADDR *pAddrs, int NumAddrs)
|
||||
{
|
||||
// First make sure that all the addresses are not registered for some
|
||||
// other favorite.
|
||||
for(int i = 0; i < NumAddrs; i++)
|
||||
{
|
||||
CEntry *pEntry = Entry(pAddrs[i]);
|
||||
if(pEntry == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for(int j = 0; j < pEntry->m_NumAddrs; j++)
|
||||
{
|
||||
if(pEntry->m_aAddrs[j] == pAddrs[i])
|
||||
{
|
||||
pEntry->m_aAddrs[j] = pEntry->m_aAddrs[pEntry->m_NumAddrs - 1];
|
||||
pEntry->m_NumAddrs -= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If the entry has become empty due to the cleaning, remove it
|
||||
// completely.
|
||||
if(pEntry->m_NumAddrs == 0)
|
||||
{
|
||||
RemoveEntry(pEntry);
|
||||
}
|
||||
}
|
||||
// Add the new entry.
|
||||
CEntry NewEntry;
|
||||
mem_zero(&NewEntry, sizeof(NewEntry));
|
||||
NewEntry.m_NumAddrs = std::min(NumAddrs, (int)std::size(NewEntry.m_aAddrs));
|
||||
for(int i = 0; i < NewEntry.m_NumAddrs; i++)
|
||||
{
|
||||
NewEntry.m_aAddrs[i] = pAddrs[i];
|
||||
m_ByAddr[pAddrs[i]] = m_aEntries.size();
|
||||
}
|
||||
NewEntry.m_AllowPing = false;
|
||||
m_aEntries.push_back(NewEntry);
|
||||
}
|
||||
|
||||
void CFavorites::AllowPing(const NETADDR *pAddrs, int NumAddrs, bool AllowPing)
|
||||
{
|
||||
for(int i = 0; i < NumAddrs; i++)
|
||||
{
|
||||
CEntry *pEntry = Entry(pAddrs[i]);
|
||||
if(pEntry == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
pEntry->m_AllowPing = AllowPing;
|
||||
}
|
||||
}
|
||||
|
||||
void CFavorites::Remove(const NETADDR *pAddrs, int NumAddrs)
|
||||
{
|
||||
for(int i = 0; i < NumAddrs; i++)
|
||||
{
|
||||
CEntry *pEntry = Entry(pAddrs[i]);
|
||||
if(pEntry == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for(int j = 0; j < pEntry->m_NumAddrs; j++)
|
||||
{
|
||||
m_ByAddr.erase(pEntry->m_aAddrs[j]);
|
||||
}
|
||||
RemoveEntry(pEntry);
|
||||
}
|
||||
}
|
||||
|
||||
void CFavorites::AllEntries(const CEntry **ppEntries, int *pNumEntries)
|
||||
{
|
||||
*ppEntries = m_aEntries.data();
|
||||
*pNumEntries = m_aEntries.size();
|
||||
}
|
||||
|
||||
CFavorites::CEntry *CFavorites::Entry(const NETADDR &Addr)
|
||||
{
|
||||
auto Entry = m_ByAddr.find(Addr);
|
||||
if(Entry == m_ByAddr.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return &m_aEntries[Entry->second];
|
||||
}
|
||||
|
||||
const CFavorites::CEntry *CFavorites::Entry(const NETADDR &Addr) const
|
||||
{
|
||||
auto Entry = m_ByAddr.find(Addr);
|
||||
if(Entry == m_ByAddr.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return &m_aEntries[Entry->second];
|
||||
}
|
||||
|
||||
void CFavorites::RemoveEntry(CEntry *pEntry)
|
||||
{
|
||||
// Replace the entry
|
||||
int Index = pEntry - &m_aEntries[0];
|
||||
*pEntry = m_aEntries[m_aEntries.size() - 1];
|
||||
m_aEntries.pop_back();
|
||||
if(Index != (int)m_aEntries.size())
|
||||
{
|
||||
for(int i = 0; i < pEntry->m_NumAddrs; i++)
|
||||
{
|
||||
m_ByAddr.at(pEntry->m_aAddrs[i]) = Index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IFavorites::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData)
|
||||
{
|
||||
((IFavorites *)pUserData)->OnConfigSave(pConfigManager);
|
||||
}
|
||||
|
||||
std::unique_ptr<IFavorites> CreateFavorites()
|
||||
{
|
||||
return std::make_unique<CFavorites>();
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <base/hash_ctxt.h>
|
||||
|
@ -24,6 +25,7 @@
|
|||
#include <engine/config.h>
|
||||
#include <engine/console.h>
|
||||
#include <engine/engine.h>
|
||||
#include <engine/favorites.h>
|
||||
#include <engine/friends.h>
|
||||
#include <engine/serverbrowser.h>
|
||||
#include <engine/storage.h>
|
||||
|
@ -49,10 +51,6 @@ CServerBrowser::CServerBrowser()
|
|||
m_ppServerlist = 0;
|
||||
m_pSortedServerlist = 0;
|
||||
|
||||
m_NumFavoriteServers = 0;
|
||||
|
||||
mem_zero(m_apServerlistIp, sizeof(m_apServerlistIp));
|
||||
|
||||
m_pFirstReqServer = 0; // request list
|
||||
m_pLastReqServer = 0;
|
||||
m_NumRequests = 0;
|
||||
|
@ -93,11 +91,9 @@ void CServerBrowser::SetBaseInfo(class CNetClient *pClient, const char *pNetVers
|
|||
str_copy(m_aNetVersion, pNetVersion);
|
||||
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
||||
m_pEngine = Kernel()->RequestInterface<IEngine>();
|
||||
m_pFavorites = Kernel()->RequestInterface<IFavorites>();
|
||||
m_pFriends = Kernel()->RequestInterface<IFriends>();
|
||||
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
||||
IConfigManager *pConfigManager = Kernel()->RequestInterface<IConfigManager>();
|
||||
if(pConfigManager)
|
||||
pConfigManager->RegisterCallback(ConfigSaveCallback, this);
|
||||
m_pPingCache = CreateServerBrowserPingCache(m_pConsole, m_pStorage);
|
||||
|
||||
RegisterCommands();
|
||||
|
@ -117,6 +113,8 @@ void CServerBrowser::Con_LeakIpAddress(IConsole::IResult *pResult, void *pUserDa
|
|||
{
|
||||
CServerBrowser *pThis = (CServerBrowser *)pUserData;
|
||||
|
||||
// We only consider the first address of every server.
|
||||
|
||||
std::vector<int> vSortedServers;
|
||||
// Sort servers by IP address, ignoring port.
|
||||
class CAddrComparer
|
||||
|
@ -125,8 +123,8 @@ void CServerBrowser::Con_LeakIpAddress(IConsole::IResult *pResult, void *pUserDa
|
|||
CServerBrowser *m_pThis;
|
||||
bool operator()(int i, int j)
|
||||
{
|
||||
NETADDR Addr1 = m_pThis->m_ppServerlist[i]->m_Addr;
|
||||
NETADDR Addr2 = m_pThis->m_ppServerlist[j]->m_Addr;
|
||||
NETADDR Addr1 = m_pThis->m_ppServerlist[i]->m_Info.m_aAddresses[0];
|
||||
NETADDR Addr2 = m_pThis->m_ppServerlist[j]->m_Info.m_aAddresses[0];
|
||||
Addr1.port = 0;
|
||||
Addr2.port = 0;
|
||||
return net_addr_comp(&Addr1, &Addr2) < 0;
|
||||
|
@ -148,7 +146,7 @@ void CServerBrowser::Con_LeakIpAddress(IConsole::IResult *pResult, void *pUserDa
|
|||
NETADDR NextAddr;
|
||||
if(i < (int)vSortedServers.size())
|
||||
{
|
||||
NextAddr = pThis->m_ppServerlist[vSortedServers[i]]->m_Addr;
|
||||
NextAddr = pThis->m_ppServerlist[vSortedServers[i]]->m_Info.m_aAddresses[0];
|
||||
NextAddr.port = 0;
|
||||
}
|
||||
bool New = Start == -1 || i == (int)vSortedServers.size() || net_addr_comp(&Addr, &NextAddr) != 0;
|
||||
|
@ -159,7 +157,7 @@ void CServerBrowser::Con_LeakIpAddress(IConsole::IResult *pResult, void *pUserDa
|
|||
pChosen->m_RequestIgnoreInfo = true;
|
||||
pThis->QueueRequest(pChosen);
|
||||
char aAddr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&pChosen->m_Addr, aAddr, sizeof(aAddr), true);
|
||||
net_addr_str(&pChosen->m_Info.m_aAddresses[0], aAddr, sizeof(aAddr), true);
|
||||
dbg_msg("serverbrowse/dbg", "queuing ping request for %s", aAddr);
|
||||
}
|
||||
if(i < (int)vSortedServers.size() && New)
|
||||
|
@ -465,14 +463,12 @@ void CServerBrowser::RemoveRequest(CServerEntry *pEntry)
|
|||
|
||||
CServerBrowser::CServerEntry *CServerBrowser::Find(const NETADDR &Addr)
|
||||
{
|
||||
CServerEntry *pEntry = m_apServerlistIp[Addr.ip[0]];
|
||||
|
||||
for(; pEntry; pEntry = pEntry->m_pNextIp)
|
||||
auto Entry = m_ByAddr.find(Addr);
|
||||
if(Entry == m_ByAddr.end())
|
||||
{
|
||||
if(net_addr_comp(&pEntry->m_Addr, &Addr) == 0)
|
||||
return pEntry;
|
||||
return nullptr;
|
||||
}
|
||||
return (CServerEntry *)0;
|
||||
return m_ppServerlist[Entry->second];
|
||||
}
|
||||
|
||||
void CServerBrowser::QueueRequest(CServerEntry *pEntry)
|
||||
|
@ -488,15 +484,47 @@ void CServerBrowser::QueueRequest(CServerEntry *pEntry)
|
|||
m_NumRequests++;
|
||||
}
|
||||
|
||||
void ServerBrowserFormatAddresses(char *pBuffer, int BufferSize, NETADDR *pAddrs, int NumAddrs)
|
||||
{
|
||||
for(int i = 0; i < NumAddrs; i++)
|
||||
{
|
||||
if(i != 0)
|
||||
{
|
||||
if(BufferSize <= 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pBuffer[0] = ',';
|
||||
pBuffer[1] = 0;
|
||||
pBuffer += 1;
|
||||
BufferSize -= 1;
|
||||
}
|
||||
if(BufferSize <= 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
net_addr_str(&pAddrs[i], pBuffer, BufferSize, true);
|
||||
int Length = str_length(pBuffer);
|
||||
pBuffer += Length;
|
||||
BufferSize -= Length;
|
||||
}
|
||||
}
|
||||
|
||||
void CServerBrowser::SetInfo(CServerEntry *pEntry, const CServerInfo &Info)
|
||||
{
|
||||
bool Fav = pEntry->m_Info.m_Favorite;
|
||||
TRISTATE Fav = pEntry->m_Info.m_Favorite;
|
||||
TRISTATE FavAllowPing = pEntry->m_Info.m_FavoriteAllowPing;
|
||||
bool Off = pEntry->m_Info.m_Official;
|
||||
NETADDR aAddresses[MAX_SERVER_ADDRESSES];
|
||||
mem_copy(aAddresses, pEntry->m_Info.m_aAddresses, sizeof(aAddresses));
|
||||
int NumAddresses = pEntry->m_Info.m_NumAddresses;
|
||||
pEntry->m_Info = Info;
|
||||
pEntry->m_Info.m_Favorite = Fav;
|
||||
pEntry->m_Info.m_FavoriteAllowPing = FavAllowPing;
|
||||
pEntry->m_Info.m_Official = Off;
|
||||
pEntry->m_Info.m_NetAddr = pEntry->m_Addr;
|
||||
net_addr_str(&pEntry->m_Info.m_NetAddr, pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aAddress), 1);
|
||||
mem_copy(pEntry->m_Info.m_aAddresses, aAddresses, sizeof(pEntry->m_Info.m_aAddresses));
|
||||
pEntry->m_Info.m_NumAddresses = NumAddresses;
|
||||
ServerBrowserFormatAddresses(pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aAddress), pEntry->m_Info.m_aAddresses, pEntry->m_Info.m_NumAddresses);
|
||||
|
||||
class CPlayerScoreNameLess
|
||||
{
|
||||
|
@ -530,23 +558,42 @@ void CServerBrowser::SetInfo(CServerEntry *pEntry, const CServerInfo &Info)
|
|||
|
||||
void CServerBrowser::SetLatency(NETADDR Addr, int Latency)
|
||||
{
|
||||
Addr.port = 0;
|
||||
for(CServerEntry *pEntry = m_apServerlistIp[Addr.ip[0]]; pEntry; pEntry = pEntry->m_pNextIp)
|
||||
{
|
||||
NETADDR Other = pEntry->m_Addr;
|
||||
Other.port = 0;
|
||||
if(net_addr_comp(&Addr, &Other) == 0 && pEntry->m_GotInfo)
|
||||
{
|
||||
pEntry->m_Info.m_Latency = Latency;
|
||||
pEntry->m_Info.m_LatencyIsEstimated = false;
|
||||
}
|
||||
}
|
||||
m_pPingCache->CachePing(Addr, Latency);
|
||||
|
||||
Addr.port = 0;
|
||||
for(int i = 0; i < m_NumServers; i++)
|
||||
{
|
||||
if(!m_ppServerlist[i]->m_GotInfo)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool Found = false;
|
||||
for(int j = 0; j < m_ppServerlist[i]->m_Info.m_NumAddresses; j++)
|
||||
{
|
||||
NETADDR Other = m_ppServerlist[i]->m_Info.m_aAddresses[j];
|
||||
Other.port = 0;
|
||||
if(Addr == Other)
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!Found)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int Ping = m_pPingCache->GetPing(m_ppServerlist[i]->m_Info.m_aAddresses, m_ppServerlist[i]->m_Info.m_NumAddresses);
|
||||
if(Ping == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
m_ppServerlist[i]->m_Info.m_Latency = Ping;
|
||||
m_ppServerlist[i]->m_Info.m_LatencyIsEstimated = false;
|
||||
}
|
||||
}
|
||||
|
||||
CServerBrowser::CServerEntry *CServerBrowser::Add(const NETADDR &Addr)
|
||||
CServerBrowser::CServerEntry *CServerBrowser::Add(const NETADDR *pAddrs, int NumAddrs)
|
||||
{
|
||||
int Hash = Addr.ip[0];
|
||||
CServerEntry *pEntry = 0;
|
||||
|
||||
// create new pEntry
|
||||
|
@ -554,37 +601,43 @@ CServerBrowser::CServerEntry *CServerBrowser::Add(const NETADDR &Addr)
|
|||
mem_zero(pEntry, sizeof(CServerEntry));
|
||||
|
||||
// set the info
|
||||
pEntry->m_Addr = Addr;
|
||||
pEntry->m_Info.m_NetAddr = Addr;
|
||||
mem_copy(pEntry->m_Info.m_aAddresses, pAddrs, NumAddrs * sizeof(pAddrs[0]));
|
||||
pEntry->m_Info.m_NumAddresses = NumAddrs;
|
||||
|
||||
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);
|
||||
ServerBrowserFormatAddresses(pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aAddress), pEntry->m_Info.m_aAddresses, pEntry->m_Info.m_NumAddresses);
|
||||
str_copy(pEntry->m_Info.m_aName, pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aName));
|
||||
|
||||
// check if it's a favorite
|
||||
pEntry->m_Info.m_Favorite = IsFavorite(Addr);
|
||||
pEntry->m_Info.m_Favorite = m_pFavorites->IsFavorite(pEntry->m_Info.m_aAddresses, pEntry->m_Info.m_NumAddresses);
|
||||
pEntry->m_Info.m_FavoriteAllowPing = m_pFavorites->IsPingAllowed(pEntry->m_Info.m_aAddresses, pEntry->m_Info.m_NumAddresses);
|
||||
|
||||
// check if it's an official server
|
||||
for(auto &Network : m_aNetworks)
|
||||
bool Official = false;
|
||||
for(int i = 0; !Official && i < (int)std::size(m_aNetworks); i++)
|
||||
{
|
||||
for(int i = 0; i < Network.m_NumCountries; i++)
|
||||
for(int j = 0; !Official && j < m_aNetworks[i].m_NumCountries; j++)
|
||||
{
|
||||
CNetworkCountry *pCntr = &Network.m_aCountries[i];
|
||||
for(int j = 0; j < pCntr->m_NumServers; j++)
|
||||
CNetworkCountry *pCntr = &m_aNetworks[i].m_aCountries[j];
|
||||
for(int k = 0; !Official && k < pCntr->m_NumServers; k++)
|
||||
{
|
||||
if(net_addr_comp(&Addr, &pCntr->m_aServers[j]) == 0)
|
||||
for(int l = 0; !Official && l < NumAddrs; l++)
|
||||
{
|
||||
pEntry->m_Info.m_Official = true;
|
||||
break;
|
||||
if(pAddrs[l] == pCntr->m_aServers[k])
|
||||
{
|
||||
Official = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pEntry->m_Info.m_Official = Official;
|
||||
|
||||
// add to the hash list
|
||||
pEntry->m_pNextIp = m_apServerlistIp[Hash];
|
||||
m_apServerlistIp[Hash] = pEntry;
|
||||
for(int i = 0; i < NumAddrs; i++)
|
||||
{
|
||||
m_ByAddr[pAddrs[i]] = m_NumServers;
|
||||
}
|
||||
|
||||
if(m_NumServers == m_NumServerCapacity)
|
||||
{
|
||||
|
@ -605,153 +658,94 @@ CServerBrowser::CServerEntry *CServerBrowser::Add(const NETADDR &Addr)
|
|||
return pEntry;
|
||||
}
|
||||
|
||||
void CServerBrowser::Set(const NETADDR &Addr, int Type, int Token, const CServerInfo *pInfo)
|
||||
void CServerBrowser::OnServerInfoUpdate(const NETADDR &Addr, int Token, const CServerInfo *pInfo)
|
||||
{
|
||||
CServerEntry *pEntry = 0;
|
||||
if(Type == IServerBrowser::SET_MASTER_ADD)
|
||||
int BasicToken = Token;
|
||||
int ExtraToken = 0;
|
||||
if(pInfo->m_Type == SERVERINFO_EXTENDED)
|
||||
{
|
||||
if(m_ServerlistType != IServerBrowser::TYPE_INTERNET)
|
||||
return;
|
||||
if(!Find(Addr))
|
||||
{
|
||||
pEntry = Add(Addr);
|
||||
QueueRequest(pEntry);
|
||||
}
|
||||
BasicToken = Token & 0xff;
|
||||
ExtraToken = Token >> 8;
|
||||
}
|
||||
else if(Type == IServerBrowser::SET_FAV_ADD)
|
||||
{
|
||||
if(m_ServerlistType != IServerBrowser::TYPE_FAVORITES)
|
||||
return;
|
||||
|
||||
if(!Find(Addr))
|
||||
{
|
||||
pEntry = Add(Addr);
|
||||
QueueRequest(pEntry);
|
||||
}
|
||||
}
|
||||
else if(Type == IServerBrowser::SET_DDNET_ADD)
|
||||
{
|
||||
if(m_ServerlistType != IServerBrowser::TYPE_DDNET)
|
||||
return;
|
||||
CServerEntry *pEntry = Find(Addr);
|
||||
|
||||
if(!Find(Addr))
|
||||
{
|
||||
pEntry = Add(Addr);
|
||||
QueueRequest(pEntry);
|
||||
}
|
||||
}
|
||||
else if(Type == IServerBrowser::SET_KOG_ADD)
|
||||
if(m_ServerlistType == IServerBrowser::TYPE_LAN)
|
||||
{
|
||||
if(m_ServerlistType != IServerBrowser::TYPE_KOG)
|
||||
return;
|
||||
|
||||
if(!Find(Addr))
|
||||
NETADDR Broadcast;
|
||||
mem_zero(&Broadcast, sizeof(Broadcast));
|
||||
Broadcast.type = m_pNetClient->NetType() | NETTYPE_LINK_BROADCAST;
|
||||
int TokenBC = GenerateToken(Broadcast);
|
||||
bool Drop = false;
|
||||
Drop = Drop || BasicToken != GetBasicToken(TokenBC);
|
||||
Drop = Drop || (pInfo->m_Type == SERVERINFO_EXTENDED && ExtraToken != GetExtraToken(TokenBC));
|
||||
if(Drop)
|
||||
{
|
||||
pEntry = Add(Addr);
|
||||
QueueRequest(pEntry);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!pEntry)
|
||||
pEntry = Add(&Addr, 1);
|
||||
}
|
||||
else if(Type == IServerBrowser::SET_HTTPINFO)
|
||||
else
|
||||
{
|
||||
if(!pEntry)
|
||||
{
|
||||
pEntry = Add(Addr);
|
||||
return;
|
||||
}
|
||||
if(pEntry)
|
||||
int TokenAddr = GenerateToken(Addr);
|
||||
bool Drop = false;
|
||||
Drop = Drop || BasicToken != GetBasicToken(TokenAddr);
|
||||
Drop = Drop || (pInfo->m_Type == SERVERINFO_EXTENDED && ExtraToken != GetExtraToken(TokenAddr));
|
||||
if(Drop)
|
||||
{
|
||||
SetInfo(pEntry, *pInfo);
|
||||
pEntry->m_RequestIgnoreInfo = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(Type == IServerBrowser::SET_TOKEN)
|
||||
|
||||
if(m_ServerlistType == IServerBrowser::TYPE_LAN)
|
||||
{
|
||||
int BasicToken = Token;
|
||||
int ExtraToken = 0;
|
||||
if(pInfo->m_Type == SERVERINFO_EXTENDED)
|
||||
SetInfo(pEntry, *pInfo);
|
||||
pEntry->m_Info.m_Latency = minimum(static_cast<int>((time_get() - m_BroadcastTime) * 1000 / time_freq()), 999);
|
||||
if(pInfo->m_Type == SERVERINFO_VANILLA && Is64Player(pInfo))
|
||||
{
|
||||
BasicToken = Token & 0xff;
|
||||
ExtraToken = Token >> 8;
|
||||
pEntry->m_Request64Legacy = true;
|
||||
// Force a quick update.
|
||||
RequestImpl64(Addr, pEntry);
|
||||
}
|
||||
}
|
||||
else if(pEntry->m_RequestTime > 0)
|
||||
{
|
||||
if(!pEntry->m_RequestIgnoreInfo)
|
||||
{
|
||||
SetInfo(pEntry, *pInfo);
|
||||
}
|
||||
|
||||
pEntry = Find(Addr);
|
||||
|
||||
if(m_ServerlistType == IServerBrowser::TYPE_LAN)
|
||||
int Latency = minimum(static_cast<int>((time_get() - pEntry->m_RequestTime) * 1000 / time_freq()), 999);
|
||||
if(!pEntry->m_RequestIgnoreInfo)
|
||||
{
|
||||
NETADDR Broadcast;
|
||||
mem_zero(&Broadcast, sizeof(Broadcast));
|
||||
Broadcast.type = m_pNetClient->NetType() | NETTYPE_LINK_BROADCAST;
|
||||
int TokenBC = GenerateToken(Broadcast);
|
||||
bool Drop = false;
|
||||
Drop = Drop || BasicToken != GetBasicToken(TokenBC);
|
||||
Drop = Drop || (pInfo->m_Type == SERVERINFO_EXTENDED && ExtraToken != GetExtraToken(TokenBC));
|
||||
if(Drop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!pEntry)
|
||||
pEntry = Add(Addr);
|
||||
pEntry->m_Info.m_Latency = Latency;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!pEntry)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int TokenAddr = GenerateToken(Addr);
|
||||
bool Drop = false;
|
||||
Drop = Drop || BasicToken != GetBasicToken(TokenAddr);
|
||||
Drop = Drop || (pInfo->m_Type == SERVERINFO_EXTENDED && ExtraToken != GetExtraToken(TokenAddr));
|
||||
if(Drop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
char aAddr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&Addr, aAddr, sizeof(aAddr), true);
|
||||
dbg_msg("serverbrowse/dbg", "received ping response from %s", aAddr);
|
||||
SetLatency(Addr, Latency);
|
||||
}
|
||||
pEntry->m_RequestTime = -1; // Request has been answered
|
||||
|
||||
if(m_ServerlistType == IServerBrowser::TYPE_LAN)
|
||||
if(!pEntry->m_RequestIgnoreInfo)
|
||||
{
|
||||
SetInfo(pEntry, *pInfo);
|
||||
pEntry->m_Info.m_Latency = minimum(static_cast<int>((time_get() - m_BroadcastTime) * 1000 / time_freq()), 999);
|
||||
if(pInfo->m_Type == SERVERINFO_VANILLA && Is64Player(pInfo))
|
||||
{
|
||||
pEntry->m_Request64Legacy = true;
|
||||
// Force a quick update.
|
||||
RequestImpl64(pEntry->m_Addr, pEntry);
|
||||
RequestImpl64(Addr, pEntry);
|
||||
}
|
||||
}
|
||||
else if(pEntry->m_RequestTime > 0)
|
||||
{
|
||||
if(!pEntry->m_RequestIgnoreInfo)
|
||||
{
|
||||
SetInfo(pEntry, *pInfo);
|
||||
}
|
||||
|
||||
int Latency = minimum(static_cast<int>((time_get() - pEntry->m_RequestTime) * 1000 / time_freq()), 999);
|
||||
if(!pEntry->m_RequestIgnoreInfo)
|
||||
{
|
||||
pEntry->m_Info.m_Latency = Latency;
|
||||
}
|
||||
else
|
||||
{
|
||||
char aAddr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&Addr, aAddr, sizeof(aAddr), true);
|
||||
dbg_msg("serverbrowse/dbg", "received ping response from %s", aAddr);
|
||||
SetLatency(Addr, Latency);
|
||||
}
|
||||
pEntry->m_RequestTime = -1; // Request has been answered
|
||||
|
||||
if(!pEntry->m_RequestIgnoreInfo)
|
||||
{
|
||||
if(pInfo->m_Type == SERVERINFO_VANILLA && Is64Player(pInfo))
|
||||
{
|
||||
pEntry->m_Request64Legacy = true;
|
||||
// Force a quick update.
|
||||
RequestImpl64(pEntry->m_Addr, pEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
RemoveRequest(pEntry);
|
||||
}
|
||||
RemoveRequest(pEntry);
|
||||
|
||||
m_SortOnNextUpdate = true;
|
||||
}
|
||||
|
@ -909,28 +903,8 @@ void CServerBrowser::SetCurrentServerPing(const NETADDR &Addr, int Ping)
|
|||
SetLatency(Addr, minimum(Ping, 999));
|
||||
}
|
||||
|
||||
void ServerBrowserFillEstimatedLatency(int OwnLocation, const IServerBrowserPingCache::CEntry *pEntries, int NumEntries, int *pIndex, NETADDR Addr, CServerInfo *pInfo)
|
||||
{
|
||||
Addr.port = 0;
|
||||
while(*pIndex < NumEntries && net_addr_comp(&pEntries[*pIndex].m_Addr, &Addr) < 0)
|
||||
{
|
||||
*pIndex += 1;
|
||||
}
|
||||
if(*pIndex >= NumEntries || net_addr_comp(&pEntries[*pIndex].m_Addr, &Addr) != 0)
|
||||
{
|
||||
pInfo->m_LatencyIsEstimated = true;
|
||||
pInfo->m_Latency = CServerInfo::EstimateLatency(OwnLocation, pInfo->m_Location);
|
||||
return;
|
||||
}
|
||||
pInfo->m_LatencyIsEstimated = false;
|
||||
pInfo->m_Latency = pEntries[*pIndex].m_Ping;
|
||||
}
|
||||
|
||||
void CServerBrowser::UpdateFromHttp()
|
||||
{
|
||||
const IServerBrowserPingCache::CEntry *pPingEntries;
|
||||
int NumPingEntries;
|
||||
m_pPingCache->GetPingCache(&pPingEntries, &NumPingEntries);
|
||||
int OwnLocation;
|
||||
if(str_comp(g_Config.m_BrLocation, "auto") == 0)
|
||||
{
|
||||
|
@ -948,24 +922,13 @@ void CServerBrowser::UpdateFromHttp()
|
|||
|
||||
int NumServers = m_pHttp->NumServers();
|
||||
int NumLegacyServers = m_pHttp->NumLegacyServers();
|
||||
std::unordered_set<NETADDR> WantedAddrs;
|
||||
std::function<bool(const NETADDR *, int)> Want = [](const NETADDR *pAddrs, int NumAddrs) { return true; };
|
||||
if(m_ServerlistType != IServerBrowser::TYPE_INTERNET)
|
||||
{
|
||||
class CWantedAddr
|
||||
{
|
||||
public:
|
||||
NETADDR m_Addr;
|
||||
bool m_FallbackToPing;
|
||||
bool m_Got;
|
||||
};
|
||||
std::vector<CWantedAddr> vWantedAddresses;
|
||||
int LegacySetType;
|
||||
if(m_ServerlistType == IServerBrowser::TYPE_FAVORITES)
|
||||
{
|
||||
for(int i = 0; i < m_NumFavoriteServers; i++)
|
||||
{
|
||||
vWantedAddresses.push_back(CWantedAddr{m_aFavoriteServers[i], m_aFavoriteServersAllowPing[i], false});
|
||||
}
|
||||
LegacySetType = IServerBrowser::SET_FAV_ADD;
|
||||
Want = [&](const NETADDR *pAddrs, int NumAddrs) -> bool { return m_pFavorites->IsFavorite(pAddrs, NumAddrs) != TRISTATE::NONE; };
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -976,13 +939,11 @@ void CServerBrowser::UpdateFromHttp()
|
|||
{
|
||||
case IServerBrowser::TYPE_DDNET:
|
||||
Network = NETWORK_DDNET;
|
||||
LegacySetType = IServerBrowser::SET_DDNET_ADD;
|
||||
pExcludeCountries = g_Config.m_BrFilterExcludeCountries;
|
||||
pExcludeTypes = g_Config.m_BrFilterExcludeTypes;
|
||||
break;
|
||||
case IServerBrowser::TYPE_KOG:
|
||||
Network = NETWORK_KOG;
|
||||
LegacySetType = IServerBrowser::SET_KOG_ADD;
|
||||
pExcludeCountries = g_Config.m_BrFilterExcludeCountriesKoG;
|
||||
pExcludeTypes = g_Config.m_BrFilterExcludeTypesKoG;
|
||||
break;
|
||||
|
@ -1016,139 +977,83 @@ void CServerBrowser::UpdateFromHttp()
|
|||
|
||||
if(DDNetFiltered(pExcludeTypes, pCntr->m_aTypes[g]))
|
||||
continue;
|
||||
vWantedAddresses.push_back(CWantedAddr{pCntr->m_aServers[g], false, false});
|
||||
WantedAddrs.insert(pCntr->m_aServers[g]);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<int> vSortedServers;
|
||||
std::vector<int> vSortedLegacyServers;
|
||||
vSortedServers.reserve(NumServers);
|
||||
for(int i = 0; i < NumServers; i++)
|
||||
{
|
||||
vSortedServers.push_back(i);
|
||||
}
|
||||
vSortedLegacyServers.reserve(NumLegacyServers);
|
||||
for(int i = 0; i < NumLegacyServers; i++)
|
||||
{
|
||||
vSortedLegacyServers.push_back(i);
|
||||
}
|
||||
|
||||
class CWantedAddrComparer
|
||||
{
|
||||
public:
|
||||
bool operator()(const CWantedAddr &a, const CWantedAddr &b)
|
||||
{
|
||||
return net_addr_comp(&a.m_Addr, &b.m_Addr) < 0;
|
||||
}
|
||||
};
|
||||
class CAddrComparer
|
||||
{
|
||||
public:
|
||||
IServerBrowserHttp *m_pHttp;
|
||||
bool operator()(int i, int j)
|
||||
{
|
||||
return net_addr_comp(&m_pHttp->ServerAddress(i), &m_pHttp->ServerAddress(j)) < 0;
|
||||
}
|
||||
};
|
||||
class CLegacyAddrComparer
|
||||
{
|
||||
public:
|
||||
IServerBrowserHttp *m_pHttp;
|
||||
bool operator()(int i, int j)
|
||||
{
|
||||
return net_addr_comp(&m_pHttp->LegacyServer(i), &m_pHttp->LegacyServer(j)) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
std::sort(vWantedAddresses.begin(), vWantedAddresses.end(), CWantedAddrComparer());
|
||||
std::sort(vSortedServers.begin(), vSortedServers.end(), CAddrComparer{m_pHttp});
|
||||
std::sort(vSortedLegacyServers.begin(), vSortedLegacyServers.end(), CLegacyAddrComparer{m_pHttp});
|
||||
|
||||
unsigned i = 0;
|
||||
unsigned j = 0;
|
||||
int p = 0;
|
||||
while(i < vWantedAddresses.size() && j < vSortedServers.size())
|
||||
{
|
||||
int Cmp = net_addr_comp(&vWantedAddresses[i].m_Addr, &m_pHttp->ServerAddress(vSortedServers[j]));
|
||||
if(Cmp != 0)
|
||||
{
|
||||
if(Cmp < 0)
|
||||
Want = [&](const NETADDR *pAddrs, int NumAddrs) -> bool {
|
||||
for(int i = 0; i < NumAddrs; i++)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
j++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
vWantedAddresses[i].m_Got = true;
|
||||
NETADDR Addr;
|
||||
CServerInfo Info;
|
||||
m_pHttp->Server(vSortedServers[j], &Addr, &Info);
|
||||
ServerBrowserFillEstimatedLatency(OwnLocation, pPingEntries, NumPingEntries, &p, Addr, &Info);
|
||||
Info.m_HasRank = HasRank(Info.m_aMap);
|
||||
Set(Addr, IServerBrowser::SET_HTTPINFO, -1, &Info);
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
i = 0;
|
||||
j = 0;
|
||||
while(i < vWantedAddresses.size() && j < vSortedLegacyServers.size())
|
||||
{
|
||||
int Cmp = net_addr_comp(&vWantedAddresses[i].m_Addr, &m_pHttp->LegacyServer(vSortedLegacyServers[j]));
|
||||
if(Cmp != 0)
|
||||
{
|
||||
if(Cmp < 0)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
j++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
vWantedAddresses[i].m_Got = true;
|
||||
Set(m_pHttp->LegacyServer(vSortedLegacyServers[j]), LegacySetType, -1, nullptr);
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
for(const CWantedAddr &Wanted : vWantedAddresses)
|
||||
{
|
||||
if(!Wanted.m_Got)
|
||||
{
|
||||
if(Wanted.m_FallbackToPing)
|
||||
{
|
||||
Set(Wanted.m_Addr, LegacySetType, -1, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Also add favorites we're not allowed to ping.
|
||||
if(LegacySetType == IServerBrowser::SET_FAV_ADD && !Find(Wanted.m_Addr))
|
||||
if(WantedAddrs.count(pAddrs[i]))
|
||||
{
|
||||
Add(Wanted.m_Addr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
return;
|
||||
}
|
||||
int p = 0;
|
||||
for(int i = 0; i < NumServers; i++)
|
||||
{
|
||||
NETADDR Addr;
|
||||
CServerInfo Info;
|
||||
m_pHttp->Server(i, &Addr, &Info);
|
||||
ServerBrowserFillEstimatedLatency(OwnLocation, pPingEntries, NumPingEntries, &p, Addr, &Info);
|
||||
CServerInfo Info = m_pHttp->Server(i);
|
||||
if(!Want(Info.m_aAddresses, Info.m_NumAddresses))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int Ping = m_pPingCache->GetPing(Info.m_aAddresses, Info.m_NumAddresses);
|
||||
Info.m_LatencyIsEstimated = Ping == -1;
|
||||
if(Info.m_LatencyIsEstimated)
|
||||
{
|
||||
Info.m_Latency = CServerInfo::EstimateLatency(OwnLocation, Info.m_Location);
|
||||
}
|
||||
else
|
||||
{
|
||||
Info.m_Latency = Ping;
|
||||
}
|
||||
Info.m_HasRank = HasRank(Info.m_aMap);
|
||||
Set(Addr, IServerBrowser::SET_HTTPINFO, -1, &Info);
|
||||
CServerEntry *pEntry = Add(Info.m_aAddresses, Info.m_NumAddresses);
|
||||
SetInfo(pEntry, Info);
|
||||
pEntry->m_RequestIgnoreInfo = true;
|
||||
}
|
||||
for(int i = 0; i < NumLegacyServers; i++)
|
||||
{
|
||||
NETADDR Addr = m_pHttp->LegacyServer(i);
|
||||
Set(Addr, IServerBrowser::SET_MASTER_ADD, -1, nullptr);
|
||||
if(!Want(&Addr, 1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
QueueRequest(Add(&Addr, 1));
|
||||
}
|
||||
|
||||
if(m_ServerlistType == IServerBrowser::TYPE_FAVORITES)
|
||||
{
|
||||
const IFavorites::CEntry *pFavorites;
|
||||
int NumFavorites;
|
||||
m_pFavorites->AllEntries(&pFavorites, &NumFavorites);
|
||||
for(int i = 0; i < NumFavorites; i++)
|
||||
{
|
||||
bool Found = false;
|
||||
for(int j = 0; j < pFavorites[i].m_NumAddrs; j++)
|
||||
{
|
||||
if(Find(pFavorites[i].m_aAddrs[j]))
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(Found)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// (Also add favorites we're not allowed to ping.)
|
||||
CServerEntry *pEntry = Add(pFavorites[i].m_aAddrs, pFavorites[i].m_NumAddrs);
|
||||
if(pFavorites->m_AllowPing)
|
||||
{
|
||||
QueueRequest(pEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_SortOnNextUpdate = true;
|
||||
}
|
||||
|
||||
void CServerBrowser::CleanUp()
|
||||
|
@ -1157,7 +1062,7 @@ void CServerBrowser::CleanUp()
|
|||
m_ServerlistHeap.Reset();
|
||||
m_NumServers = 0;
|
||||
m_NumSortedServers = 0;
|
||||
mem_zero(m_apServerlistIp, sizeof(m_apServerlistIp));
|
||||
m_ByAddr.clear();
|
||||
m_pFirstReqServer = 0;
|
||||
m_pLastReqServer = 0;
|
||||
m_NumRequests = 0;
|
||||
|
@ -1206,9 +1111,9 @@ void CServerBrowser::Update(bool ForceResort)
|
|||
if(pEntry->m_RequestTime == 0)
|
||||
{
|
||||
if(pEntry->m_Request64Legacy)
|
||||
RequestImpl64(pEntry->m_Addr, pEntry);
|
||||
RequestImpl64(pEntry->m_Info.m_aAddresses[0], pEntry);
|
||||
else
|
||||
RequestImpl(pEntry->m_Addr, pEntry, nullptr, nullptr, false);
|
||||
RequestImpl(pEntry->m_Info.m_aAddresses[0], pEntry, nullptr, nullptr, false);
|
||||
}
|
||||
|
||||
Count++;
|
||||
|
@ -1248,94 +1153,17 @@ void CServerBrowser::Update(bool ForceResort)
|
|||
// check if we need to resort
|
||||
if(m_Sorthash != SortHash() || ForceResort || m_SortOnNextUpdate)
|
||||
{
|
||||
for(int i = 0; i < m_NumServers; i++)
|
||||
{
|
||||
CServerInfo *pInfo = &m_ppServerlist[i]->m_Info;
|
||||
pInfo->m_Favorite = m_pFavorites->IsFavorite(pInfo->m_aAddresses, pInfo->m_NumAddresses);
|
||||
pInfo->m_FavoriteAllowPing = m_pFavorites->IsPingAllowed(pInfo->m_aAddresses, pInfo->m_NumAddresses);
|
||||
}
|
||||
Sort();
|
||||
m_SortOnNextUpdate = false;
|
||||
}
|
||||
}
|
||||
|
||||
int CServerBrowser::FindFavorite(const NETADDR &Addr) const
|
||||
{
|
||||
// search for the address
|
||||
for(int i = 0; i < m_NumFavoriteServers; i++)
|
||||
{
|
||||
if(net_addr_comp(&Addr, &m_aFavoriteServers[i]) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool CServerBrowser::GotInfo(const NETADDR &Addr) const
|
||||
{
|
||||
CServerEntry *pEntry = ((CServerBrowser *)this)->Find(Addr);
|
||||
return pEntry && pEntry->m_GotInfo;
|
||||
}
|
||||
|
||||
bool CServerBrowser::IsFavorite(const NETADDR &Addr) const
|
||||
{
|
||||
return FindFavorite(Addr) >= 0;
|
||||
}
|
||||
|
||||
bool CServerBrowser::IsFavoritePingAllowed(const NETADDR &Addr) const
|
||||
{
|
||||
int i = FindFavorite(Addr);
|
||||
dbg_assert(i >= 0, "invalid favorite");
|
||||
return i >= 0 && m_aFavoriteServersAllowPing[i];
|
||||
}
|
||||
|
||||
void CServerBrowser::AddFavorite(const NETADDR &Addr)
|
||||
{
|
||||
CServerEntry *pEntry;
|
||||
|
||||
if(m_NumFavoriteServers == MAX_FAVORITES)
|
||||
return;
|
||||
|
||||
// make sure that we don't already have the server in our list
|
||||
if(IsFavorite(Addr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// add the server to the list
|
||||
m_aFavoriteServers[m_NumFavoriteServers] = Addr;
|
||||
m_aFavoriteServersAllowPing[m_NumFavoriteServers] = false;
|
||||
m_NumFavoriteServers++;
|
||||
pEntry = Find(Addr);
|
||||
if(pEntry)
|
||||
pEntry->m_Info.m_Favorite = true;
|
||||
|
||||
if(g_Config.m_Debug)
|
||||
{
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr), true);
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "added fav, %s", aAddrStr);
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", aBuf);
|
||||
}
|
||||
}
|
||||
|
||||
void CServerBrowser::FavoriteAllowPing(const NETADDR &Addr, bool AllowPing)
|
||||
{
|
||||
int i = FindFavorite(Addr);
|
||||
dbg_assert(i >= 0, "invalid favorite");
|
||||
m_aFavoriteServersAllowPing[i] = AllowPing;
|
||||
}
|
||||
|
||||
void CServerBrowser::RemoveFavorite(const NETADDR &Addr)
|
||||
{
|
||||
int i = FindFavorite(Addr);
|
||||
if(i < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
mem_move(&m_aFavoriteServers[i], &m_aFavoriteServers[i + 1], sizeof(NETADDR) * (m_NumFavoriteServers - (i + 1)));
|
||||
mem_move(&m_aFavoriteServersAllowPing[i], &m_aFavoriteServersAllowPing[i + 1], sizeof(bool) * (m_NumFavoriteServers - (i + 1)));
|
||||
m_NumFavoriteServers--;
|
||||
|
||||
CServerEntry *pEntry = Find(Addr);
|
||||
if(pEntry)
|
||||
pEntry->m_Info.m_Favorite = false;
|
||||
}
|
||||
|
||||
void CServerBrowser::LoadDDNetServers()
|
||||
{
|
||||
if(!m_pDDNetInfo)
|
||||
|
@ -1573,30 +1401,6 @@ int CServerBrowser::LoadingProgression() const
|
|||
return 100.0f * Loaded / Servers;
|
||||
}
|
||||
|
||||
void CServerBrowser::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData)
|
||||
{
|
||||
CServerBrowser *pSelf = (CServerBrowser *)pUserData;
|
||||
|
||||
char aAddrStr[128];
|
||||
char aBuffer[256];
|
||||
for(int i = 0; i < pSelf->m_NumFavoriteServers; i++)
|
||||
{
|
||||
net_addr_str(&pSelf->m_aFavoriteServers[i], aAddrStr, sizeof(aAddrStr), true);
|
||||
if(!pSelf->m_aFavoriteServersAllowPing[i])
|
||||
{
|
||||
str_format(aBuffer, sizeof(aBuffer), "add_favorite %s", aAddrStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add quotes to the first parameter for backward
|
||||
// compatibility with versions that took a `r` console
|
||||
// parameter.
|
||||
str_format(aBuffer, sizeof(aBuffer), "add_favorite \"%s\" allow_ping", aAddrStr);
|
||||
}
|
||||
pConfigManager->WriteLine(aBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void CServerBrowser::DDNetFilterAdd(char *pFilter, const char *pName)
|
||||
{
|
||||
if(DDNetFiltered(pFilter, pName))
|
||||
|
|
|
@ -11,10 +11,17 @@
|
|||
#include <engine/shared/http.h>
|
||||
#include <engine/shared/memheap.h>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
class CNetClient;
|
||||
class IConfigManager;
|
||||
class IConsole;
|
||||
class IEngine;
|
||||
class IFavorites;
|
||||
class IFriends;
|
||||
class IServerBrowserHttp;
|
||||
class IServerBrowserPingCache;
|
||||
class IStorage;
|
||||
|
||||
class CServerBrowser : public IServerBrowser
|
||||
{
|
||||
|
@ -22,15 +29,12 @@ public:
|
|||
class CServerEntry
|
||||
{
|
||||
public:
|
||||
NETADDR m_Addr;
|
||||
int64_t m_RequestTime;
|
||||
bool m_RequestIgnoreInfo;
|
||||
int m_GotInfo;
|
||||
bool m_Request64Legacy;
|
||||
CServerInfo m_Info;
|
||||
|
||||
CServerEntry *m_pNextIp; // ip hashed list
|
||||
|
||||
CServerEntry *m_pPrevReq; // request list
|
||||
CServerEntry *m_pNextReq;
|
||||
};
|
||||
|
@ -54,14 +58,6 @@ public:
|
|||
m_FlagID = -1;
|
||||
m_aName[0] = '\0';
|
||||
};
|
||||
/*void Add(NETADDR Addr, char* pType) {
|
||||
if (m_NumServers < MAX_SERVERS)
|
||||
{
|
||||
m_vServers[m_NumServers] = Addr;
|
||||
str_copy(m_aTypes[m_NumServers], pType, sizeof(m_aTypes[0]));
|
||||
m_NumServers++;
|
||||
}
|
||||
};*/
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -104,13 +100,6 @@ public:
|
|||
int NumSortedServers() const override { return m_NumSortedServers; }
|
||||
const CServerInfo *SortedGet(int Index) const override;
|
||||
|
||||
bool GotInfo(const NETADDR &Addr) const override;
|
||||
bool IsFavorite(const NETADDR &Addr) const override;
|
||||
bool IsFavoritePingAllowed(const NETADDR &Addr) const override;
|
||||
void AddFavorite(const NETADDR &Addr) override;
|
||||
void FavoriteAllowPing(const NETADDR &Addr, bool AllowPing) override;
|
||||
void RemoveFavorite(const NETADDR &Addr) override;
|
||||
|
||||
const char *GetTutorialServer() override;
|
||||
void LoadDDNetRanks();
|
||||
void RecheckOfficial();
|
||||
|
@ -133,7 +122,8 @@ public:
|
|||
|
||||
//
|
||||
void Update(bool ForceResort);
|
||||
void Set(const NETADDR &Addr, int Type, int Token, const CServerInfo *pInfo);
|
||||
void OnServerInfoUpdate(const NETADDR &Addr, int Token, const CServerInfo *pInfo);
|
||||
void SetHttpInfo(const CServerInfo *pInfo);
|
||||
void RequestCurrentServer(const NETADDR &Addr) const;
|
||||
void RequestCurrentServerWithRandomToken(const NETADDR &Addr, int *pBasicToken, int *pToken) const;
|
||||
void SetCurrentServerPing(const NETADDR &Addr, int Ping);
|
||||
|
@ -147,11 +137,12 @@ public:
|
|||
int GetCurrentType() override { return m_ServerlistType; }
|
||||
|
||||
private:
|
||||
CNetClient *m_pNetClient;
|
||||
class IConsole *m_pConsole;
|
||||
class IEngine *m_pEngine;
|
||||
class IFriends *m_pFriends;
|
||||
class IStorage *m_pStorage;
|
||||
CNetClient *m_pNetClient = nullptr;
|
||||
IConsole *m_pConsole = nullptr;
|
||||
IEngine *m_pEngine = nullptr;
|
||||
IFriends *m_pFriends = nullptr;
|
||||
IFavorites *m_pFavorites = nullptr;
|
||||
IStorage *m_pStorage = nullptr;
|
||||
char m_aNetVersion[128];
|
||||
|
||||
bool m_RefreshingHttp = false;
|
||||
|
@ -162,18 +153,13 @@ private:
|
|||
CHeap m_ServerlistHeap;
|
||||
CServerEntry **m_ppServerlist;
|
||||
int *m_pSortedServerlist;
|
||||
|
||||
NETADDR m_aFavoriteServers[MAX_FAVORITES];
|
||||
bool m_aFavoriteServersAllowPing[MAX_FAVORITES];
|
||||
int m_NumFavoriteServers;
|
||||
std::unordered_map<NETADDR, int> m_ByAddr;
|
||||
|
||||
CNetwork m_aNetworks[NUM_NETWORKS];
|
||||
int m_OwnLocation = CServerInfo::LOC_UNKNOWN;
|
||||
|
||||
json_value *m_pDDNetInfo;
|
||||
|
||||
CServerEntry *m_apServerlistIp[256]; // ip hash list
|
||||
|
||||
CServerEntry *m_pFirstReqServer; // request list
|
||||
CServerEntry *m_pLastReqServer;
|
||||
int m_NumRequests;
|
||||
|
@ -198,8 +184,6 @@ private:
|
|||
|
||||
bool m_SortOnNextUpdate;
|
||||
|
||||
int FindFavorite(const NETADDR &Addr) const;
|
||||
|
||||
int GenerateToken(const NETADDR &Addr) const;
|
||||
static int GetBasicToken(int Token);
|
||||
static int GetExtraToken(int Token);
|
||||
|
@ -221,7 +205,7 @@ private:
|
|||
void CleanUp();
|
||||
|
||||
void UpdateFromHttp();
|
||||
CServerEntry *Add(const NETADDR &Addr);
|
||||
CServerEntry *Add(const NETADDR *pAddrs, int NumAddrs);
|
||||
|
||||
void RemoveRequest(CServerEntry *pEntry);
|
||||
|
||||
|
@ -232,8 +216,6 @@ private:
|
|||
|
||||
void SetInfo(CServerEntry *pEntry, const CServerInfo &Info);
|
||||
void SetLatency(NETADDR Addr, int Latency);
|
||||
|
||||
static void ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -260,15 +260,9 @@ public:
|
|||
{
|
||||
return m_vServers.size();
|
||||
}
|
||||
const NETADDR &ServerAddress(int Index) const override
|
||||
const CServerInfo &Server(int Index) const override
|
||||
{
|
||||
return m_vServers[Index].m_Addr;
|
||||
}
|
||||
void Server(int Index, NETADDR *pAddr, CServerInfo *pInfo) const override
|
||||
{
|
||||
const CEntry &Entry = m_vServers[Index];
|
||||
*pAddr = Entry.m_Addr;
|
||||
*pInfo = Entry.m_Info;
|
||||
return m_vServers[Index];
|
||||
}
|
||||
int NumLegacyServers() const override
|
||||
{
|
||||
|
@ -288,15 +282,8 @@ private:
|
|||
STATE_NO_MASTER,
|
||||
};
|
||||
|
||||
class CEntry
|
||||
{
|
||||
public:
|
||||
NETADDR m_Addr;
|
||||
CServerInfo m_Info;
|
||||
};
|
||||
|
||||
static bool Validate(json_value *pJson);
|
||||
static bool Parse(json_value *pJson, std::vector<CEntry> *pvServers, std::vector<NETADDR> *pvLegacyServers);
|
||||
static bool Parse(json_value *pJson, std::vector<CServerInfo> *pvServers, std::vector<NETADDR> *pvLegacyServers);
|
||||
|
||||
IEngine *m_pEngine;
|
||||
IConsole *m_pConsole;
|
||||
|
@ -305,7 +292,7 @@ private:
|
|||
std::shared_ptr<CHttpRequest> m_pGetServers;
|
||||
std::unique_ptr<CChooseMaster> m_pChooseMaster;
|
||||
|
||||
std::vector<CEntry> m_vServers;
|
||||
std::vector<CServerInfo> m_vServers;
|
||||
std::vector<NETADDR> m_vLegacyServers;
|
||||
};
|
||||
|
||||
|
@ -413,13 +400,13 @@ bool ServerbrowserParseUrl(NETADDR *pOut, const char *pUrl)
|
|||
}
|
||||
bool CServerBrowserHttp::Validate(json_value *pJson)
|
||||
{
|
||||
std::vector<CEntry> vServers;
|
||||
std::vector<CServerInfo> vServers;
|
||||
std::vector<NETADDR> vLegacyServers;
|
||||
return Parse(pJson, &vServers, &vLegacyServers);
|
||||
}
|
||||
bool CServerBrowserHttp::Parse(json_value *pJson, std::vector<CEntry> *pvServers, std::vector<NETADDR> *pvLegacyServers)
|
||||
bool CServerBrowserHttp::Parse(json_value *pJson, std::vector<CServerInfo> *pvServers, std::vector<NETADDR> *pvLegacyServers)
|
||||
{
|
||||
std::vector<CEntry> vServers;
|
||||
std::vector<CServerInfo> vServers;
|
||||
std::vector<NETADDR> vLegacyServers;
|
||||
|
||||
const json_value &Json = *pJson;
|
||||
|
@ -459,6 +446,7 @@ bool CServerBrowserHttp::Parse(json_value *pJson, std::vector<CEntry> *pvServers
|
|||
}
|
||||
CServerInfo SetInfo = ParsedInfo;
|
||||
SetInfo.m_Location = ParsedLocation;
|
||||
SetInfo.m_NumAddresses = 0;
|
||||
for(unsigned int a = 0; a < Addresses.u.array.length; a++)
|
||||
{
|
||||
const json_value &Address = Addresses[a];
|
||||
|
@ -466,7 +454,6 @@ bool CServerBrowserHttp::Parse(json_value *pJson, std::vector<CEntry> *pvServers
|
|||
{
|
||||
return true;
|
||||
}
|
||||
// TODO: Address address handling :P
|
||||
NETADDR ParsedAddr;
|
||||
if(ServerbrowserParseUrl(&ParsedAddr, Addresses[a]))
|
||||
{
|
||||
|
@ -474,7 +461,15 @@ bool CServerBrowserHttp::Parse(json_value *pJson, std::vector<CEntry> *pvServers
|
|||
// Skip unknown addresses.
|
||||
continue;
|
||||
}
|
||||
vServers.push_back({ParsedAddr, SetInfo});
|
||||
if(SetInfo.m_NumAddresses < (int)std::size(SetInfo.m_aAddresses))
|
||||
{
|
||||
SetInfo.m_aAddresses[SetInfo.m_NumAddresses] = ParsedAddr;
|
||||
SetInfo.m_NumAddresses += 1;
|
||||
}
|
||||
}
|
||||
if(SetInfo.m_NumAddresses > 0)
|
||||
{
|
||||
vServers.push_back(SetInfo);
|
||||
}
|
||||
}
|
||||
if(LegacyServers.type == json_array)
|
||||
|
|
|
@ -20,8 +20,7 @@ public:
|
|||
virtual bool GetBestUrl(const char **pBestUrl) const = 0;
|
||||
|
||||
virtual int NumServers() const = 0;
|
||||
virtual const NETADDR &ServerAddress(int Index) const = 0;
|
||||
virtual void Server(int Index, NETADDR *pAddr, CServerInfo *pInfo) const = 0;
|
||||
virtual const CServerInfo &Server(int Index) const = 0;
|
||||
virtual int NumLegacyServers() const = 0;
|
||||
virtual const NETADDR &LegacyServer(int Index) const = 0;
|
||||
};
|
||||
|
|
|
@ -5,19 +5,27 @@
|
|||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
class CServerBrowserPingCache : public IServerBrowserPingCache
|
||||
{
|
||||
public:
|
||||
class CEntry
|
||||
{
|
||||
public:
|
||||
NETADDR m_Addr;
|
||||
int m_Ping;
|
||||
};
|
||||
|
||||
CServerBrowserPingCache(IConsole *pConsole, IStorage *pStorage);
|
||||
virtual ~CServerBrowserPingCache() = default;
|
||||
|
||||
void Load() override;
|
||||
|
||||
void CachePing(NETADDR Addr, int Ping) override;
|
||||
void GetPingCache(const CEntry **ppEntries, int *pNumEntries) override;
|
||||
int NumEntries() const override;
|
||||
void CachePing(const NETADDR &Addr, int Ping) override;
|
||||
int GetPing(const NETADDR *pAddrs, int NumAddrs) const override;
|
||||
|
||||
private:
|
||||
IConsole *m_pConsole;
|
||||
|
@ -26,8 +34,7 @@ private:
|
|||
CSqliteStmt m_pLoadStmt;
|
||||
CSqliteStmt m_pStoreStmt;
|
||||
|
||||
std::vector<CEntry> m_vEntries;
|
||||
std::vector<CEntry> m_vNewEntries;
|
||||
std::unordered_map<NETADDR, int> m_Entries;
|
||||
};
|
||||
|
||||
CServerBrowserPingCache::CServerBrowserPingCache(IConsole *pConsole, IStorage *pStorage) :
|
||||
|
@ -55,7 +62,7 @@ void CServerBrowserPingCache::Load()
|
|||
{
|
||||
if(m_pDisk)
|
||||
{
|
||||
int PrevNewEntriesSize = m_vNewEntries.size();
|
||||
std::vector<CEntry> vNewEntries;
|
||||
|
||||
sqlite3 *pSqlite = m_pDisk.get();
|
||||
IConsole *pConsole = m_pConsole;
|
||||
|
@ -85,7 +92,7 @@ void CServerBrowserPingCache::Load()
|
|||
}
|
||||
continue;
|
||||
}
|
||||
m_vNewEntries.push_back(CEntry{Addr, Ping});
|
||||
vNewEntries.push_back(CEntry{Addr, Ping});
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -95,21 +102,31 @@ void CServerBrowserPingCache::Load()
|
|||
if(Error)
|
||||
{
|
||||
pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "serverbrowse_ping_cache", "failed to load ping cache");
|
||||
m_vNewEntries.resize(PrevNewEntriesSize);
|
||||
return;
|
||||
}
|
||||
for(const auto &Entry : vNewEntries)
|
||||
{
|
||||
m_Entries[Entry.m_Addr] = Entry.m_Ping;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CServerBrowserPingCache::CachePing(NETADDR Addr, int Ping)
|
||||
int CServerBrowserPingCache::NumEntries() const
|
||||
{
|
||||
Addr.port = 0;
|
||||
m_vNewEntries.push_back(CEntry{Addr, Ping});
|
||||
return m_Entries.size();
|
||||
}
|
||||
|
||||
void CServerBrowserPingCache::CachePing(const NETADDR &Addr, int Ping)
|
||||
{
|
||||
NETADDR AddrWithoutPort = Addr;
|
||||
AddrWithoutPort.port = 0;
|
||||
m_Entries[AddrWithoutPort] = Ping;
|
||||
if(m_pDisk)
|
||||
{
|
||||
sqlite3 *pSqlite = m_pDisk.get();
|
||||
IConsole *pConsole = m_pConsole;
|
||||
char aAddr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&Addr, aAddr, sizeof(aAddr), false);
|
||||
net_addr_str(&AddrWithoutPort, aAddr, sizeof(aAddr), false);
|
||||
|
||||
bool Error = false;
|
||||
Error = Error || !m_pStoreStmt;
|
||||
|
@ -124,80 +141,24 @@ void CServerBrowserPingCache::CachePing(NETADDR Addr, int Ping)
|
|||
}
|
||||
}
|
||||
|
||||
void CServerBrowserPingCache::GetPingCache(const CEntry **ppEntries, int *pNumEntries)
|
||||
int CServerBrowserPingCache::GetPing(const NETADDR *pAddrs, int NumAddrs) const
|
||||
{
|
||||
if(!m_vNewEntries.empty())
|
||||
int Ping = -1;
|
||||
for(int i = 0; i < NumAddrs; i++)
|
||||
{
|
||||
class CAddrComparer
|
||||
NETADDR Addr = pAddrs[i];
|
||||
Addr.port = 0;
|
||||
auto Entry = m_Entries.find(Addr);
|
||||
if(Entry == m_Entries.end())
|
||||
{
|
||||
public:
|
||||
bool operator()(const CEntry &a, const CEntry &b)
|
||||
{
|
||||
return net_addr_comp(&a.m_Addr, &b.m_Addr) < 0;
|
||||
}
|
||||
};
|
||||
std::vector<CEntry> vOldEntries;
|
||||
std::swap(m_vEntries, vOldEntries);
|
||||
|
||||
// Remove duplicates, keeping newer ones.
|
||||
std::stable_sort(m_vNewEntries.begin(), m_vNewEntries.end(), CAddrComparer());
|
||||
{
|
||||
unsigned To = 0;
|
||||
for(unsigned int From = 0; From < m_vNewEntries.size(); From++)
|
||||
{
|
||||
if(To < From)
|
||||
{
|
||||
m_vNewEntries[To] = m_vNewEntries[From];
|
||||
}
|
||||
if(From + 1 >= m_vNewEntries.size() ||
|
||||
net_addr_comp(&m_vNewEntries[From].m_Addr, &m_vNewEntries[From + 1].m_Addr) != 0)
|
||||
{
|
||||
To++;
|
||||
}
|
||||
}
|
||||
m_vNewEntries.resize(To);
|
||||
continue;
|
||||
}
|
||||
// Only keep the new entries where there are duplicates.
|
||||
m_vEntries.reserve(m_vNewEntries.size() + vOldEntries.size());
|
||||
if(Ping == -1 || Entry->second < Ping)
|
||||
{
|
||||
unsigned i = 0;
|
||||
unsigned j = 0;
|
||||
while(i < vOldEntries.size() && j < m_vNewEntries.size())
|
||||
{
|
||||
int Cmp = net_addr_comp(&vOldEntries[i].m_Addr, &m_vNewEntries[j].m_Addr);
|
||||
if(Cmp != 0)
|
||||
{
|
||||
if(Cmp < 0)
|
||||
{
|
||||
m_vEntries.push_back(vOldEntries[i]);
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vEntries.push_back(m_vNewEntries[j]);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ignore the old element if we have both.
|
||||
i++;
|
||||
}
|
||||
}
|
||||
// Add the remaining elements.
|
||||
for(; i < vOldEntries.size(); i++)
|
||||
{
|
||||
m_vEntries.push_back(vOldEntries[i]);
|
||||
}
|
||||
for(; j < m_vNewEntries.size(); j++)
|
||||
{
|
||||
m_vEntries.push_back(m_vNewEntries[j]);
|
||||
}
|
||||
Ping = Entry->second;
|
||||
}
|
||||
m_vNewEntries.clear();
|
||||
}
|
||||
*ppEntries = m_vEntries.data();
|
||||
*pNumEntries = m_vEntries.size();
|
||||
return Ping;
|
||||
}
|
||||
|
||||
IServerBrowserPingCache *CreateServerBrowserPingCache(IConsole *pConsole, IStorage *pStorage)
|
||||
|
|
|
@ -8,21 +8,14 @@ class IStorage;
|
|||
class IServerBrowserPingCache
|
||||
{
|
||||
public:
|
||||
class CEntry
|
||||
{
|
||||
public:
|
||||
NETADDR m_Addr;
|
||||
int m_Ping;
|
||||
};
|
||||
|
||||
virtual ~IServerBrowserPingCache() {}
|
||||
|
||||
virtual void Load() = 0;
|
||||
|
||||
virtual void CachePing(NETADDR Addr, int Ping) = 0;
|
||||
// The returned list is sorted by address, the addresses don't have a
|
||||
// port.
|
||||
virtual void GetPingCache(const CEntry **ppEntries, int *pNumEntries) = 0;
|
||||
virtual int NumEntries() const = 0;
|
||||
virtual void CachePing(const NETADDR &Addr, int Ping) = 0;
|
||||
// Returns -1 if the ping isn't cached.
|
||||
virtual int GetPing(const NETADDR *pAddrs, int NumAddrs) const = 0;
|
||||
};
|
||||
|
||||
IServerBrowserPingCache *CreateServerBrowserPingCache(IConsole *pConsole, IStorage *pStorage);
|
||||
|
|
45
src/engine/favorites.h
Normal file
45
src/engine/favorites.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef ENGINE_FAVORITES_H
|
||||
#define ENGINE_FAVORITES_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <base/types.h>
|
||||
#include <engine/shared/protocol.h>
|
||||
|
||||
#include "kernel.h"
|
||||
|
||||
class IConfigManager;
|
||||
|
||||
class IFavorites : public IInterface
|
||||
{
|
||||
MACRO_INTERFACE("favorites", 0)
|
||||
|
||||
protected:
|
||||
virtual void OnConfigSave(IConfigManager *pConfigManager) = 0;
|
||||
|
||||
public:
|
||||
class CEntry
|
||||
{
|
||||
public:
|
||||
int m_NumAddrs;
|
||||
NETADDR m_aAddrs[MAX_SERVER_ADDRESSES];
|
||||
bool m_AllowPing;
|
||||
};
|
||||
|
||||
virtual ~IFavorites() {}
|
||||
|
||||
virtual TRISTATE IsFavorite(const NETADDR *pAddrs, int NumAddrs) const = 0;
|
||||
// Only considers the addresses that are actually favorites.
|
||||
virtual TRISTATE IsPingAllowed(const NETADDR *pAddrs, int NumAddrs) const = 0;
|
||||
virtual void Add(const NETADDR *pAddrs, int NumAddrs) = 0;
|
||||
// Only considers the addresses that are actually favorites.
|
||||
virtual void AllowPing(const NETADDR *pAddrs, int NumAddrs, bool AllowPing) = 0;
|
||||
virtual void Remove(const NETADDR *pAddrs, int NumAddrs) = 0;
|
||||
virtual void AllEntries(const CEntry **ppEntries, int *pNumEntries) = 0;
|
||||
|
||||
// Pass the `IFavorites` instance as callback.
|
||||
static void ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData);
|
||||
};
|
||||
|
||||
std::unique_ptr<IFavorites> CreateFavorites();
|
||||
#endif // ENGINE_FAVORITES_H
|
|
@ -3,6 +3,7 @@
|
|||
#ifndef ENGINE_SERVERBROWSER_H
|
||||
#define ENGINE_SERVERBROWSER_H
|
||||
|
||||
#include <base/types.h>
|
||||
#include <engine/map.h>
|
||||
#include <engine/shared/protocol.h>
|
||||
|
||||
|
@ -50,7 +51,8 @@ public:
|
|||
uint64_t m_ReceivedPackets;
|
||||
int m_NumReceivedClients;
|
||||
|
||||
NETADDR m_NetAddr;
|
||||
int m_NumAddresses;
|
||||
NETADDR m_aAddresses[MAX_SERVER_ADDRESSES];
|
||||
|
||||
int m_QuickSearchHit;
|
||||
int m_FriendState;
|
||||
|
@ -60,7 +62,8 @@ public:
|
|||
int m_MaxPlayers;
|
||||
int m_NumPlayers;
|
||||
int m_Flags;
|
||||
bool m_Favorite;
|
||||
TRISTATE m_Favorite;
|
||||
TRISTATE m_FavoriteAllowPing;
|
||||
bool m_Official;
|
||||
int m_Location;
|
||||
bool m_LatencyIsEstimated;
|
||||
|
@ -72,7 +75,7 @@ public:
|
|||
int m_MapCrc;
|
||||
int m_MapSize;
|
||||
char m_aVersion[32];
|
||||
char m_aAddress[NETADDR_MAXSTRSIZE];
|
||||
char m_aAddress[MAX_SERVER_ADDRESSES * NETADDR_MAXSTRSIZE];
|
||||
CClient m_aClients[SERVERINFO_MAX_CLIENTS];
|
||||
mutable int m_NumFilteredPlayers;
|
||||
|
||||
|
@ -151,13 +154,6 @@ public:
|
|||
virtual int NumSortedServers() const = 0;
|
||||
virtual const CServerInfo *SortedGet(int Index) const = 0;
|
||||
|
||||
virtual bool GotInfo(const NETADDR &Addr) const = 0;
|
||||
virtual bool IsFavorite(const NETADDR &Addr) const = 0;
|
||||
virtual bool IsFavoritePingAllowed(const NETADDR &Addr) const = 0;
|
||||
virtual void AddFavorite(const NETADDR &Addr) = 0;
|
||||
virtual void FavoriteAllowPing(const NETADDR &Addr, bool AllowPing) = 0;
|
||||
virtual void RemoveFavorite(const NETADDR &Addr) = 0;
|
||||
|
||||
virtual int NumCountries(int Network) = 0;
|
||||
virtual int GetCountryFlag(int Network, int Index) = 0;
|
||||
virtual const char *GetCountryName(int Network, int Index) = 0;
|
||||
|
|
|
@ -82,6 +82,7 @@ enum
|
|||
SERVERINFO_LEVEL_MIN = 0,
|
||||
SERVERINFO_LEVEL_MAX = 2,
|
||||
|
||||
MAX_SERVER_ADDRESSES = 16,
|
||||
SERVERINFO_MAX_CLIENTS = 128,
|
||||
MAX_CLIENTS = 64,
|
||||
VANILLA_MAX_CLIENTS = 16,
|
||||
|
|
|
@ -15,6 +15,7 @@ class CConfig *CComponent::Config() const { return m_pClient->Config(); }
|
|||
class IConsole *CComponent::Console() const { return m_pClient->Console(); }
|
||||
class IDemoPlayer *CComponent::DemoPlayer() const { return m_pClient->DemoPlayer(); }
|
||||
class IDemoRecorder *CComponent::DemoRecorder(int Recorder) const { return m_pClient->DemoRecorder(Recorder); }
|
||||
class IFavorites *CComponent::Favorites() const { return m_pClient->Favorites(); }
|
||||
class IServerBrowser *CComponent::ServerBrowser() const { return m_pClient->ServerBrowser(); }
|
||||
class CLayers *CComponent::Layers() const { return m_pClient->Layers(); }
|
||||
class CCollision *CComponent::Collision() const { return m_pClient->Collision(); }
|
||||
|
|
|
@ -80,6 +80,7 @@ protected:
|
|||
* @see RECORDER_REPLAYS
|
||||
*/
|
||||
class IDemoRecorder *DemoRecorder(int Recorder) const;
|
||||
class IFavorites *Favorites() const;
|
||||
/**
|
||||
* Get the server browser interface.
|
||||
*/
|
||||
|
|
|
@ -2663,19 +2663,20 @@ bool CMenus::CheckHotKey(int Key) const
|
|||
Input()->KeyIsPressed(Key) && m_pClient->m_GameConsole.IsClosed();
|
||||
}
|
||||
|
||||
int CMenus::DoButton_CheckBox_DontCare(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
|
||||
int CMenus::DoButton_CheckBox_Tristate(const void *pID, const char *pText, TRISTATE Checked, const CUIRect *pRect)
|
||||
{
|
||||
switch(Checked)
|
||||
{
|
||||
case 0:
|
||||
case TRISTATE::NONE:
|
||||
return DoButton_CheckBox_Common(pID, pText, "", pRect);
|
||||
case 1:
|
||||
return DoButton_CheckBox_Common(pID, pText, "X", pRect);
|
||||
case 2:
|
||||
case TRISTATE::SOME:
|
||||
return DoButton_CheckBox_Common(pID, pText, "O", pRect);
|
||||
case TRISTATE::ALL:
|
||||
return DoButton_CheckBox_Common(pID, pText, "X", pRect);
|
||||
default:
|
||||
return DoButton_CheckBox_Common(pID, pText, "", pRect);
|
||||
dbg_assert(false, "invalid tristate");
|
||||
}
|
||||
dbg_break();
|
||||
}
|
||||
|
||||
int CMenus::MenuImageScan(const char *pName, int IsDir, int DirType, void *pUser)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#ifndef GAME_CLIENT_COMPONENTS_MENUS_H
|
||||
#define GAME_CLIENT_COMPONENTS_MENUS_H
|
||||
|
||||
#include <base/types.h>
|
||||
#include <base/vmath.h>
|
||||
|
||||
#include <chrono>
|
||||
|
@ -631,7 +632,7 @@ public:
|
|||
SUIAnimator m_aAnimatorsSettingsTab[SETTINGS_LENGTH];
|
||||
|
||||
// DDRace
|
||||
int DoButton_CheckBox_DontCare(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
|
||||
int DoButton_CheckBox_Tristate(const void *pID, const char *pText, TRISTATE Checked, const CUIRect *pRect);
|
||||
std::vector<CDemoItem> m_vDemos;
|
||||
void DemolistPopulate();
|
||||
bool m_Dummy;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||
#include <base/log.h>
|
||||
|
||||
#include <engine/favorites.h>
|
||||
#include <engine/friends.h>
|
||||
#include <engine/keys.h>
|
||||
#include <engine/serverbrowser.h>
|
||||
|
@ -330,7 +333,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
|
|||
}
|
||||
else if(ID == COL_FLAG_FAV)
|
||||
{
|
||||
if(pItem->m_Favorite)
|
||||
if(pItem->m_Favorite != TRISTATE::NONE)
|
||||
{
|
||||
RenderBrowserIcons(*pItem->m_pUIElement->Get(gs_OffsetColFav + 0), &Button, {0.94f, 0.4f, 0.4f, 1}, TextRender()->DefaultTextOutlineColor(), "\xEF\x80\x84", TEXTALIGN_CENTER);
|
||||
}
|
||||
|
@ -1072,28 +1075,29 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
|
|||
ButtonAddFav.VSplitLeft(5.0f, 0, &ButtonAddFav);
|
||||
static int s_AddFavButton = 0;
|
||||
static int s_LeakIpButton = 0;
|
||||
if(DoButton_CheckBox(&s_AddFavButton, Localize("Favorite"), pSelectedServer->m_Favorite, &ButtonAddFav))
|
||||
if(DoButton_CheckBox_Tristate(&s_AddFavButton, Localize("Favorite"), pSelectedServer->m_Favorite, &ButtonAddFav))
|
||||
{
|
||||
if(pSelectedServer->m_Favorite)
|
||||
if(pSelectedServer->m_Favorite != TRISTATE::NONE)
|
||||
{
|
||||
ServerBrowser()->RemoveFavorite(pSelectedServer->m_NetAddr);
|
||||
Favorites()->Remove(pSelectedServer->m_aAddresses, pSelectedServer->m_NumAddresses);
|
||||
}
|
||||
else
|
||||
{
|
||||
ServerBrowser()->AddFavorite(pSelectedServer->m_NetAddr);
|
||||
Favorites()->Add(pSelectedServer->m_aAddresses, pSelectedServer->m_NumAddresses);
|
||||
if(g_Config.m_UiPage == PAGE_LAN)
|
||||
{
|
||||
ServerBrowser()->FavoriteAllowPing(pSelectedServer->m_NetAddr, true);
|
||||
Favorites()->AllowPing(pSelectedServer->m_aAddresses, pSelectedServer->m_NumAddresses, true);
|
||||
}
|
||||
}
|
||||
Client()->ServerBrowserUpdate();
|
||||
}
|
||||
if(pSelectedServer->m_Favorite)
|
||||
if(pSelectedServer->m_Favorite != TRISTATE::NONE)
|
||||
{
|
||||
bool IpLeak = ServerBrowser()->IsFavoritePingAllowed(pSelectedServer->m_NetAddr);
|
||||
if(DoButton_CheckBox(&s_LeakIpButton, Localize("Leak IP"), IpLeak, &ButtonLeakIp))
|
||||
if(DoButton_CheckBox_Tristate(&s_LeakIpButton, Localize("Leak IP"), pSelectedServer->m_FavoriteAllowPing, &ButtonLeakIp))
|
||||
{
|
||||
ServerBrowser()->FavoriteAllowPing(pSelectedServer->m_NetAddr, !IpLeak);
|
||||
Favorites()->AllowPing(pSelectedServer->m_aAddresses, pSelectedServer->m_NumAddresses, pSelectedServer->m_FavoriteAllowPing == TRISTATE::NONE);
|
||||
}
|
||||
Client()->ServerBrowserUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <base/system.h>
|
||||
|
||||
#include <engine/demo.h>
|
||||
#include <engine/favorites.h>
|
||||
#include <engine/friends.h>
|
||||
#include <engine/ghost.h>
|
||||
#include <engine/graphics.h>
|
||||
|
@ -402,15 +403,16 @@ void CMenus::RenderServerInfo(CUIRect MainView)
|
|||
|
||||
{
|
||||
CUIRect Button;
|
||||
int IsFavorite = ServerBrowser()->IsFavorite(CurrentServerInfo.m_NetAddr);
|
||||
NETADDR ServerAddr = Client()->ServerAddress();
|
||||
TRISTATE IsFavorite = Favorites()->IsFavorite(&ServerAddr, 1);
|
||||
ServerInfo.HSplitBottom(20.0f, &ServerInfo, &Button);
|
||||
static int s_AddFavButton = 0;
|
||||
if(DoButton_CheckBox(&s_AddFavButton, Localize("Favorite"), IsFavorite, &Button))
|
||||
if(DoButton_CheckBox(&s_AddFavButton, Localize("Favorite"), IsFavorite != TRISTATE::NONE, &Button))
|
||||
{
|
||||
if(IsFavorite)
|
||||
ServerBrowser()->RemoveFavorite(CurrentServerInfo.m_NetAddr);
|
||||
if(IsFavorite != TRISTATE::NONE)
|
||||
Favorites()->Remove(&ServerAddr, 1);
|
||||
else
|
||||
ServerBrowser()->AddFavorite(CurrentServerInfo.m_NetAddr);
|
||||
Favorites()->Add(&ServerAddr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <engine/demo.h>
|
||||
#include <engine/editor.h>
|
||||
#include <engine/engine.h>
|
||||
#include <engine/favorites.h>
|
||||
#include <engine/friends.h>
|
||||
#include <engine/graphics.h>
|
||||
#include <engine/map.h>
|
||||
|
@ -91,6 +92,7 @@ void CGameClient::OnConsoleInit()
|
|||
m_pDemoPlayer = Kernel()->RequestInterface<IDemoPlayer>();
|
||||
m_pServerBrowser = Kernel()->RequestInterface<IServerBrowser>();
|
||||
m_pEditor = Kernel()->RequestInterface<IEditor>();
|
||||
m_pFavorites = Kernel()->RequestInterface<IFavorites>();
|
||||
m_pFriends = Kernel()->RequestInterface<IFriends>();
|
||||
m_pFoes = Client()->Foes();
|
||||
#if defined(CONF_AUTOUPDATE)
|
||||
|
|
|
@ -165,6 +165,7 @@ private:
|
|||
class IConsole *m_pConsole;
|
||||
class IStorage *m_pStorage;
|
||||
class IDemoPlayer *m_pDemoPlayer;
|
||||
class IFavorites *m_pFavorites;
|
||||
class IServerBrowser *m_pServerBrowser;
|
||||
class IEditor *m_pEditor;
|
||||
class IFriends *m_pFriends;
|
||||
|
@ -218,6 +219,7 @@ public:
|
|||
class ITextRender *TextRender() const { return m_pTextRender; }
|
||||
class IDemoPlayer *DemoPlayer() const { return m_pDemoPlayer; }
|
||||
class IDemoRecorder *DemoRecorder(int Recorder) const { return Client()->DemoRecorder(Recorder); }
|
||||
class IFavorites *Favorites() const { return m_pFavorites; }
|
||||
class IServerBrowser *ServerBrowser() const { return m_pServerBrowser; }
|
||||
class CRenderTools *RenderTools() { return &m_RenderTools; }
|
||||
class CLayers *Layers() { return &m_Layers; }
|
||||
|
|
|
@ -374,11 +374,12 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName)
|
|||
{
|
||||
CServerInfo CurrentServerInfo;
|
||||
m_pEditor->Client()->GetServerInfo(&CurrentServerInfo);
|
||||
const unsigned char aIPv4Localhost[16] = {127, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
const unsigned char aIPv6Localhost[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
|
||||
NETADDR ServerAddr = m_pEditor->Client()->ServerAddress();
|
||||
const unsigned char aIpv4Localhost[16] = {127, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
const unsigned char aIpv6Localhost[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
|
||||
|
||||
// and if we're on localhost
|
||||
if(!mem_comp(CurrentServerInfo.m_NetAddr.ip, aIPv4Localhost, sizeof(aIPv4Localhost)) || !mem_comp(CurrentServerInfo.m_NetAddr.ip, aIPv6Localhost, sizeof(aIPv6Localhost)))
|
||||
if(!mem_comp(ServerAddr.ip, aIpv4Localhost, sizeof(aIpv4Localhost)) || !mem_comp(ServerAddr.ip, aIpv6Localhost, sizeof(aIpv6Localhost)))
|
||||
{
|
||||
char aMapName[128];
|
||||
IStorage::StripPathAndExtension(pFileName, aMapName, sizeof(aMapName));
|
||||
|
|
|
@ -126,7 +126,7 @@ MACRO_CONFIG_INT(ClFatSkins, cl_fat_skins, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAV
|
|||
MACRO_CONFIG_INT(UiPage, ui_page, 9, 6, 10, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Interface page")
|
||||
MACRO_CONFIG_INT(UiSettingsPage, ui_settings_page, 0, 0, 9, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Interface settings page")
|
||||
MACRO_CONFIG_INT(UiToolboxPage, ui_toolbox_page, 0, 0, 2, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Toolbox page")
|
||||
MACRO_CONFIG_STR(UiServerAddress, ui_server_address, 64, "localhost:8303", CFGFLAG_CLIENT | CFGFLAG_SAVE | CFGFLAG_INSENSITIVE, "Interface server address")
|
||||
MACRO_CONFIG_STR(UiServerAddress, ui_server_address, 1024, "localhost:8303", CFGFLAG_CLIENT | CFGFLAG_SAVE | CFGFLAG_INSENSITIVE, "Interface server address")
|
||||
MACRO_CONFIG_INT(UiMousesens, ui_mousesens, 200, 1, 100000, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Mouse sensitivity for menus/editor")
|
||||
MACRO_CONFIG_INT(UiControllerSens, ui_controller_sens, 100, 1, 100000, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Controller sensitivity for menus/editor")
|
||||
|
||||
|
|
|
@ -17,87 +17,83 @@ TEST(ServerBrowser, PingCache)
|
|||
auto pStorage = std::unique_ptr<IStorage>(Info.CreateTestStorage());
|
||||
auto pPingCache = std::unique_ptr<IServerBrowserPingCache>(CreateServerBrowserPingCache(pConsole.get(), pStorage.get()));
|
||||
|
||||
const IServerBrowserPingCache::CEntry *pEntries;
|
||||
int NumEntries;
|
||||
NETADDR Localhost4, Localhost6, OtherLocalhost4, OtherLocalhost6;
|
||||
ASSERT_FALSE(net_addr_from_str(&Localhost4, "127.0.0.1:8303"));
|
||||
ASSERT_FALSE(net_addr_from_str(&Localhost6, "[::1]:8304"));
|
||||
ASSERT_FALSE(net_addr_from_str(&OtherLocalhost4, "127.0.0.1:8305"));
|
||||
ASSERT_FALSE(net_addr_from_str(&OtherLocalhost6, "[::1]:8306"));
|
||||
EXPECT_LT(net_addr_comp(&Localhost4, &Localhost6), 0);
|
||||
NETADDR aLocalhostBoth[2] = {Localhost4, Localhost6};
|
||||
|
||||
pPingCache->GetPingCache(&pEntries, &NumEntries);
|
||||
EXPECT_EQ(NumEntries, 0);
|
||||
EXPECT_EQ(pPingCache->NumEntries(), 0);
|
||||
EXPECT_EQ(pPingCache->GetPing(&Localhost4, 1), -1);
|
||||
EXPECT_EQ(pPingCache->GetPing(&Localhost6, 1), -1);
|
||||
EXPECT_EQ(pPingCache->GetPing(aLocalhostBoth, 2), -1);
|
||||
EXPECT_EQ(pPingCache->GetPing(&OtherLocalhost4, 1), -1);
|
||||
EXPECT_EQ(pPingCache->GetPing(&OtherLocalhost6, 1), -1);
|
||||
|
||||
pPingCache->Load();
|
||||
|
||||
pPingCache->GetPingCache(&pEntries, &NumEntries);
|
||||
EXPECT_EQ(NumEntries, 0);
|
||||
|
||||
NETADDR Localhost4, Localhost4Tw, Localhost6, Localhost6Tw;
|
||||
ASSERT_FALSE(net_addr_from_str(&Localhost4, "127.0.0.1"));
|
||||
ASSERT_FALSE(net_addr_from_str(&Localhost4Tw, "127.0.0.1:8303"));
|
||||
ASSERT_FALSE(net_addr_from_str(&Localhost6, "[::1]"));
|
||||
ASSERT_FALSE(net_addr_from_str(&Localhost6Tw, "[::1]:8304"));
|
||||
EXPECT_LT(net_addr_comp(&Localhost4, &Localhost6), 0);
|
||||
EXPECT_EQ(pPingCache->NumEntries(), 0);
|
||||
EXPECT_EQ(pPingCache->GetPing(&Localhost4, 1), -1);
|
||||
EXPECT_EQ(pPingCache->GetPing(&Localhost6, 1), -1);
|
||||
EXPECT_EQ(pPingCache->GetPing(aLocalhostBoth, 2), -1);
|
||||
EXPECT_EQ(pPingCache->GetPing(&OtherLocalhost4, 1), -1);
|
||||
EXPECT_EQ(pPingCache->GetPing(&OtherLocalhost6, 1), -1);
|
||||
|
||||
// Newer pings overwrite older.
|
||||
pPingCache->CachePing(Localhost4Tw, 123);
|
||||
pPingCache->CachePing(Localhost4Tw, 234);
|
||||
pPingCache->CachePing(Localhost4Tw, 345);
|
||||
pPingCache->CachePing(Localhost4Tw, 456);
|
||||
pPingCache->CachePing(Localhost4Tw, 567);
|
||||
pPingCache->CachePing(Localhost4Tw, 678);
|
||||
pPingCache->CachePing(Localhost4Tw, 789);
|
||||
pPingCache->CachePing(Localhost4Tw, 890);
|
||||
pPingCache->CachePing(Localhost4Tw, 901);
|
||||
pPingCache->CachePing(Localhost4Tw, 135);
|
||||
pPingCache->CachePing(Localhost4Tw, 246);
|
||||
pPingCache->CachePing(Localhost4Tw, 357);
|
||||
pPingCache->CachePing(Localhost4Tw, 468);
|
||||
pPingCache->CachePing(Localhost4Tw, 579);
|
||||
pPingCache->CachePing(Localhost4Tw, 680);
|
||||
pPingCache->CachePing(Localhost4Tw, 791);
|
||||
pPingCache->CachePing(Localhost4Tw, 802);
|
||||
pPingCache->CachePing(Localhost4Tw, 913);
|
||||
pPingCache->CachePing(Localhost4, 123);
|
||||
pPingCache->CachePing(Localhost4, 234);
|
||||
pPingCache->CachePing(Localhost4, 345);
|
||||
pPingCache->CachePing(Localhost4, 456);
|
||||
pPingCache->CachePing(Localhost4, 567);
|
||||
pPingCache->CachePing(Localhost4, 678);
|
||||
pPingCache->CachePing(Localhost4, 789);
|
||||
pPingCache->CachePing(Localhost4, 890);
|
||||
pPingCache->CachePing(Localhost4, 901);
|
||||
pPingCache->CachePing(Localhost4, 135);
|
||||
pPingCache->CachePing(Localhost4, 246);
|
||||
pPingCache->CachePing(Localhost4, 357);
|
||||
pPingCache->CachePing(Localhost4, 468);
|
||||
pPingCache->CachePing(Localhost4, 579);
|
||||
pPingCache->CachePing(Localhost4, 680);
|
||||
pPingCache->CachePing(Localhost4, 791);
|
||||
pPingCache->CachePing(Localhost4, 802);
|
||||
pPingCache->CachePing(Localhost4, 913);
|
||||
|
||||
pPingCache->GetPingCache(&pEntries, &NumEntries);
|
||||
EXPECT_EQ(NumEntries, 1);
|
||||
if(NumEntries >= 1)
|
||||
{
|
||||
EXPECT_TRUE(net_addr_comp(&pEntries[0].m_Addr, &Localhost4) == 0);
|
||||
EXPECT_EQ(pEntries[0].m_Ping, 913);
|
||||
}
|
||||
EXPECT_EQ(pPingCache->NumEntries(), 1);
|
||||
EXPECT_EQ(pPingCache->GetPing(&Localhost4, 1), 913);
|
||||
EXPECT_EQ(pPingCache->GetPing(&Localhost6, 1), -1);
|
||||
EXPECT_EQ(pPingCache->GetPing(aLocalhostBoth, 2), 913);
|
||||
EXPECT_EQ(pPingCache->GetPing(&OtherLocalhost4, 1), 913);
|
||||
EXPECT_EQ(pPingCache->GetPing(&OtherLocalhost6, 1), -1);
|
||||
|
||||
pPingCache->CachePing(Localhost4Tw, 234);
|
||||
pPingCache->CachePing(Localhost6Tw, 345);
|
||||
pPingCache->GetPingCache(&pEntries, &NumEntries);
|
||||
EXPECT_EQ(NumEntries, 2);
|
||||
if(NumEntries >= 2)
|
||||
{
|
||||
EXPECT_TRUE(net_addr_comp(&pEntries[0].m_Addr, &Localhost4) == 0);
|
||||
EXPECT_TRUE(net_addr_comp(&pEntries[1].m_Addr, &Localhost6) == 0);
|
||||
EXPECT_EQ(pEntries[0].m_Ping, 234);
|
||||
EXPECT_EQ(pEntries[1].m_Ping, 345);
|
||||
}
|
||||
pPingCache->CachePing(Localhost4, 234);
|
||||
pPingCache->CachePing(Localhost6, 345);
|
||||
EXPECT_EQ(pPingCache->NumEntries(), 2);
|
||||
EXPECT_EQ(pPingCache->GetPing(&Localhost4, 1), 234);
|
||||
EXPECT_EQ(pPingCache->GetPing(&Localhost6, 1), 345);
|
||||
EXPECT_EQ(pPingCache->GetPing(aLocalhostBoth, 2), 234);
|
||||
EXPECT_EQ(pPingCache->GetPing(&OtherLocalhost4, 1), 234);
|
||||
EXPECT_EQ(pPingCache->GetPing(&OtherLocalhost6, 1), 345);
|
||||
|
||||
// Port doesn't matter for overwriting.
|
||||
pPingCache->CachePing(Localhost4, 1337);
|
||||
pPingCache->GetPingCache(&pEntries, &NumEntries);
|
||||
EXPECT_EQ(NumEntries, 2);
|
||||
if(NumEntries >= 2)
|
||||
{
|
||||
EXPECT_TRUE(net_addr_comp(&pEntries[0].m_Addr, &Localhost4) == 0);
|
||||
EXPECT_TRUE(net_addr_comp(&pEntries[1].m_Addr, &Localhost6) == 0);
|
||||
EXPECT_EQ(pEntries[0].m_Ping, 1337);
|
||||
EXPECT_EQ(pEntries[1].m_Ping, 345);
|
||||
}
|
||||
EXPECT_EQ(pPingCache->NumEntries(), 2);
|
||||
EXPECT_EQ(pPingCache->GetPing(&Localhost4, 1), 1337);
|
||||
EXPECT_EQ(pPingCache->GetPing(&Localhost6, 1), 345);
|
||||
EXPECT_EQ(pPingCache->GetPing(aLocalhostBoth, 2), 345);
|
||||
EXPECT_EQ(pPingCache->GetPing(&OtherLocalhost4, 1), 1337);
|
||||
EXPECT_EQ(pPingCache->GetPing(&OtherLocalhost6, 1), 345);
|
||||
|
||||
pPingCache.reset(CreateServerBrowserPingCache(pConsole.get(), pStorage.get()));
|
||||
|
||||
// Persistence.
|
||||
pPingCache->Load();
|
||||
pPingCache->GetPingCache(&pEntries, &NumEntries);
|
||||
EXPECT_EQ(NumEntries, 2);
|
||||
if(NumEntries >= 2)
|
||||
{
|
||||
EXPECT_TRUE(net_addr_comp(&pEntries[0].m_Addr, &Localhost4) == 0);
|
||||
EXPECT_TRUE(net_addr_comp(&pEntries[1].m_Addr, &Localhost6) == 0);
|
||||
EXPECT_EQ(pEntries[0].m_Ping, 1337);
|
||||
EXPECT_EQ(pEntries[1].m_Ping, 345);
|
||||
}
|
||||
EXPECT_EQ(pPingCache->NumEntries(), 2);
|
||||
EXPECT_EQ(pPingCache->GetPing(&Localhost4, 1), 1337);
|
||||
EXPECT_EQ(pPingCache->GetPing(&Localhost6, 1), 345);
|
||||
EXPECT_EQ(pPingCache->GetPing(aLocalhostBoth, 2), 345);
|
||||
EXPECT_EQ(pPingCache->GetPing(&OtherLocalhost4, 1), 1337);
|
||||
EXPECT_EQ(pPingCache->GetPing(&OtherLocalhost6, 1), 345);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue