From cc7aeedbae355de8cc81fcf35350578f8aeaf50f Mon Sep 17 00:00:00 2001 From: Beats Date: Tue, 24 Oct 2023 01:13:52 -0300 Subject: [PATCH] fix: highscore client pages (#1735) --- src/creatures/players/player.hpp | 4 +- src/game/game.cpp | 53 +++++++++----------- src/game/game.hpp | 9 ++-- src/server/network/protocol/protocolgame.cpp | 5 +- src/server/network/protocol/protocolgame.hpp | 2 +- 5 files changed, 36 insertions(+), 37 deletions(-) diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 6cefb184e9e..791f696148c 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -1605,9 +1605,9 @@ class Player final : public Creature, public Cylinder, public Bankable { client->sendHighscoresNoData(); } } - void sendHighscores(const std::vector &characters, uint8_t categoryId, uint32_t vocationId, uint16_t page, uint16_t pages) { + void sendHighscores(const std::vector &characters, uint8_t categoryId, uint32_t vocationId, uint16_t page, uint16_t pages, uint32_t updateTimer) { if (client) { - client->sendHighscores(characters, categoryId, vocationId, page, pages); + client->sendHighscores(characters, categoryId, vocationId, page, pages, updateTimer); } } void addAsyncOngoingTask(uint64_t flags) { diff --git a/src/game/game.cpp b/src/game/game.cpp index 046de46a20f..b3706b7bf38 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -7968,14 +7968,18 @@ void Game::processHighscoreResults(DBResult_ptr result, uint32_t playerID, uint8 pages /= entriesPerPage; std::ostringstream cacheKeyStream; - cacheKeyStream << "Highscore_" << static_cast(category) << "_" << static_cast(vocation) << "_" << static_cast(entriesPerPage); + cacheKeyStream << "Highscore_" << static_cast(category) << "_" << static_cast(vocation) << "_" << static_cast(entriesPerPage) << "_" << page; std::string cacheKey = cacheKeyStream.str(); auto it = highscoreCache.find(cacheKey); - auto now = std::chrono::steady_clock::now(); + auto now = std::chrono::system_clock::now(); if (it != highscoreCache.end() && (now - it->second.timestamp < HIGHSCORE_CACHE_EXPIRATION_TIME)) { auto &cacheEntry = it->second; - player->sendHighscores(cacheEntry.characters, category, vocation, page, static_cast(pages)); + auto cachedTime = it->second.timestamp; + auto durationSinceEpoch = cachedTime.time_since_epoch(); + auto secondsSinceEpoch = std::chrono::duration_cast(durationSinceEpoch).count(); + auto updateTimer = static_cast(secondsSinceEpoch); + player->sendHighscores(cacheEntry.characters, category, vocation, cacheEntry.page, static_cast(cacheEntry.entriesPerPage), updateTimer); } else { std::vector characters; characters.reserve(result->countResults()); @@ -7992,25 +7996,14 @@ void Game::processHighscoreResults(DBResult_ptr result, uint32_t playerID, uint8 } while (result->next()); } - player->sendHighscores(characters, category, vocation, page, static_cast(pages)); - highscoreCache[cacheKey] = { characters, now }; + player->sendHighscores(characters, category, vocation, page, static_cast(pages), getTimeNow()); + highscoreCache[cacheKey] = { characters, page, pages, now }; } } -std::string Game::getCachedQueryHighscore(const std::string &key) { - auto it = queryCache.find(key); - if (it != queryCache.end()) { - auto now = std::chrono::steady_clock::now(); - if (now - it->second.timestamp < CACHE_EXPIRATION_TIME) { - return it->second.query; - } - } - return ""; -} - -void Game::cacheQueryHighscore(const std::string &key, const std::string &query) { - auto now = std::chrono::steady_clock::now(); - queryCache[key] = { query, now }; +void Game::cacheQueryHighscore(const std::string &key, const std::string &query, uint32_t page, uint8_t entriesPerPage) { + QueryHighscoreCacheEntry queryEntry { query, page, entriesPerPage, std::chrono::steady_clock::now() }; + queryCache[key] = queryEntry; } std::string Game::generateHighscoreOrGetCachedQueryForEntries(const std::string &categoryName, uint32_t page, uint8_t entriesPerPage, uint32_t vocation) { @@ -8018,13 +8011,15 @@ std::string Game::generateHighscoreOrGetCachedQueryForEntries(const std::string cacheKeyStream << "Entries_" << categoryName << "_" << page << "_" << static_cast(entriesPerPage) << "_" << vocation; std::string cacheKey = cacheKeyStream.str(); - std::string cachedQuery = getCachedQueryHighscore(cacheKey); - if (!cachedQuery.empty()) { - return cachedQuery; + if (queryCache.find(cacheKey) != queryCache.end()) { + const QueryHighscoreCacheEntry &cachedEntry = queryCache[cacheKey]; + if (cachedEntry.page == page) { + return cachedEntry.query; + } } std::string newQuery = generateHighscoreQueryForEntries(categoryName, page, entriesPerPage, vocation); - cacheQueryHighscore(cacheKey, newQuery); + cacheQueryHighscore(cacheKey, newQuery, page, entriesPerPage); return newQuery; } @@ -8034,13 +8029,15 @@ std::string Game::generateHighscoreOrGetCachedQueryForOurRank(const std::string cacheKeyStream << "OurRank_" << categoryName << "_" << static_cast(entriesPerPage) << "_" << playerGUID << "_" << vocation; std::string cacheKey = cacheKeyStream.str(); - std::string cachedQuery = getCachedQueryHighscore(cacheKey); - if (!cachedQuery.empty()) { - return cachedQuery; + if (queryCache.find(cacheKey) != queryCache.end()) { + const QueryHighscoreCacheEntry &cachedEntry = queryCache[cacheKey]; + if (cachedEntry.page == entriesPerPage) { + return cachedEntry.query; + } } std::string newQuery = generateHighscoreQueryForOurRank(categoryName, entriesPerPage, playerGUID, vocation); - cacheQueryHighscore(cacheKey, newQuery); + cacheQueryHighscore(cacheKey, newQuery, entriesPerPage, entriesPerPage); return newQuery; } @@ -8092,7 +8089,7 @@ void Game::playerHighscores(std::shared_ptr player, HighscoreType_t type uint32_t playerID = player->getID(); std::function callback = [this, playerID, category, vocation, entriesPerPage](DBResult_ptr result, bool) { - processHighscoreResults(result, playerID, category, vocation, entriesPerPage); + processHighscoreResults(std::move(result), playerID, category, vocation, entriesPerPage); }; g_databaseTasks().store(query, callback); diff --git a/src/game/game.hpp b/src/game/game.hpp index e84cb4a513b..a5c7cd116c0 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -50,12 +50,16 @@ static constexpr std::chrono::minutes HIGHSCORE_CACHE_EXPIRATION_TIME { 10 }; // struct QueryHighscoreCacheEntry { std::string query; + uint32_t page; + uint8_t entriesPerPage; std::chrono::time_point timestamp; }; struct HighscoreCacheEntry { std::vector characters; - std::chrono::time_point timestamp; + uint32_t page; + uint32_t entriesPerPage; + std::chrono::time_point timestamp; }; class Game { @@ -900,10 +904,9 @@ class Game { // Variable members (m_) std::unique_ptr m_IOWheel; - void cacheQueryHighscore(const std::string &key, const std::string &query); + void cacheQueryHighscore(const std::string &key, const std::string &query, uint32_t page, uint8_t entriesPerPage); void processHighscoreResults(DBResult_ptr result, uint32_t playerID, uint8_t category, uint32_t vocation, uint8_t entriesPerPage); - std::string getCachedQueryHighscore(const std::string &key); std::string generateVocationConditionHighscore(uint32_t vocation); std::string generateHighscoreQueryForEntries(const std::string &categoryName, uint32_t page, uint8_t entriesPerPage, uint32_t vocation); std::string generateHighscoreQueryForOurRank(const std::string &categoryName, uint8_t entriesPerPage, uint32_t playerGUID, uint32_t vocation); diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 53aedeb1c88..a2466038c99 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -2066,7 +2066,7 @@ void ProtocolGame::sendHighscoresNoData() { writeToOutputBuffer(msg); } -void ProtocolGame::sendHighscores(const std::vector &characters, uint8_t categoryId, uint32_t vocationId, uint16_t page, uint16_t pages) { +void ProtocolGame::sendHighscores(const std::vector &characters, uint8_t categoryId, uint32_t vocationId, uint16_t page, uint16_t pages, uint32_t updateTimer) { if (oldProtocol) { return; } @@ -2145,8 +2145,7 @@ void ProtocolGame::sendHighscores(const std::vector &charact msg.addByte(0xFF); // ?? msg.addByte(0); // ?? msg.addByte(1); // ?? - msg.add(time(nullptr)); // Last Update - + msg.add(updateTimer); // Last Update msg.setBufferPosition(vocationPosition); msg.addByte(vocations); writeToOutputBuffer(msg); diff --git a/src/server/network/protocol/protocolgame.hpp b/src/server/network/protocol/protocolgame.hpp index df7a9f53a35..2295c1036ea 100644 --- a/src/server/network/protocol/protocolgame.hpp +++ b/src/server/network/protocol/protocolgame.hpp @@ -132,7 +132,7 @@ class ProtocolGame final : public Protocol { void parseHighscores(NetworkMessage &msg); void parseTaskHuntingAction(NetworkMessage &msg); void sendHighscoresNoData(); - void sendHighscores(const std::vector &characters, uint8_t categoryId, uint32_t vocationId, uint16_t page, uint16_t pages); + void sendHighscores(const std::vector &characters, uint8_t categoryId, uint32_t vocationId, uint16_t page, uint16_t pages, uint32_t updateTimer); void parseGreet(NetworkMessage &msg); void parseBugReport(NetworkMessage &msg);