From d64d38e582ec32b1acd0de5d23558308a04cda1d Mon Sep 17 00:00:00 2001 From: Future Date: Sun, 26 May 2024 12:11:52 +0200 Subject: [PATCH 1/5] feat(t6): load leaderboard definitions from raw --- .../AssetLoaders/AssetLoaderLeaderboard.cpp | 43 +++++ .../T6/AssetLoaders/AssetLoaderLeaderboard.h | 17 ++ .../Leaderboard/JsonLeaderboardDefLoader.cpp | 152 ++++++++++++++++++ .../T6/Leaderboard/JsonLeaderboardDefLoader.h | 11 ++ 4 files changed, 223 insertions(+) create mode 100644 src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLeaderboard.cpp create mode 100644 src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLeaderboard.h create mode 100644 src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp create mode 100644 src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.h diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLeaderboard.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLeaderboard.cpp new file mode 100644 index 00000000..1cb993c7 --- /dev/null +++ b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLeaderboard.cpp @@ -0,0 +1,43 @@ +#include "AssetLoaderLeaderboard.h" + +#include "Game/T6/CommonT6.h" +#include "Game/T6/Leaderboard/JsonLeaderboardDefLoader.h" +#include "Game/T6/T6.h" +#include "Pool/GlobalAssetPool.h" + +#include +#include +#include + +using namespace T6; + +void* AssetLoaderLeaderboard::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) +{ + auto* leaderboard = memory->Create(); + memset(leaderboard, 0, sizeof(LeaderboardDef)); + leaderboard->name = memory->Dup(assetName.c_str()); + return leaderboard; +} + +bool AssetLoaderLeaderboard::CanLoadFromRaw() const +{ + return true; +} + +bool AssetLoaderLeaderboard::LoadFromRaw( + const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const +{ + const auto file = searchPath->Open(std::format("leaderboards/{}.json", assetName)); + if (!file.IsOpen()) + return false; + + auto* leaderboardDef = memory->Alloc(); + leaderboardDef->name = memory->Dup(assetName.c_str()); + + if (LoadLeaderboardAsJson(*file.m_stream, *leaderboardDef, memory)) + manager->AddAsset(assetName, leaderboardDef); + else + std::cerr << std::format("Failed to load leaderboard \"{}\"\n", assetName); + + return true; +} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLeaderboard.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLeaderboard.h new file mode 100644 index 00000000..13c3e2a2 --- /dev/null +++ b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLeaderboard.h @@ -0,0 +1,17 @@ +#pragma once +#include "AssetLoading/BasicAssetLoader.h" +#include "AssetLoading/IAssetLoadingManager.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" + +namespace T6 +{ + class AssetLoaderLeaderboard final : public BasicAssetLoader + { + public: + _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; + _NODISCARD bool CanLoadFromRaw() const override; + bool + LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; + }; +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp b/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp new file mode 100644 index 00000000..df1b3314 --- /dev/null +++ b/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp @@ -0,0 +1,152 @@ + +#include "JsonLeaderboardDefLoader.h" + +#include "Game/T6/CommonT6.h" +#include "Game/T6/Leaderboard/JsonLeaderboardDef.h" + +#include +#include +#include + +using namespace nlohmann; +using namespace T6; + +namespace +{ + class JsonLoader + { + public: + JsonLoader(std::istream& stream, MemoryManager& memory) + : m_stream(stream), + m_memory(memory) + { + } + + bool Load(LeaderboardDef& leaderboardDef) const + { + const auto jRoot = json::parse(m_stream); + std::string type; + unsigned version; + + jRoot.at("_type").get_to(type); + jRoot.at("_version").get_to(version); + + if (type != "leaderboard" || version != 1u) + { + std::cerr << std::format("Tried to load leaderboard \"{}\" but did not find expected type leaderboard of version 1\n", leaderboardDef.name); + return false; + } + + const auto jLeaderboard = jRoot.get(); + return CreateLeaderboardFromJson(jLeaderboard, leaderboardDef); + } + + private: + static bool CreateTrackTypeFlagsFromJson(const JsonLeaderboardDef& jLeaderboardDef, int& gameFlags) + { + for (const auto gameFlag : jLeaderboardDef.trackTypes) + gameFlags |= gameFlag; + + return true; + } + + bool CreateColumnDefFromJson(const JsonColumnDef& jColumn, LbColumnDef& lbColumnDef, LeaderboardDef& leaderboardDef) const + { + lbColumnDef.name = m_memory.Dup(jColumn.name.c_str()); + lbColumnDef.colId = jColumn.colId; + + if (jColumn.dwColIndex) + lbColumnDef.dwColIndex = jColumn.dwColIndex.value(); + else + lbColumnDef.dwColIndex = 0; + + if (jColumn.hidden) + lbColumnDef.hidden = jColumn.hidden.value(); + else + lbColumnDef.hidden = false; + + if (jColumn.statName) + lbColumnDef.statName = m_memory.Dup(jColumn.statName->c_str()); + else + lbColumnDef.statName = nullptr; + + lbColumnDef.type = jColumn.type; + + if (jColumn.precision) + lbColumnDef.precision = jColumn.precision.value(); + else + lbColumnDef.precision = 0; + + lbColumnDef.agg = jColumn.aggregationFunction; + + if (jColumn.localization) + lbColumnDef.localization = m_memory.Dup(jColumn.localization->c_str()); + else + lbColumnDef.localization = nullptr; + + if (jColumn.uiCalColX) + lbColumnDef.uiCalColX = jColumn.uiCalColX.value(); + else + lbColumnDef.uiCalColX = 0; + + if (jColumn.uiCalColY) + lbColumnDef.uiCalColY = jColumn.uiCalColY.value(); + else + lbColumnDef.uiCalColY = 0; + + return true; + } + + bool CreateLeaderboardFromJson(const JsonLeaderboardDef& jLeaderboardDef, LeaderboardDef& leaderboardDef) const + { + leaderboardDef.id = jLeaderboardDef.id; + leaderboardDef.dwColumnCount = jLeaderboardDef.dwColumnCount; + + if (jLeaderboardDef.xpColId) + leaderboardDef.xpColId = jLeaderboardDef.xpColId.value(); + else + leaderboardDef.xpColId = -1; + + if (jLeaderboardDef.prestigeColId) + leaderboardDef.prestigeColId = jLeaderboardDef.prestigeColId.value(); + else + leaderboardDef.prestigeColId = -1; + + if (!jLeaderboardDef.columns.empty()) + { + leaderboardDef.columnCount = static_cast(jLeaderboardDef.columns.size()); + leaderboardDef.columns = m_memory.Alloc(leaderboardDef.columnCount); + + for (auto i = 0; i < leaderboardDef.columnCount; ++i) + { + if (!CreateColumnDefFromJson(jLeaderboardDef.columns[i], leaderboardDef.columns[i], leaderboardDef)) + return false; + } + } + else + { + leaderboardDef.columnCount = 0; + leaderboardDef.columns = nullptr; + } + + leaderboardDef.updateType = jLeaderboardDef.updateType; + + if (!CreateTrackTypeFlagsFromJson(jLeaderboardDef, leaderboardDef.trackTypes)) + return false; + + return true; + } + + std::istream& m_stream; + MemoryManager& m_memory; + }; +} // namespace + +namespace T6 +{ + bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager* memory) + { + const JsonLoader loader(stream, *memory); + return loader.Load(leaderboard); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.h b/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.h new file mode 100644 index 00000000..9c145ae5 --- /dev/null +++ b/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.h @@ -0,0 +1,11 @@ +#pragma once + +#include "Game/T6/T6.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager* memory); +} // namespace T6 From 709168165f247a6901bf87cb2f1edd4f8acdf620 Mon Sep 17 00:00:00 2001 From: Future Date: Sun, 26 May 2024 12:14:34 +0200 Subject: [PATCH 2/5] t6: fix default value for dwcolumn --- src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp b/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp index df1b3314..729aac64 100644 --- a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp +++ b/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp @@ -58,7 +58,7 @@ namespace if (jColumn.dwColIndex) lbColumnDef.dwColIndex = jColumn.dwColIndex.value(); else - lbColumnDef.dwColIndex = 0; + lbColumnDef.dwColIndex = -1; if (jColumn.hidden) lbColumnDef.hidden = jColumn.hidden.value(); From 9367aa889bffeb92d1e8809f4bc997fd41c6e551 Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 1 Jun 2024 14:14:56 +0200 Subject: [PATCH 3/5] chore: load t6 leaderboard asset loader --- src/ObjLoading/Game/T6/ObjLoaderT6.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp index 2aab34df..99b60ca8 100644 --- a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp +++ b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp @@ -2,6 +2,7 @@ #include "AssetLoaders/AssetLoaderFontIcon.h" #include "AssetLoaders/AssetLoaderGfxImage.h" +#include "AssetLoaders/AssetLoaderLeaderboard.h" #include "AssetLoaders/AssetLoaderLocalizeEntry.h" #include "AssetLoaders/AssetLoaderMaterial.h" #include "AssetLoaders/AssetLoaderPhysConstraints.h" @@ -77,7 +78,7 @@ namespace T6 REGISTER_ASSET_LOADER(BasicAssetLoader) REGISTER_ASSET_LOADER(AssetLoaderRawFile) REGISTER_ASSET_LOADER(AssetLoaderStringTable) - REGISTER_ASSET_LOADER(BasicAssetLoader) + REGISTER_ASSET_LOADER(AssetLoaderLeaderboard) REGISTER_ASSET_LOADER(BasicAssetLoader) REGISTER_ASSET_LOADER(BasicAssetLoader) REGISTER_ASSET_LOADER(BasicAssetLoader) From 7c5795f5bcbe768802389ddba800f18510e4b6c2 Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 1 Jun 2024 14:23:23 +0200 Subject: [PATCH 4/5] chore: use std::optional value_or for t6 leaderboard reading --- .../Leaderboard/JsonLeaderboardDefLoader.cpp | 38 ++++--------------- 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp b/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp index 729aac64..84cbadfd 100644 --- a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp +++ b/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp @@ -55,15 +55,8 @@ namespace lbColumnDef.name = m_memory.Dup(jColumn.name.c_str()); lbColumnDef.colId = jColumn.colId; - if (jColumn.dwColIndex) - lbColumnDef.dwColIndex = jColumn.dwColIndex.value(); - else - lbColumnDef.dwColIndex = -1; - - if (jColumn.hidden) - lbColumnDef.hidden = jColumn.hidden.value(); - else - lbColumnDef.hidden = false; + lbColumnDef.dwColIndex = jColumn.dwColIndex.value_or(-1); + lbColumnDef.hidden = jColumn.hidden.value_or(false); if (jColumn.statName) lbColumnDef.statName = m_memory.Dup(jColumn.statName->c_str()); @@ -72,10 +65,7 @@ namespace lbColumnDef.type = jColumn.type; - if (jColumn.precision) - lbColumnDef.precision = jColumn.precision.value(); - else - lbColumnDef.precision = 0; + lbColumnDef.precision = jColumn.precision.value_or(0); lbColumnDef.agg = jColumn.aggregationFunction; @@ -84,15 +74,8 @@ namespace else lbColumnDef.localization = nullptr; - if (jColumn.uiCalColX) - lbColumnDef.uiCalColX = jColumn.uiCalColX.value(); - else - lbColumnDef.uiCalColX = 0; - - if (jColumn.uiCalColY) - lbColumnDef.uiCalColY = jColumn.uiCalColY.value(); - else - lbColumnDef.uiCalColY = 0; + lbColumnDef.uiCalColX = jColumn.uiCalColX.value_or(0); + lbColumnDef.uiCalColY = jColumn.uiCalColY.value_or(0); return true; } @@ -102,15 +85,8 @@ namespace leaderboardDef.id = jLeaderboardDef.id; leaderboardDef.dwColumnCount = jLeaderboardDef.dwColumnCount; - if (jLeaderboardDef.xpColId) - leaderboardDef.xpColId = jLeaderboardDef.xpColId.value(); - else - leaderboardDef.xpColId = -1; - - if (jLeaderboardDef.prestigeColId) - leaderboardDef.prestigeColId = jLeaderboardDef.prestigeColId.value(); - else - leaderboardDef.prestigeColId = -1; + leaderboardDef.xpColId = jLeaderboardDef.xpColId.value_or(-1); + leaderboardDef.prestigeColId = jLeaderboardDef.prestigeColId.value_or(-1); if (!jLeaderboardDef.columns.empty()) { From e68877464d75ab0cb4a2e3bef2009a8e553f89a4 Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 1 Jun 2024 14:23:33 +0200 Subject: [PATCH 5/5] fix: iw5 leaderboard track type reading --- .../Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp b/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp index 84cbadfd..9971a218 100644 --- a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp +++ b/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp @@ -42,10 +42,10 @@ namespace } private: - static bool CreateTrackTypeFlagsFromJson(const JsonLeaderboardDef& jLeaderboardDef, int& gameFlags) + static bool CreateTrackTypeFlagsFromJson(const JsonLeaderboardDef& jLeaderboardDef, int& trackTypeFlags) { - for (const auto gameFlag : jLeaderboardDef.trackTypes) - gameFlags |= gameFlag; + for (const auto trackType : jLeaderboardDef.trackTypes) + trackTypeFlags |= 1 << trackType; return true; }