Skip to content

Commit 259959e

Browse files
committed
Fix a bunch of server list issues, including with sort and server-info button
1 parent fe53eef commit 259959e

File tree

10 files changed

+890
-257
lines changed

10 files changed

+890
-257
lines changed

Client/core/ServerBrowser/CServerBrowser.RemoteMasterServer.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,9 @@ bool CRemoteMasterServer::ParseListVer2(CServerListItemList& itemList)
465465
{
466466
pItem->SetDataQuality(uiDataQuality);
467467

468+
// Remember previous no-response
469+
bool bWasPreviouslyMarkedNoResponse = pItem->bMasterServerSaysNoResponse;
470+
468471
if (bHasPlayerCount)
469472
stream.Read(pItem->nPlayers);
470473
if (bHasMaxPlayerCount)
@@ -503,6 +506,11 @@ bool CRemoteMasterServer::ParseListVer2(CServerListItemList& itemList)
503506
{
504507
stream.Read(pItem->bMasterServerSaysNoResponse);
505508
}
509+
else if (bWasPreviouslyMarkedNoResponse)
510+
{
511+
// Reset no-response flag when server reappears in master list without responding flag
512+
pItem->bMasterServerSaysNoResponse = false;
513+
}
506514

507515
if (bHasRestrictionFlags)
508516
{

Client/core/ServerBrowser/CServerBrowser.cpp

Lines changed: 360 additions & 58 deletions
Large diffs are not rendered by default.

Client/core/ServerBrowser/CServerBrowser.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ class CServerBrowser : public CSingleton<CServerBrowser>
9191
std::string GetServerPassword(const std::string& strHost);
9292
void ClearServerPasswords();
9393

94-
void SetStatusText(std::string strStatus);
95-
void SetAddressBarText(std::string strText);
94+
void SetStatusText(std::string_view strStatus);
95+
void SetAddressBarText(std::string_view strText);
9696

9797
CServerListItem* FindSelectedServer(ServerBrowserType Type);
9898
CServerListItem* FindServerFromRow(ServerBrowserType Type, int iRow);
@@ -202,6 +202,7 @@ class CServerBrowser : public CSingleton<CServerBrowser>
202202
private:
203203
struct SFilterState;
204204
struct SListRefreshState;
205+
struct SSortState;
205206

206207
enum
207208
{
@@ -216,6 +217,7 @@ class CServerBrowser : public CSingleton<CServerBrowser>
216217
[[nodiscard]] CServerList* GetServerList(ServerBrowserType Type);
217218
void AddServerToList(CServerListItem* pServer, ServerBrowserType Type, const SFilterState& filterState);
218219
bool RemoveSelectedServerFromRecentlyPlayedList();
220+
void UpdateFilteredPlayerCountStatus(ServerBrowserType Type, CServerList* pDataList = nullptr);
219221

220222
bool OnClick(CGUIElement* pElement);
221223
bool OnDoubleClick(CGUIElement* pElement);
@@ -242,6 +244,7 @@ class CServerBrowser : public CSingleton<CServerBrowser>
242244

243245
bool OnServerListChangeRow(CGUIKeyEventArgs Args);
244246
bool OnServerListKeyDown(CGUIKeyEventArgs Args);
247+
bool OnServerListSortChanged(CGUIElement* pElement);
245248

246249
ServerBrowserType GetCurrentServerBrowserType();
247250
ServerBrowserType GetCurrentServerBrowserTypeForSave();
@@ -256,6 +259,8 @@ class CServerBrowser : public CSingleton<CServerBrowser>
256259
bool ProcessServerListRefreshBatch(ServerBrowserType type, std::size_t uiMaxSteps);
257260
void ProcessPendingListRefreshes();
258261
void SuspendServerLists();
262+
void UpdateSortState(ServerBrowserType type);
263+
void ApplyListSort(ServerBrowserType type, unsigned int uiColumn, SortDirection direction, bool bUpdateStoredState = false);
259264
[[nodiscard]] bool IsListRefreshInProgress(ServerBrowserType type) const;
260265
[[nodiscard]] std::size_t GetListRefreshBatchSize() const;
261266
[[nodiscard]] std::size_t GetHiddenListRefreshBatchSize() const;
@@ -289,6 +294,12 @@ class CServerBrowser : public CSingleton<CServerBrowser>
289294
std::optional<SFilterState> filterSnapshot;
290295
};
291296

297+
struct SSortState
298+
{
299+
unsigned int uiColumn = 0;
300+
SortDirection direction = SortDirections::None;
301+
};
302+
292303
CServerListInternet m_ServersInternet;
293304
CServerListLAN m_ServersLAN;
294305
CServerList m_ServersFavourites;
@@ -318,10 +329,16 @@ class CServerBrowser : public CSingleton<CServerBrowser>
318329
bool m_bPendingFilterUpdate[SERVER_BROWSER_TYPE_COUNT];
319330
unsigned long m_ulNextFilterUpdateTime[SERVER_BROWSER_TYPE_COUNT];
320331
SFilterState m_FilterState[SERVER_BROWSER_TYPE_COUNT];
332+
SSortState m_SortState[SERVER_BROWSER_TYPE_COUNT];
321333

322334
bool m_bPendingConfigSave;
323335
unsigned long m_ulNextConfigSaveTime;
324336
SListRefreshState m_ListRefreshState[SERVER_BROWSER_TYPE_COUNT];
325337
unsigned long m_ulNextListLayoutTime[SERVER_BROWSER_TYPE_COUNT] = {};
326338
unsigned long m_ulHiddenRefreshBoostEnableTime = 0;
339+
int m_iIgnoreSortCallbacks = 0;
340+
341+
// Player list retry tracking - retry queries for servers that haven't responded with player data
342+
CServerListItem* m_pLastSelectedServerForPlayerList[SERVER_BROWSER_TYPE_COUNT] = {};
343+
std::chrono::milliseconds m_msLastPlayerListQueryRetryTime[SERVER_BROWSER_TYPE_COUNT] = {};
327344
};

Client/core/ServerBrowser/CServerCache.cpp

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ class CServerCache : public CServerCacheInterface
5959
virtual void GetServerCachedInfo(CServerListItem* pItem);
6060
virtual void SetServerCachedInfo(const CServerListItem* pItem);
6161
virtual void GetServerListCachedInfo(CServerList* pList);
62-
virtual bool GenerateServerList(CServerList* pList);
62+
virtual bool GenerateServerList(CServerList* pList, bool bAllowNonResponding = false);
63+
virtual void SetServerListCachedInfo(CServerList* pList);
6364

6465
CServerCache();
6566
~CServerCache();
@@ -93,7 +94,9 @@ CServerCacheInterface* GetServerCache()
9394
//
9495
// CServerCache::CServerCache
9596
//
96-
//
97+
// Initialize server cache by loading from persistent disk storage.
98+
// The cache file (servercache.xml) is never deleted and persists across sessions.
99+
// Cache entries are synced (updated) on each session, not regenerated.
97100
//
98101
///////////////////////////////////////////////////////////////
99102
CServerCache::CServerCache()
@@ -117,6 +120,8 @@ CServerCache::~CServerCache()
117120
// CServerCache::LoadServerCache
118121
//
119122
// Load cache data from config
123+
// The in-memory cache is cleared and reloaded from disk.
124+
// The disk file is never deleted; it persists across game sessions.
120125
//
121126
///////////////////////////////////////////////////////////////
122127
bool CServerCache::LoadServerCache()
@@ -197,7 +202,8 @@ bool CServerCache::LoadServerCache()
197202
//
198203
// CServerCache::SaveServerCache
199204
//
200-
// Save cache data to config
205+
// Persist cache changes to disk when data has been modified.
206+
// Always syncs complete state; never clears the disk file.
201207
//
202208
///////////////////////////////////////////////////////////////
203209
void CServerCache::SaveServerCache(bool bWaitUntilFinished)
@@ -256,7 +262,9 @@ DWORD WINAPI CServerCache::StaticThreadProc(LPVOID lpdwThreadParam)
256262
//
257263
// CServerCache::StaticSaveServerCache
258264
//
259-
//
265+
// Synchronize cache to disk by writing all current in-memory entries.
266+
// The XML tree is rebuilt on each save (not appended to) for consistency,
267+
// but the file itself is never deleted. Servers are synced, not purged.
260268
//
261269
///////////////////////////////////////////////////////////////
262270
void CServerCache::StaticSaveServerCache()
@@ -273,18 +281,17 @@ void CServerCache::StaticSaveServerCache()
273281
if (!pNode)
274282
return;
275283

276-
// Start by clearing out all previous nodes
284+
// Clear in-memory XML structure and rebuild from current cache state.
285+
// This does NOT delete the disk file; it only rewrites its contents with current data.
277286
pNode->DeleteAllSubNodes();
278287

279288
// Transfer each item from m_ServerCachedMap into dataSet
280289
CDataInfoSet dataSet;
281-
for (std::map<CCachedKey, CCachedInfo>::iterator it = ms_ServerCachedMap.begin(); it != ms_ServerCachedMap.end(); ++it)
290+
for (const auto& [key, info] : ms_ServerCachedMap)
282291
{
283-
const CCachedKey& key = it->first;
284-
const CCachedInfo& info = it->second;
285292

286-
// Don't save cache of non responding servers
287-
if (info.nMaxPlayers == 0 || info.uiCacheNoReplyCount > 3)
293+
// Only exclude servers that have failed multiple consecutive query attempts
294+
if (info.uiCacheNoReplyCount > 3)
288295
continue;
289296

290297
SDataInfoItem item;
@@ -327,6 +334,9 @@ void CServerCache::StaticSaveServerCache()
327334
///////////////////////////////////////////////////////////////
328335
void CServerCache::GetServerCachedInfo(CServerListItem* pItem)
329336
{
337+
if (!pItem)
338+
return;
339+
330340
CCachedKey key;
331341
key.ulIp = pItem->Address.s_addr;
332342
key.usGamePort = pItem->usGamePort;
@@ -378,6 +388,9 @@ void CServerCache::GetServerCachedInfo(CServerListItem* pItem)
378388
///////////////////////////////////////////////////////////////
379389
void CServerCache::SetServerCachedInfo(const CServerListItem* pItem)
380390
{
391+
if (!pItem)
392+
return;
393+
381394
CCachedKey key;
382395
key.ulIp = pItem->Address.s_addr;
383396
key.usGamePort = pItem->usGamePort;
@@ -424,15 +437,21 @@ void CServerCache::SetServerCachedInfo(const CServerListItem* pItem)
424437
///////////////////////////////////////////////////////////////
425438
void CServerCache::GetServerListCachedInfo(CServerList* pList)
426439
{
427-
// Get cached info for each server
428-
for (CServerListIterator it = pList->IteratorBegin(); it != pList->IteratorEnd(); it++)
429-
GetServerCachedInfo(*it);
440+
if (!pList)
441+
return;
442+
443+
for (auto it = pList->IteratorBegin(); it != pList->IteratorEnd(); ++it)
444+
{
445+
if (*it)
446+
GetServerCachedInfo(*it);
447+
}
430448

431-
// Remove servers not in serverlist from cache
432449
std::map<CCachedKey, CCachedInfo> nextServerCachedMap;
433-
for (CServerListIterator it = pList->IteratorBegin(); it != pList->IteratorEnd(); it++)
450+
for (auto it = pList->IteratorBegin(); it != pList->IteratorEnd(); ++it)
434451
{
435452
CServerListItem* pItem = *it;
453+
if (!pItem)
454+
continue;
436455
CCachedKey key;
437456
key.ulIp = pItem->Address.s_addr;
438457
key.usGamePort = pItem->usGamePort;
@@ -442,22 +461,44 @@ void CServerCache::GetServerListCachedInfo(CServerList* pList)
442461
m_ServerCachedMap = nextServerCachedMap;
443462
}
444463

464+
///////////////////////////////////////////////////////////////
465+
//
466+
// CServerCache::SetServerListCachedInfo
467+
//
468+
// Cache all servers in list
469+
//
470+
///////////////////////////////////////////////////////////////
471+
void CServerCache::SetServerListCachedInfo(CServerList* pList)
472+
{
473+
if (!pList)
474+
return;
475+
476+
for (auto it = pList->IteratorBegin(); it != pList->IteratorEnd(); ++it)
477+
{
478+
if (*it)
479+
SetServerCachedInfo(*it);
480+
}
481+
}
482+
445483
///////////////////////////////////////////////////////////////
446484
//
447485
// CServerCache::GenerateServerList
448486
//
449487
// Create serverlist content from the cache
450488
//
451489
///////////////////////////////////////////////////////////////
452-
bool CServerCache::GenerateServerList(CServerList* pList)
490+
bool CServerCache::GenerateServerList(CServerList* pList, bool bAllowNonResponding)
453491
{
454-
for (std::map<CCachedKey, CCachedInfo>::iterator it = m_ServerCachedMap.begin(); it != m_ServerCachedMap.end(); ++it)
492+
if (!pList)
493+
return false;
494+
495+
for (const auto& [key, info] : m_ServerCachedMap)
455496
{
456-
const CCachedKey& key = it->first;
457-
const CCachedInfo& info = it->second;
458497

459-
// Don't add non responding servers
460-
if (info.nMaxPlayers == 0 || info.uiCacheNoReplyCount > 3)
498+
// When master server is offline, include all cached servers. Otherwise exclude servers that
499+
// have consistently failed to respond (uiCacheNoReplyCount > 3). New servers without response data
500+
// should still be included since they may not have been queried yet.
501+
if (!bAllowNonResponding && (info.uiCacheNoReplyCount > 3))
461502
continue;
462503

463504
ushort usGamePort = key.usGamePort;

Client/core/ServerBrowser/CServerCache.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
*
1111
*****************************************************************************/
1212

13+
class CServerList;
14+
class CServerListItem;
15+
1316
class CServerCacheInterface
1417
{
1518
public:
@@ -18,7 +21,8 @@ class CServerCacheInterface
1821
virtual void GetServerCachedInfo(CServerListItem* pItem) = 0;
1922
virtual void SetServerCachedInfo(const CServerListItem* pItem) = 0;
2023
virtual void GetServerListCachedInfo(CServerList* pList) = 0;
21-
virtual bool GenerateServerList(CServerList* pList) = 0;
24+
virtual bool GenerateServerList(CServerList* pList, bool bAllowNonResponding = false) = 0;
25+
virtual void SetServerListCachedInfo(CServerList* pList) = 0; // Cache all servers in the list
2226
};
2327

2428
CServerCacheInterface* GetServerCache();

0 commit comments

Comments
 (0)