From 3de393250340ad27aa2dcac39afe9ed93c114959 Mon Sep 17 00:00:00 2001 From: TheMatt2 Date: Wed, 12 Jan 2022 22:48:27 -0500 Subject: [PATCH] Comply with Xiphoseer required changes. Remove the CDClientDatabase::ExecuteQueryWithArgs() function and replace it with CDClientDatabase::CreatePreppedStmt(). This prevents a developer from accidently using %s, or incorrectly passing std::string, and causing a silent error. --- dDatabase/CDClientDatabase.cpp | 5 + dDatabase/CDClientDatabase.h | 12 +- dDatabase/Tables/CDBehaviorParameterTable.cpp | 8 +- dGame/dBehaviors/Behavior.cpp | 52 +++-- dGame/dBehaviors/SwitchMultipleBehavior.cpp | 10 +- dGame/dComponents/BaseCombatAIComponent.cpp | 16 +- dGame/dComponents/BuffComponent.cpp | 8 +- dGame/dComponents/DestroyableComponent.cpp | 7 +- dGame/dComponents/InventoryComponent.cpp | 186 +++++++++--------- dGame/dComponents/MissionComponent.cpp | 7 +- dGame/dComponents/PetComponent.cpp | 8 +- .../PropertyManagementComponent.cpp | 16 +- dGame/dComponents/RenderComponent.cpp | 10 +- .../RocketLaunchpadControlComponent.cpp | 8 +- dGame/dComponents/SkillComponent.cpp | 15 +- dGame/dGameMessages/GameMessages.cpp | 8 +- dGame/dInventory/Item.cpp | 8 +- dGame/dInventory/ItemSet.cpp | 16 +- dGame/dUtilities/Preconditions.cpp | 8 +- dGame/dUtilities/SlashCommandHandler.cpp | 12 +- dWorldServer/WorldServer.cpp | 8 +- dZoneManager/dZoneManager.cpp | 8 +- 22 files changed, 247 insertions(+), 189 deletions(-) diff --git a/dDatabase/CDClientDatabase.cpp b/dDatabase/CDClientDatabase.cpp index d61d6fe7..d09b2daa 100644 --- a/dDatabase/CDClientDatabase.cpp +++ b/dDatabase/CDClientDatabase.cpp @@ -13,3 +13,8 @@ void CDClientDatabase::Connect(const std::string& filename) { CppSQLite3Query CDClientDatabase::ExecuteQuery(const std::string& query) { return conn->execQuery(query.c_str()); } + +//! Makes prepared statements +CppSQLite3Statement CDClientDatabase::CreatePreppedStmt(const std::string& query) { + return conn->compileStatement(query.c_str()); +} diff --git a/dDatabase/CDClientDatabase.h b/dDatabase/CDClientDatabase.h index 5028e0bd..91e9ee10 100644 --- a/dDatabase/CDClientDatabase.h +++ b/dDatabase/CDClientDatabase.h @@ -43,15 +43,7 @@ namespace CDClientDatabase { //! Queries the CDClient and parses arguments /*! \param query The query with formatted arguments - \return the results of the query + \return prepared SQLite Statement */ - // Due to the template, implementation must be in the header. - template - CppSQLite3Query ExecuteQueryWithArgs(const std::string& query, Args... args) { - CppSQLite3Buffer sqlBuf; - sqlBuf.format(query.c_str(), args...); - - std::string safe_query = (const char *) sqlBuf; - return ExecuteQuery(safe_query); - } + CppSQLite3Statement CreatePreppedStmt(const std::string& query); }; diff --git a/dDatabase/Tables/CDBehaviorParameterTable.cpp b/dDatabase/Tables/CDBehaviorParameterTable.cpp index 2a1554cb..3087ba6d 100644 --- a/dDatabase/Tables/CDBehaviorParameterTable.cpp +++ b/dDatabase/Tables/CDBehaviorParameterTable.cpp @@ -59,9 +59,11 @@ float CDBehaviorParameterTable::GetEntry(const uint32_t behaviorID, const std::s } #ifndef CDCLIENT_CACHE_ALL - auto tableData = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT parameterID, value FROM BehaviorParameter WHERE behaviorID = %u;", - behaviorID); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT parameterID, value FROM BehaviorParameter WHERE behaviorID = ?;"); + query.bind(1, (int) behaviorID); + + auto tableData = query.execQuery(); m_Entries.insert_or_assign(behaviorID, 0); diff --git a/dGame/dBehaviors/Behavior.cpp b/dGame/dBehaviors/Behavior.cpp index 2e3290f7..351a4ada 100644 --- a/dGame/dBehaviors/Behavior.cpp +++ b/dGame/dBehaviors/Behavior.cpp @@ -276,9 +276,11 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) } BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId) { - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT templateID FROM BehaviorTemplate WHERE behaviorID = %u;", - behaviorId); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT templateID FROM BehaviorTemplate WHERE behaviorID = ?;"); + query.bind(1, (int) behaviorId); + + auto result = query.execQuery(); // Make sure we do not proceed if we are trying to load an invalid behavior if (result.eof()) @@ -349,18 +351,24 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID } } + // The SQlite result object becomes invalid if the query object leaves scope. + // So both queries are defined before the if statement CppSQLite3Query result; - if (!type.empty()) - { - result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT effectName FROM BehaviorEffect WHERE effectType = %Q AND effectID = %u;", - typeString.c_str(), effectId); - } - else - { - result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT effectName, effectType FROM BehaviorEffect WHERE effectID = %u;", - effectId); + auto typeQuery = CDClientDatabase::CreatePreppedStmt( + "SELECT effectName FROM BehaviorEffect WHERE effectType = ? AND effectID = ?;"); + + auto idQuery = CDClientDatabase::CreatePreppedStmt( + "SELECT effectName, effectType FROM BehaviorEffect WHERE effectID = ?;"); + + if (!type.empty()) { + typeQuery.bind(1, typeString.c_str()); + typeQuery.bind(2, (int) effectId); + + result = typeQuery.execQuery(); + } else { + idQuery.bind(1, (int) effectId); + + result = idQuery.execQuery(); } if (result.eof() || result.fieldIsNull(0)) @@ -406,9 +414,11 @@ Behavior::Behavior(const uint32_t behaviorId) this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY; } - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT templateID, effectID, effectHandle FROM BehaviorTemplate WHERE behaviorID = %u;", - behaviorId); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT templateID, effectID, effectHandle FROM BehaviorTemplate WHERE behaviorID = ?;"); + query.bind(1, (int) behaviorId); + + auto result = query.execQuery(); // Make sure we do not proceed if we are trying to load an invalid behavior if (result.eof()) @@ -481,9 +491,11 @@ std::map Behavior::GetParameterNames() const { std::map parameters; - auto tableData = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT parameterID, value FROM BehaviorParameter WHERE behaviorID = %u;", - this->m_behaviorId); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT parameterID, value FROM BehaviorParameter WHERE behaviorID = ?;"); + query.bind(1, (int) this->m_behaviorId); + + auto tableData = query.execQuery(); while (!tableData.eof()) { diff --git a/dGame/dBehaviors/SwitchMultipleBehavior.cpp b/dGame/dBehaviors/SwitchMultipleBehavior.cpp index 062ae9f0..93662060 100644 --- a/dGame/dBehaviors/SwitchMultipleBehavior.cpp +++ b/dGame/dBehaviors/SwitchMultipleBehavior.cpp @@ -40,12 +40,14 @@ void SwitchMultipleBehavior::Calculate(BehaviorContext* context, RakNet::BitStre } void SwitchMultipleBehavior::Load() { - auto result = CDClientDatabase::ExecuteQueryWithArgs( + auto query = CDClientDatabase::CreatePreppedStmt( "SELECT replace(bP1.parameterID, 'behavior ', '') as key, bP1.value as behavior, " - "(select bP2.value FROM BehaviorParameter bP2 WHERE bP2.behaviorID = %u AND bP2.parameterID LIKE 'value %' " + "(select bP2.value FROM BehaviorParameter bP2 WHERE bP2.behaviorID = ?1 AND bP2.parameterID LIKE 'value %' " "AND replace(bP1.parameterID, 'behavior ', '') = replace(bP2.parameterID, 'value ', '')) as value " - "FROM BehaviorParameter bP1 WHERE bP1.behaviorID = %u AND bP1.parameterID LIKE 'behavior %';", - this->m_behaviorId, this->m_behaviorId); + "FROM BehaviorParameter bP1 WHERE bP1.behaviorID = ?1 AND bP1.parameterID LIKE 'behavior %';"); + query.bind(1, (int) this->m_behaviorId); + + auto result = query.execQuery(); while (!result.eof()) { const auto behavior_id = static_cast(result.getFloatField(1)); diff --git a/dGame/dComponents/BaseCombatAIComponent.cpp b/dGame/dComponents/BaseCombatAIComponent.cpp index 994f49c4..4d82036f 100644 --- a/dGame/dComponents/BaseCombatAIComponent.cpp +++ b/dGame/dComponents/BaseCombatAIComponent.cpp @@ -35,9 +35,11 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id) m_SoftTimer = 5.0f; //Grab the aggro information from BaseCombatAI: - auto componentResult = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT aggroRadius, tetherSpeed, pursuitSpeed, softTetherRadius, hardTetherRadius FROM BaseCombatAIComponent WHERE id = %u;", - id); + auto componentQuery = CDClientDatabase::CreatePreppedStmt( + "SELECT aggroRadius, tetherSpeed, pursuitSpeed, softTetherRadius, hardTetherRadius FROM BaseCombatAIComponent WHERE id = ?;"); + componentQuery.bind(1, (int) id); + + auto componentResult = componentQuery.execQuery(); if (!componentResult.eof()) { @@ -62,9 +64,11 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id) /* * Find skills */ - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT skillID, cooldown, behaviorID FROM SkillBehavior WHERE skillID IN (SELECT skillID FROM ObjectSkills WHERE objectTemplate = %d);", - parent->GetLOT()); + auto skillQuery = CDClientDatabase::CreatePreppedStmt( + "SELECT skillID, cooldown, behaviorID FROM SkillBehavior WHERE skillID IN (SELECT skillID FROM ObjectSkills WHERE objectTemplate = ?);"); + skillQuery.bind(1, (int) parent->GetLOT()); + + auto result = skillQuery.execQuery(); while (!result.eof()) { const auto skillId = static_cast(result.getIntField(0)); diff --git a/dGame/dComponents/BuffComponent.cpp b/dGame/dComponents/BuffComponent.cpp index afa5b321..9c12e87d 100644 --- a/dGame/dComponents/BuffComponent.cpp +++ b/dGame/dComponents/BuffComponent.cpp @@ -371,10 +371,12 @@ const std::vector& BuffComponent::GetBuffParameters(int32_t buffI return pair->second; } - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT * FROM BuffParameters WHERE BuffID = %d;", - buffId); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT * FROM BuffParameters WHERE BuffID = ?;"); + query.bind(1, (int) buffId); + auto result = query.execQuery(); + std::vector parameters {}; while (!result.eof()) diff --git a/dGame/dComponents/DestroyableComponent.cpp b/dGame/dComponents/DestroyableComponent.cpp index 91ff8b6e..1afd4b58 100644 --- a/dGame/dComponents/DestroyableComponent.cpp +++ b/dGame/dComponents/DestroyableComponent.cpp @@ -373,8 +373,11 @@ void DestroyableComponent::AddFaction(const int32_t factionID, const bool ignore m_FactionIDs.push_back(factionID); m_DirtyHealth = true; - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT enemyList FROM Factions WHERE faction = %d;", factionID); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT enemyList FROM Factions WHERE faction = ?;"); + query.bind(1, (int) factionID); + + auto result = query.execQuery(); if (result.eof()) return; diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 1f9b4cc6..bedb912d 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -50,18 +50,18 @@ InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* do auto items = inventoryComponentTable->Query([=](const CDInventoryComponent entry) { return entry.id == componentId; }); auto slot = 0u; - + for (const auto& item : items) { if (!item.equip || !Inventory::IsValidItem(item.itemid)) { continue; } - + const LWOOBJID id = ObjectIDManager::Instance()->GenerateObjectID(); const auto& info = Inventory::FindItemComponent(item.itemid); - + UpdateSlot(info.equipLocation, { id, static_cast(item.itemid), item.count, slot++ }); } } @@ -86,7 +86,7 @@ Inventory* InventoryComponent::GetInventory(const eInventoryType type) case eInventoryType::VAULT_ITEMS: size = 40u; break; - + default: break; } @@ -173,7 +173,7 @@ void InventoryComponent::AddItem( auto* missions = static_cast(this->m_Parent->GetComponent(COMPONENT_TYPE_MISSION)); auto* inventory = GetInventory(inventoryType); - + if (!config.empty() || bound) { const auto slot = inventory->FindEmptySlot(); @@ -184,7 +184,7 @@ void InventoryComponent::AddItem( return; } - + auto* item = new Item(lot, inventory, slot, count, config, parent, showFlyingLoot, isModMoveAndEquip, subKey, bound); if (missions != nullptr && !IsTransferInventory(inventoryType)) @@ -196,7 +196,7 @@ void InventoryComponent::AddItem( } const auto info = Inventory::FindItemComponent(lot); - + auto left = count; int32_t outOfSpace = 0; @@ -211,7 +211,7 @@ void InventoryComponent::AddItem( { stack = 1; } - + auto* existing = FindItemByLot(lot, inventoryType); if (existing != nullptr) @@ -235,7 +235,7 @@ void InventoryComponent::AddItem( const auto size = std::min(left, stack); left -= size; - + int32_t slot; if (preferredSlot != -1 && inventory->IsSlotEmpty(preferredSlot)) @@ -248,7 +248,7 @@ void InventoryComponent::AddItem( { slot = inventory->FindEmptySlot(); } - + if (slot == -1) { auto* player = dynamic_cast(GetParent()); @@ -271,9 +271,9 @@ void InventoryComponent::AddItem( { GameMessages::SendDropClientLoot(this->m_Parent, this->m_Parent->GetObjectID(), lot, 0, this->m_Parent->GetPosition(), 1); } - + break; - + default: break; } @@ -323,7 +323,7 @@ void InventoryComponent::RemoveItem(const LOT lot, const uint32_t count, eInvent { break; } - + const auto delta = std::min(left, item->GetCount()); item->SetCount(item->GetCount() - delta); @@ -338,11 +338,11 @@ void InventoryComponent::MoveItemToInventory(Item* item, const eInventoryType in { return; } - + auto* origin = item->GetInventory(); - + const auto lot = item->GetLot(); - + if (item->GetConfig().empty() && !item->GetBound() || (item->GetBound() && item->GetInfo().isBOP)) { auto left = std::min(count, origin->GetLotCount(lot)); @@ -380,7 +380,7 @@ void InventoryComponent::MoveItemToInventory(Item* item, const eInventoryType in { config.push_back(data->Copy()); } - + const auto delta = std::min(item->GetCount(), count); AddItem(lot, delta, inventory, config, LWOOBJID_EMPTY, showFlyingLot, isModMoveAndEquip, LWOOBJID_EMPTY, origin->GetType(), 0, item->GetBound(), preferredSlot); @@ -438,7 +438,7 @@ Item* InventoryComponent::FindItemByLot(const LOT lot, eInventoryType inventoryT return inventory->FindItemByLot(lot, ignoreEquipped, ignoreBound); } -Item* InventoryComponent::FindItemBySubKey(LWOOBJID id, eInventoryType inventoryType) +Item* InventoryComponent::FindItemBySubKey(LWOOBJID id, eInventoryType inventoryType) { if (inventoryType == INVALID) { @@ -597,7 +597,7 @@ void InventoryComponent::LoadXml(tinyxml2::XMLDocument* document) unsigned int count; bool bound; LWOOBJID subKey = LWOOBJID_EMPTY; - + itemElement->QueryAttribute("id", &id); itemElement->QueryAttribute("l", &lot); itemElement->QueryAttribute("eq", &equipped); @@ -608,23 +608,23 @@ void InventoryComponent::LoadXml(tinyxml2::XMLDocument* document) // Begin custom xml auto parent = LWOOBJID_EMPTY; - + itemElement->QueryAttribute("parent", &parent); // End custom xml std::vector config; auto* extraInfo = itemElement->FirstChildElement("x"); - + if (extraInfo) { std::string modInfo = extraInfo->Attribute("ma"); - + LDFBaseData* moduleAssembly = new LDFData(u"assemblyPartLOTs", GeneralUtils::ASCIIToUTF16(modInfo.substr(2, modInfo.size() - 1))); - + config.push_back(moduleAssembly); } - + const auto* item = new Item(id, lot, inventory, slot, count, bound, config, parent, subKey); if (equipped) @@ -702,7 +702,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) bags->LinkEndChild(bag); } - + auto* items = inventoryElement->FirstChildElement("items"); if (items == nullptr) @@ -756,10 +756,10 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) itemElement->LinkEndChild(extraInfo); } - + bagElement->LinkEndChild(itemElement); } - + items->LinkEndChild(bagElement); } } @@ -769,13 +769,13 @@ void InventoryComponent::Serialize(RakNet::BitStream* outBitStream, const bool b if (bIsInitialUpdate || m_Dirty) { outBitStream->Write(true); - + outBitStream->Write(m_Equipped.size()); for (const auto& pair : m_Equipped) { const auto item = pair.second; - + if (bIsInitialUpdate) { AddItemSkills(item.lot); @@ -783,19 +783,19 @@ void InventoryComponent::Serialize(RakNet::BitStream* outBitStream, const bool b outBitStream->Write(item.id); outBitStream->Write(item.lot); - + outBitStream->Write0(); - + outBitStream->Write(item.count > 0); if (item.count > 0) outBitStream->Write(item.count); - + outBitStream->Write(item.slot != 0); if (item.slot != 0) outBitStream->Write(item.slot); - + outBitStream->Write0(); - + outBitStream->Write0(); //TODO: This is supposed to be true and write the assemblyPartLOTs when they're present. - + outBitStream->Write1(); } @@ -805,7 +805,7 @@ void InventoryComponent::Serialize(RakNet::BitStream* outBitStream, const bool b { outBitStream->Write(false); } - + outBitStream->Write(false); } @@ -814,7 +814,7 @@ void InventoryComponent::ResetFlags() m_Dirty = false; } -void InventoryComponent::Update(float deltaTime) +void InventoryComponent::Update(float deltaTime) { for (auto* set : m_Itemsets) { @@ -843,7 +843,7 @@ void InventoryComponent::UpdateSlot(const std::string& location, EquippedItem it UnEquipItem(old); } } - + m_Equipped.insert_or_assign(location, item); m_Dirty = true; @@ -855,14 +855,14 @@ void InventoryComponent::RemoveSlot(const std::string& location) { return; } - + m_Equipped.erase(location); m_Dirty = true; } void InventoryComponent::EquipItem(Item* item, const bool skipChecks) -{ +{ if (!Inventory::IsValidItem(item->GetLot())) { return; @@ -908,7 +908,7 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) const auto building = character->GetBuildMode(); const auto type = static_cast(item->GetInfo().itemType); - + if (item->GetLot() == 8092 && m_Parent->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { EntityInfo info {}; @@ -976,7 +976,7 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) { return; } - + if (type == ITEM_TYPE_LOOT_MODEL || type == ITEM_TYPE_VEHICLE) { return; @@ -995,12 +995,12 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) const auto lot = item->GetLot(); CheckItemSet(lot); - + for (auto* set : m_Itemsets) { set->OnEquip(lot); } - + if (lot == 1727) GameMessages::SendSetJetpackMode(m_Parent, false, true, false); if (lot == 7292) GameMessages::SendSetJetpackMode(m_Parent, true, true, false); if (lot == 14442) GameMessages::SendSetJetpackMode(m_Parent, false, true, true); @@ -1011,11 +1011,11 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) } GenerateProxies(item); - + UpdateSlot(item->GetInfo().equipLocation, { item->GetId(), item->GetLot(), item->GetCount(), item->GetSlot() }); ApplyBuff(item->GetLot()); - + AddItemSkills(item->GetLot()); EntityManager::Instance()->SerializeEntity(m_Parent); @@ -1029,7 +1029,7 @@ void InventoryComponent::UnEquipItem(Item* item) } const auto lot = item->GetLot(); - + if (!Inventory::IsValidItem(lot)) { return; @@ -1047,11 +1047,11 @@ void InventoryComponent::UnEquipItem(Item* item) if (lot == 14442) GameMessages::SendSetJetpackMode(m_Parent, false, false, true); RemoveBuff(item->GetLot()); - + RemoveItemSkills(item->GetLot()); RemoveSlot(item->GetInfo().equipLocation); - + PurgeProxies(item); EntityManager::Instance()->SerializeEntity(m_Parent); @@ -1069,7 +1069,7 @@ void InventoryComponent::ApplyBuff(const LOT lot) const const auto buffs = FindBuffs(lot, true); for (const auto buff : buffs) - { + { SkillComponent::HandleUnmanaged(buff, m_Parent->GetObjectID()); } } @@ -1142,10 +1142,13 @@ void InventoryComponent::CheckItemSet(const LOT lot) { return; } - std::cout << "INVENTORY CHECK" << std::endl; - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT setID FROM ItemSets WHERE itemIDs LIKE '%%%d%%';", - lot); + const std::string lot_query = "%" + std::to_string(lot) + "%"; + + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT setID FROM ItemSets WHERE itemIDs LIKE ?;"); + query.bind(1, lot_query.c_str()); + + auto result = query.execQuery(); while (!result.eof()) { const auto id = result.getIntField(0); @@ -1173,11 +1176,11 @@ void InventoryComponent::CheckItemSet(const LOT lot) { } m_ItemSetsChecked.push_back(lot); - + result.finalize(); } -void InventoryComponent::SetConsumable(LOT lot) +void InventoryComponent::SetConsumable(LOT lot) { m_Consumable = lot; } @@ -1197,13 +1200,13 @@ void InventoryComponent::AddItemSkills(const LOT lot) { return; } - + const auto index = m_Skills.find(slot); if (index != m_Skills.end()) { const auto old = index->second; - + GameMessages::SendRemoveSkill(m_Parent, old); } @@ -1213,7 +1216,7 @@ void InventoryComponent::AddItemSkills(const LOT lot) { return; } - + GameMessages::SendAddSkill(m_Parent, skill, static_cast(slot)); m_Skills.insert_or_assign(slot, skill); @@ -1222,14 +1225,14 @@ void InventoryComponent::AddItemSkills(const LOT lot) void InventoryComponent::RemoveItemSkills(const LOT lot) { const auto info = Inventory::FindItemComponent(lot); - + const auto slot = FindBehaviorSlot(static_cast(info.itemType)); - + if (slot == BehaviorSlot::Invalid) { return; } - + const auto index = m_Skills.find(slot); if (index == m_Skills.end()) @@ -1242,7 +1245,7 @@ void InventoryComponent::RemoveItemSkills(const LOT lot) GameMessages::SendRemoveSkill(m_Parent, old); m_Skills.erase(slot); - + if (slot == BehaviorSlot::Primary) { m_Skills.insert_or_assign(BehaviorSlot::Primary, 1); @@ -1251,7 +1254,7 @@ void InventoryComponent::RemoveItemSkills(const LOT lot) } } -void InventoryComponent::TriggerPassiveAbility(PassiveAbilityTrigger trigger) +void InventoryComponent::TriggerPassiveAbility(PassiveAbilityTrigger trigger) { for (auto* set : m_Itemsets) { @@ -1278,7 +1281,7 @@ bool InventoryComponent::HasAnyPassive(const std::vectorGetObjectID()); @@ -1288,7 +1291,7 @@ void InventoryComponent::DespawnPet() } } -void InventoryComponent::SpawnPet(Item* item) +void InventoryComponent::SpawnPet(Item* item) { auto* current = PetComponent::GetActivePet(m_Parent->GetObjectID()); @@ -1307,11 +1310,11 @@ void InventoryComponent::SpawnPet(Item* item) info.pos = m_Parent->GetPosition(); info.rot = NiQuaternion::IDENTITY; info.spawnerID = m_Parent->GetObjectID(); - + auto* pet = EntityManager::Instance()->CreateEntity(info); auto* petComponent = pet->GetComponent(); - + if (petComponent != nullptr) { petComponent->Activate(item); @@ -1320,7 +1323,7 @@ void InventoryComponent::SpawnPet(Item* item) EntityManager::Instance()->ConstructEntity(pet); } -void InventoryComponent::SetDatabasePet(LWOOBJID id, const DatabasePet& data) +void InventoryComponent::SetDatabasePet(LWOOBJID id, const DatabasePet& data) { m_Pets.insert_or_assign(id, data); } @@ -1341,7 +1344,7 @@ bool InventoryComponent::IsPet(LWOOBJID id) const return pair != m_Pets.end(); } -void InventoryComponent::RemoveDatabasePet(LWOOBJID id) +void InventoryComponent::RemoveDatabasePet(LWOOBJID id) { m_Pets.erase(id); } @@ -1364,7 +1367,7 @@ BehaviorSlot InventoryComponent::FindBehaviorSlot(const eItemType type) } } -bool InventoryComponent::IsTransferInventory(eInventoryType type) +bool InventoryComponent::IsTransferInventory(eInventoryType type) { return type == VENDOR_BUYBACK || type == VAULT_ITEMS || type == VAULT_MODELS || type == TEMP_ITEMS || type == TEMP_MODELS; } @@ -1415,12 +1418,12 @@ std::vector InventoryComponent::FindBuffs(const LOT lot, bool castOnEq continue; } - + if (missions != nullptr && castOnEquip) { missions->Progress(MissionTaskType::MISSION_TASK_TYPE_SKILL, result.skillID); } - + buffs.push_back(static_cast(entry.behaviorID)); } } @@ -1428,18 +1431,18 @@ std::vector InventoryComponent::FindBuffs(const LOT lot, bool castOnEq return buffs; } -void InventoryComponent::SetNPCItems(const std::vector& items) +void InventoryComponent::SetNPCItems(const std::vector& items) { m_Equipped.clear(); auto slot = 0u; - + for (const auto& item : items) { const LWOOBJID id = ObjectIDManager::Instance()->GenerateObjectID(); const auto& info = Inventory::FindItemComponent(item); - + UpdateSlot(info.equipLocation, { id, static_cast(item), 1, slot++ }, true); } @@ -1474,9 +1477,9 @@ std::vector InventoryComponent::GenerateProxies(Item* parent) { return proxies; } - + subItems.erase(std::remove_if(subItems.begin(), subItems.end(), ::isspace), subItems.end()); - + std::stringstream stream(subItems); std::string segment; std::vector lots; @@ -1491,7 +1494,7 @@ std::vector InventoryComponent::GenerateProxies(Item* parent) { Game::logger->Log("InventoryComponent", "Failed to parse proxy (%s): (%s)!\n", segment.c_str(), exception.what()); } - } + } for (const auto lot : lots) { @@ -1508,7 +1511,7 @@ std::vector InventoryComponent::GenerateProxies(Item* parent) proxies.push_back(proxy); } - + return proxies; } @@ -1517,7 +1520,7 @@ std::vector InventoryComponent::FindProxies(const LWOOBJID parent) auto* inventory = GetInventory(ITEM_SETS); std::vector proxies; - + for (const auto& pair : inventory->GetItems()) { auto* item = pair.second; @@ -1559,7 +1562,7 @@ bool InventoryComponent::IsParentValid(Item* root) } const auto id = root->GetId(); - + for (const auto& pair : m_Inventories) { const auto items = pair.second->GetItems(); @@ -1581,7 +1584,7 @@ bool InventoryComponent::IsParentValid(Item* root) void InventoryComponent::CheckProxyIntegrity() { std::vector dead; - + for (const auto& pair : m_Inventories) { const auto& items = pair.second->GetItems(); @@ -1596,7 +1599,7 @@ void InventoryComponent::CheckProxyIntegrity() { continue; } - + if (IsValidProxy(parent)) { continue; @@ -1621,7 +1624,7 @@ void InventoryComponent::CheckProxyIntegrity() for (const auto& candidate : items) { auto* item = candidate.second; - + const auto parent = item->GetParent(); if (parent != LWOOBJID_EMPTY) @@ -1653,7 +1656,7 @@ void InventoryComponent::CheckProxyIntegrity() void InventoryComponent::PurgeProxies(Item* item) { const auto root = item->GetParent(); - + if (root != LWOOBJID_EMPTY) { item = FindItemById(root); @@ -1662,7 +1665,7 @@ void InventoryComponent::PurgeProxies(Item* item) { UnEquipItem(item); } - + return; } @@ -1676,7 +1679,7 @@ void InventoryComponent::PurgeProxies(Item* item) } } -void InventoryComponent::LoadPetXml(tinyxml2::XMLDocument* document) +void InventoryComponent::LoadPetXml(tinyxml2::XMLDocument* document) { auto* petInventoryElement = document->FirstChildElement("obj")->FirstChildElement("pet"); @@ -1694,7 +1697,7 @@ void InventoryComponent::LoadPetXml(tinyxml2::XMLDocument* document) LWOOBJID id; LOT lot; int32_t moderationStatus; - + petElement->QueryAttribute("id", &id); petElement->QueryAttribute("l", &lot); petElement->QueryAttribute("m", &moderationStatus); @@ -1711,7 +1714,7 @@ void InventoryComponent::LoadPetXml(tinyxml2::XMLDocument* document) } } -void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument* document) +void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument* document) { auto* petInventoryElement = document->FirstChildElement("obj")->FirstChildElement("pet"); @@ -1733,8 +1736,7 @@ void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument* document) petElement->SetAttribute("m", pet.second.moderationState); petElement->SetAttribute("n", pet.second.name.c_str()); petElement->SetAttribute("t", 0); - + petInventoryElement->LinkEndChild(petElement); } } - diff --git a/dGame/dComponents/MissionComponent.cpp b/dGame/dComponents/MissionComponent.cpp index 5945394b..1b809f48 100644 --- a/dGame/dComponents/MissionComponent.cpp +++ b/dGame/dComponents/MissionComponent.cpp @@ -450,8 +450,11 @@ const std::vector& MissionComponent::QueryAchievements(MissionTaskType } bool MissionComponent::RequiresItem(const LOT lot) { - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT type FROM Objects WHERE id = %d;", lot); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT type FROM Objects WHERE id = ?;"); + query.bind(1, (int) lot); + + auto result = query.execQuery(); if (result.eof()) { return false; diff --git a/dGame/dComponents/PetComponent.cpp b/dGame/dComponents/PetComponent.cpp index 8c51791a..b31cd35f 100644 --- a/dGame/dComponents/PetComponent.cpp +++ b/dGame/dComponents/PetComponent.cpp @@ -167,9 +167,11 @@ void PetComponent::OnUse(Entity* originator) std::string buildFile; if (cached == buildCache.end()) { - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT ValidPiecesLXF, PuzzleModelLot, Timelimit, NumValidPieces, imagCostPerBuild FROM TamingBuildPuzzles WHERE NPCLot = %d;", - m_Parent->GetLOT()); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT ValidPiecesLXF, PuzzleModelLot, Timelimit, NumValidPieces, imagCostPerBuild FROM TamingBuildPuzzles WHERE NPCLot = ?;"); + query.bind(1, (int) m_Parent->GetLOT()); + + auto result = query.execQuery(); if (result.eof()) { diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index 543f99a2..d685e8e9 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -40,9 +40,11 @@ PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Compo const auto zoneId = worldId.GetMapID(); const auto cloneId = worldId.GetCloneID(); - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT id FROM PropertyTemplate WHERE mapID = %d;", - (int) zoneId); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT id FROM PropertyTemplate WHERE mapID = ?;"); + query.bind(1, (int) zoneId); + + auto result = query.execQuery(); if (result.eof() || result.fieldIsNull(0)) { @@ -96,9 +98,11 @@ std::vector PropertyManagementComponent::GetPaths() const { const auto zoneId = dZoneManager::Instance()->GetZone()->GetWorldID(); - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT path FROM PropertyTemplate WHERE mapID = %u;", - zoneId); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT path FROM PropertyTemplate WHERE mapID = ?;"); + query.bind(1, (int) zoneId); + + auto result = query.execQuery(); std::vector paths {}; diff --git a/dGame/dComponents/RenderComponent.cpp b/dGame/dComponents/RenderComponent.cpp index b4787d40..faec4ab6 100644 --- a/dGame/dComponents/RenderComponent.cpp +++ b/dGame/dComponents/RenderComponent.cpp @@ -199,9 +199,13 @@ void RenderComponent::PlayEffect(const int32_t effectId, const std::u16string& e } const std::string effectType_str = GeneralUtils::UTF16ToWTF8(effectType); - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT animation_length FROM Animations WHERE animation_type IN (SELECT animationName FROM BehaviorEffect WHERE effectID = %d AND effectType = %Q);", - effectId, effectType_str.c_str()); + + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT animation_length FROM Animations WHERE animation_type IN (SELECT animationName FROM BehaviorEffect WHERE effectID = ? AND effectType = ?);"); + query.bind(1, effectId); + query.bind(2, effectType_str.c_str()); + + auto result = query.execQuery(); if (result.eof() || result.fieldIsNull(0)) { result.finalize(); diff --git a/dGame/dComponents/RocketLaunchpadControlComponent.cpp b/dGame/dComponents/RocketLaunchpadControlComponent.cpp index a117fffc..507c75cb 100644 --- a/dGame/dComponents/RocketLaunchpadControlComponent.cpp +++ b/dGame/dComponents/RocketLaunchpadControlComponent.cpp @@ -18,10 +18,12 @@ #include "PacketUtils.h" RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(Entity* parent, int rocketId) : Component(parent) { - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT targetZone, defaultZoneID, targetScene, altLandingPrecondition, altLandingSpawnPointName FROM RocketLaunchpadControlComponent WHERE id = %d;", - rocketId); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT targetZone, defaultZoneID, targetScene, altLandingPrecondition, altLandingSpawnPointName FROM RocketLaunchpadControlComponent WHERE id = ?;"); + query.bind(1, rocketId); + auto result = query.execQuery(); + if (!result.eof() && !result.fieldIsNull(0)) { m_TargetZone = result.getIntField(0); diff --git a/dGame/dComponents/SkillComponent.cpp b/dGame/dComponents/SkillComponent.cpp index 4396c669..b5896d16 100644 --- a/dGame/dComponents/SkillComponent.cpp +++ b/dGame/dComponents/SkillComponent.cpp @@ -86,9 +86,11 @@ void SkillComponent::SyncPlayerProjectile(const LWOOBJID projectileId, RakNet::B const auto sync_entry = this->m_managedProjectiles.at(index); - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT behaviorID FROM SkillBehavior WHERE skillID = (SELECT skillID FROM ObjectSkills WHERE objectTemplate = %d);", - sync_entry.lot); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT behaviorID FROM SkillBehavior WHERE skillID = (SELECT skillID FROM ObjectSkills WHERE objectTemplate = ?);"); + query.bind(1, (int) sync_entry.lot); + + auto result = query.execQuery(); if (result.eof()) { Game::logger->Log("SkillComponent", "Failed to find skill id for (%i)!\n", sync_entry.lot); @@ -434,9 +436,10 @@ void SkillComponent::SyncProjectileCalculation(const ProjectileSyncEntry& entry) return; } - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT behaviorID FROM SkillBehavior WHERE skillID = (SELECT skillID FROM ObjectSkills WHERE objectTemplate = %d);", - entry.lot); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT behaviorID FROM SkillBehavior WHERE skillID = (SELECT skillID FROM ObjectSkills WHERE objectTemplate = ?);"); + query.bind(1, (int) entry.lot); + auto result = query.execQuery(); if (result.eof()) { Game::logger->Log("SkillComponent", "Failed to find skill id for (%i)!\n", entry.lot); diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 0e30244b..5b6b8a8c 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -2509,9 +2509,11 @@ void GameMessages::HandleBBBSaveRequest(RakNet::BitStream* inStream, Entity* ent const auto zoneId = worldId.GetMapID(); const auto cloneId = worldId.GetCloneID(); - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT id FROM PropertyTemplate WHERE mapID = %d;", - (int) zoneId); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT id FROM PropertyTemplate WHERE mapID = ?;"); + query.bind(1, (int) zoneId); + + auto result = query.execQuery(); if (result.eof() || result.fieldIsNull(0)) { return; diff --git a/dGame/dInventory/Item.cpp b/dGame/dInventory/Item.cpp index 92a208cb..77256a20 100644 --- a/dGame/dInventory/Item.cpp +++ b/dGame/dInventory/Item.cpp @@ -386,9 +386,11 @@ void Item::DisassembleModel() const auto componentId = table->GetByIDAndType(GetLot(), COMPONENT_TYPE_RENDER); - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT render_asset FROM RenderComponent WHERE id = %d;", - componentId); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT render_asset FROM RenderComponent WHERE id = ?;"); + query.bind(1, (int) componentId); + + auto result = query.execQuery(); if (result.eof()) { diff --git a/dGame/dInventory/ItemSet.cpp b/dGame/dInventory/ItemSet.cpp index 93e86a81..70b77a70 100644 --- a/dGame/dInventory/ItemSet.cpp +++ b/dGame/dInventory/ItemSet.cpp @@ -15,9 +15,11 @@ ItemSet::ItemSet(const uint32_t id, InventoryComponent* inventoryComponent) this->m_PassiveAbilities = ItemSetPassiveAbility::FindAbilities(id, m_InventoryComponent->GetParent(), this); - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT skillSetWith2, skillSetWith3, skillSetWith4, skillSetWith5, skillSetWith6, itemIDs FROM ItemSets WHERE setID = %u;", - id); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT skillSetWith2, skillSetWith3, skillSetWith4, skillSetWith5, skillSetWith6, itemIDs FROM ItemSets WHERE setID = ?;"); + query.bind(1, (int) id); + + auto result = query.execQuery(); if (result.eof()) { @@ -31,9 +33,11 @@ ItemSet::ItemSet(const uint32_t id, InventoryComponent* inventoryComponent) continue; } - auto skillResult = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT SkillID FROM ItemSetSkills WHERE SkillSetID = %d;", - result.getIntField(i)); + auto skillQuery = CDClientDatabase::CreatePreppedStmt( + "SELECT SkillID FROM ItemSetSkills WHERE SkillSetID = ?;"); + skillQuery.bind(1, result.getIntField(i)); + + auto skillResult = skillQuery.execQuery(); if (skillResult.eof()) { diff --git a/dGame/dUtilities/Preconditions.cpp b/dGame/dUtilities/Preconditions.cpp index 5b68685c..da149498 100644 --- a/dGame/dUtilities/Preconditions.cpp +++ b/dGame/dUtilities/Preconditions.cpp @@ -16,9 +16,11 @@ std::map Preconditions::cache = {}; Precondition::Precondition(const uint32_t condition) { - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT type, targetLOT, targetCount FROM Preconditions WHERE id = %u;", - condition); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT type, targetLOT, targetCount FROM Preconditions WHERE id = ?;"); + query.bind(1, (int) condition); + + auto result = query.execQuery(); if (result.eof()) { diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index fa601946..feb85d1a 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -1243,11 +1243,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit } if (chatCommand == "lookup" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() == 1) { - std::string query = "%" + args[0] + "%"; - const char* query_cstr = query.c_str(); - auto tables = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT `id`, `name` FROM `Objects` WHERE `displayName` LIKE %Q OR `name` LIKE %Q OR `description` LIKE %Q LIMIT 50", - query_cstr, query_cstr, query_cstr); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT `id`, `name` FROM `Objects` WHERE `displayName` LIKE ?1 OR `name` LIKE ?1 OR `description` LIKE ?1 LIMIT 50"); + + const std::string query_text = "%" + args[0] + "%"; + query.bind(1, query_text.c_str()); + + auto tables = query.execQuery(); while (!tables.eof()) { std::string message = std::to_string(tables.getIntField(0)) + " - " + tables.getStringField(1); diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index ce3774e9..1c7f42a7 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -1059,9 +1059,11 @@ void HandlePacket(Packet* packet) { const auto zoneId = Game::server->GetZoneID(); const auto cloneId = g_CloneID; - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT id FROM PropertyTemplate WHERE mapID = %u;", - zoneId); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT id FROM PropertyTemplate WHERE mapID = ?;"); + query.bind(1, (int) zoneId); + + auto result = query.execQuery(); if (result.eof() || result.fieldIsNull(0)) { Game::logger->Log("WorldServer", "No property templates found for zone %d, not sending BBB\n", zoneId); diff --git a/dZoneManager/dZoneManager.cpp b/dZoneManager/dZoneManager.cpp index 6ed6c719..181d8310 100644 --- a/dZoneManager/dZoneManager.cpp +++ b/dZoneManager/dZoneManager.cpp @@ -26,9 +26,11 @@ void dZoneManager::Initialize(const LWOZONEID& zoneID) { LOT zoneControlTemplate = 2365; - auto result = CDClientDatabase::ExecuteQueryWithArgs( - "SELECT zoneControlTemplate, ghostdistance_min, ghostdistance FROM ZoneTable WHERE zoneID = %d;", - (int) zoneID.GetMapID()); + auto query = CDClientDatabase::CreatePreppedStmt( + "SELECT zoneControlTemplate, ghostdistance_min, ghostdistance FROM ZoneTable WHERE zoneID = ?;"); + query.bind(1, (int) zoneID.GetMapID()); + + auto result = query.execQuery(); if (!result.eof()) { zoneControlTemplate = result.getIntField("zoneControlTemplate", 2365);