From 6b7396546ad51f3f8bcd5319484b4904b8a6c3e9 Mon Sep 17 00:00:00 2001 From: Aaron Kimbrell Date: Tue, 27 Oct 2026 09:53:13 -0500 Subject: [PATCH] refactor: look up the oldest zone files' scenes in a CDClient SceneTable table Zone held a std::function that queried the SceneTable, so tests could swap it out. CDSceneTableTable now loads the table with the others, and Zone looks scenes up in it; tests fill its entries like the zone table's. Co-Authored-By: Claude Opus 5.5 --- .../CDClientDatabase/CDClientManager.cpp | 2 ++ .../CDClientTables/CDSceneTableTable.cpp | 28 +++++++++++++++++++ .../CDClientTables/CDSceneTableTable.h | 17 +++++++++++ .../CDClientTables/CMakeLists.txt | 1 + dZoneManager/Zone.cpp | 17 ++++------- dZoneManager/Zone.h | 7 ----- .../ZoneFileVersionTests.cpp | 17 ++++++----- 7 files changed, 63 insertions(+), 26 deletions(-) create mode 100644 dDatabase/CDClientDatabase/CDClientTables/CDSceneTableTable.cpp create mode 100644 dDatabase/CDClientDatabase/CDClientTables/CDSceneTableTable.h diff --git a/dDatabase/CDClientDatabase/CDClientManager.cpp b/dDatabase/CDClientDatabase/CDClientManager.cpp index 9aea07110..3fb8331d6 100644 --- a/dDatabase/CDClientDatabase/CDClientManager.cpp +++ b/dDatabase/CDClientDatabase/CDClientManager.cpp @@ -24,6 +24,7 @@ #include "CDRebuildComponentTable.h" #include "CDScriptComponentTable.h" #include "CDSkillBehaviorTable.h" +#include "CDSceneTableTable.h" #include "CDZoneTableTable.h" #include "CDTamingBuildPuzzleTable.h" #include "CDVendorComponentTable.h" @@ -144,6 +145,7 @@ void CDClientManager::LoadValuesFromDatabase() { CDRebuildComponentTable::Instance().LoadValuesFromDatabase(); CDRewardCodesTable::Instance().LoadValuesFromDatabase(); CDRewardsTable::Instance().LoadValuesFromDatabase(); + CDSceneTableTable::LoadValuesFromDatabase(); CDScriptComponentTable::Instance().LoadValuesFromDatabase(); CDSkillBehaviorTable::Instance().LoadValuesFromDatabase(); CDTamingBuildPuzzleTable::Instance().LoadValuesFromDatabase(); diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDSceneTableTable.cpp b/dDatabase/CDClientDatabase/CDClientTables/CDSceneTableTable.cpp new file mode 100644 index 000000000..db6777254 --- /dev/null +++ b/dDatabase/CDClientDatabase/CDClientTables/CDSceneTableTable.cpp @@ -0,0 +1,28 @@ +#include "CDSceneTableTable.h" + +namespace CDSceneTableTable { + Table entries; + + void LoadValuesFromDatabase() { + // Get the data from the database + auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM SceneTable"); + while (!tableData.eof()) { + CDSceneTable entry; + entry.sceneID = tableData.getIntField("sceneID", -1); + entry.sceneName = tableData.getStringField("sceneName", ""); + + entries[entry.sceneID] = entry; + tableData.nextRow(); + } + } + + //! Queries the table with a sceneID to find. + const CDSceneTable* Query(uint32_t sceneID) { + const auto& iter = entries.find(sceneID); + if (iter != entries.end()) { + return &iter->second; + } + + return nullptr; + } +} diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDSceneTableTable.h b/dDatabase/CDClientDatabase/CDClientTables/CDSceneTableTable.h new file mode 100644 index 000000000..fd4b773d2 --- /dev/null +++ b/dDatabase/CDClientDatabase/CDClientTables/CDSceneTableTable.h @@ -0,0 +1,17 @@ +#pragma once + +// Custom Classes +#include "CDTable.h" + +struct CDSceneTable { + uint32_t sceneID; //!< The scene's ID, as zone files before version 30 list their scenes + std::string sceneName; //!< The scene's file +}; + +namespace CDSceneTableTable { + using Table = std::map; + void LoadValuesFromDatabase(); + + // Queries the table with a sceneID to find. + const CDSceneTable* Query(uint32_t sceneID); +}; diff --git a/dDatabase/CDClientDatabase/CDClientTables/CMakeLists.txt b/dDatabase/CDClientDatabase/CDClientTables/CMakeLists.txt index 57731ad93..75f25d182 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CMakeLists.txt +++ b/dDatabase/CDClientDatabase/CDClientTables/CMakeLists.txt @@ -35,6 +35,7 @@ set(DDATABASE_CDCLIENTDATABASE_CDCLIENTTABLES_SOURCES "CDActivitiesTable.cpp" "CDRebuildComponentTable.cpp" "CDRewardCodesTable.cpp" "CDRewardsTable.cpp" + "CDSceneTableTable.cpp" "CDScriptComponentTable.cpp" "CDSkillBehaviorTable.cpp" "CDTamingBuildPuzzleTable.cpp" diff --git a/dZoneManager/Zone.cpp b/dZoneManager/Zone.cpp index 794053d24..785008614 100644 --- a/dZoneManager/Zone.cpp +++ b/dZoneManager/Zone.cpp @@ -11,8 +11,8 @@ #include "dConfig.h" #include "AssetManager.h" -#include "CDClientDatabase.h" #include "CDClientManager.h" +#include "CDSceneTableTable.h" #include "CDZoneTableTable.h" #include "Spawner.h" #include "dZoneManager.h" @@ -31,13 +31,6 @@ Zone::Zone(const LWOZONEID zoneID) : m_CheckSum = 0; m_WorldID = 0; m_SceneCount = 0; - m_SceneTableLookup = [](uint32_t sceneTableID) -> std::optional { - auto query = CDClientDatabase::CreatePreppedStmt("SELECT sceneName FROM SceneTable WHERE sceneID = ?;"); - query.bind(1, static_cast(sceneTableID)); - auto result = query.execQuery(); - if (result.eof() || result.fieldIsNull("sceneName")) return std::nullopt; - return std::string(result.getStringField("sceneName")); - }; } Zone::~Zone() { @@ -332,11 +325,11 @@ void Zone::KeepLoadedScenes() { std::map resolved; uint32_t index = 0; for (auto& scene : m_Scenes | std::views::values) { - const auto sceneName = m_SceneTableLookup(scene.sceneTableID); - if (!sceneName) continue; + const auto* sceneTableEntry = CDSceneTableTable::Query(scene.sceneTableID); + if (!sceneTableEntry) continue; scene.id = index < 256 ? index : UINT32_MAX; - scene.filename = *sceneName; - scene.name = *sceneName; + scene.filename = sceneTableEntry->sceneName; + scene.name = sceneTableEntry->sceneName; const std::string luTriggersPath = scene.filename.substr(0, scene.filename.size() - 4) + ".lutriggers"; if (Game::assetManager->HasFile((m_ZonePath + luTriggersPath).c_str())) LoadLUTriggers(luTriggersPath, scene); resolved[LWOSCENEID(scene.id, 0)] = std::move(scene); diff --git a/dZoneManager/Zone.h b/dZoneManager/Zone.h index 7a0613b6f..6db15f3a3 100644 --- a/dZoneManager/Zone.h +++ b/dZoneManager/Zone.h @@ -7,8 +7,6 @@ #include #include #include -#include -#include #include "Raw.h" namespace LUTriggers { @@ -235,10 +233,6 @@ public: LUTriggers::Trigger* GetTrigger(uint32_t sceneID, uint32_t triggerID) const; const Path* GetPath(std::string name) const; - // The CDClient SceneTable's sceneName for a scene of a file from before PrePreAlpha; the database's by default - using SceneTableLookup = std::function(uint32_t sceneTableID)>; - void SetSceneTableLookup(SceneTableLookup lookup) { m_SceneTableLookup = std::move(lookup); } - uint32_t GetWorldID() const { return m_WorldID; } [[nodiscard]] std::string GetZoneName() const { return m_ZoneName; } std::string GetZoneRawPath() const { return m_ZoneRawPath; } @@ -284,7 +278,6 @@ private: std::map m_MapRevisions; //rhs is the revision! //private ("helper") functions: - SceneTableLookup m_SceneTableLookup; void LoadScene(std::istream& file, uint32_t index); void KeepLoadedScenes(); void LoadLUTriggers(std::string triggerFile, SceneRef& scene); diff --git a/tests/dGameTests/dZoneManagerTests/ZoneFileVersionTests.cpp b/tests/dGameTests/dZoneManagerTests/ZoneFileVersionTests.cpp index faa58bb5a..27402df6a 100644 --- a/tests/dGameTests/dZoneManagerTests/ZoneFileVersionTests.cpp +++ b/tests/dGameTests/dZoneManagerTests/ZoneFileVersionTests.cpp @@ -5,6 +5,7 @@ #include #include "AssetManager.h" +#include "CDSceneTableTable.h" #include "CDZoneTableTable.h" #include "Zone.h" #include "dZoneManager.h" @@ -14,6 +15,11 @@ namespace CDZoneTableTable { extern Table entries; } +// The scene table's storage (CDSceneTableTable.cpp), to add the scenes of the oldest zone files +namespace CDSceneTableTable { + extern Table entries; +} + namespace { template void Write(std::ostream& stream, const T& value) { @@ -93,11 +99,10 @@ protected: TearDownDependencies(); } - Zone* LoadZone(const std::string& data, Zone::SceneTableLookup lookup = nullptr) const { + Zone* LoadZone(const std::string& data) const { std::ofstream(root / "res" / "maps" / "testzone" / "test.luz", std::ios::binary).write(data.data(), data.size()); Game::zoneManager->LoadZone(LWOZONEID(TEST_MAP, 0, 0)); Zone* zone = Game::zoneManager->GetZoneMut(); - if (lookup) zone->SetSceneTableLookup(std::move(lookup)); zone->LoadZoneIntoMemory(); return zone; } @@ -144,11 +149,9 @@ TEST_F(ZoneFileVersionTest, OldestScenesComeFromTheSceneTable) { Write(stream, 0); // boundary lines WriteString8(stream, "test.raw"); Write(stream, 0); // trailing bytes: older readers read a name and description here - const Zone* zone = LoadZone(stream.str(), [](uint32_t sceneTableID) -> std::optional { - if (sceneTableID == 3) return "three.lvl"; - if (sceneTableID == 7) return "seven.lvl"; - return std::nullopt; - }); + CDSceneTableTable::entries = { { 3, { 3, "three.lvl" } }, { 7, { 7, "seven.lvl" } } }; + const Zone* zone = LoadZone(stream.str()); + CDSceneTableTable::entries.clear(); const std::vector> expected = { { LWOSCENEID(0, 0), "three.lvl" }, { LWOSCENEID(1, 0), "seven.lvl" } }; EXPECT_EQ(Scenes(zone), expected) << version;