diff --git a/dGame/LeaderboardManager.cpp b/dGame/LeaderboardManager.cpp index c662bd6d..c350dda8 100644 --- a/dGame/LeaderboardManager.cpp +++ b/dGame/LeaderboardManager.cpp @@ -16,6 +16,8 @@ #include "CDActivitiesTable.h" #include "Metrics.hpp" +LeaderboardManager::LeaderboardCache LeaderboardManager::leaderboardCache = {}; + Leaderboard::Leaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, LWOOBJID relatedPlayer, const Leaderboard::Type leaderboardType) { this->gameID = gameID; this->weekly = weekly; @@ -34,10 +36,10 @@ void Leaderboard::WriteLeaderboardRow(std::ostringstream& leaderboard, const uin void Leaderboard::Serialize(RakNet::BitStream* bitStream) { bitStream->Write(gameID); - bitStream->Write(leaderboardType); + bitStream->Write(infoType); std::ostringstream leaderboard; - + Game::logger->Log("LeaderboardManager", "game is %i info type %i ", gameID, infoType); leaderboard << "ADO.Result=7:1\n"; // Unused in 1.10.64, but is in captures leaderboard << "Result.Count=1:1\n"; // number of results, always 1? leaderboard << "Result[0].Index=0:RowNumber\n"; // "Primary key" @@ -46,13 +48,18 @@ void Leaderboard::Serialize(RakNet::BitStream* bitStream) { int32_t rowNumber = 0; for (auto& entry : entries) { for (auto* data : entry) { + Game::logger->Log("LeaderboardManager", "writing data %s", data->GetString().c_str()); WriteLeaderboardRow(leaderboard, rowNumber, data); } rowNumber++; } - + Game::logger->Log("LeaderboardManager", "leaderboard is %s", leaderboard.str().c_str()); // Serialize the thing to a BitStream - bitStream->WriteAlignedBytes((const unsigned char*)leaderboard.str().c_str(), leaderboard.tellp()); + uint32_t leaderboardSize = leaderboard.tellp(); + bitStream->Write(leaderboardSize); + // Doing this all in 1 call so there is no possbility of a dangling pointer. + bitStream->WriteAlignedBytes(reinterpret_cast(GeneralUtils::ASCIIToUTF16(leaderboard.str()).c_str()), leaderboard.tellp() * 2); + if (leaderboardSize > 0) bitStream->Write(0); bitStream->Write0(); bitStream->Write0(); } @@ -80,7 +87,7 @@ void Leaderboard::QueryToLdf(std::unique_ptr& rows) { entry.push_back(new LDFData(u"LastPlayed", rows->getUInt64("lastPlayed"))); entry.push_back(new LDFData(u"NumPlayed", 1)); entry.push_back(new LDFData(u"name", GeneralUtils::ASCIIToUTF16(rows->getString("name").c_str()))); - entry.push_back(new LDFData(u"RowNumber", rows->getInt("ranking"))); + entry.push_back(new LDFData(u"RowNumber", rows->getInt("ranking"))); switch (leaderboardType) { case Type::ShootingGallery: entry.push_back(new LDFData(u"HitPercentage", rows->getDouble("hitPercentage"))); @@ -101,7 +108,7 @@ void Leaderboard::QueryToLdf(std::unique_ptr& rows) { // NumWins:1 break; case Type::UnusedLeaderboard4: - entry.push_back(new LDFData(u"Score", rows->getInt("score"))); + entry.push_back(new LDFData(u"Points", rows->getInt("score"))); // Points:1 break; case Type::MonumentRace: @@ -113,19 +120,19 @@ void Leaderboard::QueryToLdf(std::unique_ptr& rows) { // Time:1 break; case Type::Survival: - entry.push_back(new LDFData(u"Score", rows->getInt("score"))); + entry.push_back(new LDFData(u"Points", rows->getInt("score"))); // Points:1 entry.push_back(new LDFData(u"Time", rows->getInt("bestTime"))); // Time:1 break; case Type::SurvivalNS: - entry.push_back(new LDFData(u"Score", rows->getInt("score"))); + entry.push_back(new LDFData(u"Wave", rows->getInt("score"))); // Wave:1 entry.push_back(new LDFData(u"Time", rows->getInt("bestTime"))); // Time:1 break; case Type::Donations: - entry.push_back(new LDFData(u"Score", rows->getInt("score"))); + entry.push_back(new LDFData(u"Points", rows->getInt("score"))); // Score:1 break; case Type::None: @@ -320,11 +327,13 @@ void Leaderboard::SetupLeaderboard(uint32_t resultStart, uint32_t resultEnd) { } std::unique_ptr baseResult(baseQuery->executeQuery()); + Game::logger->Log("LeaderboardManager", "%s", baseRankingBuffer); if (!baseResult->next()) return; // In this case, there are no entries in the leaderboard for this game. uint32_t relatedPlayerLeaderboardId = baseResult->getInt("id"); // Create and execute the actual save here + Game::logger->Log("LeaderboardManager", "query is %s", lookupBuffer); std::unique_ptr query(Database::CreatePreppedStmt(lookupBuffer)); query->setInt(1, this->gameID); @@ -461,7 +470,7 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, GameID gameID, Lead int32_t time; time = va_arg(argsCopy, int32_t); - if (time < oldTime) { + if (time > oldTime) { saveQuery = FormatInsert(selectedColumns, insertFormat, activityScore, true); } break; @@ -507,7 +516,8 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, GameID gameID, Lead case Leaderboard::Type::None: default: Game::logger->Log("LeaderboardManager", "Unknown leaderboard type %i. Cannot save score!", leaderboardType); - break; + va_end(argsCopy); + return; } } else { saveQuery = FormatInsert(selectedColumns, insertFormat, activityScore, false); @@ -543,7 +553,7 @@ Leaderboard::Type LeaderboardManager::GetLeaderboardType(const GameID gameID) { std::vector activities = activitiesTable->Query([=](const CDActivities& entry) { return (entry.ActivityID == gameID); }); - auto type = activities.empty() ? static_cast(activities.at(0).leaderboardType) : Leaderboard::Type::None; + auto type = !activities.empty() ? static_cast(activities.at(0).leaderboardType) : Leaderboard::Type::None; leaderboardCache.insert_or_assign(gameID, type); return type; } diff --git a/dGame/dComponents/RacingControlComponent.cpp b/dGame/dComponents/RacingControlComponent.cpp index 703ec7f3..f74c92fa 100644 --- a/dGame/dComponents/RacingControlComponent.cpp +++ b/dGame/dComponents/RacingControlComponent.cpp @@ -23,6 +23,7 @@ #include "dConfig.h" #include "Loot.h" #include "eMissionTaskType.h" +#include "LeaderboardManager.h" #ifndef M_PI #define M_PI 3.14159265358979323846264338327950288 @@ -391,9 +392,7 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player, } if (id == "rewardButton") { - if (data->collectedRewards) { - return; - } + if (data->collectedRewards) return; data->collectedRewards = true; @@ -401,6 +400,8 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player, const auto score = m_LoadedPlayers * 10 + data->finished; LootGenerator::Instance().GiveActivityLoot(player, m_Parent, m_ActivityID, score); + auto leaderboardType = LeaderboardManager::Instance().GetLeaderboardType(m_ActivityID); + LeaderboardManager::Instance().SaveScore(player->GetObjectID(), m_ActivityID, leaderboardType, 3, data->bestLapTime, data->raceTime, data->finished == 1); // Giving rewards GameMessages::SendNotifyRacingClient( diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 55f40037..992311cb 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -1639,7 +1639,7 @@ void GameMessages::SendActivitySummaryLeaderboardData(const LWOOBJID& objectID, bitStream.Write(GAME_MSG::GAME_MSG_SEND_ACTIVITY_SUMMARY_LEADERBOARD_DATA); leaderboard->Serialize(&bitStream); - + PacketUtils::SavePacket("leaderboardData.bin", (const char*)bitStream.GetData(), bitStream.GetNumberOfBytesUsed()); SEND_PACKET; } @@ -1661,7 +1661,7 @@ void GameMessages::HandleRequestActivitySummaryLeaderboardData(RakNet::BitStream bool weekly = inStream->ReadBit(); - LeaderboardManager::Instance().SendLeaderboard(gameID, queryType, weekly, target, resultsStart, resultsEnd); + LeaderboardManager::Instance().SendLeaderboard(gameID, queryType, weekly, entity->GetObjectID(), resultsStart, resultsEnd); } void GameMessages::HandleActivityStateChangeRequest(RakNet::BitStream* inStream, Entity* entity) { diff --git a/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp b/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp index 7da4ccef..03ed9328 100644 --- a/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp +++ b/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp @@ -96,8 +96,7 @@ void NpcAgCourseStarter::OnFireEventServerSide(Entity* self, Entity* sender, std } EntityManager::Instance()->SerializeEntity(self); - //LeaderboardManager::SaveScore(sender->GetObjectID(), scriptedActivityComponent->GetActivityID(), - // 0, (uint32_t)finish); + // LeaderboardManager::Instance().SaveFootRaceScore(sender->GetObjectID(), scriptedActivityComponent->GetActivityID(), finish); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"ToggleLeaderBoard", scriptedActivityComponent->GetActivityID(), 0, sender->GetObjectID(), diff --git a/dScripts/ActivityManager.cpp b/dScripts/ActivityManager.cpp index acfa5a68..3e039024 100644 --- a/dScripts/ActivityManager.cpp +++ b/dScripts/ActivityManager.cpp @@ -73,24 +73,27 @@ void ActivityManager::StopActivity(Entity* self, const LWOOBJID playerID, const LootGenerator::Instance().GiveActivityLoot(player, self, gameID, CalculateActivityRating(self, playerID)); - // Save the new score to the leaderboard and show the leaderboard to the player - //LeaderboardManager::SaveScore(playerID, gameID, score, value1); - //const auto* leaderboard = LeaderboardManager::GetLeaderboard(gameID, InfoType::Standings, - // false, player->GetObjectID()); - //GameMessages::SendActivitySummaryLeaderboardData(self->GetObjectID(), leaderboard, player->GetSystemAddress()); - //delete leaderboard; - - // Makes the leaderboard show up for the player - GameMessages::SendNotifyClientObject(self->GetObjectID(), u"ToggleLeaderBoard", - gameID, 0, playerID, "", - player->GetSystemAddress()); - if (sac != nullptr) { sac->PlayerRemove(player->GetObjectID()); } } } +void ActivityManager::SaveScore(Entity* self, LWOOBJID playerID, uint32_t val1, uint32_t val2, uint32_t val3) { + auto* player = EntityManager::Instance()->GetEntity(playerID); + if (!player) return; + + auto* sac = self->GetComponent(); + uint32_t gameID = sac != nullptr ? sac->GetActivityID() : self->GetLOT(); + // Save the new score to the leaderboard and show the leaderboard to the player + auto leaderboardType = LeaderboardManager::GetLeaderboardType(gameID); + Game::logger->Log("ActivityManager", "leaderboard type %i %i", leaderboardType, gameID); + LeaderboardManager::Instance().SaveScore(playerID, gameID, leaderboardType, 3, val1, val2, val3); + + // Makes the leaderboard show up for the player + GameMessages::SendNotifyClientObject(self->GetObjectID(), u"ToggleLeaderBoard", gameID, 0, playerID, "", player->GetSystemAddress()); +} + bool ActivityManager::TakeActivityCost(const Entity* self, const LWOOBJID playerID) { auto* sac = self->GetComponent(); if (sac == nullptr) diff --git a/dScripts/ActivityManager.h b/dScripts/ActivityManager.h index 640cf4bf..633fd5d8 100644 --- a/dScripts/ActivityManager.h +++ b/dScripts/ActivityManager.h @@ -18,6 +18,7 @@ public: static bool TakeActivityCost(const Entity* self, LWOOBJID playerID); static uint32_t GetActivityID(const Entity* self); void StopActivity(Entity* self, LWOOBJID playerID, uint32_t score, uint32_t value1 = 0, uint32_t value2 = 0, bool quit = false); + void SaveScore(Entity* self, LWOOBJID playerID, uint32_t val1 = 0, uint32_t val2 = 0, uint32_t val3 = 0); virtual uint32_t CalculateActivityRating(Entity* self, LWOOBJID playerID); static void GetLeaderboardData(Entity* self, LWOOBJID playerID, uint32_t activityID, uint32_t numResults = 0); // void FreezePlayer(Entity *self, const LWOOBJID playerID, const bool state) const; diff --git a/dScripts/ai/ACT/FootRace/BaseFootRaceManager.cpp b/dScripts/ai/ACT/FootRace/BaseFootRaceManager.cpp index 1c3fb830..3efb5ff4 100644 --- a/dScripts/ai/ACT/FootRace/BaseFootRaceManager.cpp +++ b/dScripts/ai/ACT/FootRace/BaseFootRaceManager.cpp @@ -42,6 +42,7 @@ void BaseFootRaceManager::OnFireEventServerSide(Entity* self, Entity* sender, st } StopActivity(self, player->GetObjectID(), 0, param1); + SaveScore(self, player->GetObjectID(), param1, param2, param3); } } }