From d3b594145839ec2b542af5f495dd95e42fd3cc84 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Sep 2025 15:22:58 +0000 Subject: [PATCH] Fix CDClient database dependency issues for component tests by implementing LoadValuesFromDefaults and database connectivity checks Co-authored-by: aronwk-aaron <26027722+aronwk-aaron@users.noreply.github.com> --- .../CDClientDatabase/CDClientManager.cpp | 7 +++ .../CDComponentsRegistryTable.cpp | 20 ++++++ .../CDComponentsRegistryTable.h | 1 + .../CDClientTables/CDItemComponentTable.cpp | 56 +++++++++++++++++ .../CDClientTables/CDItemComponentTable.h | 1 + .../CDClientTables/CDLootMatrixTable.cpp | 22 +++++++ .../CDClientTables/CDLootMatrixTable.h | 1 + .../CDClientTables/CDLootTableTable.cpp | 20 ++++++ .../CDClientTables/CDLootTableTable.h | 1 + .../CDClientTables/CDMissionsTable.cpp | 61 +++++++++++++++++++ .../CDClientTables/CDMissionsTable.h | 1 + .../CDClientTables/CDSkillBehaviorTable.cpp | 16 +++++ .../CDClientTables/CDSkillBehaviorTable.h | 1 + .../CDClientTables/CDVendorComponentTable.cpp | 16 +++++ .../CDClientTables/CDVendorComponentTable.h | 1 + dGame/dComponents/BaseCombatAIComponent.cpp | 29 +++++---- dGame/dComponents/BuffComponent.cpp | 6 ++ 17 files changed, 247 insertions(+), 13 deletions(-) diff --git a/dDatabase/CDClientDatabase/CDClientManager.cpp b/dDatabase/CDClientDatabase/CDClientManager.cpp index d76e89d2..551dfb51 100644 --- a/dDatabase/CDClientDatabase/CDClientManager.cpp +++ b/dDatabase/CDClientDatabase/CDClientManager.cpp @@ -161,4 +161,11 @@ void CDClientManager::LoadValuesFromDefaults() { CDActivitiesTable::Instance().LoadValuesFromDefaults(); CDActivityRewardsTable::Instance().LoadValuesFromDefaults(); CDCurrencyTableTable::Instance().LoadValuesFromDefaults(); + CDMissionsTable::Instance().LoadValuesFromDefaults(); + CDComponentsRegistryTable::Instance().LoadValuesFromDefaults(); + CDItemComponentTable::Instance().LoadValuesFromDefaults(); + CDSkillBehaviorTable::Instance().LoadValuesFromDefaults(); + CDVendorComponentTable::Instance().LoadValuesFromDefaults(); + CDLootMatrixTable::Instance().LoadValuesFromDefaults(); + CDLootTableTable::Instance().LoadValuesFromDefaults(); } diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDComponentsRegistryTable.cpp b/dDatabase/CDClientDatabase/CDClientTables/CDComponentsRegistryTable.cpp index 4944c13b..33cbf73d 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDComponentsRegistryTable.cpp +++ b/dDatabase/CDClientDatabase/CDClientTables/CDComponentsRegistryTable.cpp @@ -20,6 +20,20 @@ void CDComponentsRegistryTable::LoadValuesFromDatabase() { tableData.finalize(); } +void CDComponentsRegistryTable::LoadValuesFromDefaults() { + auto& entries = GetEntriesMutable(); + entries.clear(); + + // Add some default component registrations for common LOTs + // Component type ITEM (LOT 1000) + entries.insert_or_assign(static_cast(eReplicaComponentType::ITEM) << 32 | static_cast(1000), 1); + entries.insert_or_assign(1000, 0); + + // Component type VENDOR (LOT 2000) + entries.insert_or_assign(static_cast(eReplicaComponentType::VENDOR) << 32 | static_cast(2000), 1); + entries.insert_or_assign(2000, 0); +} + int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) { auto& entries = GetEntriesMutable(); auto exists = entries.find(id); @@ -28,6 +42,12 @@ int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponent return iter == entries.end() ? defaultValue : iter->second; } + // If database is not connected (e.g., in tests), return default value + if (!CDClientDatabase::isConnected) { + entries.insert_or_assign(id, 0); + return defaultValue; + } + // Now get the data. Get all components of this entity so we dont do a query for each component auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM ComponentsRegistry WHERE id = ?;"); query.bind(1, static_cast(id)); diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDComponentsRegistryTable.h b/dDatabase/CDClientDatabase/CDClientTables/CDComponentsRegistryTable.h index 2165f907..b943be96 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDComponentsRegistryTable.h +++ b/dDatabase/CDClientDatabase/CDClientTables/CDComponentsRegistryTable.h @@ -16,5 +16,6 @@ struct CDComponentsRegistry { class CDComponentsRegistryTable : public CDTable> { public: void LoadValuesFromDatabase(); + void LoadValuesFromDefaults(); int32_t GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue = 0); }; diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDItemComponentTable.cpp b/dDatabase/CDClientDatabase/CDClientTables/CDItemComponentTable.cpp index 0d8b1ad9..7054c1a8 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDItemComponentTable.cpp +++ b/dDatabase/CDClientDatabase/CDClientTables/CDItemComponentTable.cpp @@ -70,6 +70,56 @@ void CDItemComponentTable::LoadValuesFromDatabase() { tableData.finalize(); } +void CDItemComponentTable::LoadValuesFromDefaults() { + auto& entries = GetEntriesMutable(); + entries.clear(); + + // Add default item component entry + CDItemComponent defaultEntry{ + .id = 1, + .equipLocation = "", + .baseValue = 0, + .isKitPiece = false, + .rarity = 0, + .itemType = 0, + .itemInfo = 0, + .inLootTable = false, + .inVendor = false, + .isUnique = false, + .isBOP = false, + .isBOE = false, + .reqFlagID = 0, + .reqSpecialtyID = 0, + .reqSpecRank = 0, + .reqAchievementID = 0, + .stackSize = 1, + .color1 = 0, + .decal = 0, + .offsetGroupID = 0, + .buildTypes = 0, + .reqPrecondition = "", + .animationFlag = 0, + .equipEffects = 0, + .readyForQA = false, + .itemRating = 0, + .isTwoHanded = false, + .minNumRequired = 0, + .delResIndex = 0, + .currencyLOT = 0, + .altCurrencyCost = 0, + .subItems = "", + .noEquipAnimation = false, + .commendationLOT = 0, + .commendationCost = 0, + .currencyCosts = "", + .locStatus = 0, + .forgeType = 0, + .SellMultiplier = 1.0f, + }; + + entries.insert(std::make_pair(defaultEntry.id, defaultEntry)); +} + const CDItemComponent& CDItemComponentTable::GetItemComponentByID(uint32_t skillID) { auto& entries = GetEntriesMutable(); const auto& it = entries.find(skillID); @@ -77,6 +127,12 @@ const CDItemComponent& CDItemComponentTable::GetItemComponentByID(uint32_t skill return it->second; } + // If database is not connected (e.g., in tests), return the default entry + if (!CDClientDatabase::isConnected) { + entries.insert(std::make_pair(skillID, Default)); + return Default; + } + auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM ItemComponent WHERE id = ?;"); query.bind(1, static_cast(skillID)); diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDItemComponentTable.h b/dDatabase/CDClientDatabase/CDClientTables/CDItemComponentTable.h index 60a3e412..d5cc0f34 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDItemComponentTable.h +++ b/dDatabase/CDClientDatabase/CDClientTables/CDItemComponentTable.h @@ -52,6 +52,7 @@ struct CDItemComponent { class CDItemComponentTable : public CDTable> { public: void LoadValuesFromDatabase(); + void LoadValuesFromDefaults(); static std::map ParseCraftingCurrencies(const CDItemComponent& itemComponent); // Gets an entry by ID diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDLootMatrixTable.cpp b/dDatabase/CDClientDatabase/CDClientTables/CDLootMatrixTable.cpp index cd8ae5c4..d88d5e87 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDLootMatrixTable.cpp +++ b/dDatabase/CDClientDatabase/CDClientTables/CDLootMatrixTable.cpp @@ -39,6 +39,23 @@ void CDLootMatrixTable::LoadValuesFromDatabase() { } } +void CDLootMatrixTable::LoadValuesFromDefaults() { + auto& entries = GetEntriesMutable(); + entries.clear(); + + // Add default loot matrix entry + CDLootMatrix defaultEntry{ + .LootTableIndex = 1, + .RarityTableIndex = 1, + .percent = 1.0f, + .minToDrop = 1, + .maxToDrop = 1, + .flagID = 0, + }; + + entries[0].push_back(defaultEntry); +} + const LootMatrixEntries& CDLootMatrixTable::GetMatrix(uint32_t matrixId) { auto& entries = GetEntriesMutable(); auto itr = entries.find(matrixId); @@ -46,6 +63,11 @@ const LootMatrixEntries& CDLootMatrixTable::GetMatrix(uint32_t matrixId) { return itr->second; } + // If database is not connected (e.g., in tests), return empty vector + if (!CDClientDatabase::isConnected) { + return entries[matrixId]; // Creates empty vector + } + auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM LootMatrix where LootMatrixIndex = ?;"); query.bind(1, static_cast(matrixId)); diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDLootMatrixTable.h b/dDatabase/CDClientDatabase/CDClientTables/CDLootMatrixTable.h index b0ce7e0f..80029188 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDLootMatrixTable.h +++ b/dDatabase/CDClientDatabase/CDClientTables/CDLootMatrixTable.h @@ -19,6 +19,7 @@ typedef std::vector LootMatrixEntries; class CDLootMatrixTable : public CDTable> { public: void LoadValuesFromDatabase(); + void LoadValuesFromDefaults(); // Gets a matrix by ID or inserts a blank one if none existed. const LootMatrixEntries& GetMatrix(uint32_t matrixId); diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDLootTableTable.cpp b/dDatabase/CDClientDatabase/CDClientTables/CDLootTableTable.cpp index 0781897f..191fea68 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDLootTableTable.cpp +++ b/dDatabase/CDClientDatabase/CDClientTables/CDLootTableTable.cpp @@ -66,6 +66,21 @@ void CDLootTableTable::LoadValuesFromDatabase() { } } +void CDLootTableTable::LoadValuesFromDefaults() { + auto& entries = GetEntriesMutable(); + entries.clear(); + + // Add default loot table entry + CDLootTable defaultEntry{ + .itemid = 1000, + .LootTableIndex = 1, + .MissionDrop = false, + .sortPriority = 1, + }; + + entries[1].push_back(defaultEntry); +} + const LootTableEntries& CDLootTableTable::GetTable(const uint32_t tableId) { auto& entries = GetEntriesMutable(); auto itr = entries.find(tableId); @@ -73,6 +88,11 @@ const LootTableEntries& CDLootTableTable::GetTable(const uint32_t tableId) { return itr->second; } + // If database is not connected (e.g., in tests), return empty vector + if (!CDClientDatabase::isConnected) { + return entries[tableId]; // Creates empty vector + } + auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM LootTable WHERE LootTableIndex = ?;"); query.bind(1, static_cast(tableId)); auto tableData = query.execQuery(); diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDLootTableTable.h b/dDatabase/CDClientDatabase/CDClientTables/CDLootTableTable.h index c88ba03c..c743c083 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDLootTableTable.h +++ b/dDatabase/CDClientDatabase/CDClientTables/CDLootTableTable.h @@ -21,6 +21,7 @@ private: public: void LoadValuesFromDatabase(); + void LoadValuesFromDefaults(); // Queries the table with a custom "where" clause const LootTableEntries& GetTable(const uint32_t tableId); }; diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.cpp b/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.cpp index c98254ea..5e97613d 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.cpp +++ b/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.cpp @@ -83,6 +83,67 @@ void CDMissionsTable::LoadValuesFromDatabase() { Default.id = -1; } +void CDMissionsTable::LoadValuesFromDefaults() { + auto& entries = GetEntriesMutable(); + entries.clear(); + + // Add default mission entry + CDMissions defaultEntry{ + .id = 1, + .defined_type = "Mission", + .defined_subtype = "", + .UISortOrder = 0, + .offer_objectID = -1, + .target_objectID = -1, + .reward_currency = 0, + .LegoScore = 0, + .reward_reputation = 0, + .isChoiceReward = false, + .reward_item1 = 0, + .reward_item1_count = 0, + .reward_item2 = 0, + .reward_item2_count = 0, + .reward_item3 = 0, + .reward_item3_count = 0, + .reward_item4 = 0, + .reward_item4_count = 0, + .reward_emote = -1, + .reward_emote2 = -1, + .reward_emote3 = -1, + .reward_emote4 = -1, + .reward_maximagination = -1, + .reward_maxhealth = -1, + .reward_maxinventory = -1, + .reward_maxmodel = -1, + .reward_maxwidget = -1, + .reward_maxwallet = -1, + .repeatable = false, + .reward_currency_repeatable = 0, + .reward_item1_repeatable = 0, + .reward_item1_repeat_count = 0, + .reward_item2_repeatable = 0, + .reward_item2_repeat_count = 0, + .reward_item3_repeatable = 0, + .reward_item3_repeat_count = 0, + .reward_item4_repeatable = 0, + .reward_item4_repeat_count = 0, + .time_limit = -1, + .isMission = true, + .missionIconID = -1, + .prereqMissionID = "", + .localize = false, + .inMOTD = false, + .cooldownTime = -1, + .isRandom = false, + .randomPool = "", + .UIPrereqID = -1, + .reward_bankinventory = -1, + }; + + entries.push_back(defaultEntry); + Default.id = -1; +} + std::vector CDMissionsTable::Query(std::function predicate) { std::vector data = cpplinq::from(GetEntries()) diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.h b/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.h index c5ae0e88..4cfdd6a9 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.h +++ b/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.h @@ -63,6 +63,7 @@ struct CDMissions { class CDMissionsTable : public CDTable> { public: void LoadValuesFromDatabase(); + void LoadValuesFromDefaults(); // Queries the table with a custom "where" clause std::vector Query(std::function predicate); diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDSkillBehaviorTable.cpp b/dDatabase/CDClientDatabase/CDClientTables/CDSkillBehaviorTable.cpp index 0df67884..d0dc730e 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDSkillBehaviorTable.cpp +++ b/dDatabase/CDClientDatabase/CDClientTables/CDSkillBehaviorTable.cpp @@ -50,6 +50,22 @@ void CDSkillBehaviorTable::LoadValuesFromDatabase() { tableData.finalize(); } +void CDSkillBehaviorTable::LoadValuesFromDefaults() { + auto& entries = GetEntriesMutable(); + entries.clear(); + + // Add default skill behavior entry + CDSkillBehavior defaultEntry{ + .skillID = 1, + .behaviorID = 1, + .imaginationcost = 0, + .cooldowngroup = 0, + .cooldown = 0.0f, + }; + + entries.insert(std::make_pair(defaultEntry.skillID, defaultEntry)); +} + const CDSkillBehavior& CDSkillBehaviorTable::GetSkillByID(uint32_t skillID) { auto& entries = GetEntries(); auto it = entries.find(skillID); diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDSkillBehaviorTable.h b/dDatabase/CDClientDatabase/CDClientTables/CDSkillBehaviorTable.h index 19225d19..c1d17c40 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDSkillBehaviorTable.h +++ b/dDatabase/CDClientDatabase/CDClientTables/CDSkillBehaviorTable.h @@ -28,6 +28,7 @@ struct CDSkillBehavior { class CDSkillBehaviorTable : public CDTable> { public: void LoadValuesFromDatabase(); + void LoadValuesFromDefaults(); // Gets an entry by skillID const CDSkillBehavior& GetSkillByID(uint32_t skillID); diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDVendorComponentTable.cpp b/dDatabase/CDClientDatabase/CDClientTables/CDVendorComponentTable.cpp index f639a7e3..424f605d 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDVendorComponentTable.cpp +++ b/dDatabase/CDClientDatabase/CDClientTables/CDVendorComponentTable.cpp @@ -34,6 +34,22 @@ void CDVendorComponentTable::LoadValuesFromDatabase() { tableData.finalize(); } +void CDVendorComponentTable::LoadValuesFromDefaults() { + auto& entries = GetEntriesMutable(); + entries.clear(); + + // Add default vendor component entry + CDVendorComponent defaultEntry{ + .id = 1, + .buyScalar = 1.0f, + .sellScalar = 1.0f, + .refreshTimeSeconds = 0.0f, + .LootMatrixIndex = 0, + }; + + entries.push_back(defaultEntry); +} + //! Queries the table with a custom "where" clause std::vector CDVendorComponentTable::Query(std::function predicate) { diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDVendorComponentTable.h b/dDatabase/CDClientDatabase/CDClientTables/CDVendorComponentTable.h index cbed2d13..c2eda560 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDVendorComponentTable.h +++ b/dDatabase/CDClientDatabase/CDClientTables/CDVendorComponentTable.h @@ -14,6 +14,7 @@ struct CDVendorComponent { class CDVendorComponentTable : public CDTable> { public: void LoadValuesFromDatabase(); + void LoadValuesFromDefaults(); // Queries the table with a custom "where" clause std::vector Query(std::function predicate); }; diff --git a/dGame/dComponents/BaseCombatAIComponent.cpp b/dGame/dComponents/BaseCombatAIComponent.cpp index fb0d69f2..41b2be58 100644 --- a/dGame/dComponents/BaseCombatAIComponent.cpp +++ b/dGame/dComponents/BaseCombatAIComponent.cpp @@ -68,28 +68,31 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id) /* * Find skills */ - auto skillQuery = CDClientDatabase::CreatePreppedStmt( - "SELECT skillID, cooldown, behaviorID FROM SkillBehavior WHERE skillID IN (SELECT skillID FROM ObjectSkills WHERE objectTemplate = ?);"); - skillQuery.bind(1, static_cast(parent->GetLOT())); + // Only execute skill query if database is connected + if (CDClientDatabase::isConnected) { + auto skillQuery = CDClientDatabase::CreatePreppedStmt( + "SELECT skillID, cooldown, behaviorID FROM SkillBehavior WHERE skillID IN (SELECT skillID FROM ObjectSkills WHERE objectTemplate = ?);"); + skillQuery.bind(1, static_cast(parent->GetLOT())); - auto result = skillQuery.execQuery(); + auto result = skillQuery.execQuery(); - while (!result.eof()) { - const auto skillId = static_cast(result.getIntField("skillID")); + while (!result.eof()) { + const auto skillId = static_cast(result.getIntField("skillID")); - const auto abilityCooldown = static_cast(result.getFloatField("cooldown")); + const auto abilityCooldown = static_cast(result.getFloatField("cooldown")); - const auto behaviorId = static_cast(result.getIntField("behaviorID")); + const auto behaviorId = static_cast(result.getIntField("behaviorID")); - auto* behavior = Behavior::CreateBehavior(behaviorId); + auto* behavior = Behavior::CreateBehavior(behaviorId); - std::stringstream behaviorQuery; + std::stringstream behaviorQuery; - AiSkillEntry entry = { skillId, 0, abilityCooldown, behavior }; + AiSkillEntry entry = { skillId, 0, abilityCooldown, behavior }; - m_SkillEntries.push_back(entry); + m_SkillEntries.push_back(entry); - result.nextRow(); + result.nextRow(); + } } Stun(1.0f); diff --git a/dGame/dComponents/BuffComponent.cpp b/dGame/dComponents/BuffComponent.cpp index 2c940647..a7062e3d 100644 --- a/dGame/dComponents/BuffComponent.cpp +++ b/dGame/dComponents/BuffComponent.cpp @@ -435,6 +435,12 @@ const std::vector& BuffComponent::GetBuffParameters(int32_t buffI return pair->second; } + // If database is not connected (e.g., in tests), return empty parameters + if (!CDClientDatabase::isConnected) { + m_Cache.insert_or_assign(buffId, std::vector{}); + return m_Cache.find(buffId)->second; + } + auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM BuffParameters WHERE BuffID = ?;"); query.bind(1, static_cast(buffId));