From 53bee99fa5ae270102cc87a2373b77d7f66e67b9 Mon Sep 17 00:00:00 2001 From: Beats Date: Sun, 22 Oct 2023 02:55:36 -0300 Subject: [PATCH 1/4] fix highscore --- src/creatures/players/player.hpp | 4 +- src/game/game.cpp | 52 +++++++++++--------- src/game/game.hpp | 8 ++- src/server/network/protocol/protocolgame.cpp | 9 ++-- src/server/network/protocol/protocolgame.hpp | 2 +- 5 files changed, 41 insertions(+), 34 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..50677a52993 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,8 +7996,8 @@ 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 }; } } @@ -8008,39 +8012,39 @@ std::string Game::getCachedQueryHighscore(const std::string &key) { 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) { - std::ostringstream cacheKeyStream; - cacheKeyStream << "Entries_" << categoryName << "_" << page << "_" << static_cast(entriesPerPage) << "_" << vocation; - std::string cacheKey = cacheKeyStream.str(); + std::string cacheKey = std::format("Entries_{}_{}_{}_{}", categoryName, page, static_cast(entriesPerPage), vocation); - 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; } -std::string Game::generateHighscoreOrGetCachedQueryForOurRank(const std::string &categoryName, uint8_t entriesPerPage, uint32_t playerGUID, uint32_t vocation) { - std::ostringstream cacheKeyStream; - cacheKeyStream << "OurRank_" << categoryName << "_" << static_cast(entriesPerPage) << "_" << playerGUID << "_" << vocation; - std::string cacheKey = cacheKeyStream.str(); +std::string Game::generateHighscoreOrGetCachedQueryForOurRank(const std::string& categoryName, uint8_t entriesPerPage, uint32_t playerGUID, uint32_t vocation) { + std::string cacheKey = std::format("OurRank_{}_{}_{}_{}", categoryName, static_cast(entriesPerPage), playerGUID, vocation); - 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 +8096,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..bca3d4a7705 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,7 +904,7 @@ 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); diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 53aedeb1c88..12947df41f6 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -2029,8 +2029,8 @@ void ProtocolGame::parseHighscores(NetworkMessage &msg) { uint32_t vocation = msg.get(); uint16_t page = 1; const std::string worldName = msg.getString(); - msg.getByte(); // Game World Category - msg.getByte(); // BattlEye World Type + auto a = msg.getByte(); // Game World Category + auto b = msg.getByte(); // BattlEye World Type if (type == HIGHSCORE_GETENTRIES) { page = std::max(1, msg.get()); } @@ -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); From 0ae49239ef5f3ae79b1c2a1d00687d8ab0d1c596 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Sun, 22 Oct 2023 05:56:58 +0000 Subject: [PATCH 2/4] Code format - (Clang-format) --- src/game/game.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/game/game.cpp b/src/game/game.cpp index 50677a52993..2043884bb67 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -8013,7 +8013,7 @@ std::string Game::getCachedQueryHighscore(const std::string &key) { } 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()}; + QueryHighscoreCacheEntry queryEntry { query, page, entriesPerPage, std::chrono::steady_clock::now() }; queryCache[key] = queryEntry; } @@ -8021,7 +8021,7 @@ std::string Game::generateHighscoreOrGetCachedQueryForEntries(const std::string std::string cacheKey = std::format("Entries_{}_{}_{}_{}", categoryName, page, static_cast(entriesPerPage), vocation); if (queryCache.find(cacheKey) != queryCache.end()) { - const QueryHighscoreCacheEntry& cachedEntry = queryCache[cacheKey]; + const QueryHighscoreCacheEntry &cachedEntry = queryCache[cacheKey]; if (cachedEntry.page == page) { return cachedEntry.query; } @@ -8033,11 +8033,11 @@ std::string Game::generateHighscoreOrGetCachedQueryForEntries(const std::string return newQuery; } -std::string Game::generateHighscoreOrGetCachedQueryForOurRank(const std::string& categoryName, uint8_t entriesPerPage, uint32_t playerGUID, uint32_t vocation) { +std::string Game::generateHighscoreOrGetCachedQueryForOurRank(const std::string &categoryName, uint8_t entriesPerPage, uint32_t playerGUID, uint32_t vocation) { std::string cacheKey = std::format("OurRank_{}_{}_{}_{}", categoryName, static_cast(entriesPerPage), playerGUID, vocation); if (queryCache.find(cacheKey) != queryCache.end()) { - const QueryHighscoreCacheEntry& cachedEntry = queryCache[cacheKey]; + const QueryHighscoreCacheEntry &cachedEntry = queryCache[cacheKey]; if (cachedEntry.page == entriesPerPage) { return cachedEntry.query; } From 337730393a2eaad43adb262a854e72355727a02a Mon Sep 17 00:00:00 2001 From: Beats Date: Sun, 22 Oct 2023 02:58:50 -0300 Subject: [PATCH 3/4] clear --- src/server/network/protocol/protocolgame.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 12947df41f6..a2466038c99 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -2029,8 +2029,8 @@ void ProtocolGame::parseHighscores(NetworkMessage &msg) { uint32_t vocation = msg.get(); uint16_t page = 1; const std::string worldName = msg.getString(); - auto a = msg.getByte(); // Game World Category - auto b = msg.getByte(); // BattlEye World Type + msg.getByte(); // Game World Category + msg.getByte(); // BattlEye World Type if (type == HIGHSCORE_GETENTRIES) { page = std::max(1, msg.get()); } From 796e37e4931168d7645b77c401e38d68cc88852a Mon Sep 17 00:00:00 2001 From: Beats Date: Sun, 22 Oct 2023 04:01:14 -0300 Subject: [PATCH 4/4] fix build linux --- src/game/game.cpp | 19 ++++++------------- src/game/game.hpp | 1 - 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/game/game.cpp b/src/game/game.cpp index 2043884bb67..b3706b7bf38 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -8001,24 +8001,15 @@ void Game::processHighscoreResults(DBResult_ptr result, uint32_t playerID, uint8 } } -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, 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) { - std::string cacheKey = std::format("Entries_{}_{}_{}_{}", categoryName, page, static_cast(entriesPerPage), vocation); + std::ostringstream cacheKeyStream; + cacheKeyStream << "Entries_" << categoryName << "_" << page << "_" << static_cast(entriesPerPage) << "_" << vocation; + std::string cacheKey = cacheKeyStream.str(); if (queryCache.find(cacheKey) != queryCache.end()) { const QueryHighscoreCacheEntry &cachedEntry = queryCache[cacheKey]; @@ -8034,7 +8025,9 @@ std::string Game::generateHighscoreOrGetCachedQueryForEntries(const std::string } std::string Game::generateHighscoreOrGetCachedQueryForOurRank(const std::string &categoryName, uint8_t entriesPerPage, uint32_t playerGUID, uint32_t vocation) { - std::string cacheKey = std::format("OurRank_{}_{}_{}_{}", categoryName, static_cast(entriesPerPage), playerGUID, vocation); + std::ostringstream cacheKeyStream; + cacheKeyStream << "OurRank_" << categoryName << "_" << static_cast(entriesPerPage) << "_" << playerGUID << "_" << vocation; + std::string cacheKey = cacheKeyStream.str(); if (queryCache.find(cacheKey) != queryCache.end()) { const QueryHighscoreCacheEntry &cachedEntry = queryCache[cacheKey]; diff --git a/src/game/game.hpp b/src/game/game.hpp index bca3d4a7705..a5c7cd116c0 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -907,7 +907,6 @@ class Game { 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);