Working in game!

- Add score saving for races
- Fix some bugs
- Still work to do.
This commit is contained in:
David Markowitz 2023-05-09 01:42:11 -07:00
parent 411c9eaf1f
commit 7a067e7b48
7 changed files with 46 additions and 31 deletions

View File

@ -16,6 +16,8 @@
#include "CDActivitiesTable.h" #include "CDActivitiesTable.h"
#include "Metrics.hpp" #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) { Leaderboard::Leaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, LWOOBJID relatedPlayer, const Leaderboard::Type leaderboardType) {
this->gameID = gameID; this->gameID = gameID;
this->weekly = weekly; this->weekly = weekly;
@ -34,10 +36,10 @@ void Leaderboard::WriteLeaderboardRow(std::ostringstream& leaderboard, const uin
void Leaderboard::Serialize(RakNet::BitStream* bitStream) { void Leaderboard::Serialize(RakNet::BitStream* bitStream) {
bitStream->Write(gameID); bitStream->Write(gameID);
bitStream->Write(leaderboardType); bitStream->Write(infoType);
std::ostringstream leaderboard; 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 << "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.Count=1:1\n"; // number of results, always 1?
leaderboard << "Result[0].Index=0:RowNumber\n"; // "Primary key" leaderboard << "Result[0].Index=0:RowNumber\n"; // "Primary key"
@ -46,13 +48,18 @@ void Leaderboard::Serialize(RakNet::BitStream* bitStream) {
int32_t rowNumber = 0; int32_t rowNumber = 0;
for (auto& entry : entries) { for (auto& entry : entries) {
for (auto* data : entry) { for (auto* data : entry) {
Game::logger->Log("LeaderboardManager", "writing data %s", data->GetString().c_str());
WriteLeaderboardRow(leaderboard, rowNumber, data); WriteLeaderboardRow(leaderboard, rowNumber, data);
} }
rowNumber++; rowNumber++;
} }
Game::logger->Log("LeaderboardManager", "leaderboard is %s", leaderboard.str().c_str());
// Serialize the thing to a BitStream // Serialize the thing to a BitStream
bitStream->WriteAlignedBytes((const unsigned char*)leaderboard.str().c_str(), leaderboard.tellp()); uint32_t leaderboardSize = leaderboard.tellp();
bitStream->Write<uint32_t>(leaderboardSize);
// Doing this all in 1 call so there is no possbility of a dangling pointer.
bitStream->WriteAlignedBytes(reinterpret_cast<const unsigned char*>(GeneralUtils::ASCIIToUTF16(leaderboard.str()).c_str()), leaderboard.tellp() * 2);
if (leaderboardSize > 0) bitStream->Write<uint16_t>(0);
bitStream->Write0(); bitStream->Write0();
bitStream->Write0(); bitStream->Write0();
} }
@ -80,7 +87,7 @@ void Leaderboard::QueryToLdf(std::unique_ptr<sql::ResultSet>& rows) {
entry.push_back(new LDFData<uint64_t>(u"LastPlayed", rows->getUInt64("lastPlayed"))); entry.push_back(new LDFData<uint64_t>(u"LastPlayed", rows->getUInt64("lastPlayed")));
entry.push_back(new LDFData<int32_t>(u"NumPlayed", 1)); entry.push_back(new LDFData<int32_t>(u"NumPlayed", 1));
entry.push_back(new LDFData<std::u16string>(u"name", GeneralUtils::ASCIIToUTF16(rows->getString("name").c_str()))); entry.push_back(new LDFData<std::u16string>(u"name", GeneralUtils::ASCIIToUTF16(rows->getString("name").c_str())));
entry.push_back(new LDFData<int32_t>(u"RowNumber", rows->getInt("ranking"))); entry.push_back(new LDFData<uint64_t>(u"RowNumber", rows->getInt("ranking")));
switch (leaderboardType) { switch (leaderboardType) {
case Type::ShootingGallery: case Type::ShootingGallery:
entry.push_back(new LDFData<float>(u"HitPercentage", rows->getDouble("hitPercentage"))); entry.push_back(new LDFData<float>(u"HitPercentage", rows->getDouble("hitPercentage")));
@ -101,7 +108,7 @@ void Leaderboard::QueryToLdf(std::unique_ptr<sql::ResultSet>& rows) {
// NumWins:1 // NumWins:1
break; break;
case Type::UnusedLeaderboard4: case Type::UnusedLeaderboard4:
entry.push_back(new LDFData<int32_t>(u"Score", rows->getInt("score"))); entry.push_back(new LDFData<int32_t>(u"Points", rows->getInt("score")));
// Points:1 // Points:1
break; break;
case Type::MonumentRace: case Type::MonumentRace:
@ -113,19 +120,19 @@ void Leaderboard::QueryToLdf(std::unique_ptr<sql::ResultSet>& rows) {
// Time:1 // Time:1
break; break;
case Type::Survival: case Type::Survival:
entry.push_back(new LDFData<int32_t>(u"Score", rows->getInt("score"))); entry.push_back(new LDFData<int32_t>(u"Points", rows->getInt("score")));
// Points:1 // Points:1
entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("bestTime"))); entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("bestTime")));
// Time:1 // Time:1
break; break;
case Type::SurvivalNS: case Type::SurvivalNS:
entry.push_back(new LDFData<int32_t>(u"Score", rows->getInt("score"))); entry.push_back(new LDFData<int32_t>(u"Wave", rows->getInt("score")));
// Wave:1 // Wave:1
entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("bestTime"))); entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("bestTime")));
// Time:1 // Time:1
break; break;
case Type::Donations: case Type::Donations:
entry.push_back(new LDFData<int32_t>(u"Score", rows->getInt("score"))); entry.push_back(new LDFData<int32_t>(u"Points", rows->getInt("score")));
// Score:1 // Score:1
break; break;
case Type::None: case Type::None:
@ -320,11 +327,13 @@ void Leaderboard::SetupLeaderboard(uint32_t resultStart, uint32_t resultEnd) {
} }
std::unique_ptr<sql::ResultSet> baseResult(baseQuery->executeQuery()); std::unique_ptr<sql::ResultSet> 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. if (!baseResult->next()) return; // In this case, there are no entries in the leaderboard for this game.
uint32_t relatedPlayerLeaderboardId = baseResult->getInt("id"); uint32_t relatedPlayerLeaderboardId = baseResult->getInt("id");
// Create and execute the actual save here // Create and execute the actual save here
Game::logger->Log("LeaderboardManager", "query is %s", lookupBuffer);
std::unique_ptr<sql::PreparedStatement> query(Database::CreatePreppedStmt(lookupBuffer)); std::unique_ptr<sql::PreparedStatement> query(Database::CreatePreppedStmt(lookupBuffer));
query->setInt(1, this->gameID); query->setInt(1, this->gameID);
@ -461,7 +470,7 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, GameID gameID, Lead
int32_t time; int32_t time;
time = va_arg(argsCopy, int32_t); time = va_arg(argsCopy, int32_t);
if (time < oldTime) { if (time > oldTime) {
saveQuery = FormatInsert(selectedColumns, insertFormat, activityScore, true); saveQuery = FormatInsert(selectedColumns, insertFormat, activityScore, true);
} }
break; break;
@ -507,7 +516,8 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, GameID gameID, Lead
case Leaderboard::Type::None: case Leaderboard::Type::None:
default: default:
Game::logger->Log("LeaderboardManager", "Unknown leaderboard type %i. Cannot save score!", leaderboardType); Game::logger->Log("LeaderboardManager", "Unknown leaderboard type %i. Cannot save score!", leaderboardType);
break; va_end(argsCopy);
return;
} }
} else { } else {
saveQuery = FormatInsert(selectedColumns, insertFormat, activityScore, false); saveQuery = FormatInsert(selectedColumns, insertFormat, activityScore, false);
@ -543,7 +553,7 @@ Leaderboard::Type LeaderboardManager::GetLeaderboardType(const GameID gameID) {
std::vector<CDActivities> activities = activitiesTable->Query([=](const CDActivities& entry) { std::vector<CDActivities> activities = activitiesTable->Query([=](const CDActivities& entry) {
return (entry.ActivityID == gameID); return (entry.ActivityID == gameID);
}); });
auto type = activities.empty() ? static_cast<Leaderboard::Type>(activities.at(0).leaderboardType) : Leaderboard::Type::None; auto type = !activities.empty() ? static_cast<Leaderboard::Type>(activities.at(0).leaderboardType) : Leaderboard::Type::None;
leaderboardCache.insert_or_assign(gameID, type); leaderboardCache.insert_or_assign(gameID, type);
return type; return type;
} }

