diff --git a/dDatabase/CDClientDatabase/CDClientManager.cpp b/dDatabase/CDClientDatabase/CDClientManager.cpp index 7b46484a4..bf80fa1e2 100644 --- a/dDatabase/CDClientDatabase/CDClientManager.cpp +++ b/dDatabase/CDClientDatabase/CDClientManager.cpp @@ -33,6 +33,7 @@ #include "CDEventGatingTable.h" #include "CDScriptComponentTable.h" #include "CDSkillBehaviorTable.h" +#include "CDSceneTableTable.h" #include "CDZoneTableTable.h" #include "CDTamingBuildPuzzleTable.h" #include "CDVendorComponentTable.h" @@ -194,6 +195,7 @@ void CDClientManager::LoadValuesFromDatabase(const std::filesystem::path& fdbPat 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 56d057c10..a54891f71 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CMakeLists.txt +++ b/dDatabase/CDClientDatabase/CDClientTables/CMakeLists.txt @@ -39,6 +39,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 3b3b17854..5f8e91bd0 100644 --- a/dZoneManager/Zone.cpp +++ b/dZoneManager/Zone.cpp @@ -12,6 +12,7 @@ #include "AssetManager.h" #include "CDClientManager.h" +#include "CDSceneTableTable.h" #include "CDZoneTableTable.h" #include "CDClientDatabase.h" #include "Spawner.h" @@ -32,13 +33,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() { @@ -70,7 +64,11 @@ void Zone::LoadZoneIntoMemory() { ZoneFile zoneFile; zoneFile.Read(file); // The oldest files name their scenes by SceneTable ID - zoneFile.ResolveSceneTable(m_SceneTableLookup); + zoneFile.ResolveSceneTable([](uint32_t sceneTableID) -> std::optional { + const auto* sceneTableEntry = CDSceneTableTable::Query(sceneTableID); + if (!sceneTableEntry) return std::nullopt; + return sceneTableEntry->sceneName; + }); m_FileFormatVersion = zoneFile.fileFormatVersion; m_WorldID = zoneFile.worldID; if (static_cast(m_WorldID) != m_ZoneID.GetMapID()) LOG("WorldID: %i doesn't match MapID %i! Is this intended?", m_WorldID, m_ZoneID.GetMapID()); diff --git a/dZoneManager/Zone.h b/dZoneManager/Zone.h index 5904cfa6b..57836d0c6 100644 --- a/dZoneManager/Zone.h +++ b/dZoneManager/Zone.h @@ -7,8 +7,6 @@ #include "ZoneScenes.h" #include "tinyxml2.h" #include -#include -#include #include #include #include "Raw.h" @@ -43,10 +41,6 @@ public: const uint32_t GetChecksum() const { return m_CheckSum; } 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); } const std::vector& GetPaths() const { return m_Paths; } // A path that isn't in the zone's files (tests); earlier GetPath pointers may move void AddPath(Path path) { m_Paths.push_back(std::move(path)); } @@ -103,7 +97,6 @@ private: std::vector m_Paths; std::map m_MapRevisions; //rhs is the revision! - SceneTableLookup m_SceneTableLookup; //private ("helper") functions: void LoadScene(ZoneScene&& zoneScene); 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;