Skip to content

Commit

Permalink
fix: highscore client pages (opentibiabr#1735)
Browse files Browse the repository at this point in the history
  • Loading branch information
beats-dh authored Oct 24, 2023
1 parent 9d0b803 commit cc7aeed
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 37 deletions.
4 changes: 2 additions & 2 deletions src/creatures/players/player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1605,9 +1605,9 @@ class Player final : public Creature, public Cylinder, public Bankable {
client->sendHighscoresNoData();
}
}
void sendHighscores(const std::vector<HighscoreCharacter> &characters, uint8_t categoryId, uint32_t vocationId, uint16_t page, uint16_t pages) {
void sendHighscores(const std::vector<HighscoreCharacter> &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) {
Expand Down
53 changes: 25 additions & 28 deletions src/game/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7968,14 +7968,18 @@ void Game::processHighscoreResults(DBResult_ptr result, uint32_t playerID, uint8
pages /= entriesPerPage;

std::ostringstream cacheKeyStream;
cacheKeyStream << "Highscore_" << static_cast<int>(category) << "_" << static_cast<int>(vocation) << "_" << static_cast<int>(entriesPerPage);
cacheKeyStream << "Highscore_" << static_cast<int>(category) << "_" << static_cast<int>(vocation) << "_" << static_cast<int>(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<uint16_t>(pages));
auto cachedTime = it->second.timestamp;
auto durationSinceEpoch = cachedTime.time_since_epoch();
auto secondsSinceEpoch = std::chrono::duration_cast<std::chrono::seconds>(durationSinceEpoch).count();
auto updateTimer = static_cast<uint32_t>(secondsSinceEpoch);
player->sendHighscores(cacheEntry.characters, category, vocation, cacheEntry.page, static_cast<uint16_t>(cacheEntry.entriesPerPage), updateTimer);
} else {
std::vector<HighscoreCharacter> characters;
characters.reserve(result->countResults());
Expand All @@ -7992,39 +7996,30 @@ void Game::processHighscoreResults(DBResult_ptr result, uint32_t playerID, uint8
} while (result->next());
}

player->sendHighscores(characters, category, vocation, page, static_cast<uint16_t>(pages));
highscoreCache[cacheKey] = { characters, now };
player->sendHighscores(characters, category, vocation, page, static_cast<uint16_t>(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) {
std::ostringstream cacheKeyStream;
cacheKeyStream << "Entries_" << categoryName << "_" << page << "_" << static_cast<int>(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;
}
Expand All @@ -8034,13 +8029,15 @@ std::string Game::generateHighscoreOrGetCachedQueryForOurRank(const std::string
cacheKeyStream << "OurRank_" << categoryName << "_" << static_cast<int>(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;
}
Expand Down Expand Up @@ -8092,7 +8089,7 @@ void Game::playerHighscores(std::shared_ptr<Player> player, HighscoreType_t type

uint32_t playerID = player->getID();
std::function<void(DBResult_ptr, bool)> 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);
Expand Down
9 changes: 6 additions & 3 deletions src/game/game.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::chrono::steady_clock> timestamp;
};

struct HighscoreCacheEntry {
std::vector<HighscoreCharacter> characters;
std::chrono::time_point<std::chrono::steady_clock> timestamp;
uint32_t page;
uint32_t entriesPerPage;
std::chrono::time_point<std::chrono::system_clock> timestamp;
};

class Game {
Expand Down Expand Up @@ -900,10 +904,9 @@ class Game {
// Variable members (m_)
std::unique_ptr<IOWheel> 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);
Expand Down
5 changes: 2 additions & 3 deletions src/server/network/protocol/protocolgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2066,7 +2066,7 @@ void ProtocolGame::sendHighscoresNoData() {
writeToOutputBuffer(msg);
}

void ProtocolGame::sendHighscores(const std::vector<HighscoreCharacter> &characters, uint8_t categoryId, uint32_t vocationId, uint16_t page, uint16_t pages) {
void ProtocolGame::sendHighscores(const std::vector<HighscoreCharacter> &characters, uint8_t categoryId, uint32_t vocationId, uint16_t page, uint16_t pages, uint32_t updateTimer) {
if (oldProtocol) {
return;
}
Expand Down Expand Up @@ -2145,8 +2145,7 @@ void ProtocolGame::sendHighscores(const std::vector<HighscoreCharacter> &charact
msg.addByte(0xFF); // ??
msg.addByte(0); // ??
msg.addByte(1); // ??
msg.add<uint32_t>(time(nullptr)); // Last Update

msg.add<uint32_t>(updateTimer); // Last Update
msg.setBufferPosition(vocationPosition);
msg.addByte(vocations);
writeToOutputBuffer(msg);
Expand Down
2 changes: 1 addition & 1 deletion src/server/network/protocol/protocolgame.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class ProtocolGame final : public Protocol {
void parseHighscores(NetworkMessage &msg);
void parseTaskHuntingAction(NetworkMessage &msg);
void sendHighscoresNoData();
void sendHighscores(const std::vector<HighscoreCharacter> &characters, uint8_t categoryId, uint32_t vocationId, uint16_t page, uint16_t pages);
void sendHighscores(const std::vector<HighscoreCharacter> &characters, uint8_t categoryId, uint32_t vocationId, uint16_t page, uint16_t pages, uint32_t updateTimer);

void parseGreet(NetworkMessage &msg);
void parseBugReport(NetworkMessage &msg);
Expand Down

0 comments on commit cc7aeed

Please sign in to comment.