View File

@ -23,6 +23,7 @@
#include "dConfig.h" #include "dConfig.h"
#include "Loot.h" #include "Loot.h"
#include "eMissionTaskType.h" #include "eMissionTaskType.h"
#include "LeaderboardManager.h"
#ifndef M_PI #ifndef M_PI
#define M_PI 3.14159265358979323846264338327950288 #define M_PI 3.14159265358979323846264338327950288
@ -391,9 +392,7 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player,
} }
if (id == "rewardButton") { if (id == "rewardButton") {
if (data->collectedRewards) { if (data->collectedRewards) return;
return;
}
data->collectedRewards = true; data->collectedRewards = true;
@ -401,6 +400,8 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player,
const auto score = m_LoadedPlayers * 10 + data->finished; const auto score = m_LoadedPlayers * 10 + data->finished;
LootGenerator::Instance().GiveActivityLoot(player, m_Parent, m_ActivityID, score); 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 // Giving rewards
GameMessages::SendNotifyRacingClient( GameMessages::SendNotifyRacingClient(

View File

@ -1639,7 +1639,7 @@ void GameMessages::SendActivitySummaryLeaderboardData(const LWOOBJID& objectID,
bitStream.Write(GAME_MSG::GAME_MSG_SEND_ACTIVITY_SUMMARY_LEADERBOARD_DATA); bitStream.Write(GAME_MSG::GAME_MSG_SEND_ACTIVITY_SUMMARY_LEADERBOARD_DATA);
leaderboard->Serialize(&bitStream); leaderboard->Serialize(&bitStream);
PacketUtils::SavePacket("leaderboardData.bin", (const char*)bitStream.GetData(), bitStream.GetNumberOfBytesUsed());
SEND_PACKET; SEND_PACKET;
} }
@ -1661,7 +1661,7 @@ void GameMessages::HandleRequestActivitySummaryLeaderboardData(RakNet::BitStream
bool weekly = inStream->ReadBit(); 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) { void GameMessages::HandleActivityStateChangeRequest(RakNet::BitStream* inStream, Entity* entity) {

View File

@ -96,8 +96,7 @@ void NpcAgCourseStarter::OnFireEventServerSide(Entity* self, Entity* sender, std
} }
EntityManager::Instance()->SerializeEntity(self); EntityManager::Instance()->SerializeEntity(self);
//LeaderboardManager::SaveScore(sender->GetObjectID(), scriptedActivityComponent->GetActivityID(), // LeaderboardManager::Instance().SaveFootRaceScore(sender->GetObjectID(), scriptedActivityComponent->GetActivityID(), finish);
// 0, (uint32_t)finish);
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"ToggleLeaderBoard", GameMessages::SendNotifyClientObject(self->GetObjectID(), u"ToggleLeaderBoard",
scriptedActivityComponent->GetActivityID(), 0, sender->GetObjectID(), scriptedActivityComponent->GetActivityID(), 0, sender->GetObjectID(),

View File

@ -73,24 +73,27 @@ void ActivityManager::StopActivity(Entity* self, const LWOOBJID playerID, const
LootGenerator::Instance().GiveActivityLoot(player, self, gameID, CalculateActivityRating(self, playerID)); 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) { if (sac != nullptr) {
sac->PlayerRemove(player->GetObjectID()); 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<ScriptedActivityComponent>();
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) { bool ActivityManager::TakeActivityCost(const Entity* self, const LWOOBJID playerID) {
auto* sac = self->GetComponent<ScriptedActivityComponent>(); auto* sac = self->GetComponent<ScriptedActivityComponent>();
if (sac == nullptr) if (sac == nullptr)

View File

@ -18,6 +18,7 @@ public:
static bool TakeActivityCost(const Entity* self, LWOOBJID playerID); static bool TakeActivityCost(const Entity* self, LWOOBJID playerID);
static uint32_t GetActivityID(const Entity* self); 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 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); virtual uint32_t CalculateActivityRating(Entity* self, LWOOBJID playerID);
static void GetLeaderboardData(Entity* self, LWOOBJID playerID, uint32_t activityID, uint32_t numResults = 0); 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; // void FreezePlayer(Entity *self, const LWOOBJID playerID, const bool state) const;

View File

@ -42,6 +42,7 @@ void BaseFootRaceManager::OnFireEventServerSide(Entity* self, Entity* sender, st
} }
StopActivity(self, player->GetObjectID(), 0, param1); StopActivity(self, player->GetObjectID(), 0, param1);
SaveScore(self, player->GetObjectID(), param1, param2, param3);
} }
} }
} }