diff --git a/common/database/database_update.cpp b/common/database/database_update.cpp index 0542d130d..30036fdd7 100644 --- a/common/database/database_update.cpp +++ b/common/database/database_update.cpp @@ -142,6 +142,7 @@ bool DatabaseUpdate::UpdateManifest( if (version_low != version_high) { LogSys.DisableMySQLErrorLogs(); + bool force_interactive = false; for (int version = version_low + 1; version <= version_high; ++version) { for (auto &e: entries) { if (e.version == version) { @@ -163,6 +164,10 @@ bool DatabaseUpdate::UpdateManifest( prefix, e.description ); + + if (!has_migration && e.force_interactive) { + force_interactive = true; + } } } } @@ -187,6 +192,42 @@ bool DatabaseUpdate::UpdateManifest( LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH)); } + if (force_interactive) { + LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH)); + LogInfo("Some migrations require user input. Running interactively"); + LogInfo("This is usually due to a major change that could cause data loss"); + LogInfo("Your server is automatically backed up before these updates are applied"); + LogInfo("but you should also make sure you take a backup prior to running this update"); + LogInfo("Would you like to run this update? [y/n] (Timeout 60s)"); + LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH)); + + // user input + std::string input; + bool gave_input = false; + time_t start_time = time(nullptr); + time_t wait_time_seconds = 60; + + // spawn a concurrent thread that waits for input from std::cin + std::thread t1( + [&]() { + std::cin >> input; + gave_input = true; + } + ); + t1.detach(); + + // check the inputReceived flag once every 50ms for 10 seconds + while (time(nullptr) < start_time + wait_time_seconds && !gave_input) { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + + // prompt for user skip + if (Strings::Trim(input) != "y") { + LogInfo("Exiting due to user input"); + std::exit(1); + } + } + for (auto &m: missing_migrations) { for (auto &e: entries) { if (e.version == m) { diff --git a/common/database/database_update.h b/common/database/database_update.h index be820a9e8..312be1f17 100644 --- a/common/database/database_update.h +++ b/common/database/database_update.h @@ -11,6 +11,7 @@ struct ManifestEntry { std::string match{}; // match field that is not always used, but works in conjunction with "condition" values [missing|match|contains] std::string sql{}; // the SQL DDL that gets ran when the condition is true bool content_schema_update{}; // if true, this migration is a content schema update and should be ran against the content database + bool force_interactive; // if true, this migration will always be run interactively }; struct DatabaseVersion { diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 4a64160ce..a279ce90b 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -6388,6 +6388,107 @@ CREATE INDEX idx_trader_active_transaction ON trader (active_transaction); ALTER TABLE `trader` ADD COLUMN `listing_date` DATETIME NULL DEFAULT NULL AFTER `active_transaction`, ADD INDEX `idx_trader_listing_date` (`listing_date`); +)", + .content_schema_update = false + }, + ManifestEntry{ + .version = 9297, + .description = "2024_01_22_sharedbank_guid_primary_key.sql", + .check = "SHOW COLUMN FROM `sharedbank` LIKE 'guid'", + .condition = "empty", + .match = "", + .sql = R"( +ALTER TABLE `sharedbank` +CHANGE COLUMN `acctid` `account_id` int(11) UNSIGNED NOT NULL DEFAULT 0 FIRST, +CHANGE COLUMN `slotid` `slot_id` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `account_id`, +CHANGE COLUMN `itemid` `item_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `slot_id`, +CHANGE COLUMN `augslot1` `augment_one` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `charges`, +CHANGE COLUMN `augslot2` `augment_two` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_one`, +CHANGE COLUMN `augslot3` `augment_three` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_two`, +CHANGE COLUMN `augslot4` `augment_four` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_three`, +CHANGE COLUMN `augslot5` `augment_five` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_four`, +CHANGE COLUMN `augslot6` `augment_six` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_five`, +MODIFY COLUMN `charges` smallint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `item_id`, +ADD COLUMN `color` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `charges`, +ADD COLUMN `ornament_icon` int(11) UNSIGNED NOT NULL AFTER `custom_data`, +ADD COLUMN `ornament_idfile` int(11) UNSIGNED NOT NULL AFTER `ornament_icon`, +ADD COLUMN `ornament_hero_model` int(11) NOT NULL AFTER `ornament_idfile`, +ADD COLUMN `guid` bigint(20) UNSIGNED NOT NULL DEFAULT 0 AFTER `ornament_hero_model`, +ADD PRIMARY KEY (`account_id`, `slot_id`); +)", + .content_schema_update = false, + .force_interactive = true + }, + ManifestEntry{ + .version = 9298, + .description = "2024_10_24_inventory_changes.sql", + .check = "SHOW COLUMN FROM `inventory` LIKE 'charid'", + .condition = "empty", + .match = "", + .sql = R"( +ALTER TABLE `inventory` +CHANGE COLUMN `charid` `character_id` int(11) UNSIGNED NOT NULL DEFAULT 0 FIRST, +CHANGE COLUMN `slotid` `slot_id` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `character_id`, +CHANGE COLUMN `itemid` `item_id` int(11) UNSIGNED NULL DEFAULT 0 AFTER `slot_id`, +CHANGE COLUMN `augslot1` `augment_one` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `color`, +CHANGE COLUMN `augslot2` `augment_two` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_one`, +CHANGE COLUMN `augslot3` `augment_three` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_two`, +CHANGE COLUMN `augslot4` `augment_four` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_three`, +CHANGE COLUMN `augslot5` `augment_five` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_four`, +CHANGE COLUMN `augslot6` `augment_six` mediumint(7) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_five`, +CHANGE COLUMN `ornamenticon` `ornament_icon` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `custom_data`, +CHANGE COLUMN `ornamentidfile` `ornament_idfile` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `ornament_icon`, +DROP PRIMARY KEY, +ADD PRIMARY KEY (`character_id`, `slot_id`) USING BTREE; +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 251) + 4010) WHERE `slot_id` BETWEEN 251 AND 260; -- Bag 1 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 261) + 4210) WHERE `slot_id` BETWEEN 261 AND 270; -- Bag 2 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 271) + 4410) WHERE `slot_id` BETWEEN 271 AND 280; -- Bag 3 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 281) + 4610) WHERE `slot_id` BETWEEN 281 AND 290; -- Bag 4 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 291) + 4810) WHERE `slot_id` BETWEEN 291 AND 300; -- Bag 5 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 301) + 5010) WHERE `slot_id` BETWEEN 301 AND 310; -- Bag 6 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 311) + 5210) WHERE `slot_id` BETWEEN 311 AND 320; -- Bag 7 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 321) + 5410) WHERE `slot_id` BETWEEN 321 AND 330; -- Bag 8 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 331) + 5610) WHERE `slot_id` BETWEEN 331 AND 340; -- Bag 9 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 341) + 5810) WHERE `slot_id` BETWEEN 341 AND 350; -- Bag 10 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 351) + 6010) WHERE `slot_id` BETWEEN 351 AND 360; -- Cursor Bag +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2031) + 6210) WHERE `slot_id` BETWEEN 2031 AND 2040; -- Bank Bag 1 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2041) + 6410) WHERE `slot_id` BETWEEN 2041 AND 2050; -- Bank Bag 2 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2051) + 6610) WHERE `slot_id` BETWEEN 2051 AND 2060; -- Bank Bag 3 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2061) + 6810) WHERE `slot_id` BETWEEN 2061 AND 2070; -- Bank Bag 4 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2071) + 7010) WHERE `slot_id` BETWEEN 2071 AND 2080; -- Bank Bag 5 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2081) + 7210) WHERE `slot_id` BETWEEN 2081 AND 2090; -- Bank Bag 6 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2091) + 7410) WHERE `slot_id` BETWEEN 2091 AND 2100; -- Bank Bag 7 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2101) + 7610) WHERE `slot_id` BETWEEN 2101 AND 2110; -- Bank Bag 8 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2111) + 7810) WHERE `slot_id` BETWEEN 2111 AND 2120; -- Bank Bag 9 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2121) + 8010) WHERE `slot_id` BETWEEN 2121 AND 2130; -- Bank Bag 10 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2131) + 8210) WHERE `slot_id` BETWEEN 2131 AND 2140; -- Bank Bag 11 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2141) + 8410) WHERE `slot_id` BETWEEN 2141 AND 2150; -- Bank Bag 12 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2151) + 8610) WHERE `slot_id` BETWEEN 2151 AND 2160; -- Bank Bag 13 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2161) + 8810) WHERE `slot_id` BETWEEN 2161 AND 2170; -- Bank Bag 14 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2171) + 9010) WHERE `slot_id` BETWEEN 2171 AND 2180; -- Bank Bag 15 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2181) + 9210) WHERE `slot_id` BETWEEN 2181 AND 2190; -- Bank Bag 16 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2191) + 9410) WHERE `slot_id` BETWEEN 2191 AND 2200; -- Bank Bag 17 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2201) + 9610) WHERE `slot_id` BETWEEN 2201 AND 2210; -- Bank Bag 18 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2211) + 9810) WHERE `slot_id` BETWEEN 2211 AND 2220; -- Bank Bag 19 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2221) + 10010) WHERE `slot_id` BETWEEN 2221 AND 2230; -- Bank Bag 20 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2231) + 10210) WHERE `slot_id` BETWEEN 2231 AND 2240; -- Bank Bag 21 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2241) + 10410) WHERE `slot_id` BETWEEN 2241 AND 2250; -- Bank Bag 22 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2251) + 10610) WHERE `slot_id` BETWEEN 2251 AND 2260; -- Bank Bag 23 +UPDATE `inventory` SET `slot_id` = ((`slot_id` - 2261) + 10810) WHERE `slot_id` BETWEEN 2261 AND 2270; -- Bank Bag 24 +UPDATE `sharedbank` SET `slot_id` = ((`slot_id` - 2531) + 11010) WHERE `slot_id` BETWEEN 2531 AND 2540; -- Shared Bank Bag 1 +UPDATE `sharedbank` SET `slot_id` = ((`slot_id` - 2541) + 11210) WHERE `slot_id` BETWEEN 2541 AND 2550; -- Shared Bank Bag 2 +)", + .content_schema_update = false + }, + ManifestEntry{ + .version = 9299, + .description = "2024_10_24_merchantlist_temp_uncap.sql", + .check = "SHOW CREATE TABLE `merchantlist_temp`", + .condition = "contains", + .match = "`slot` tinyint(3)", + .sql = R"( +ALTER TABLE `merchantlist_temp` +MODIFY COLUMN `slot` int UNSIGNED NOT NULL DEFAULT 0 AFTER `npcid`; )", .content_schema_update = false } diff --git a/common/emu_constants.h b/common/emu_constants.h index 7da8196d3..63361dbf3 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -132,7 +132,7 @@ namespace EQ using RoF2::invtype::KRONO_SIZE; using RoF2::invtype::OTHER_SIZE; - using Titanium::invtype::TRADE_NPC_SIZE; + using RoF2::invtype::TRADE_NPC_SIZE; using RoF2::invtype::TYPE_INVALID; using RoF2::invtype::TYPE_BEGIN; @@ -159,7 +159,7 @@ namespace EQ using RoF2::invslot::SLOT_INVALID; using RoF2::invslot::SLOT_BEGIN; - using Titanium::invslot::SLOT_TRADESKILL_EXPERIMENT_COMBINE; + using RoF2::invslot::SLOT_TRADESKILL_EXPERIMENT_COMBINE; const int16 SLOT_AUGMENT_GENERIC_RETURN = 1001; // clients don't appear to use this method... (internal inventory return value) @@ -179,28 +179,28 @@ namespace EQ using RoF2::invslot::BONUS_STAT_END; using RoF2::invslot::BONUS_SKILL_END; - using Titanium::invslot::BANK_BEGIN; - using SoF::invslot::BANK_END; + using RoF2::invslot::BANK_BEGIN; + using RoF2::invslot::BANK_END; - using Titanium::invslot::SHARED_BANK_BEGIN; - using Titanium::invslot::SHARED_BANK_END; + using RoF2::invslot::SHARED_BANK_BEGIN; + using RoF2::invslot::SHARED_BANK_END; - using Titanium::invslot::TRADE_BEGIN; - using Titanium::invslot::TRADE_END; + using RoF2::invslot::TRADE_BEGIN; + using RoF2::invslot::TRADE_END; - using Titanium::invslot::TRADE_NPC_END; + using RoF2::invslot::TRADE_NPC_END; - using Titanium::invslot::WORLD_BEGIN; - using Titanium::invslot::WORLD_END; + using RoF2::invslot::WORLD_BEGIN; + using RoF2::invslot::WORLD_END; - using Titanium::invslot::TRIBUTE_BEGIN; - using Titanium::invslot::TRIBUTE_END; + using RoF2::invslot::TRIBUTE_BEGIN; + using RoF2::invslot::TRIBUTE_END; - using Titanium::invslot::GUILD_TRIBUTE_BEGIN; - using Titanium::invslot::GUILD_TRIBUTE_END; + using RoF2::invslot::GUILD_TRIBUTE_BEGIN; + using RoF2::invslot::GUILD_TRIBUTE_END; const int16 CORPSE_BEGIN = invslot::slotGeneral1; - const int16 CORPSE_END = CORPSE_BEGIN + invslot::slotCursor; + const int16 CORPSE_END = CORPSE_BEGIN + invslot::slotCursor; using RoF2::invslot::EQUIPMENT_BITMASK; using RoF2::invslot::GENERAL_BITMASK; @@ -214,38 +214,40 @@ namespace EQ } // namespace invslot namespace invbag { - using Titanium::invbag::SLOT_INVALID; - using Titanium::invbag::SLOT_BEGIN; - using Titanium::invbag::SLOT_END; - using Titanium::invbag::SLOT_COUNT; + using RoF2::invbag::SLOT_INVALID; + using RoF2::invbag::SLOT_BEGIN; + using RoF2::invbag::SLOT_END; + using RoF2::invbag::SLOT_COUNT; - using Titanium::invbag::GENERAL_BAGS_BEGIN; + using RoF2::invslot::WORLD_END; + + const int16 GENERAL_BAGS_BEGIN = WORLD_END + 1; const int16 GENERAL_BAGS_COUNT = invslot::GENERAL_COUNT * SLOT_COUNT; - const int16 GENERAL_BAGS_END = (GENERAL_BAGS_BEGIN + GENERAL_BAGS_COUNT) - 1; + const int16 GENERAL_BAGS_END = (GENERAL_BAGS_BEGIN + GENERAL_BAGS_COUNT) - 1; const int16 GENERAL_BAGS_8_COUNT = 8 * SLOT_COUNT; - const int16 GENERAL_BAGS_8_END = (GENERAL_BAGS_BEGIN + GENERAL_BAGS_8_COUNT) - 1; + const int16 GENERAL_BAGS_8_END = (GENERAL_BAGS_BEGIN + GENERAL_BAGS_8_COUNT) - 1; - const int16 CURSOR_BAG_BEGIN = 351; + const int16 CURSOR_BAG_BEGIN = GENERAL_BAGS_END + 1; const int16 CURSOR_BAG_COUNT = SLOT_COUNT; - const int16 CURSOR_BAG_END = (CURSOR_BAG_BEGIN + CURSOR_BAG_COUNT) - 1; + const int16 CURSOR_BAG_END = (CURSOR_BAG_BEGIN + CURSOR_BAG_COUNT) - 1; - using Titanium::invbag::BANK_BAGS_BEGIN; + const int16 BANK_BAGS_BEGIN = CURSOR_BAG_END + 1; const int16 BANK_BAGS_COUNT = (invtype::BANK_SIZE * SLOT_COUNT); - const int16 BANK_BAGS_END = (BANK_BAGS_BEGIN + BANK_BAGS_COUNT) - 1; + const int16 BANK_BAGS_END = (BANK_BAGS_BEGIN + BANK_BAGS_COUNT) - 1; const int16 BANK_BAGS_16_COUNT = 16 * SLOT_COUNT; - const int16 BANK_BAGS_16_END = (BANK_BAGS_BEGIN + BANK_BAGS_16_COUNT) - 1; + const int16 BANK_BAGS_16_END = (BANK_BAGS_BEGIN + BANK_BAGS_16_COUNT) - 1; - using Titanium::invbag::SHARED_BANK_BAGS_BEGIN; + const int16 SHARED_BANK_BAGS_BEGIN = BANK_BAGS_END + 1; const int16 SHARED_BANK_BAGS_COUNT = invtype::SHARED_BANK_SIZE * SLOT_COUNT; - const int16 SHARED_BANK_BAGS_END = (SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_COUNT) - 1; + const int16 SHARED_BANK_BAGS_END = (SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_COUNT) - 1; - using Titanium::invbag::TRADE_BAGS_BEGIN; + const int16 TRADE_BAGS_BEGIN = SHARED_BANK_BAGS_END + 1; const int16 TRADE_BAGS_COUNT = invtype::TRADE_SIZE * SLOT_COUNT; - const int16 TRADE_BAGS_END = (TRADE_BAGS_BEGIN + TRADE_BAGS_COUNT) - 1; + const int16 TRADE_BAGS_END = (TRADE_BAGS_BEGIN + TRADE_BAGS_COUNT) - 1; - using Titanium::invbag::GetInvBagIndexName; + using RoF2::invbag::GetInvBagIndexName; } // namespace invbag diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index d83c2ab16..4022a08ce 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -28,6 +28,7 @@ #include "strings.h" #include "../common/light_source.h" +#include "data_verification.h" //#include @@ -44,6 +45,7 @@ ItemInstQueue::~ItemInstQueue() for (auto iter = m_list.begin(); iter != m_list.end(); ++iter) { safe_delete(*iter); } + m_list.clear(); } @@ -62,8 +64,9 @@ void ItemInstQueue::push_front(EQ::ItemInstance* inst) // Remove item from front of queue EQ::ItemInstance* ItemInstQueue::pop() { - if (m_list.empty()) + if (m_list.empty()) { return nullptr; + } EQ::ItemInstance* inst = m_list.front(); m_list.pop_front(); @@ -73,8 +76,9 @@ EQ::ItemInstance* ItemInstQueue::pop() // Remove item from back of queue EQ::ItemInstance* ItemInstQueue::pop_back() { - if (m_list.empty()) + if (m_list.empty()) { return nullptr; + } EQ::ItemInstance* inst = m_list.back(); m_list.pop_back(); @@ -87,7 +91,6 @@ EQ::ItemInstance* ItemInstQueue::peek_front() const return (m_list.empty()) ? nullptr : m_list.front(); } - // // class EQ::InventoryProfile // @@ -96,26 +99,31 @@ EQ::InventoryProfile::~InventoryProfile() for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) { safe_delete(iter->second); } + m_worn.clear(); for (auto iter = m_inv.begin(); iter != m_inv.end(); ++iter) { safe_delete(iter->second); } + m_inv.clear(); for (auto iter = m_bank.begin(); iter != m_bank.end(); ++iter) { safe_delete(iter->second); } + m_bank.clear(); for (auto iter = m_shbank.begin(); iter != m_shbank.end(); ++iter) { safe_delete(iter->second); } + m_shbank.clear(); for (auto iter = m_trade.begin(); iter != m_trade.end(); ++iter) { safe_delete(iter->second); } + m_trade.clear(); } @@ -136,6 +144,7 @@ void EQ::InventoryProfile::CleanDirty() { delete (*iter); ++iter; } + dirty_inst.clear(); } @@ -157,59 +166,44 @@ EQ::ItemInstance* EQ::InventoryProfile::GetItem(int16 slot_id) const } // Non bag slots - else if (slot_id >= invslot::TRADE_BEGIN && slot_id <= invslot::TRADE_END) { + if (EQ::ValueWithin(slot_id, invslot::TRADE_BEGIN, invslot::TRADE_END)) { result = _GetItem(m_trade, slot_id); - } - else if (slot_id >= invslot::SHARED_BANK_BEGIN && slot_id <= invslot::SHARED_BANK_END) { - // Shared Bank slots + } else if (EQ::ValueWithin(slot_id, invslot::SHARED_BANK_BEGIN, invslot::SHARED_BANK_END)) { result = _GetItem(m_shbank, slot_id); - } - else if (slot_id >= invslot::BANK_BEGIN && slot_id <= invslot::BANK_END) { - // Bank slots + } else if (EQ::ValueWithin(slot_id, invslot::BANK_BEGIN, invslot::BANK_END)) { result = _GetItem(m_bank, slot_id); - } - else if ((slot_id >= invslot::GENERAL_BEGIN && slot_id <= invslot::GENERAL_END)) { - // Personal inventory slots + } else if (EQ::ValueWithin(slot_id, invslot::GENERAL_BEGIN, invslot::GENERAL_END)) { result = _GetItem(m_inv, slot_id); - } - else if ((slot_id >= invslot::EQUIPMENT_BEGIN && slot_id <= invslot::EQUIPMENT_END) || - (slot_id >= invslot::TRIBUTE_BEGIN && slot_id <= invslot::TRIBUTE_END) || - (slot_id >= invslot::GUILD_TRIBUTE_BEGIN && slot_id <= invslot::GUILD_TRIBUTE_END)) { - // Equippable slots (on body) + } else if ( + EQ::ValueWithin(slot_id, invslot::EQUIPMENT_BEGIN, invslot::EQUIPMENT_END) || + EQ::ValueWithin(slot_id, invslot::TRIBUTE_BEGIN, invslot::TRIBUTE_END) || + EQ::ValueWithin(slot_id, invslot::GUILD_TRIBUTE_BEGIN, invslot::GUILD_TRIBUTE_END) + ) { result = _GetItem(m_worn, slot_id); } // Inner bag slots - else if (slot_id >= invbag::TRADE_BAGS_BEGIN && slot_id <= invbag::TRADE_BAGS_END) { - // Trade bag slots + else if (EQ::ValueWithin(slot_id, invbag::TRADE_BAGS_BEGIN, invbag::TRADE_BAGS_END)) { ItemInstance* inst = _GetItem(m_trade, InventoryProfile::CalcSlotId(slot_id)); if (inst && inst->IsClassBag()) { result = inst->GetItem(InventoryProfile::CalcBagIdx(slot_id)); } - } - else if (slot_id >= invbag::SHARED_BANK_BAGS_BEGIN && slot_id <= invbag::SHARED_BANK_BAGS_END) { - // Shared Bank bag slots + } else if (EQ::ValueWithin(slot_id, invbag::SHARED_BANK_BAGS_BEGIN, invbag::SHARED_BANK_BAGS_END)) { ItemInstance* inst = _GetItem(m_shbank, InventoryProfile::CalcSlotId(slot_id)); if (inst && inst->IsClassBag()) { result = inst->GetItem(InventoryProfile::CalcBagIdx(slot_id)); } - } - else if (slot_id >= invbag::BANK_BAGS_BEGIN && slot_id <= invbag::BANK_BAGS_END) { - // Bank bag slots + } else if (EQ::ValueWithin(slot_id, invbag::BANK_BAGS_BEGIN, invbag::BANK_BAGS_END)) { ItemInstance* inst = _GetItem(m_bank, InventoryProfile::CalcSlotId(slot_id)); if (inst && inst->IsClassBag()) { result = inst->GetItem(InventoryProfile::CalcBagIdx(slot_id)); } - } - else if (slot_id >= invbag::CURSOR_BAG_BEGIN && slot_id <= invbag::CURSOR_BAG_END) { - // Cursor bag slots + } else if (EQ::ValueWithin(slot_id, invbag::CURSOR_BAG_BEGIN, invbag::CURSOR_BAG_END)) { ItemInstance* inst = m_cursor.peek_front(); if (inst && inst->IsClassBag()) { result = inst->GetItem(InventoryProfile::CalcBagIdx(slot_id)); } - } - else if (slot_id >= invbag::GENERAL_BAGS_BEGIN && slot_id <= invbag::GENERAL_BAGS_END) { - // Personal inventory bag slots + } else if (EQ::ValueWithin(slot_id, invbag::GENERAL_BAGS_BEGIN, invbag::GENERAL_BAGS_END)) { ItemInstance* inst = _GetItem(m_inv, InventoryProfile::CalcSlotId(slot_id)); if (inst && inst->IsClassBag()) { result = inst->GetItem(InventoryProfile::CalcBagIdx(slot_id)); @@ -228,25 +222,27 @@ EQ::ItemInstance* EQ::InventoryProfile::GetItem(int16 slot_id, uint8 bagidx) con // Put an item into specified slot int16 EQ::InventoryProfile::PutItem(int16 slot_id, const ItemInstance& inst) { - if (slot_id <= EQ::invslot::POSSESSIONS_END && slot_id >= EQ::invslot::POSSESSIONS_BEGIN) { - if ((((uint64)1 << slot_id) & m_lookup->PossessionsBitmask) == 0) + if (EQ::ValueWithin(slot_id, EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END)) { + if ((((uint64) 1 << slot_id) & m_lookup->PossessionsBitmask) == 0) { return EQ::invslot::SLOT_INVALID; - } - else if (slot_id <= EQ::invbag::GENERAL_BAGS_END && slot_id >= EQ::invbag::GENERAL_BAGS_BEGIN) { + } + } else if (EQ::ValueWithin(slot_id, EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END)) { auto temp_slot = EQ::invslot::GENERAL_BEGIN + ((slot_id - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT); - if ((((uint64)1 << temp_slot) & m_lookup->PossessionsBitmask) == 0) + if ((((uint64) 1 << temp_slot) & m_lookup->PossessionsBitmask) == 0) { return EQ::invslot::SLOT_INVALID; - } - else if (slot_id <= EQ::invslot::BANK_END && slot_id >= EQ::invslot::BANK_BEGIN) { - if ((slot_id - EQ::invslot::BANK_BEGIN) >= m_lookup->InventoryTypeSize.Bank) + } + } else if (EQ::ValueWithin(slot_id, EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END)) { + if ((slot_id - EQ::invslot::BANK_BEGIN) >= m_lookup->InventoryTypeSize.Bank) { return EQ::invslot::SLOT_INVALID; - } - else if (slot_id <= EQ::invbag::BANK_BAGS_END && slot_id >= EQ::invbag::BANK_BAGS_BEGIN) { + } + } else if (EQ::ValueWithin(slot_id, EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END)) { auto temp_slot = (slot_id - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT; - if (temp_slot >= m_lookup->InventoryTypeSize.Bank) + if (temp_slot >= m_lookup->InventoryTypeSize.Bank) { return EQ::invslot::SLOT_INVALID; + } } + // Clean up item already in slot (if exists) DeleteItem(slot_id); @@ -281,26 +277,23 @@ bool EQ::InventoryProfile::SwapItem( ) { fail_state = swapInvalid; - if (source_slot <= EQ::invslot::POSSESSIONS_END && source_slot >= EQ::invslot::POSSESSIONS_BEGIN) { - if ((((uint64) 1 << source_slot) & m_lookup->PossessionsBitmask) == 0) { + if (EQ::ValueWithin(source_slot, EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END)) { + if ((((uint64)1 << source_slot) & m_lookup->PossessionsBitmask) == 0) { fail_state = swapNotAllowed; return false; } - } - else if (source_slot <= EQ::invbag::GENERAL_BAGS_END && source_slot >= EQ::invbag::GENERAL_BAGS_BEGIN) { + } else if (EQ::ValueWithin(source_slot, EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END)) { auto temp_slot = EQ::invslot::GENERAL_BEGIN + ((source_slot - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT); if ((((uint64)1 << temp_slot) & m_lookup->PossessionsBitmask) == 0) { fail_state = swapNotAllowed; return false; } - } - else if (source_slot <= EQ::invslot::BANK_END && source_slot >= EQ::invslot::BANK_BEGIN) { + } else if (EQ::ValueWithin(source_slot, EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END)) { if ((source_slot - EQ::invslot::BANK_BEGIN) >= m_lookup->InventoryTypeSize.Bank) { fail_state = swapNotAllowed; return false; } - } - else if (source_slot <= EQ::invbag::BANK_BAGS_END && source_slot >= EQ::invbag::BANK_BAGS_BEGIN) { + } else if (EQ::ValueWithin(source_slot, EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END)) { auto temp_slot = (source_slot - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT; if (temp_slot >= m_lookup->InventoryTypeSize.Bank) { fail_state = swapNotAllowed; @@ -308,26 +301,23 @@ bool EQ::InventoryProfile::SwapItem( } } - if (destination_slot <= EQ::invslot::POSSESSIONS_END && destination_slot >= EQ::invslot::POSSESSIONS_BEGIN) { + if (EQ::ValueWithin(destination_slot, EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END)) { if ((((uint64)1 << destination_slot) & m_lookup->PossessionsBitmask) == 0) { fail_state = swapNotAllowed; return false; } - } - else if (destination_slot <= EQ::invbag::GENERAL_BAGS_END && destination_slot >= EQ::invbag::GENERAL_BAGS_BEGIN) { + } else if (EQ::ValueWithin(destination_slot, EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END)) { auto temp_slot = EQ::invslot::GENERAL_BEGIN + ((destination_slot - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT); if ((((uint64)1 << temp_slot) & m_lookup->PossessionsBitmask) == 0) { fail_state = swapNotAllowed; return false; } - } - else if (destination_slot <= EQ::invslot::BANK_END && destination_slot >= EQ::invslot::BANK_BEGIN) { + } else if (EQ::ValueWithin(destination_slot, EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END)) { if ((destination_slot - EQ::invslot::BANK_BEGIN) >= m_lookup->InventoryTypeSize.Bank) { fail_state = swapNotAllowed; return false; } - } - else if (destination_slot <= EQ::invbag::BANK_BAGS_END && destination_slot >= EQ::invbag::BANK_BAGS_BEGIN) { + } else if (EQ::ValueWithin(destination_slot, EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END)) { auto temp_slot = (destination_slot - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT; if (temp_slot >= m_lookup->InventoryTypeSize.Bank) { fail_state = swapNotAllowed; @@ -335,6 +325,7 @@ bool EQ::InventoryProfile::SwapItem( } } + // Temp holding areas for source and destination ItemInstance *source_item_instance = GetItem(source_slot); ItemInstance *destination_item_instance = GetItem(destination_slot); @@ -346,20 +337,23 @@ bool EQ::InventoryProfile::SwapItem( } source_item_instance->SetEvolveEquipped(false); - if ((destination_slot >= invslot::EQUIPMENT_BEGIN && destination_slot <= invslot::EQUIPMENT_END)) { + if (EQ::ValueWithin(destination_slot, invslot::EQUIPMENT_BEGIN, invslot::EQUIPMENT_END)) { auto source_item = source_item_instance->GetItem(); if (!source_item) { fail_state = swapNullData; return false; } + if (race_id && class_id && !source_item->IsEquipable(race_id, class_id)) { fail_state = swapRaceClass; return false; } + if (deity_id && source_item->Deity && !(Deity::GetBitmask(deity_id) & source_item->Deity)) { fail_state = swapDeity; return false; } + if (level && source_item->ReqLevel && level < source_item->ReqLevel) { fail_state = swapLevel; return false; @@ -377,20 +371,23 @@ bool EQ::InventoryProfile::SwapItem( } destination_item_instance->SetEvolveEquipped(false); - if ((source_slot >= invslot::EQUIPMENT_BEGIN && source_slot <= invslot::EQUIPMENT_END)) { + if (EQ::ValueWithin(source_slot, invslot::EQUIPMENT_BEGIN, invslot::EQUIPMENT_END)) { auto destination_item = destination_item_instance->GetItem(); if (!destination_item) { fail_state = swapNullData; return false; } + if (race_id && class_id && !destination_item->IsEquipable(race_id, class_id)) { fail_state = swapRaceClass; return false; } + if (deity_id && destination_item->Deity && !(Deity::GetBitmask(deity_id) & destination_item->Deity)) { fail_state = swapDeity; return false; } + if (level && destination_item->ReqLevel && level < destination_item->ReqLevel) { fail_state = swapLevel; return false; @@ -449,10 +446,8 @@ bool EQ::InventoryProfile::DeleteItem(int16 slot_id, int16 quantity) { bool EQ::InventoryProfile::CheckNoDrop(int16 slot_id, bool recurse) { ItemInstance* inst = GetItem(slot_id); - if (!inst) - return false; - return (!inst->IsDroppable(recurse)); + return inst ? !inst->IsDroppable(recurse) : false; } // Remove item from bucket without memory delete @@ -463,40 +458,32 @@ EQ::ItemInstance* EQ::InventoryProfile::PopItem(int16 slot_id) if (slot_id == invslot::slotCursor) { p = m_cursor.pop(); - } - else if (slot_id >= invslot::EQUIPMENT_BEGIN && slot_id <= invslot::EQUIPMENT_END) { + } else if (EQ::ValueWithin(slot_id, invslot::EQUIPMENT_BEGIN, invslot::EQUIPMENT_END)) { p = m_worn[slot_id]; m_worn.erase(slot_id); - } - else if (slot_id >= invslot::GENERAL_BEGIN && slot_id <= invslot::GENERAL_END) { + } else if (EQ::ValueWithin(slot_id, invslot::GENERAL_BEGIN, invslot::GENERAL_END)) { p = m_inv[slot_id]; m_inv.erase(slot_id); - } - else if (slot_id >= invslot::TRIBUTE_BEGIN && slot_id <= invslot::TRIBUTE_END) { + } else if (EQ::ValueWithin(slot_id, invslot::TRIBUTE_BEGIN, invslot::TRIBUTE_END)) { p = m_worn[slot_id]; m_worn.erase(slot_id); - } - else if (slot_id >= invslot::GUILD_TRIBUTE_BEGIN && slot_id <= invslot::GUILD_TRIBUTE_END) { + } else if (EQ::ValueWithin(slot_id, invslot::GUILD_TRIBUTE_BEGIN, invslot::GUILD_TRIBUTE_END)) { p = m_worn[slot_id]; m_worn.erase(slot_id); - } - else if (slot_id >= invslot::BANK_BEGIN && slot_id <= invslot::BANK_END) { + } else if (EQ::ValueWithin(slot_id, invslot::BANK_BEGIN, invslot::BANK_END)) { p = m_bank[slot_id]; m_bank.erase(slot_id); - } - else if (slot_id >= invslot::SHARED_BANK_BEGIN && slot_id <= invslot::SHARED_BANK_END) { + } else if (EQ::ValueWithin(slot_id, invslot::SHARED_BANK_BEGIN, invslot::SHARED_BANK_END)) { p = m_shbank[slot_id]; m_shbank.erase(slot_id); - } - else if (slot_id >= invslot::TRADE_BEGIN && slot_id <= invslot::TRADE_END) { + } else if (EQ::ValueWithin(slot_id, invslot::TRADE_BEGIN, invslot::TRADE_END)) { p = m_trade[slot_id]; m_trade.erase(slot_id); - } - else { - // Is slot inside bag? - ItemInstance* baginst = GetItem(InventoryProfile::CalcSlotId(slot_id)); - if (baginst != nullptr && baginst->IsClassBag()) { - p = baginst->PopItem(InventoryProfile::CalcBagIdx(slot_id)); + } else { + // Is slot inside bag? + ItemInstance* bag_inst = GetItem(InventoryProfile::CalcSlotId(slot_id)); + if (bag_inst && bag_inst->IsClassBag()) { + p = bag_inst->PopItem(InventoryProfile::CalcBagIdx(slot_id)); } } @@ -504,43 +491,49 @@ EQ::ItemInstance* EQ::InventoryProfile::PopItem(int16 slot_id) return p; } -bool EQ::InventoryProfile::HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity) { - +bool EQ::InventoryProfile::HasSpaceForItem(const ItemData* ItemToTry, int16 Quantity) +{ if (ItemToTry->Stackable) { - for (int16 i = invslot::GENERAL_BEGIN; i <= invslot::GENERAL_END; i++) { - if ((((uint64)1 << i) & m_lookup->PossessionsBitmask) == 0) + if ((((uint64) 1 << i) & m_lookup->PossessionsBitmask) == 0) { continue; - - ItemInstance* InvItem = GetItem(i); - - if (InvItem && (InvItem->GetItem()->ID == ItemToTry->ID) && (InvItem->GetCharges() < InvItem->GetItem()->StackSize)) { - - int ChargeSlotsLeft = InvItem->GetItem()->StackSize - InvItem->GetCharges(); - - if (Quantity <= ChargeSlotsLeft) - return true; - - Quantity -= ChargeSlotsLeft; - } - if (InvItem && InvItem->IsClassBag()) { - int16 BaseSlotID = InventoryProfile::CalcSlotId(i, invbag::SLOT_BEGIN); - uint8 BagSize = InvItem->GetItem()->BagSlots; - for (uint8 BagSlot = invbag::SLOT_BEGIN; BagSlot < BagSize; BagSlot++) { + ItemInstance* inv_item = GetItem(i); - InvItem = GetItem(BaseSlotID + BagSlot); + if ( + inv_item && + inv_item->GetItem()->ID == ItemToTry->ID && + inv_item->GetCharges() < inv_item->GetItem()->StackSize + ) { + int charges_left = inv_item->GetItem()->StackSize - inv_item->GetCharges(); - if (InvItem && (InvItem->GetItem()->ID == ItemToTry->ID) && - (InvItem->GetCharges() < InvItem->GetItem()->StackSize)) { + if (Quantity <= charges_left) { + return true; + } - int ChargeSlotsLeft = InvItem->GetItem()->StackSize - InvItem->GetCharges(); + Quantity -= charges_left; + } - if (Quantity <= ChargeSlotsLeft) + if (inv_item && inv_item->IsClassBag()) { + int16 base_slot_id = InventoryProfile::CalcSlotId(i, invbag::SLOT_BEGIN); + uint8 bag_slots = inv_item->GetItem()->BagSlots; + + for (uint8 bag_slot = invbag::SLOT_BEGIN; bag_slot < bag_slots; bag_slot++) { + inv_item = GetItem(base_slot_id + bag_slot); + + if ( + inv_item && + inv_item->GetItem()->ID == ItemToTry->ID && + inv_item->GetCharges() < inv_item->GetItem()->StackSize + ) { + int charges_left = inv_item->GetItem()->StackSize - inv_item->GetCharges(); + + if (Quantity <= charges_left) { return true; + } - Quantity -= ChargeSlotsLeft; + Quantity -= charges_left; } } } @@ -548,51 +541,46 @@ bool EQ::InventoryProfile::HasSpaceForItem(const ItemData *ItemToTry, int16 Quan } for (int16 i = invslot::GENERAL_BEGIN; i <= invslot::GENERAL_END; i++) { - if ((((uint64)1 << i) & m_lookup->PossessionsBitmask) == 0) + if ((((uint64) 1 << i) & m_lookup->PossessionsBitmask) == 0) { continue; - - ItemInstance* InvItem = GetItem(i); - - if (!InvItem) { - - if (!ItemToTry->Stackable) { - - if (Quantity == 1) - return true; - else - Quantity--; - } - else { - if (Quantity <= ItemToTry->StackSize) - return true; - else - Quantity -= ItemToTry->StackSize; - } - } - else if (InvItem->IsClassBag() && CanItemFitInContainer(ItemToTry, InvItem->GetItem())) { - int16 BaseSlotID = InventoryProfile::CalcSlotId(i, invbag::SLOT_BEGIN); + ItemInstance* inv_item = GetItem(i); - uint8 BagSize = InvItem->GetItem()->BagSlots; + if (!inv_item) { + if (!ItemToTry->Stackable) { + if (Quantity == 1) { + return true; + } else { + Quantity--; + } + } else { + if (Quantity <= ItemToTry->StackSize) { + return true; + } else { + Quantity -= ItemToTry->StackSize; + } + } + } else if (inv_item->IsClassBag() && CanItemFitInContainer(ItemToTry, inv_item->GetItem())) { + int16 base_slot_id = InventoryProfile::CalcSlotId(i, invbag::SLOT_BEGIN); + uint8 bag_slots = inv_item->GetItem()->BagSlots; - for (uint8 BagSlot = invbag::SLOT_BEGIN; BagSlot < BagSize; BagSlot++) { + for (uint8 bag_slot = invbag::SLOT_BEGIN; bag_slot < bag_slots; bag_slot++) { + inv_item = GetItem(base_slot_id + bag_slot); - InvItem = GetItem(BaseSlotID + BagSlot); - - if (!InvItem) { + if (!inv_item) { if (!ItemToTry->Stackable) { - - if (Quantity == 1) + if (Quantity == 1) { return true; - else + } else { Quantity--; - } - else { - if (Quantity <= ItemToTry->StackSize) + } + } else { + if (Quantity <= ItemToTry->StackSize) { return true; - else + } else { Quantity -= ItemToTry->StackSize; + } } } } @@ -600,7 +588,6 @@ bool EQ::InventoryProfile::HasSpaceForItem(const ItemData *ItemToTry, int16 Quan } return false; - } // Checks that user has at least 'quantity' number of items in a given inventory slot @@ -680,40 +667,46 @@ int16 EQ::InventoryProfile::HasItem(uint32 item_id, uint8 quantity, uint8 where) // Check each inventory bucket if (where & invWhereWorn) { slot_id = _HasItem(m_worn, item_id, quantity); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } if (where & invWherePersonal) { slot_id = _HasItem(m_inv, item_id, quantity); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } if (where & invWhereBank) { slot_id = _HasItem(m_bank, item_id, quantity); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } if (where & invWhereSharedBank) { slot_id = _HasItem(m_shbank, item_id, quantity); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } if (where & invWhereTrading) { slot_id = _HasItem(m_trade, item_id, quantity); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } // Behavioral change - Limbo is no longer checked due to improper handling of return value if (where & invWhereCursor) { // Check cursor queue slot_id = _HasItem(m_cursor, item_id, quantity); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } return slot_id; @@ -727,40 +720,46 @@ int16 EQ::InventoryProfile::HasItemByUse(uint8 use, uint8 quantity, uint8 where) // Check each inventory bucket if (where & invWhereWorn) { slot_id = _HasItemByUse(m_worn, use, quantity); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } if (where & invWherePersonal) { slot_id = _HasItemByUse(m_inv, use, quantity); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } if (where & invWhereBank) { slot_id = _HasItemByUse(m_bank, use, quantity); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } if (where & invWhereSharedBank) { slot_id = _HasItemByUse(m_shbank, use, quantity); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } if (where & invWhereTrading) { slot_id = _HasItemByUse(m_trade, use, quantity); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } // Behavioral change - Limbo is no longer checked due to improper handling of return value if (where & invWhereCursor) { // Check cursor queue slot_id = _HasItemByUse(m_cursor, use, quantity); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } return slot_id; @@ -773,40 +772,46 @@ int16 EQ::InventoryProfile::HasItemByLoreGroup(uint32 loregroup, uint8 where) // Check each inventory bucket if (where & invWhereWorn) { slot_id = _HasItemByLoreGroup(m_worn, loregroup); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } if (where & invWherePersonal) { slot_id = _HasItemByLoreGroup(m_inv, loregroup); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } if (where & invWhereBank) { slot_id = _HasItemByLoreGroup(m_bank, loregroup); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } if (where & invWhereSharedBank) { slot_id = _HasItemByLoreGroup(m_shbank, loregroup); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } if (where & invWhereTrading) { slot_id = _HasItemByLoreGroup(m_trade, loregroup); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } // Behavioral change - Limbo is no longer checked due to improper handling of return value if (where & invWhereCursor) { // Check cursor queue slot_id = _HasItemByLoreGroup(m_cursor, loregroup); - if (slot_id != INVALID_INDEX) + if (slot_id != INVALID_INDEX) { return slot_id; + } } return slot_id; @@ -834,7 +839,7 @@ int16 EQ::InventoryProfile::FindFreeSlot(bool for_bag, bool try_cursor, uint8 mi continue; } - const auto *inst = GetItem(i); + const EQ::ItemInstance* inst = GetItem(i); if (inst && inst->IsClassBag() && inst->GetItem()->BagSize >= min_size) { if (inst->GetItem()->BagType == item::BagTypeQuiver && inst->GetItem()->ItemType != item::ItemTypeArrow) { @@ -842,8 +847,8 @@ int16 EQ::InventoryProfile::FindFreeSlot(bool for_bag, bool try_cursor, uint8 mi } const int16 base_slot_id = InventoryProfile::CalcSlotId(i, invbag::SLOT_BEGIN); + const uint8 slots = inst->GetItem()->BagSlots; - const uint8 slots = inst->GetItem()->BagSlots; for (uint8 j = invbag::SLOT_BEGIN; j < slots; j++) { if (!GetItem(base_slot_id + j)) { // Found available slot within bag @@ -871,22 +876,25 @@ int16 EQ::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst, i // // I'll probably implement a bitmask in the new inventory system to avoid having to adjust stack bias - if ((general_start < invslot::GENERAL_BEGIN) || (general_start > invslot::GENERAL_END)) - return INVALID_INDEX; - if (bag_start > invbag::SLOT_END) - return INVALID_INDEX; - - if (!inst || !inst->GetID()) + if ( + !EQ::ValueWithin(general_start, invslot::GENERAL_BEGIN, invslot::GENERAL_END) || + bag_start > invbag::SLOT_END || + !inst || + !inst->GetID() + ) { return INVALID_INDEX; + } // step 1: find room for bags (caller should really ask for slots for bags first to avoid sending them to cursor..and bag item loss) if (inst->IsClassBag()) { for (int16 free_slot = general_start; free_slot <= invslot::GENERAL_END; ++free_slot) { - if ((((uint64)1 << free_slot) & m_lookup->PossessionsBitmask) == 0) + if ((((uint64) 1 << free_slot) & m_lookup->PossessionsBitmask) == 0) { continue; + } - if (!m_inv[free_slot]) + if (!m_inv[free_slot]) { return free_slot; + } } return invslot::slotCursor; // return cursor since bags do not stack and will not fit inside other bags..yet...) @@ -895,37 +903,55 @@ int16 EQ::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst, i // step 2: find partial room for stackables if (inst->IsStackable()) { for (int16 free_slot = general_start; free_slot <= invslot::GENERAL_END; ++free_slot) { - if ((((uint64)1 << free_slot) & m_lookup->PossessionsBitmask) == 0) + if ((((uint64) 1 << free_slot) & m_lookup->PossessionsBitmask) == 0) { continue; + } const ItemInstance* main_inst = m_inv[free_slot]; - if (!main_inst) + if (!main_inst) { continue; + } - if ((main_inst->GetID() == inst->GetID()) && (main_inst->GetCharges() < main_inst->GetItem()->StackSize)) + if ( + main_inst->GetID() == inst->GetID() && + main_inst->GetCharges() < main_inst->GetItem()->StackSize + ) { return free_slot; + } } for (int16 free_slot = general_start; free_slot <= invslot::GENERAL_END; ++free_slot) { - if ((((uint64)1 << free_slot) & m_lookup->PossessionsBitmask) == 0) + if ((((uint64) 1 << free_slot) & m_lookup->PossessionsBitmask) == 0) { continue; + } const ItemInstance* main_inst = m_inv[free_slot]; - if (!main_inst) + if (!main_inst) { continue; + } if (main_inst->IsClassBag()) { // if item-specific containers already have bad items, we won't fix it here... uint8 _bag_start = (free_slot > general_start) ? invbag::SLOT_BEGIN : bag_start; - for (uint8 free_bag_slot = _bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot <= invbag::SLOT_END); ++free_bag_slot) { + + for ( + uint8 free_bag_slot = _bag_start; + (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot <= invbag::SLOT_END); + ++free_bag_slot + ) { const ItemInstance* sub_inst = main_inst->GetItem(free_bag_slot); - if (!sub_inst) + if (!sub_inst) { continue; + } - if ((sub_inst->GetID() == inst->GetID()) && (sub_inst->GetCharges() < sub_inst->GetItem()->StackSize)) + if ( + sub_inst->GetID() == inst->GetID() && + sub_inst->GetCharges() < sub_inst->GetItem()->StackSize + ) { return InventoryProfile::CalcSlotId(free_slot, free_bag_slot); + } } } } @@ -934,18 +960,30 @@ int16 EQ::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst, i // step 3a: find room for container-specific items (ItemClassArrow) if (inst->GetItem()->ItemType == item::ItemTypeArrow) { for (int16 free_slot = general_start; free_slot <= invslot::GENERAL_END; ++free_slot) { - if ((((uint64)1 << free_slot) & m_lookup->PossessionsBitmask) == 0) + if ((((uint64) 1 << free_slot) & m_lookup->PossessionsBitmask) == 0) { continue; + } const ItemInstance* main_inst = m_inv[free_slot]; - if (!main_inst || (main_inst->GetItem()->BagType != item::BagTypeQuiver) || !main_inst->IsClassBag()) + if ( + !main_inst || + main_inst->GetItem()->BagType != item::BagTypeQuiver || + !main_inst->IsClassBag() + ) { continue; + } uint8 _bag_start = (free_slot > general_start) ? invbag::SLOT_BEGIN : bag_start; - for (uint8 free_bag_slot = _bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot <= invbag::SLOT_END); ++free_bag_slot) { - if (!main_inst->GetItem(free_bag_slot)) + + for ( + uint8 free_bag_slot = _bag_start; + (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot <= invbag::SLOT_END); + ++free_bag_slot + ) { + if (!main_inst->GetItem(free_bag_slot)) { return InventoryProfile::CalcSlotId(free_slot, free_bag_slot); + } } } } @@ -953,47 +991,73 @@ int16 EQ::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst, i // step 3b: find room for container-specific items (ItemClassSmallThrowing) if (inst->GetItem()->ItemType == item::ItemTypeSmallThrowing) { for (int16 free_slot = general_start; free_slot <= invslot::GENERAL_END; ++free_slot) { - if ((((uint64)1 << free_slot) & m_lookup->PossessionsBitmask) == 0) + if ((((uint64) 1 << free_slot) & m_lookup->PossessionsBitmask) == 0) { continue; + } const ItemInstance* main_inst = m_inv[free_slot]; - if (!main_inst || (main_inst->GetItem()->BagType != item::BagTypeBandolier) || !main_inst->IsClassBag()) + if ( + !main_inst || + main_inst->GetItem()->BagType != item::BagTypeBandolier || + !main_inst->IsClassBag() + ) { continue; + } uint8 _bag_start = (free_slot > general_start) ? invbag::SLOT_BEGIN : bag_start; - for (uint8 free_bag_slot = _bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot <= invbag::SLOT_END); ++free_bag_slot) { - if (!main_inst->GetItem(free_bag_slot)) + + for ( + uint8 free_bag_slot = _bag_start; + (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot <= invbag::SLOT_END); + ++free_bag_slot + ) { + if (!main_inst->GetItem(free_bag_slot)) { return InventoryProfile::CalcSlotId(free_slot, free_bag_slot); + } } } } // step 4: just find an empty slot for (int16 free_slot = general_start; free_slot <= invslot::GENERAL_END; ++free_slot) { - if ((((uint64)1 << free_slot) & m_lookup->PossessionsBitmask) == 0) + if ((((uint64) 1 << free_slot) & m_lookup->PossessionsBitmask) == 0) { continue; + } const ItemInstance* main_inst = m_inv[free_slot]; - if (!main_inst) + if (!main_inst) { return free_slot; + } } for (int16 free_slot = general_start; free_slot <= invslot::GENERAL_END; ++free_slot) { - if ((((uint64)1 << free_slot) & m_lookup->PossessionsBitmask) == 0) + if ((((uint64) 1 << free_slot) & m_lookup->PossessionsBitmask) == 0) { continue; + } const ItemInstance* main_inst = m_inv[free_slot]; if (main_inst && main_inst->IsClassBag()) { - if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == item::BagTypeBandolier) || (main_inst->GetItem()->BagType == item::BagTypeQuiver)) + if ( + main_inst->GetItem()->BagSize < inst->GetItem()->Size || + main_inst->GetItem()->BagType == item::BagTypeBandolier || + main_inst->GetItem()->BagType == item::BagTypeQuiver + ) { continue; + } uint8 _bag_start = (free_slot > general_start) ? invbag::SLOT_BEGIN : bag_start; - for (uint8 free_bag_slot = _bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot <= invbag::SLOT_END); ++free_bag_slot) { - if (!main_inst->GetItem(free_bag_slot)) + + for ( + uint8 free_bag_slot = _bag_start; + (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot <= invbag::SLOT_END); + ++free_bag_slot + ) { + if (!main_inst->GetItem(free_bag_slot)) { return InventoryProfile::CalcSlotId(free_slot, free_bag_slot); + } } } } @@ -1003,7 +1067,8 @@ int16 EQ::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst, i } // Opposite of below: Get parent bag slot_id from a slot inside of bag -int16 EQ::InventoryProfile::CalcSlotId(int16 slot_id) { +int16 EQ::InventoryProfile::CalcSlotId(int16 slot_id) +{ int16 parent_slot_id = INVALID_INDEX; // this is not a bag range... using this risks over-writing existing items @@ -1011,19 +1076,15 @@ int16 EQ::InventoryProfile::CalcSlotId(int16 slot_id) { // parent_slot_id = EmuConstants::BANK_BEGIN + (slot_id - EmuConstants::BANK_BEGIN) / EmuConstants::ITEM_CONTAINER_SIZE; //else if (slot_id >= 3100 && slot_id <= 3179) should be {3031..3110}..where did this range come from!!? (verified db save range) - if (slot_id >= invbag::GENERAL_BAGS_BEGIN && slot_id <= invbag::GENERAL_BAGS_END) { + if (EQ::ValueWithin(slot_id, invbag::GENERAL_BAGS_BEGIN, invbag::GENERAL_BAGS_END)) { parent_slot_id = invslot::GENERAL_BEGIN + (slot_id - invbag::GENERAL_BAGS_BEGIN) / invbag::SLOT_COUNT; - } - else if (slot_id >= invbag::CURSOR_BAG_BEGIN && slot_id <= invbag::CURSOR_BAG_END) { + } else if (EQ::ValueWithin(slot_id, invbag::CURSOR_BAG_BEGIN, invbag::CURSOR_BAG_END)) { parent_slot_id = invslot::slotCursor; - } - else if (slot_id >= invbag::BANK_BAGS_BEGIN && slot_id <= invbag::BANK_BAGS_END) { + } else if (EQ::ValueWithin(slot_id, invbag::BANK_BAGS_BEGIN, invbag::BANK_BAGS_END)) { parent_slot_id = invslot::BANK_BEGIN + (slot_id - invbag::BANK_BAGS_BEGIN) / invbag::SLOT_COUNT; - } - else if (slot_id >= invbag::SHARED_BANK_BAGS_BEGIN && slot_id <= invbag::SHARED_BANK_BAGS_END) { + } else if (EQ::ValueWithin(slot_id, invbag::SHARED_BANK_BAGS_BEGIN, invbag::SHARED_BANK_BAGS_END)) { parent_slot_id = invslot::SHARED_BANK_BEGIN + (slot_id - invbag::SHARED_BANK_BAGS_BEGIN) / invbag::SLOT_COUNT; - } - else if (slot_id >= invbag::TRADE_BAGS_BEGIN && slot_id <= invbag::TRADE_BAGS_END) { + } else if (EQ::ValueWithin(slot_id, invbag::TRADE_BAGS_BEGIN, invbag::TRADE_BAGS_END)) { parent_slot_id = invslot::TRADE_BEGIN + (slot_id - invbag::TRADE_BAGS_BEGIN) / invbag::SLOT_COUNT; } @@ -1031,25 +1092,23 @@ int16 EQ::InventoryProfile::CalcSlotId(int16 slot_id) { } // Calculate slot_id for an item within a bag -int16 EQ::InventoryProfile::CalcSlotId(int16 bagslot_id, uint8 bagidx) { - if (!InventoryProfile::SupportsContainers(bagslot_id)) +int16 EQ::InventoryProfile::CalcSlotId(int16 bagslot_id, uint8 bagidx) +{ + if (!InventoryProfile::SupportsContainers(bagslot_id)) { return INVALID_INDEX; + } int16 slot_id = INVALID_INDEX; - if (bagslot_id == invslot::slotCursor || bagslot_id == 8000) { + if (bagslot_id == invslot::slotCursor) { slot_id = invbag::CURSOR_BAG_BEGIN + bagidx; - } - else if (bagslot_id >= invslot::GENERAL_BEGIN && bagslot_id <= invslot::GENERAL_END) { + } else if (EQ::ValueWithin(bagslot_id, invslot::GENERAL_BEGIN, invslot::GENERAL_END)) { slot_id = invbag::GENERAL_BAGS_BEGIN + (bagslot_id - invslot::GENERAL_BEGIN) * invbag::SLOT_COUNT + bagidx; - } - else if (bagslot_id >= invslot::BANK_BEGIN && bagslot_id <= invslot::BANK_END) { + } else if (EQ::ValueWithin(bagslot_id, invslot::BANK_BEGIN, invslot::BANK_END)) { slot_id = invbag::BANK_BAGS_BEGIN + (bagslot_id - invslot::BANK_BEGIN) * invbag::SLOT_COUNT + bagidx; - } - else if (bagslot_id >= invslot::SHARED_BANK_BEGIN && bagslot_id <= invslot::SHARED_BANK_END) { + } else if (EQ::ValueWithin(bagslot_id, invslot::SHARED_BANK_BEGIN, invslot::SHARED_BANK_END)) { slot_id = invbag::SHARED_BANK_BAGS_BEGIN + (bagslot_id - invslot::SHARED_BANK_BEGIN) * invbag::SLOT_COUNT + bagidx; - } - else if (bagslot_id >= invslot::TRADE_BEGIN && bagslot_id <= invslot::TRADE_END) { + } else if (EQ::ValueWithin(bagslot_id, invslot::TRADE_BEGIN, invslot::TRADE_END)) { slot_id = invbag::TRADE_BAGS_BEGIN + (bagslot_id - invslot::TRADE_BEGIN) * invbag::SLOT_COUNT + bagidx; } @@ -1059,26 +1118,17 @@ int16 EQ::InventoryProfile::CalcSlotId(int16 bagslot_id, uint8 bagidx) { uint8 EQ::InventoryProfile::CalcBagIdx(int16 slot_id) { uint8 index = 0; - // this is not a bag range... using this risks over-writing existing items - //else if (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END) - // index = (slot_id - EmuConstants::BANK_BEGIN) % EmuConstants::ITEM_CONTAINER_SIZE; - - if (slot_id >= invbag::GENERAL_BAGS_BEGIN && slot_id <= invbag::GENERAL_BAGS_END) { + if (EQ::ValueWithin(slot_id, invbag::GENERAL_BAGS_BEGIN, invbag::GENERAL_BAGS_END)) { index = (slot_id - invbag::GENERAL_BAGS_BEGIN) % invbag::SLOT_COUNT; - } - else if (slot_id >= invbag::CURSOR_BAG_BEGIN && slot_id <= invbag::CURSOR_BAG_END) { + } else if (EQ::ValueWithin(slot_id, invbag::CURSOR_BAG_BEGIN, invbag::CURSOR_BAG_END)) { index = (slot_id - invbag::CURSOR_BAG_BEGIN); // % invbag::SLOT_COUNT; - not needed since range is 10 slots - } - else if (slot_id >= invbag::BANK_BAGS_BEGIN && slot_id <= invbag::BANK_BAGS_END) { + } else if (EQ::ValueWithin(slot_id, invbag::BANK_BAGS_BEGIN, invbag::BANK_BAGS_END)) { index = (slot_id - invbag::BANK_BAGS_BEGIN) % invbag::SLOT_COUNT; - } - else if (slot_id >= invbag::SHARED_BANK_BAGS_BEGIN && slot_id <= invbag::SHARED_BANK_BAGS_END) { + } else if (EQ::ValueWithin(slot_id, invbag::SHARED_BANK_BAGS_BEGIN, invbag::SHARED_BANK_BAGS_END)) { index = (slot_id - invbag::SHARED_BANK_BAGS_BEGIN) % invbag::SLOT_COUNT; - } - else if (slot_id >= invbag::TRADE_BAGS_BEGIN && slot_id <= invbag::TRADE_BAGS_END) { + } else if (EQ::ValueWithin(slot_id, invbag::TRADE_BAGS_BEGIN, invbag::TRADE_BAGS_END)) { index = (slot_id - invbag::TRADE_BAGS_BEGIN) % invbag::SLOT_COUNT; - } - else if (slot_id >= invslot::WORLD_BEGIN && slot_id <= invslot::WORLD_END) { + } else if (EQ::ValueWithin(slot_id, invslot::WORLD_BEGIN, invslot::WORLD_END)) { index = (slot_id - invslot::WORLD_BEGIN); // % invbag::SLOT_COUNT; - not needed since range is 10 slots } @@ -1114,45 +1164,53 @@ int16 EQ::InventoryProfile::CalcSlotFromMaterial(uint8 material) uint8 EQ::InventoryProfile::CalcMaterialFromSlot(int16 equipslot) { - switch (equipslot) - { - case invslot::slotHead: - return textures::armorHead; - case invslot::slotChest: - return textures::armorChest; - case invslot::slotArms: - return textures::armorArms; - case invslot::slotWrist1: - //case SLOT_BRACER02: // non-live behavior - return textures::armorWrist; - case invslot::slotHands: - return textures::armorHands; - case invslot::slotLegs: - return textures::armorLegs; - case invslot::slotFeet: - return textures::armorFeet; - case invslot::slotPrimary: - return textures::weaponPrimary; - case invslot::slotSecondary: - return textures::weaponSecondary; - default: - return textures::materialInvalid; + switch (equipslot) { + case invslot::slotHead: + return textures::armorHead; + case invslot::slotChest: + return textures::armorChest; + case invslot::slotArms: + return textures::armorArms; + case invslot::slotWrist1: + return textures::armorWrist; + case invslot::slotHands: + return textures::armorHands; + case invslot::slotLegs: + return textures::armorLegs; + case invslot::slotFeet: + return textures::armorFeet; + case invslot::slotPrimary: + return textures::weaponPrimary; + case invslot::slotSecondary: + return textures::weaponSecondary; + default: + return textures::materialInvalid; } } bool EQ::InventoryProfile::CanItemFitInContainer(const ItemData *ItemToTry, const ItemData *Container) { - if (!ItemToTry || !Container) + if (!ItemToTry || !Container) { return false; + } - if (ItemToTry->Size > Container->BagSize) + if (ItemToTry->Size > Container->BagSize) { return false; + } - if ((Container->BagType == item::BagTypeQuiver) && (ItemToTry->ItemType != item::ItemTypeArrow)) + if ( + Container->BagType == item::BagTypeQuiver && + ItemToTry->ItemType != item::ItemTypeArrow + ) { return false; + } - if ((Container->BagType == item::BagTypeBandolier) && (ItemToTry->ItemType != item::ItemTypeSmallThrowing)) + if ( + Container->BagType == item::BagTypeBandolier && + ItemToTry->ItemType != item::ItemTypeSmallThrowing + ) { return false; + } return true; } @@ -1160,15 +1218,14 @@ bool EQ::InventoryProfile::CanItemFitInContainer(const ItemData *ItemToTry, cons bool EQ::InventoryProfile::SupportsClickCasting(int16 slot_id) { // there are a few non-potion items that identify as ItemTypePotion..so, we still need to ubiquitously include the equipment range - if (slot_id >= invslot::EQUIPMENT_BEGIN && slot_id <= invslot::EQUIPMENT_END) { + if (EQ::ValueWithin(slot_id, invslot::EQUIPMENT_BEGIN, invslot::EQUIPMENT_END)) { return true; - } - else if (slot_id >= invslot::GENERAL_BEGIN && slot_id <= invslot::GENERAL_END) { + } else if (EQ::ValueWithin(slot_id, invslot::GENERAL_BEGIN, invslot::GENERAL_END)) { return true; - } - else if (slot_id >= invbag::GENERAL_BAGS_BEGIN && slot_id <= invbag::GENERAL_BAGS_END) { - if (inventory::StaticLookup(m_mob_version)->AllowClickCastFromBag) + } else if (EQ::ValueWithin(slot_id, invbag::GENERAL_BAGS_BEGIN, invbag::GENERAL_BAGS_END)) { + if (inventory::StaticLookup(m_mob_version)->AllowClickCastFromBag) { return true; + } } return false; @@ -1177,13 +1234,11 @@ bool EQ::InventoryProfile::SupportsClickCasting(int16 slot_id) bool EQ::InventoryProfile::SupportsPotionBeltCasting(int16 slot_id) { // does this have the same criteria as 'SupportsClickCasting' above? (bag clicking per client) - if (slot_id >= invslot::EQUIPMENT_BEGIN && slot_id <= invslot::EQUIPMENT_END) { + if (EQ::ValueWithin(slot_id, invslot::EQUIPMENT_BEGIN, invslot::EQUIPMENT_END)) { return true; - } - else if (slot_id >= invslot::GENERAL_BEGIN && slot_id <= invslot::GENERAL_END) { + } else if (EQ::ValueWithin(slot_id, invslot::GENERAL_BEGIN, invslot::GENERAL_END)) { return true; - } - else if (slot_id >= invbag::GENERAL_BAGS_BEGIN && slot_id <= invbag::GENERAL_BAGS_END) { + } else if (EQ::ValueWithin(slot_id, invbag::GENERAL_BAGS_BEGIN, invbag::GENERAL_BAGS_END)) { return true; } @@ -1193,11 +1248,12 @@ bool EQ::InventoryProfile::SupportsPotionBeltCasting(int16 slot_id) // Test whether a given slot can support a container item bool EQ::InventoryProfile::SupportsContainers(int16 slot_id) { - if ((slot_id == invslot::slotCursor) || - (slot_id >= invslot::GENERAL_BEGIN && slot_id <= invslot::GENERAL_END) || - (slot_id >= invslot::BANK_BEGIN && slot_id <= invslot::BANK_END) || - (slot_id >= invslot::SHARED_BANK_BEGIN && slot_id <= invslot::SHARED_BANK_END) || - (slot_id >= invslot::TRADE_BEGIN && slot_id <= invslot::TRADE_END) + if ( + slot_id == invslot::slotCursor || + EQ::ValueWithin(slot_id, invslot::GENERAL_BEGIN, invslot::GENERAL_END) || + EQ::ValueWithin(slot_id, invslot::BANK_BEGIN, invslot::BANK_END) || + EQ::ValueWithin(slot_id, invslot::SHARED_BANK_BEGIN, invslot::SHARED_BANK_END) || + EQ::ValueWithin(slot_id, invslot::TRADE_BEGIN, invslot::TRADE_END) ) { return true; } @@ -1246,84 +1302,65 @@ uint8 EQ::InventoryProfile::FindBrightestLightType() uint8 brightest_light_type = 0; for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) { - if ((iter->first < invslot::EQUIPMENT_BEGIN || iter->first > invslot::EQUIPMENT_END)) + if (!EQ::ValueWithin(iter->first, invslot::EQUIPMENT_BEGIN, invslot::EQUIPMENT_END)) { continue; + } - if (iter->first == invslot::slotAmmo) + if (iter->first == invslot::slotAmmo) { continue; + } - auto inst = iter->second; - if (inst == nullptr) + EQ::ItemInstance* inst = iter->second; + if (!inst) { continue; + } - auto item = inst->GetItem(); - if (item == nullptr) + const EQ::ItemData* item = inst->GetItem(); + if (!item) { continue; + } - if (lightsource::IsLevelGreater(item->Light, brightest_light_type)) + if (lightsource::IsLevelGreater(item->Light, brightest_light_type)) { brightest_light_type = item->Light; + } } uint8 general_light_type = 0; for (auto iter = m_inv.begin(); iter != m_inv.end(); ++iter) { - if (iter->first < invslot::GENERAL_BEGIN || iter->first > invslot::GENERAL_END) + if (!EQ::ValueWithin(iter->first, invslot::GENERAL_BEGIN, invslot::GENERAL_END)) { continue; + } - auto inst = iter->second; - if (inst == nullptr) + EQ::ItemInstance* inst = iter->second; + if (!inst) { continue; + } - auto item = inst->GetItem(); - if (item == nullptr) + const EQ::ItemData* item = inst->GetItem(); + if (!item) { continue; + } - if (!item->IsClassCommon()) - continue; - if (item->Light < 9 || item->Light > 13) + if (!item->IsClassCommon()) { continue; + } - if (lightsource::TypeToLevel(item->Light)) + if (!EQ::ValueWithin(item->Light, 9, 13)) { + continue; + } + + if (lightsource::TypeToLevel(item->Light)) { general_light_type = item->Light; + } } - if (lightsource::IsLevelGreater(general_light_type, brightest_light_type)) + if (lightsource::IsLevelGreater(general_light_type, brightest_light_type)) { brightest_light_type = general_light_type; + } return brightest_light_type; } -void EQ::InventoryProfile::dumpEntireInventory() { - - dumpWornItems(); - dumpInventory(); - dumpBankItems(); - dumpSharedBankItems(); - - std::cout << std::endl; -} - -void EQ::InventoryProfile::dumpWornItems() { - std::cout << "Worn items:" << std::endl; - dumpItemCollection(m_worn); -} - -void EQ::InventoryProfile::dumpInventory() { - std::cout << "Inventory items:" << std::endl; - dumpItemCollection(m_inv); -} - -void EQ::InventoryProfile::dumpBankItems() { - - std::cout << "Bank items:" << std::endl; - dumpItemCollection(m_bank); -} - -void EQ::InventoryProfile::dumpSharedBankItems() { - - std::cout << "Shared Bank items:" << std::endl; - dumpItemCollection(m_shbank); -} - int EQ::InventoryProfile::GetSlotByItemInstCollection(const std::map &collection, ItemInstance *inst) { for (auto iter = collection.begin(); iter != collection.end(); ++iter) { ItemInstance *t_inst = iter->second; @@ -1343,57 +1380,22 @@ int EQ::InventoryProfile::GetSlotByItemInstCollection(const std::map &collection) -{ - for (auto it = collection.cbegin(); it != collection.cend(); ++it) { - auto inst = it->second; - if (!inst || !inst->GetItem()) - continue; - - std::string slot = StringFormat("Slot %d: %s (%d)", it->first, it->second->GetItem()->Name, (inst->GetCharges() <= 0) ? 1 : inst->GetCharges()); - std::cout << slot << std::endl; - - dumpBagContents(inst, &it); - } -} - -void EQ::InventoryProfile::dumpBagContents(ItemInstance *inst, std::map::const_iterator *it) -{ - if (!inst || !inst->IsClassBag()) - return; - - // Go through bag, if bag - for (auto itb = inst->_cbegin(); itb != inst->_cend(); ++itb) { - ItemInstance* baginst = itb->second; - if (!baginst || !baginst->GetItem()) - continue; - - std::string subSlot = StringFormat(" Slot %d: %s (%d)", InventoryProfile::CalcSlotId((*it)->first, itb->first), - baginst->GetItem()->Name, (baginst->GetCharges() <= 0) ? 1 : baginst->GetCharges()); - std::cout << subSlot << std::endl; - } - -} - // Internal Method: Retrieves item within an inventory bucket EQ::ItemInstance* EQ::InventoryProfile::_GetItem(const std::map& bucket, int16 slot_id) const { - if (slot_id <= EQ::invslot::POSSESSIONS_END && slot_id >= EQ::invslot::POSSESSIONS_BEGIN) { - if ((((uint64)1 << slot_id) & m_lookup->PossessionsBitmask) == 0) + if (EQ::ValueWithin(slot_id, EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END)) { + if ((((uint64) 1 << slot_id) & m_lookup->PossessionsBitmask) == 0) { return nullptr; - } - else if (slot_id <= EQ::invslot::BANK_END && slot_id >= EQ::invslot::BANK_BEGIN) { - if (slot_id - EQ::invslot::BANK_BEGIN >= m_lookup->InventoryTypeSize.Bank) + } + } else if (EQ::ValueWithin(slot_id, EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END)) { + if (slot_id - EQ::invslot::BANK_BEGIN >= m_lookup->InventoryTypeSize.Bank) { return nullptr; + } } auto it = bucket.find(slot_id); - if (it != bucket.end()) { - return it->second; - } - // Not found! - return nullptr; + return it != bucket.end() ? it->second : nullptr; } // Internal Method: "put" item into bucket, without regard for what is currently in bucket @@ -1403,14 +1405,14 @@ int16 EQ::InventoryProfile::_PutItem(int16 slot_id, ItemInstance* inst) // What happens here when we _PutItem(MainCursor)? Bad things..really bad things... // // If putting a nullptr into slot, we need to remove slot without memory delete - if (inst == nullptr) { + if (!inst) { //Why do we not delete the poped item here???? PopItem(slot_id); return slot_id; } - int16 result = INVALID_INDEX; - int16 parentSlot = INVALID_INDEX; + int16 result = INVALID_INDEX; + int16 parent_slot = INVALID_INDEX; inst->SetEvolveEquipped(false); @@ -1419,57 +1421,49 @@ int16 EQ::InventoryProfile::_PutItem(int16 slot_id, ItemInstance* inst) m_cursor.pop(); // no memory delete, clients of this function know what they are doing m_cursor.push_front(inst); result = slot_id; - } - else if (slot_id >= invslot::EQUIPMENT_BEGIN && slot_id <= invslot::EQUIPMENT_END) { + } else if (EQ::ValueWithin(slot_id, invslot::EQUIPMENT_BEGIN, invslot::EQUIPMENT_END)) { if ((((uint64)1 << slot_id) & m_lookup->PossessionsBitmask) != 0) { if (inst->IsEvolving()) { inst->SetEvolveEquipped(true); } + m_worn[slot_id] = inst; result = slot_id; } - } - else if ((slot_id >= invslot::GENERAL_BEGIN && slot_id <= invslot::GENERAL_END)) { - if ((((uint64)1 << slot_id) & m_lookup->PossessionsBitmask) != 0) { + } else if (EQ::ValueWithin(slot_id, invslot::GENERAL_BEGIN, invslot::GENERAL_END)) { + if ((((uint64) 1 << slot_id) & m_lookup->PossessionsBitmask) != 0) { m_inv[slot_id] = inst; result = slot_id; } - } - else if (slot_id >= invslot::TRIBUTE_BEGIN && slot_id <= invslot::TRIBUTE_END) { + } else if (EQ::ValueWithin(slot_id, invslot::TRIBUTE_BEGIN, invslot::TRIBUTE_END)) { m_worn[slot_id] = inst; result = slot_id; - } - else if (slot_id >= invslot::GUILD_TRIBUTE_BEGIN && slot_id <= invslot::GUILD_TRIBUTE_END) { + } else if (EQ::ValueWithin(slot_id, invslot::GUILD_TRIBUTE_BEGIN, invslot::GUILD_TRIBUTE_END)) { m_worn[slot_id] = inst; result = slot_id; - } - else if (slot_id >= invslot::BANK_BEGIN && slot_id <= invslot::BANK_END) { + } else if (EQ::ValueWithin(slot_id, invslot::BANK_BEGIN, invslot::BANK_END)) { if (slot_id - EQ::invslot::BANK_BEGIN < m_lookup->InventoryTypeSize.Bank) { m_bank[slot_id] = inst; result = slot_id; } - } - else if (slot_id >= invslot::SHARED_BANK_BEGIN && slot_id <= invslot::SHARED_BANK_END) { + } else if (EQ::ValueWithin(slot_id, invslot::SHARED_BANK_BEGIN, invslot::SHARED_BANK_END)) { m_shbank[slot_id] = inst; result = slot_id; - } - else if (slot_id >= invslot::TRADE_BEGIN && slot_id <= invslot::TRADE_END) { + } else if (EQ::ValueWithin(slot_id, invslot::TRADE_BEGIN, invslot::TRADE_END)) { m_trade[slot_id] = inst; result = slot_id; - } - else { + } else { // Slot must be within a bag - parentSlot = InventoryProfile::CalcSlotId(slot_id); - ItemInstance* baginst = GetItem(parentSlot); // Get parent bag - if (baginst && baginst->IsClassBag()) - { + parent_slot = InventoryProfile::CalcSlotId(slot_id); + ItemInstance* baginst = GetItem(parent_slot); // Get parent bag + if (baginst && baginst->IsClassBag()) { baginst->_PutItem(InventoryProfile::CalcBagIdx(slot_id), inst); result = slot_id; } } if (result == INVALID_INDEX) { - LogError("Invalid slot_id specified ({}) with parent slot id ({})", slot_id, parentSlot); + LogError("Invalid slot_id specified ({}) with parent slot id ({})", slot_id, parent_slot); InventoryProfile::MarkDirty(inst); // Slot not found, clean up } @@ -1482,44 +1476,55 @@ int16 EQ::InventoryProfile::_HasItem(std::map& bucket, uin uint32 quantity_found = 0; for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) { - if (iter->first <= EQ::invslot::POSSESSIONS_END && iter->first >= EQ::invslot::POSSESSIONS_BEGIN) { - if ((((uint64)1 << iter->first) & m_lookup->PossessionsBitmask) == 0) + if (EQ::ValueWithin(iter->first, EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END)) { + if ((((uint64) 1 << iter->first) & m_lookup->PossessionsBitmask) == 0) { continue; - } - else if (iter->first <= EQ::invslot::BANK_END && iter->first >= EQ::invslot::BANK_BEGIN) { - if (iter->first - EQ::invslot::BANK_BEGIN >= m_lookup->InventoryTypeSize.Bank) + } + } else if (EQ::ValueWithin(iter->first, EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END)) { + if (iter->first - EQ::invslot::BANK_BEGIN >= m_lookup->InventoryTypeSize.Bank) { continue; + } } - auto inst = iter->second; - if (inst == nullptr) { continue; } + EQ::ItemInstance* inst = iter->second; + if (!inst) { + continue; + } if (inst->GetID() == item_id) { quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); - if (quantity_found >= quantity) + if (quantity_found >= quantity) { return iter->first; + } } for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) { - if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) + if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) { return invslot::SLOT_AUGMENT_GENERIC_RETURN; + } } - if (!inst->IsClassBag()) { continue; } + if (!inst->IsClassBag()) { + continue; + } for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { - auto bag_inst = bag_iter->second; - if (bag_inst == nullptr) { continue; } + EQ::ItemInstance* bag_inst = bag_iter->second; + if (!bag_inst) { + continue; + } if (bag_inst->GetID() == item_id) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); - if (quantity_found >= quantity) + if (quantity_found >= quantity) { return InventoryProfile::CalcSlotId(iter->first, bag_iter->first); + } } for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) { - if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) + if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) { return invslot::SLOT_AUGMENT_GENERIC_RETURN; + } } } } @@ -1539,35 +1544,45 @@ int16 EQ::InventoryProfile::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint uint32 quantity_found = 0; for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) { - auto inst = *iter; - if (inst == nullptr) { continue; } + EQ::ItemInstance* inst = *iter; + if (!inst) { + continue; + } if (inst->GetID() == item_id) { quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); - if (quantity_found >= quantity) + if (quantity_found >= quantity) { return invslot::slotCursor; + } } for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) { - if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) + if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) { return invslot::SLOT_AUGMENT_GENERIC_RETURN; + } } - if (!inst->IsClassBag()) { continue; } + if (!inst->IsClassBag()) { + continue; + } for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { - auto bag_inst = bag_iter->second; - if (bag_inst == nullptr) { continue; } + EQ::ItemInstance* bag_inst = bag_iter->second; + if (!bag_inst) { + continue; + } if (bag_inst->GetID() == item_id) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); - if (quantity_found >= quantity) + if (quantity_found >= quantity) { return InventoryProfile::CalcSlotId(invslot::slotCursor, bag_iter->first); + } } for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) { - if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) + if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) { return invslot::SLOT_AUGMENT_GENERIC_RETURN; + } } } @@ -1584,34 +1599,43 @@ int16 EQ::InventoryProfile::_HasItemByUse(std::map& bucket uint32 quantity_found = 0; for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) { - if (iter->first <= EQ::invslot::POSSESSIONS_END && iter->first >= EQ::invslot::POSSESSIONS_BEGIN) { - if ((((uint64)1 << iter->first) & m_lookup->PossessionsBitmask) == 0) + if (EQ::ValueWithin(iter->first, EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END)) { + if ((((uint64) 1 << iter->first) & m_lookup->PossessionsBitmask) == 0) { continue; - } - else if (iter->first <= EQ::invslot::BANK_END && iter->first >= EQ::invslot::BANK_BEGIN) { - if (iter->first - EQ::invslot::BANK_BEGIN >= m_lookup->InventoryTypeSize.Bank) + } + } else if (EQ::ValueWithin(iter->first, EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END)) { + if (iter->first - EQ::invslot::BANK_BEGIN >= m_lookup->InventoryTypeSize.Bank) { continue; + } } - auto inst = iter->second; - if (inst == nullptr) { continue; } + EQ::ItemInstance* inst = iter->second; + if (!inst) { + continue; + } if (inst->IsClassCommon() && inst->GetItem()->ItemType == use) { quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); - if (quantity_found >= quantity) + if (quantity_found >= quantity) { return iter->first; + } } - if (!inst->IsClassBag()) { continue; } + if (!inst->IsClassBag()) { + continue; + } for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { - auto bag_inst = bag_iter->second; - if (bag_inst == nullptr) { continue; } + EQ::ItemInstance* bag_inst = bag_iter->second; + if (!bag_inst) { + continue; + } if (bag_inst->IsClassCommon() && bag_inst->GetItem()->ItemType == use) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); - if (quantity_found >= quantity) + if (quantity_found >= quantity) { return InventoryProfile::CalcSlotId(iter->first, bag_iter->first); + } } } } @@ -1625,25 +1649,33 @@ int16 EQ::InventoryProfile::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint uint32 quantity_found = 0; for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) { - auto inst = *iter; - if (inst == nullptr) { continue; } + EQ::ItemInstance* inst = *iter; + if (!inst) { + continue; + } if (inst->IsClassCommon() && inst->GetItem()->ItemType == use) { quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); - if (quantity_found >= quantity) + if (quantity_found >= quantity) { return invslot::slotCursor; + } } - if (!inst->IsClassBag()) { continue; } + if (!inst->IsClassBag()) { + continue; + } for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { - auto bag_inst = bag_iter->second; - if (bag_inst == nullptr) { continue; } + EQ::ItemInstance* bag_inst = bag_iter->second; + if (!bag_inst) { + continue; + } if (bag_inst->IsClassCommon() && bag_inst->GetItem()->ItemType == use) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); - if (quantity_found >= quantity) + if (quantity_found >= quantity) { return InventoryProfile::CalcSlotId(invslot::slotCursor, bag_iter->first); + } } } @@ -1657,44 +1689,57 @@ int16 EQ::InventoryProfile::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint int16 EQ::InventoryProfile::_HasItemByLoreGroup(std::map& bucket, uint32 loregroup) { for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) { - if (iter->first <= EQ::invslot::POSSESSIONS_END && iter->first >= EQ::invslot::POSSESSIONS_BEGIN) { - if ((((uint64)1 << iter->first) & m_lookup->PossessionsBitmask) == 0) + if (EQ::ValueWithin(iter->first, EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END)) { + if ((((uint64) 1 << iter->first) & m_lookup->PossessionsBitmask) == 0) { continue; - } - else if (iter->first <= EQ::invslot::BANK_END && iter->first >= EQ::invslot::BANK_BEGIN) { - if (iter->first - EQ::invslot::BANK_BEGIN >= m_lookup->InventoryTypeSize.Bank) + } + } else if (EQ::ValueWithin(iter->first, EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END)) { + if (iter->first - EQ::invslot::BANK_BEGIN >= m_lookup->InventoryTypeSize.Bank) { continue; + } } - auto inst = iter->second; - if (inst == nullptr) { continue; } + EQ::ItemInstance* inst = iter->second; + if (!inst) { + continue; + } - if (inst->GetItem()->LoreGroup == loregroup) + if (inst->GetItem()->LoreGroup == loregroup) { return iter->first; + } for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) { auto aug_inst = inst->GetAugment(index); if (aug_inst == nullptr) { continue; } - if (aug_inst->GetItem()->LoreGroup == loregroup) + if (aug_inst->GetItem()->LoreGroup == loregroup) { return invslot::SLOT_AUGMENT_GENERIC_RETURN; + } } - if (!inst->IsClassBag()) { continue; } + if (!inst->IsClassBag()) { + continue; + } for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { - auto bag_inst = bag_iter->second; - if (bag_inst == nullptr) { continue; } + EQ::ItemInstance* bag_inst = bag_iter->second; + if (!bag_inst) { + continue; + } - if (bag_inst->IsClassCommon() && bag_inst->GetItem()->LoreGroup == loregroup) + if (bag_inst->IsClassCommon() && bag_inst->GetItem()->LoreGroup == loregroup) { return InventoryProfile::CalcSlotId(iter->first, bag_iter->first); + } for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) { - auto aug_inst = bag_inst->GetAugment(index); - if (aug_inst == nullptr) { continue; } + EQ::ItemInstance* aug_inst = bag_inst->GetAugment(index); + if (!aug_inst) { + continue; + } - if (aug_inst->GetItem()->LoreGroup == loregroup) + if (aug_inst->GetItem()->LoreGroup == loregroup) { return invslot::SLOT_AUGMENT_GENERIC_RETURN; + } } } } @@ -1706,35 +1751,49 @@ int16 EQ::InventoryProfile::_HasItemByLoreGroup(std::map& int16 EQ::InventoryProfile::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) { for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) { - auto inst = *iter; - if (inst == nullptr) { continue; } - - if (inst->GetItem()->LoreGroup == loregroup) - return invslot::slotCursor; - - for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) { - auto aug_inst = inst->GetAugment(index); - if (aug_inst == nullptr) { continue; } - - if (aug_inst->GetItem()->LoreGroup == loregroup) - return invslot::SLOT_AUGMENT_GENERIC_RETURN; + EQ::ItemInstance* inst = *iter; + if (!inst) { + continue; } - if (!inst->IsClassBag()) { continue; } + if (inst->GetItem()->LoreGroup == loregroup) { + return invslot::slotCursor; + } + + for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) { + EQ::ItemInstance* aug_inst = inst->GetAugment(index); + if (!aug_inst) { + continue; + } + + if (aug_inst->GetItem()->LoreGroup == loregroup) { + return invslot::SLOT_AUGMENT_GENERIC_RETURN; + } + } + + if (!inst->IsClassBag()) { + continue; + } for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { - auto bag_inst = bag_iter->second; - if (bag_inst == nullptr) { continue; } + EQ::ItemInstance* bag_inst = bag_iter->second; + if (!bag_inst) { + continue; + } - if (bag_inst->IsClassCommon() && bag_inst->GetItem()->LoreGroup == loregroup) + if (bag_inst->IsClassCommon() && bag_inst->GetItem()->LoreGroup == loregroup) { return InventoryProfile::CalcSlotId(invslot::slotCursor, bag_iter->first); + } for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) { - auto aug_inst = bag_inst->GetAugment(index); - if (aug_inst == nullptr) { continue; } + EQ::ItemInstance* aug_inst = bag_inst->GetAugment(index); + if (!aug_inst) { + continue; + } - if (aug_inst->GetItem()->LoreGroup == loregroup) + if (aug_inst->GetItem()->LoreGroup == loregroup) { return invslot::SLOT_AUGMENT_GENERIC_RETURN; + } } } @@ -1759,42 +1818,9 @@ std::vector EQ::InventoryProfile::GetAugmentIDsBySlotID(int16 slot_id) return augments; } -std::vector EQ::InventoryProfile::FindAllFreeSlotsThatFitItem(const EQ::ItemData *item_data) -{ - std::vector free_slots{}; - for (int16 i = EQ::invslot::GENERAL_BEGIN; i <= EQ::invslot::GENERAL_END; i++) { - if ((((uint64) 1 << i) & GetLookup()->PossessionsBitmask) == 0) { - continue; - } - - EQ::ItemInstance *inv_item = GetItem(i); - - if (!inv_item) { - // Found available slot in personal inventory - free_slots.push_back(i); - } - - if (inv_item->IsClassBag() && - EQ::InventoryProfile::CanItemFitInContainer(item_data, inv_item->GetItem())) { - - int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(i, EQ::invbag::SLOT_BEGIN); - uint8 bag_size = inv_item->GetItem()->BagSlots; - - for (uint8 bag_slot = EQ::invbag::SLOT_BEGIN; bag_slot < bag_size; bag_slot++) { - auto bag_item = GetItem(base_slot_id + bag_slot); - if (!bag_item) { - // Found available slot within bag - free_slots.push_back(i); - } - } - } - } - return free_slots; -} - int16 EQ::InventoryProfile::FindFirstFreeSlotThatFitsItem(const EQ::ItemData *item_data) { - for (int16 i = EQ::invslot::GENERAL_BEGIN; i <= EQ::invslot::GENERAL_END; i++) { + for (int16 i = EQ::invslot::GENERAL_BEGIN; i <= EQ::invslot::GENERAL_END; i++) { if ((((uint64) 1 << i) & GetLookup()->PossessionsBitmask) == 0) { continue; } diff --git a/common/inventory_profile.h b/common/inventory_profile.h index 8e364aa5a..887afd512 100644 --- a/common/inventory_profile.h +++ b/common/inventory_profile.h @@ -178,7 +178,6 @@ namespace EQ // Locate an available inventory slot int16 FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size = 0, bool is_arrow = false); int16 FindFreeSlotForTradeItem(const ItemInstance* inst, int16 general_start = invslot::GENERAL_BEGIN, uint8 bag_start = invbag::SLOT_BEGIN); - std::vector FindAllFreeSlotsThatFitItem(const EQ::ItemData *inst); int16 FindFirstFreeSlotThatFitsItem(const EQ::ItemData *inst); // Calculate slot_id for an item within a bag @@ -201,12 +200,6 @@ namespace EQ uint8 FindBrightestLightType(); - void dumpEntireInventory(); - void dumpWornItems(); - void dumpInventory(); - void dumpBankItems(); - void dumpSharedBankItems(); - void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, const std::string& value); void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, int value); void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, float value); @@ -226,8 +219,6 @@ namespace EQ /////////////////////////////// int GetSlotByItemInstCollection(const std::map &collection, ItemInstance *inst); - void dumpItemCollection(const std::map &collection); - void dumpBagContents(ItemInstance *inst, std::map::const_iterator *it); // Retrieves item within an inventory bucket ItemInstance* _GetItem(const std::map& bucket, int16 slot_id) const; diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index a2fe623e0..4230be80d 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -37,7 +37,7 @@ namespace RoF2 const bool AllowOverLevelEquipment = true; - const bool AllowEmptyBagInBag = true; + const bool AllowEmptyBagInBag = true; const bool AllowClickCastFromBag = true; } /*inventory*/ @@ -77,38 +77,38 @@ namespace RoF2 } // namespace enum_ using namespace enum_; - const int16 POSSESSIONS_SIZE = 34; - const int16 BANK_SIZE = 24; - const int16 SHARED_BANK_SIZE = 2; - const int16 TRADE_SIZE = 8; - const int16 WORLD_SIZE = 10; - const int16 LIMBO_SIZE = 36; - const int16 TRIBUTE_SIZE = 5; - const int16 TROPHY_TRIBUTE_SIZE = 0;//unknown - const int16 GUILD_TRIBUTE_SIZE = 2;//unverified - const int16 MERCHANT_SIZE = 200; - const int16 DELETED_SIZE = 0;//unknown - "Recovery Tab" - const int16 CORPSE_SIZE = POSSESSIONS_SIZE; - const int16 BAZAAR_SIZE = 200; - const int16 INSPECT_SIZE = 23; - const int16 REAL_ESTATE_SIZE = 0;//unknown - const int16 VIEW_MOD_PC_SIZE = POSSESSIONS_SIZE; - const int16 VIEW_MOD_BANK_SIZE = BANK_SIZE; + const int16 POSSESSIONS_SIZE = 34; + const int16 BANK_SIZE = 24; + const int16 SHARED_BANK_SIZE = 2; + const int16 TRADE_SIZE = 8; + const int16 WORLD_SIZE = 10; + const int16 LIMBO_SIZE = 36; + const int16 TRIBUTE_SIZE = 5; + const int16 TROPHY_TRIBUTE_SIZE = 0;//unknown + const int16 GUILD_TRIBUTE_SIZE = 2;//unverified + const int16 MERCHANT_SIZE = 500; + const int16 DELETED_SIZE = 0;//unknown - "Recovery Tab" + const int16 CORPSE_SIZE = POSSESSIONS_SIZE; + const int16 BAZAAR_SIZE = 200; + const int16 INSPECT_SIZE = 23; + const int16 REAL_ESTATE_SIZE = 0;//unknown + const int16 VIEW_MOD_PC_SIZE = POSSESSIONS_SIZE; + const int16 VIEW_MOD_BANK_SIZE = BANK_SIZE; const int16 VIEW_MOD_SHARED_BANK_SIZE = SHARED_BANK_SIZE; - const int16 VIEW_MOD_LIMBO_SIZE = LIMBO_SIZE; - const int16 ALT_STORAGE_SIZE = 0;//unknown - "Shroud Bank" - const int16 ARCHIVED_SIZE = 0;//unknown - const int16 MAIL_SIZE = 0;//unknown + const int16 VIEW_MOD_LIMBO_SIZE = LIMBO_SIZE; + const int16 ALT_STORAGE_SIZE = 0;//unknown - "Shroud Bank" + const int16 ARCHIVED_SIZE = 0;//unknown + const int16 MAIL_SIZE = 0;//unknown const int16 GUILD_TROPHY_TRIBUTE_SIZE = 0;//unknown - const int16 KRONO_SIZE = 0;//unknown - const int16 OTHER_SIZE = 0;//unknown + const int16 KRONO_SIZE = 0;//unknown + const int16 OTHER_SIZE = 0;//unknown const int16 TRADE_NPC_SIZE = 4; // defined by implication const int16 TYPE_INVALID = IINVALID; - const int16 TYPE_BEGIN = typePossessions; - const int16 TYPE_END = typeOther; - const int16 TYPE_COUNT = (TYPE_END - TYPE_BEGIN) + 1; + const int16 TYPE_BEGIN = typePossessions; + const int16 TYPE_END = typeOther; + const int16 TYPE_COUNT = (TYPE_END - TYPE_BEGIN) + 1; int16 GetInvTypeSize(int16 inv_type); const char* GetInvTypeName(int16 inv_type); @@ -162,33 +162,54 @@ namespace RoF2 } // namespace enum_ using namespace enum_; - const int16 SLOT_INVALID = IINVALID; - const int16 SLOT_BEGIN = INULL; + const int16 SLOT_TRADESKILL_EXPERIMENT_COMBINE = 1000; + const int16 SLOT_INVALID = IINVALID; + const int16 SLOT_BEGIN = INULL; + + const int16 BANK_BEGIN = 2000; + const int16 BANK_END = (BANK_BEGIN + invtype::BANK_SIZE) - 1; + + const int16 SHARED_BANK_BEGIN = 2500; + const int16 SHARED_BANK_END = (SHARED_BANK_BEGIN + invtype::SHARED_BANK_SIZE) - 1; + + const int16 TRADE_BEGIN = 3000; + const int16 TRADE_END = (TRADE_BEGIN + invtype::TRADE_SIZE) - 1; + + const int16 TRADE_NPC_END = (TRADE_BEGIN + invtype::TRADE_NPC_SIZE) - 1; // defined by implication + + const int16 WORLD_BEGIN = 4000; + const int16 WORLD_END = (WORLD_BEGIN + invtype::WORLD_SIZE) - 1; + + const int16 TRIBUTE_BEGIN = 400; + const int16 TRIBUTE_END = (TRIBUTE_BEGIN + invtype::TRIBUTE_SIZE) - 1; + + const int16 GUILD_TRIBUTE_BEGIN = 450; + const int16 GUILD_TRIBUTE_END = (GUILD_TRIBUTE_BEGIN + invtype::GUILD_TRIBUTE_SIZE) - 1; const int16 POSSESSIONS_BEGIN = slotCharm; - const int16 POSSESSIONS_END = slotCursor; + const int16 POSSESSIONS_END = slotCursor; const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1; const int16 EQUIPMENT_BEGIN = slotCharm; - const int16 EQUIPMENT_END = slotAmmo; + const int16 EQUIPMENT_END = slotAmmo; const int16 EQUIPMENT_COUNT = (EQUIPMENT_END - EQUIPMENT_BEGIN) + 1; const int16 GENERAL_BEGIN = slotGeneral1; - const int16 GENERAL_END = slotGeneral10; + const int16 GENERAL_END = slotGeneral10; const int16 GENERAL_COUNT = (GENERAL_END - GENERAL_BEGIN) + 1; - const int16 BONUS_BEGIN = invslot::slotCharm; - const int16 BONUS_STAT_END = invslot::slotPowerSource; + const int16 BONUS_BEGIN = invslot::slotCharm; + const int16 BONUS_STAT_END = invslot::slotPowerSource; const int16 BONUS_SKILL_END = invslot::slotAmmo; const int16 CORPSE_BEGIN = invslot::slotGeneral1; - const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor; + const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor; - const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF; - const uint64 GENERAL_BITMASK = 0x00000001FF800000; - const uint64 CURSOR_BITMASK = 0x0000000200000000; + const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF; + const uint64 GENERAL_BITMASK = 0x00000001FF800000; + const uint64 CURSOR_BITMASK = 0x0000000200000000; const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+) - const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+) + const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+) const char* GetInvPossessionsSlotName(int16 inv_slot); @@ -199,10 +220,21 @@ namespace RoF2 namespace invbag { inline EQ::versions::ClientVersion GetInvBagRef() { return EQ::versions::ClientVersion::RoF2; } - const int16 SLOT_INVALID = IINVALID; - const int16 SLOT_BEGIN = INULL; - const int16 SLOT_END = 9; //254; - const int16 SLOT_COUNT = 10; //255; // server Size will be 255..unsure what actual client is (test) + const int16 SLOT_TRADESKILL_EXPERIMENT_COMBINE = 1000; + const int16 SLOT_INVALID = IINVALID; + const int16 SLOT_BEGIN = INULL; + const int16 SLOT_COUNT = 200; + const int16 SLOT_END = SLOT_COUNT - 1; + + const int16 GENERAL_BAGS_BEGIN = 251; + + const int16 CURSOR_BAG_BEGIN = 351; + + const int16 BANK_BAGS_BEGIN = 2031; + + const int16 SHARED_BANK_BAGS_BEGIN = 2531; + + const int16 TRADE_BAGS_BEGIN = 3031; const char* GetInvBagIndexName(int16 bag_index); @@ -212,9 +244,9 @@ namespace RoF2 inline EQ::versions::ClientVersion GetInvAugRef() { return EQ::versions::ClientVersion::RoF2; } const int16 SOCKET_INVALID = IINVALID; - const int16 SOCKET_BEGIN = INULL; - const int16 SOCKET_END = 5; - const int16 SOCKET_COUNT = 6; + const int16 SOCKET_BEGIN = INULL; + const int16 SOCKET_END = 5; + const int16 SOCKET_COUNT = 6; const char* GetInvAugIndexName(int16 aug_index); @@ -292,7 +324,7 @@ namespace RoF2 namespace spells { inline EQ::versions::ClientVersion GetSkillsRef() { return EQ::versions::ClientVersion::RoF2; } - + enum class CastingSlot : uint32 { Gem1 = 0, Gem2 = 1, @@ -315,7 +347,7 @@ namespace RoF2 const int SPELL_ID_MAX = 45000; const int SPELLBOOK_SIZE = 720; const int SPELL_GEM_COUNT = static_cast(CastingSlot::MaxGems); - + const int LONG_BUFFS = 42; const int SHORT_BUFFS = 20; const int DISC_BUFFS = 1; diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 831198363..2d9275942 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -2463,25 +2463,25 @@ struct WhoAllReturnStruct { struct BeginTrader_Struct { uint32 action; uint32 unknown04; - uint64 serial_number[80]; - uint32 cost[80]; + uint64 serial_number[EQ::invtype::BAZAAR_SIZE]; + uint32 cost[EQ::invtype::BAZAAR_SIZE]; }; struct Trader_Struct { uint32 action; uint32 unknown004; - uint64 item_id[80]; - uint32 item_cost[80]; + uint64 item_id[EQ::invtype::BAZAAR_SIZE]; + uint32 item_cost[EQ::invtype::BAZAAR_SIZE]; }; struct ClickTrader_Struct { uint32 code; uint32 unknown[161];//damn soe this is totally pointless :/ but at least your finally using memset! Good job :) -LE - uint32 itemcost[80]; + uint32 itemcost[EQ::invtype::BAZAAR_SIZE]; }; struct GetItems_Struct{ - uint32 items[80]; + uint32 items[EQ::invtype::BAZAAR_SIZE]; }; struct BecomeTrader_Struct { diff --git a/common/repositories/base/base_inventory_repository.h b/common/repositories/base/base_inventory_repository.h index a029ac6b4..9a4b5122b 100644 --- a/common/repositories/base/base_inventory_repository.h +++ b/common/repositories/base/base_inventory_repository.h @@ -19,48 +19,48 @@ class BaseInventoryRepository { public: struct Inventory { - uint32_t charid; - uint32_t slotid; - uint32_t itemid; + uint32_t character_id; + uint32_t slot_id; + uint32_t item_id; uint16_t charges; uint32_t color; - uint32_t augslot1; - uint32_t augslot2; - uint32_t augslot3; - uint32_t augslot4; - uint32_t augslot5; - int32_t augslot6; + uint32_t augment_one; + uint32_t augment_two; + uint32_t augment_three; + uint32_t augment_four; + uint32_t augment_five; + uint32_t augment_six; uint8_t instnodrop; std::string custom_data; - uint32_t ornamenticon; - uint32_t ornamentidfile; + uint32_t ornament_icon; + uint32_t ornament_idfile; int32_t ornament_hero_model; uint64_t guid; }; static std::string PrimaryKey() { - return std::string("charid"); + return std::string("character_id"); } static std::vector Columns() { return { - "charid", - "slotid", - "itemid", + "character_id", + "slot_id", + "item_id", "charges", "color", - "augslot1", - "augslot2", - "augslot3", - "augslot4", - "augslot5", - "augslot6", + "augment_one", + "augment_two", + "augment_three", + "augment_four", + "augment_five", + "augment_six", "instnodrop", "custom_data", - "ornamenticon", - "ornamentidfile", + "ornament_icon", + "ornament_idfile", "ornament_hero_model", "guid", }; @@ -69,21 +69,21 @@ public: static std::vector SelectColumns() { return { - "charid", - "slotid", - "itemid", + "character_id", + "slot_id", + "item_id", "charges", "color", - "augslot1", - "augslot2", - "augslot3", - "augslot4", - "augslot5", - "augslot6", + "augment_one", + "augment_two", + "augment_three", + "augment_four", + "augment_five", + "augment_six", "instnodrop", "custom_data", - "ornamenticon", - "ornamentidfile", + "ornament_icon", + "ornament_idfile", "ornament_hero_model", "guid", }; @@ -126,21 +126,21 @@ public: { Inventory e{}; - e.charid = 0; - e.slotid = 0; - e.itemid = 0; + e.character_id = 0; + e.slot_id = 0; + e.item_id = 0; e.charges = 0; e.color = 0; - e.augslot1 = 0; - e.augslot2 = 0; - e.augslot3 = 0; - e.augslot4 = 0; - e.augslot5 = 0; - e.augslot6 = 0; + e.augment_one = 0; + e.augment_two = 0; + e.augment_three = 0; + e.augment_four = 0; + e.augment_five = 0; + e.augment_six = 0; e.instnodrop = 0; e.custom_data = ""; - e.ornamenticon = 0; - e.ornamentidfile = 0; + e.ornament_icon = 0; + e.ornament_idfile = 0; e.ornament_hero_model = 0; e.guid = 0; @@ -153,7 +153,7 @@ public: ) { for (auto &inventory : inventorys) { - if (inventory.charid == inventory_id) { + if (inventory.character_id == inventory_id) { return inventory; } } @@ -179,21 +179,21 @@ public: if (results.RowCount() == 1) { Inventory e{}; - e.charid = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; - e.slotid = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.itemid = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.character_id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.slot_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; e.charges = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; e.color = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; - e.augslot1 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; - e.augslot2 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; - e.augslot3 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; - e.augslot4 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.augslot5 = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; - e.augslot6 = row[10] ? static_cast(atoi(row[10])) : 0; + e.augment_one = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.augment_two = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_three = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_four = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_five = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_six = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; e.instnodrop = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; e.custom_data = row[12] ? row[12] : ""; - e.ornamenticon = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; - e.ornamentidfile = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; + e.ornament_icon = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; + e.ornament_idfile = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; e.ornament_hero_model = row[15] ? static_cast(atoi(row[15])) : 0; e.guid = row[16] ? strtoull(row[16], nullptr, 10) : 0; @@ -229,21 +229,21 @@ public: auto columns = Columns(); - v.push_back(columns[0] + " = " + std::to_string(e.charid)); - v.push_back(columns[1] + " = " + std::to_string(e.slotid)); - v.push_back(columns[2] + " = " + std::to_string(e.itemid)); + v.push_back(columns[0] + " = " + std::to_string(e.character_id)); + v.push_back(columns[1] + " = " + std::to_string(e.slot_id)); + v.push_back(columns[2] + " = " + std::to_string(e.item_id)); v.push_back(columns[3] + " = " + std::to_string(e.charges)); v.push_back(columns[4] + " = " + std::to_string(e.color)); - v.push_back(columns[5] + " = " + std::to_string(e.augslot1)); - v.push_back(columns[6] + " = " + std::to_string(e.augslot2)); - v.push_back(columns[7] + " = " + std::to_string(e.augslot3)); - v.push_back(columns[8] + " = " + std::to_string(e.augslot4)); - v.push_back(columns[9] + " = " + std::to_string(e.augslot5)); - v.push_back(columns[10] + " = " + std::to_string(e.augslot6)); + v.push_back(columns[5] + " = " + std::to_string(e.augment_one)); + v.push_back(columns[6] + " = " + std::to_string(e.augment_two)); + v.push_back(columns[7] + " = " + std::to_string(e.augment_three)); + v.push_back(columns[8] + " = " + std::to_string(e.augment_four)); + v.push_back(columns[9] + " = " + std::to_string(e.augment_five)); + v.push_back(columns[10] + " = " + std::to_string(e.augment_six)); v.push_back(columns[11] + " = " + std::to_string(e.instnodrop)); v.push_back(columns[12] + " = '" + Strings::Escape(e.custom_data) + "'"); - v.push_back(columns[13] + " = " + std::to_string(e.ornamenticon)); - v.push_back(columns[14] + " = " + std::to_string(e.ornamentidfile)); + v.push_back(columns[13] + " = " + std::to_string(e.ornament_icon)); + v.push_back(columns[14] + " = " + std::to_string(e.ornament_idfile)); v.push_back(columns[15] + " = " + std::to_string(e.ornament_hero_model)); v.push_back(columns[16] + " = " + std::to_string(e.guid)); @@ -253,7 +253,7 @@ public: TableName(), Strings::Implode(", ", v), PrimaryKey(), - e.charid + e.character_id ) ); @@ -267,21 +267,21 @@ public: { std::vector v; - v.push_back(std::to_string(e.charid)); - v.push_back(std::to_string(e.slotid)); - v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.item_id)); v.push_back(std::to_string(e.charges)); v.push_back(std::to_string(e.color)); - v.push_back(std::to_string(e.augslot1)); - v.push_back(std::to_string(e.augslot2)); - v.push_back(std::to_string(e.augslot3)); - v.push_back(std::to_string(e.augslot4)); - v.push_back(std::to_string(e.augslot5)); - v.push_back(std::to_string(e.augslot6)); + v.push_back(std::to_string(e.augment_one)); + v.push_back(std::to_string(e.augment_two)); + v.push_back(std::to_string(e.augment_three)); + v.push_back(std::to_string(e.augment_four)); + v.push_back(std::to_string(e.augment_five)); + v.push_back(std::to_string(e.augment_six)); v.push_back(std::to_string(e.instnodrop)); v.push_back("'" + Strings::Escape(e.custom_data) + "'"); - v.push_back(std::to_string(e.ornamenticon)); - v.push_back(std::to_string(e.ornamentidfile)); + v.push_back(std::to_string(e.ornament_icon)); + v.push_back(std::to_string(e.ornament_idfile)); v.push_back(std::to_string(e.ornament_hero_model)); v.push_back(std::to_string(e.guid)); @@ -294,7 +294,7 @@ public: ); if (results.Success()) { - e.charid = results.LastInsertedID(); + e.character_id = results.LastInsertedID(); return e; } @@ -313,21 +313,21 @@ public: for (auto &e: entries) { std::vector v; - v.push_back(std::to_string(e.charid)); - v.push_back(std::to_string(e.slotid)); - v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.item_id)); v.push_back(std::to_string(e.charges)); v.push_back(std::to_string(e.color)); - v.push_back(std::to_string(e.augslot1)); - v.push_back(std::to_string(e.augslot2)); - v.push_back(std::to_string(e.augslot3)); - v.push_back(std::to_string(e.augslot4)); - v.push_back(std::to_string(e.augslot5)); - v.push_back(std::to_string(e.augslot6)); + v.push_back(std::to_string(e.augment_one)); + v.push_back(std::to_string(e.augment_two)); + v.push_back(std::to_string(e.augment_three)); + v.push_back(std::to_string(e.augment_four)); + v.push_back(std::to_string(e.augment_five)); + v.push_back(std::to_string(e.augment_six)); v.push_back(std::to_string(e.instnodrop)); v.push_back("'" + Strings::Escape(e.custom_data) + "'"); - v.push_back(std::to_string(e.ornamenticon)); - v.push_back(std::to_string(e.ornamentidfile)); + v.push_back(std::to_string(e.ornament_icon)); + v.push_back(std::to_string(e.ornament_idfile)); v.push_back(std::to_string(e.ornament_hero_model)); v.push_back(std::to_string(e.guid)); @@ -363,21 +363,21 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { Inventory e{}; - e.charid = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; - e.slotid = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.itemid = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.character_id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.slot_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; e.charges = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; e.color = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; - e.augslot1 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; - e.augslot2 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; - e.augslot3 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; - e.augslot4 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.augslot5 = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; - e.augslot6 = row[10] ? static_cast(atoi(row[10])) : 0; + e.augment_one = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.augment_two = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_three = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_four = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_five = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_six = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; e.instnodrop = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; e.custom_data = row[12] ? row[12] : ""; - e.ornamenticon = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; - e.ornamentidfile = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; + e.ornament_icon = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; + e.ornament_idfile = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; e.ornament_hero_model = row[15] ? static_cast(atoi(row[15])) : 0; e.guid = row[16] ? strtoull(row[16], nullptr, 10) : 0; @@ -404,21 +404,21 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { Inventory e{}; - e.charid = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; - e.slotid = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.itemid = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.character_id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.slot_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; e.charges = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; e.color = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; - e.augslot1 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; - e.augslot2 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; - e.augslot3 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; - e.augslot4 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.augslot5 = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; - e.augslot6 = row[10] ? static_cast(atoi(row[10])) : 0; + e.augment_one = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.augment_two = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_three = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_four = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_five = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_six = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; e.instnodrop = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; e.custom_data = row[12] ? row[12] : ""; - e.ornamenticon = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; - e.ornamentidfile = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; + e.ornament_icon = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; + e.ornament_idfile = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; e.ornament_hero_model = row[15] ? static_cast(atoi(row[15])) : 0; e.guid = row[16] ? strtoull(row[16], nullptr, 10) : 0; @@ -495,21 +495,21 @@ public: { std::vector v; - v.push_back(std::to_string(e.charid)); - v.push_back(std::to_string(e.slotid)); - v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.item_id)); v.push_back(std::to_string(e.charges)); v.push_back(std::to_string(e.color)); - v.push_back(std::to_string(e.augslot1)); - v.push_back(std::to_string(e.augslot2)); - v.push_back(std::to_string(e.augslot3)); - v.push_back(std::to_string(e.augslot4)); - v.push_back(std::to_string(e.augslot5)); - v.push_back(std::to_string(e.augslot6)); + v.push_back(std::to_string(e.augment_one)); + v.push_back(std::to_string(e.augment_two)); + v.push_back(std::to_string(e.augment_three)); + v.push_back(std::to_string(e.augment_four)); + v.push_back(std::to_string(e.augment_five)); + v.push_back(std::to_string(e.augment_six)); v.push_back(std::to_string(e.instnodrop)); v.push_back("'" + Strings::Escape(e.custom_data) + "'"); - v.push_back(std::to_string(e.ornamenticon)); - v.push_back(std::to_string(e.ornamentidfile)); + v.push_back(std::to_string(e.ornament_icon)); + v.push_back(std::to_string(e.ornament_idfile)); v.push_back(std::to_string(e.ornament_hero_model)); v.push_back(std::to_string(e.guid)); @@ -534,21 +534,21 @@ public: for (auto &e: entries) { std::vector v; - v.push_back(std::to_string(e.charid)); - v.push_back(std::to_string(e.slotid)); - v.push_back(std::to_string(e.itemid)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.item_id)); v.push_back(std::to_string(e.charges)); v.push_back(std::to_string(e.color)); - v.push_back(std::to_string(e.augslot1)); - v.push_back(std::to_string(e.augslot2)); - v.push_back(std::to_string(e.augslot3)); - v.push_back(std::to_string(e.augslot4)); - v.push_back(std::to_string(e.augslot5)); - v.push_back(std::to_string(e.augslot6)); + v.push_back(std::to_string(e.augment_one)); + v.push_back(std::to_string(e.augment_two)); + v.push_back(std::to_string(e.augment_three)); + v.push_back(std::to_string(e.augment_four)); + v.push_back(std::to_string(e.augment_five)); + v.push_back(std::to_string(e.augment_six)); v.push_back(std::to_string(e.instnodrop)); v.push_back("'" + Strings::Escape(e.custom_data) + "'"); - v.push_back(std::to_string(e.ornamenticon)); - v.push_back(std::to_string(e.ornamentidfile)); + v.push_back(std::to_string(e.ornament_icon)); + v.push_back(std::to_string(e.ornament_idfile)); v.push_back(std::to_string(e.ornament_hero_model)); v.push_back(std::to_string(e.guid)); diff --git a/common/repositories/base/base_sharedbank_repository.h b/common/repositories/base/base_sharedbank_repository.h new file mode 100644 index 000000000..d208251da --- /dev/null +++ b/common/repositories/base/base_sharedbank_repository.h @@ -0,0 +1,560 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_SHAREDBANK_REPOSITORY_H +#define EQEMU_BASE_SHAREDBANK_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseSharedbankRepository { +public: + struct Sharedbank { + uint32_t account_id; + uint32_t slot_id; + uint32_t item_id; + uint16_t charges; + uint32_t color; + uint32_t augment_one; + uint32_t augment_two; + uint32_t augment_three; + uint32_t augment_four; + uint32_t augment_five; + uint32_t augment_six; + std::string custom_data; + uint32_t ornament_icon; + uint32_t ornament_idfile; + int32_t ornament_hero_model; + uint64_t guid; + }; + + static std::string PrimaryKey() + { + return std::string("account_id"); + } + + static std::vector Columns() + { + return { + "account_id", + "slot_id", + "item_id", + "charges", + "color", + "augment_one", + "augment_two", + "augment_three", + "augment_four", + "augment_five", + "augment_six", + "custom_data", + "ornament_icon", + "ornament_idfile", + "ornament_hero_model", + "guid", + }; + } + + static std::vector SelectColumns() + { + return { + "account_id", + "slot_id", + "item_id", + "charges", + "color", + "augment_one", + "augment_two", + "augment_three", + "augment_four", + "augment_five", + "augment_six", + "custom_data", + "ornament_icon", + "ornament_idfile", + "ornament_hero_model", + "guid", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("sharedbank"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static Sharedbank NewEntity() + { + Sharedbank e{}; + + e.account_id = 0; + e.slot_id = 0; + e.item_id = 0; + e.charges = 0; + e.color = 0; + e.augment_one = 0; + e.augment_two = 0; + e.augment_three = 0; + e.augment_four = 0; + e.augment_five = 0; + e.augment_six = 0; + e.custom_data = ""; + e.ornament_icon = 0; + e.ornament_idfile = 0; + e.ornament_hero_model = 0; + e.guid = 0; + + return e; + } + + static Sharedbank GetSharedbank( + const std::vector &sharedbanks, + int sharedbank_id + ) + { + for (auto &sharedbank : sharedbanks) { + if (sharedbank.account_id == sharedbank_id) { + return sharedbank; + } + } + + return NewEntity(); + } + + static Sharedbank FindOne( + Database& db, + int sharedbank_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + sharedbank_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + Sharedbank e{}; + + e.account_id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.slot_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.charges = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.color = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.augment_one = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.augment_two = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_three = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_four = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_five = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_six = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.custom_data = row[11] ? row[11] : ""; + e.ornament_icon = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; + e.ornament_idfile = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; + e.ornament_hero_model = row[14] ? static_cast(atoi(row[14])) : 0; + e.guid = row[15] ? strtoull(row[15], nullptr, 10) : 0; + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int sharedbank_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + sharedbank_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const Sharedbank &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[0] + " = " + std::to_string(e.account_id)); + v.push_back(columns[1] + " = " + std::to_string(e.slot_id)); + v.push_back(columns[2] + " = " + std::to_string(e.item_id)); + v.push_back(columns[3] + " = " + std::to_string(e.charges)); + v.push_back(columns[4] + " = " + std::to_string(e.color)); + v.push_back(columns[5] + " = " + std::to_string(e.augment_one)); + v.push_back(columns[6] + " = " + std::to_string(e.augment_two)); + v.push_back(columns[7] + " = " + std::to_string(e.augment_three)); + v.push_back(columns[8] + " = " + std::to_string(e.augment_four)); + v.push_back(columns[9] + " = " + std::to_string(e.augment_five)); + v.push_back(columns[10] + " = " + std::to_string(e.augment_six)); + v.push_back(columns[11] + " = '" + Strings::Escape(e.custom_data) + "'"); + v.push_back(columns[12] + " = " + std::to_string(e.ornament_icon)); + v.push_back(columns[13] + " = " + std::to_string(e.ornament_idfile)); + v.push_back(columns[14] + " = " + std::to_string(e.ornament_hero_model)); + v.push_back(columns[15] + " = " + std::to_string(e.guid)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.account_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static Sharedbank InsertOne( + Database& db, + Sharedbank e + ) + { + std::vector v; + + v.push_back(std::to_string(e.account_id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.color)); + v.push_back(std::to_string(e.augment_one)); + v.push_back(std::to_string(e.augment_two)); + v.push_back(std::to_string(e.augment_three)); + v.push_back(std::to_string(e.augment_four)); + v.push_back(std::to_string(e.augment_five)); + v.push_back(std::to_string(e.augment_six)); + v.push_back("'" + Strings::Escape(e.custom_data) + "'"); + v.push_back(std::to_string(e.ornament_icon)); + v.push_back(std::to_string(e.ornament_idfile)); + v.push_back(std::to_string(e.ornament_hero_model)); + v.push_back(std::to_string(e.guid)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.account_id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.account_id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.color)); + v.push_back(std::to_string(e.augment_one)); + v.push_back(std::to_string(e.augment_two)); + v.push_back(std::to_string(e.augment_three)); + v.push_back(std::to_string(e.augment_four)); + v.push_back(std::to_string(e.augment_five)); + v.push_back(std::to_string(e.augment_six)); + v.push_back("'" + Strings::Escape(e.custom_data) + "'"); + v.push_back(std::to_string(e.ornament_icon)); + v.push_back(std::to_string(e.ornament_idfile)); + v.push_back(std::to_string(e.ornament_hero_model)); + v.push_back(std::to_string(e.guid)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + Sharedbank e{}; + + e.account_id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.slot_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.charges = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.color = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.augment_one = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.augment_two = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_three = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_four = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_five = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_six = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.custom_data = row[11] ? row[11] : ""; + e.ornament_icon = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; + e.ornament_idfile = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; + e.ornament_hero_model = row[14] ? static_cast(atoi(row[14])) : 0; + e.guid = row[15] ? strtoull(row[15], nullptr, 10) : 0; + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + Sharedbank e{}; + + e.account_id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.slot_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.charges = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.color = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.augment_one = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.augment_two = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_three = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_four = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_five = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_six = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.custom_data = row[11] ? row[11] : ""; + e.ornament_icon = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; + e.ornament_idfile = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; + e.ornament_hero_model = row[14] ? static_cast(atoi(row[14])) : 0; + e.guid = row[15] ? strtoull(row[15], nullptr, 10) : 0; + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const Sharedbank &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.account_id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.color)); + v.push_back(std::to_string(e.augment_one)); + v.push_back(std::to_string(e.augment_two)); + v.push_back(std::to_string(e.augment_three)); + v.push_back(std::to_string(e.augment_four)); + v.push_back(std::to_string(e.augment_five)); + v.push_back(std::to_string(e.augment_six)); + v.push_back("'" + Strings::Escape(e.custom_data) + "'"); + v.push_back(std::to_string(e.ornament_icon)); + v.push_back(std::to_string(e.ornament_idfile)); + v.push_back(std::to_string(e.ornament_hero_model)); + v.push_back(std::to_string(e.guid)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.account_id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.color)); + v.push_back(std::to_string(e.augment_one)); + v.push_back(std::to_string(e.augment_two)); + v.push_back(std::to_string(e.augment_three)); + v.push_back(std::to_string(e.augment_four)); + v.push_back(std::to_string(e.augment_five)); + v.push_back(std::to_string(e.augment_six)); + v.push_back("'" + Strings::Escape(e.custom_data) + "'"); + v.push_back(std::to_string(e.ornament_icon)); + v.push_back(std::to_string(e.ornament_idfile)); + v.push_back(std::to_string(e.ornament_hero_model)); + v.push_back(std::to_string(e.guid)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_SHAREDBANK_REPOSITORY_H diff --git a/common/repositories/sharedbank_repository.h b/common/repositories/sharedbank_repository.h index 15243d83e..d0aa47eaf 100644 --- a/common/repositories/sharedbank_repository.h +++ b/common/repositories/sharedbank_repository.h @@ -3,310 +3,47 @@ #include "../database.h" #include "../strings.h" +#include "base/base_sharedbank_repository.h" -class SharedbankRepository { +class SharedbankRepository: public BaseSharedbankRepository { public: - struct Sharedbank { - int acctid; - int slotid; - int itemid; - int16 charges; - int augslot1; - int augslot2; - int augslot3; - int augslot4; - int augslot5; - int augslot6; - std::string custom_data; - }; - static std::string PrimaryKey() - { - return std::string(""); - } + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * SharedbankRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * SharedbankRepository::GetWhereNeverExpires() + * SharedbankRepository::GetWhereXAndY() + * SharedbankRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ - static std::vector Columns() - { - return { - "acctid", - "slotid", - "itemid", - "charges", - "augslot1", - "augslot2", - "augslot3", - "augslot4", - "augslot5", - "augslot6", - "custom_data", - }; - } - - static std::string ColumnsRaw() - { - return std::string(Strings::Implode(", ", Columns())); - } - - static std::string InsertColumnsRaw() - { - std::vector insert_columns; - - for (auto &column : Columns()) { - if (column == PrimaryKey()) { - continue; - } - - insert_columns.push_back(column); - } - - return std::string(Strings::Implode(", ", insert_columns)); - } - - static std::string TableName() - { - return std::string("sharedbank"); - } - - static std::string BaseSelect() - { - return fmt::format( - "SELECT {} FROM {}", - ColumnsRaw(), - TableName() - ); - } - - static std::string BaseInsert() - { - return fmt::format( - "INSERT INTO {} ({}) ", - TableName(), - InsertColumnsRaw() - ); - } - - static Sharedbank NewEntity() - { - Sharedbank entry{}; - - entry.acctid = 0; - entry.slotid = 0; - entry.itemid = 0; - entry.charges = 0; - entry.augslot1 = 0; - entry.augslot2 = 0; - entry.augslot3 = 0; - entry.augslot4 = 0; - entry.augslot5 = 0; - entry.augslot6 = 0; - entry.custom_data = 0; - - return entry; - } - - static Sharedbank GetSharedbankEntry( - const std::vector &sharedbanks, - int sharedbank_id - ) - { - for (auto &sharedbank : sharedbanks) { - if (sharedbank. == sharedbank_id) { - return sharedbank; - } - } - - return NewEntity(); - } - - static Sharedbank FindOne( - int sharedbank_id - ) - { - auto results = database.QueryDatabase( - fmt::format( - "{} WHERE id = {} LIMIT 1", - BaseSelect(), - sharedbank_id - ) - ); - - auto row = results.begin(); - if (results.RowCount() == 1) { - Sharedbank entry{}; - - entry.acctid = atoi(row[0]); - entry.slotid = atoi(row[1]); - entry.itemid = atoi(row[2]); - entry.charges = atoi(row[3]); - entry.augslot1 = atoi(row[4]); - entry.augslot2 = atoi(row[5]); - entry.augslot3 = atoi(row[6]); - entry.augslot4 = atoi(row[7]); - entry.augslot5 = atoi(row[8]); - entry.augslot6 = atoi(row[9]); - entry.custom_data = row[10]; - - return entry; - } - - return NewEntity(); - } - - static int DeleteOne( - int sharedbank_id - ) - { - auto results = database.QueryDatabase( - fmt::format( - "DELETE FROM {} WHERE {} = {}", - TableName(), - PrimaryKey(), - sharedbank_id - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static int UpdateOne( - Sharedbank sharedbank_entry - ) - { - std::vector update_values; - - auto columns = Columns(); - - update_values.push_back(columns[0] + " = " + std::to_string(sharedbank_entry.acctid)); - update_values.push_back(columns[1] + " = " + std::to_string(sharedbank_entry.slotid)); - update_values.push_back(columns[2] + " = " + std::to_string(sharedbank_entry.itemid)); - update_values.push_back(columns[3] + " = " + std::to_string(sharedbank_entry.charges)); - update_values.push_back(columns[4] + " = " + std::to_string(sharedbank_entry.augslot1)); - update_values.push_back(columns[5] + " = " + std::to_string(sharedbank_entry.augslot2)); - update_values.push_back(columns[6] + " = " + std::to_string(sharedbank_entry.augslot3)); - update_values.push_back(columns[7] + " = " + std::to_string(sharedbank_entry.augslot4)); - update_values.push_back(columns[8] + " = " + std::to_string(sharedbank_entry.augslot5)); - update_values.push_back(columns[9] + " = " + std::to_string(sharedbank_entry.augslot6)); - update_values.push_back(columns[10] + " = '" + Strings::Escape(sharedbank_entry.custom_data) + "'"); - - auto results = database.QueryDatabase( - fmt::format( - "UPDATE {} SET {} WHERE {} = {}", - TableName(), - Strings::Implode(", ", update_values), - PrimaryKey(), - sharedbank_entry. - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static Sharedbank InsertOne( - Sharedbank sharedbank_entry - ) - { - std::vector insert_values; - - insert_values.push_back(std::to_string(sharedbank_entry.acctid)); - insert_values.push_back(std::to_string(sharedbank_entry.slotid)); - insert_values.push_back(std::to_string(sharedbank_entry.itemid)); - insert_values.push_back(std::to_string(sharedbank_entry.charges)); - insert_values.push_back(std::to_string(sharedbank_entry.augslot1)); - insert_values.push_back(std::to_string(sharedbank_entry.augslot2)); - insert_values.push_back(std::to_string(sharedbank_entry.augslot3)); - insert_values.push_back(std::to_string(sharedbank_entry.augslot4)); - insert_values.push_back(std::to_string(sharedbank_entry.augslot5)); - insert_values.push_back(std::to_string(sharedbank_entry.augslot6)); - insert_values.push_back("'" + Strings::Escape(sharedbank_entry.custom_data) + "'"); - - auto results = database.QueryDatabase( - fmt::format( - "{} VALUES ({})", - BaseInsert(), - Strings::Implode(",", insert_values) - ) - ); - - if (results.Success()) { - sharedbank_entry.id = results.LastInsertedID(); - return sharedbank_entry; - } - - sharedbank_entry = InstanceListRepository::NewEntity(); - - return sharedbank_entry; - } - - static int InsertMany( - std::vector sharedbank_entries - ) - { - std::vector insert_chunks; - - for (auto &sharedbank_entry: sharedbank_entries) { - std::vector insert_values; - - insert_values.push_back(std::to_string(sharedbank_entry.acctid)); - insert_values.push_back(std::to_string(sharedbank_entry.slotid)); - insert_values.push_back(std::to_string(sharedbank_entry.itemid)); - insert_values.push_back(std::to_string(sharedbank_entry.charges)); - insert_values.push_back(std::to_string(sharedbank_entry.augslot1)); - insert_values.push_back(std::to_string(sharedbank_entry.augslot2)); - insert_values.push_back(std::to_string(sharedbank_entry.augslot3)); - insert_values.push_back(std::to_string(sharedbank_entry.augslot4)); - insert_values.push_back(std::to_string(sharedbank_entry.augslot5)); - insert_values.push_back(std::to_string(sharedbank_entry.augslot6)); - insert_values.push_back("'" + Strings::Escape(sharedbank_entry.custom_data) + "'"); - - insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")"); - } - - std::vector insert_values; - - auto results = database.QueryDatabase( - fmt::format( - "{} VALUES {}", - BaseInsert(), - Strings::Implode(",", insert_chunks) - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static std::vector All() - { - std::vector all_entries; - - auto results = database.QueryDatabase( - fmt::format( - "{}", - BaseSelect() - ) - ); - - all_entries.reserve(results.RowCount()); - - for (auto row = results.begin(); row != results.end(); ++row) { - Sharedbank entry{}; - - entry.acctid = atoi(row[0]); - entry.slotid = atoi(row[1]); - entry.itemid = atoi(row[2]); - entry.charges = atoi(row[3]); - entry.augslot1 = atoi(row[4]); - entry.augslot2 = atoi(row[5]); - entry.augslot3 = atoi(row[6]); - entry.augslot4 = atoi(row[7]); - entry.augslot5 = atoi(row[8]); - entry.augslot6 = atoi(row[9]); - entry.custom_data = row[10]; - - all_entries.push_back(entry); - } - - return all_entries; - } + // Custom extended repository methods here }; diff --git a/common/ruletypes.h b/common/ruletypes.h index 71b5c4ebd..b80e16fa1 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -339,7 +339,7 @@ RULE_STRING(World, MOTD, "", "Server MOTD sent on login, change from empty to ha RULE_STRING(World, Rules, "", "Server Rules, change from empty to have this be used instead of variables table 'rules' value, lines are pipe (|) separated, example: A|B|C") RULE_BOOL(World, EnableAutoLogin, false, "Enables or disables auto login of characters, allowing people to log characters in directly from loginserver to ingame") RULE_BOOL(World, EnablePVPRegions, true, "Enables or disables PVP Regions automatically setting your PVP flag") -RULE_STRING(World, SupportedClients, "", "Comma-delimited list of clients to restrict to. Supported values are Titanium | SoF | SoD | UF | RoF | RoF2. Example: Titanium,RoF2") +RULE_STRING(World, SupportedClients, "RoF2", "Comma-delimited list of clients to restrict to. Supported values are Titanium | SoF | SoD | UF | RoF | RoF2. Example: Titanium,RoF2") RULE_STRING(World, CustomFilesKey, "", "Enable if the server requires custom files and sends a key to validate. Empty string to disable. Example: eqcustom_v1") RULE_STRING(World, CustomFilesUrl, "github.com/knervous/eqnexus/releases", "URL to display at character select if client is missing custom files") RULE_INT(World, CustomFilesAdminLevel, 20, "Admin level at which custom file key is not required when CustomFilesKey is specified") diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 679bffe9d..0674f222f 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -50,6 +50,7 @@ #include "repositories/skill_caps_repository.h" #include "repositories/inventory_repository.h" #include "repositories/books_repository.h" +#include "repositories/sharedbank_repository.h" namespace ItemField { @@ -192,242 +193,268 @@ SharedDatabase::MailKeys SharedDatabase::GetMailKey(int character_id) return MailKeys{}; } -bool SharedDatabase::SaveCursor(uint32 char_id, std::list::const_iterator &start, std::list::const_iterator &end) +bool SharedDatabase::SaveCursor( + uint32 char_id, + std::list::const_iterator& start, + std::list::const_iterator& end +) { - // Delete cursor items - const std::string query = StringFormat("DELETE FROM inventory WHERE charid = %i " - "AND ((slotid >= 8000 AND slotid <= 8999) " - "OR slotid = %i OR (slotid >= %i AND slotid <= %i) )", - char_id, EQ::invslot::slotCursor, - EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END); - const auto results = QueryDatabase(query); - if (!results.Success()) { - std::cout << "Clearing cursor failed: " << results.ErrorMessage() << std::endl; - return false; - } + const int deleted = InventoryRepository::DeleteWhere( + *this, + fmt::format( + "`character_id` = {} AND (`slot_id` = {} OR `slot_id` BETWEEN {} AND {})", + char_id, + EQ::invslot::slotCursor, + EQ::invbag::CURSOR_BAG_BEGIN, + EQ::invbag::CURSOR_BAG_END + ) + ); - int i = 8000; - for(auto& it = start; it != end; ++it, i++) { - if (i > 8999) { break; } // shouldn't be anything in the queue that indexes this high - const EQ::ItemInstance *inst = *it; - const int16 use_slot = (i == 8000) ? EQ::invslot::slotCursor : i; + int16 i = EQ::invslot::slotCursor; + for (auto& it = start; it != end; ++it, i++) { + // shouldn't be anything in the queue that indexes this high + if (i > EQ::invbag::CURSOR_BAG_END) { + break; + } + + const EQ::ItemInstance* inst = *it; + const int16 use_slot = i == EQ::invslot::slotCursor ? EQ::invslot::slotCursor : i; if (!SaveInventory(char_id, inst, use_slot)) { return false; } - } + } return true; } bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const EQ::ItemInstance* inst) { - // Delete cursor items - const std::string query = StringFormat("SELECT itemid, charges FROM sharedbank " - "WHERE acctid = %d AND slotid = %d", - account_id, slot_id); - auto results = QueryDatabase(query); - if (!results.Success()) { - //returning true is less harmful in the face of a query error - return true; + if (!inst || !inst->GetItem()) { + return false; } - if (results.RowCount() == 0) - return false; + const auto& l = SharedbankRepository::GetWhere( + *this, + fmt::format( + "`account_id` = {} AND `slot_id` = {} LIMIT 1", + account_id, + slot_id + ) + ); - auto& row = results.begin(); + if (l.empty()) { + return false; + } - const uint32 id = Strings::ToUnsignedInt(row[0]); - const uint16 charges = Strings::ToUnsignedInt(row[1]); + const auto& e = l.front(); - uint16 expect_charges; + uint16 expect_charges = inst->GetCharges() >= 0 ? inst->GetCharges() : std::numeric_limits::max(); - if(inst->GetCharges() >= 0) - expect_charges = inst->GetCharges(); - else - expect_charges = 0x7FFF; - - if(id != inst->GetItem()->ID || charges != expect_charges) - return false; - - return true; + return e.item_id == inst->GetID() && e.charges == expect_charges; } -bool SharedDatabase::SaveInventory(uint32 char_id, const EQ::ItemInstance* inst, int16 slot_id) { - - //never save tribute slots: - if (slot_id >= EQ::invslot::TRIBUTE_BEGIN && slot_id <= EQ::invslot::TRIBUTE_END) - return true; - if (slot_id >= EQ::invslot::GUILD_TRIBUTE_BEGIN && slot_id <= EQ::invslot::GUILD_TRIBUTE_END) +bool SharedDatabase::SaveInventory(uint32 char_id, const EQ::ItemInstance* inst, int16 slot_id) +{ + // Don't save any Tribute slots + if ( + EQ::ValueWithin(slot_id, EQ::invslot::GUILD_TRIBUTE_BEGIN, EQ::invslot::GUILD_TRIBUTE_END) || + EQ::ValueWithin(slot_id, EQ::invslot::TRIBUTE_BEGIN, EQ::invslot::TRIBUTE_END) + ) { return true; + } - if (slot_id >= EQ::invslot::SHARED_BANK_BEGIN && slot_id <= EQ::invbag::SHARED_BANK_BAGS_END) { - // Shared bank inventory + if ( + EQ::ValueWithin(slot_id, EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END) || + EQ::ValueWithin(slot_id, EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END) + ) { if (!inst) { return DeleteSharedBankSlot(char_id, slot_id); - } - else { + } else { // Needed to clear out bag slots that 'REPLACE' in UpdateSharedBankSlot does not overwrite..otherwise, duplication occurs // (This requires that parent then child items be sent..which should be how they are currently passed) - if (EQ::InventoryProfile::SupportsContainers(slot_id)) + if (EQ::InventoryProfile::SupportsContainers(slot_id)) { DeleteSharedBankSlot(char_id, slot_id); + } + return UpdateSharedBankSlot(char_id, inst, slot_id); } - } - else if (!inst) { // All other inventory + } else if (!inst) { // All other inventory return DeleteInventorySlot(char_id, slot_id); } // Needed to clear out bag slots that 'REPLACE' in UpdateInventorySlot does not overwrite..otherwise, duplication occurs // (This requires that parent then child items be sent..which should be how they are currently passed) - if (EQ::InventoryProfile::SupportsContainers(slot_id)) + if (EQ::InventoryProfile::SupportsContainers(slot_id)) { DeleteInventorySlot(char_id, slot_id); - return UpdateInventorySlot(char_id, inst, slot_id); -} - -bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const EQ::ItemInstance* inst, int16 slot_id) { - // need to check 'inst' argument for valid pointer - - uint32 augslot[EQ::invaug::SOCKET_COUNT] = { 0, 0, 0, 0, 0, 0 }; - if (inst->IsClassCommon()) { - for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { - const EQ::ItemInstance *auginst = inst->GetItem(i); - augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; - } } - uint16 charges; - if(inst->GetCharges() >= 0) - charges = inst->GetCharges(); - else - charges = 0x7FFF; - - // Update/Insert item - const std::string query = StringFormat("REPLACE INTO inventory " - "(charid, slotid, itemid, charges, instnodrop, custom_data, color, " - "augslot1, augslot2, augslot3, augslot4, augslot5, augslot6, ornamenticon, ornamentidfile, ornament_hero_model, guid) " - "VALUES( %lu, %lu, %lu, %lu, %lu, '%s', %lu, " - "%lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu)", - static_cast(char_id), static_cast(slot_id), static_cast(inst->GetItem()->ID), - static_cast(charges), static_cast(inst->IsAttuned() ? 1 : 0), - inst->GetCustomDataString().c_str(), static_cast(inst->GetColor()), - static_cast(augslot[0]), static_cast(augslot[1]), static_cast(augslot[2]), - static_cast(augslot[3]), static_cast(augslot[4]), static_cast(augslot[5]), static_cast(inst->GetOrnamentationIcon()), - static_cast(inst->GetOrnamentationIDFile()), static_cast(inst->GetOrnamentHeroModel()), inst->GetSerialNumber()); - const auto results = QueryDatabase(query); - - // Save bag contents, if slot supports bag contents - if (inst->IsClassBag() && EQ::InventoryProfile::SupportsContainers(slot_id)) - // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' - // messages through attrition (and the modded code in SaveInventory) - for (uint8 idx = EQ::invbag::SLOT_BEGIN; idx < inst->GetItem()->BagSlots && idx <= EQ::invbag::SLOT_END; idx++) { - const EQ::ItemInstance* baginst = inst->GetItem(idx); - SaveInventory(char_id, baginst, EQ::InventoryProfile::CalcSlotId(slot_id, idx)); - } - - if (!results.Success()) { - return false; - } - - return true; + return UpdateInventorySlot(char_id, inst, slot_id); } -bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const EQ::ItemInstance* inst, int16 slot_id) { - // need to check 'inst' argument for valid pointer - - uint32 augslot[EQ::invaug::SOCKET_COUNT] = { 0, 0, 0, 0, 0, 0 }; - if (inst->IsClassCommon()) { - for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { - const EQ::ItemInstance *auginst = inst->GetItem(i); - augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; - } +bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const EQ::ItemInstance* inst, int16 slot_id) +{ + if (!inst || !inst->GetItem()) { + return false; } -// Update/Insert item - const uint32 account_id = GetAccountIDByChar(char_id); - uint16 charges; - if(inst->GetCharges() >= 0) - charges = inst->GetCharges(); - else - charges = 0x7FFF; + std::vector augment_ids = inst->GetAugmentIDs(); - const std::string query = StringFormat("REPLACE INTO sharedbank " - "(acctid, slotid, itemid, charges, custom_data, " - "augslot1, augslot2, augslot3, augslot4, augslot5, augslot6) " - "VALUES( %lu, %lu, %lu, %lu, '%s', " - "%lu, %lu, %lu, %lu, %lu, %lu)", - static_cast(account_id), static_cast(slot_id), static_cast(inst->GetItem()->ID), - static_cast(charges), inst->GetCustomDataString().c_str(), static_cast(augslot[0]), - static_cast(augslot[1]), static_cast(augslot[2]), static_cast(augslot[3]), static_cast(augslot[4]), - static_cast(augslot[5])); - const auto results = QueryDatabase(query); + uint16 charges = inst->GetCharges() >= 0 ? inst->GetCharges() : std::numeric_limits::max(); - // Save bag contents, if slot supports bag contents + auto e = InventoryRepository::NewEntity(); + + e.character_id = char_id; + e.slot_id = slot_id; + e.item_id = inst->GetID(); + e.charges = charges; + e.color = inst->GetColor(); + e.augment_one = augment_ids[0]; + e.augment_two = augment_ids[1]; + e.augment_three = augment_ids[2]; + e.augment_four = augment_ids[3]; + e.augment_five = augment_ids[4]; + e.augment_six = augment_ids[5]; + e.instnodrop = inst->IsAttuned() ? 1 : 0; + e.custom_data = inst->GetCustomDataString(); + e.ornament_icon = inst->GetOrnamentationIcon(); + e.ornament_idfile = inst->GetOrnamentationIDFile(); + e.ornament_hero_model = inst->GetOrnamentHeroModel(); + e.guid = inst->GetSerialNumber(); + + const int replaced = InventoryRepository::ReplaceOne(*this, e); + + // Save bag contents, if slot supports bag contents if (inst->IsClassBag() && EQ::InventoryProfile::SupportsContainers(slot_id)) { // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) - for (uint8 idx = EQ::invbag::SLOT_BEGIN; idx < inst->GetItem()->BagSlots && idx <= EQ::invbag::SLOT_END; idx++) { - const EQ::ItemInstance* baginst = inst->GetItem(idx); - SaveInventory(char_id, baginst, EQ::InventoryProfile::CalcSlotId(slot_id, idx)); + for ( + uint8 i = EQ::invbag::SLOT_BEGIN; + i < inst->GetItem()->BagSlots && i <= EQ::invbag::SLOT_END; + i++ + ) { + const EQ::ItemInstance* bag_inst = inst->GetItem(i); + SaveInventory(char_id, bag_inst, EQ::InventoryProfile::CalcSlotId(slot_id, i)); } } - if (!results.Success()) { - return false; - } - - return true; + return replaced; } -bool SharedDatabase::DeleteInventorySlot(uint32 char_id, int16 slot_id) { +bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const EQ::ItemInstance* inst, int16 slot_id) +{ + if (!inst || !inst->GetItem()) { + return false; + } - // Delete item - std::string query = StringFormat("DELETE FROM inventory WHERE charid = %i AND slotid = %i", char_id, slot_id); - auto results = QueryDatabase(query); - if (!results.Success()) { - return false; - } + std::vector augment_ids = inst->GetAugmentIDs(); - // Delete bag slots, if need be - if (!EQ::InventoryProfile::SupportsContainers(slot_id)) - return true; + uint16 charges = inst->GetCharges() >= 0 ? inst->GetCharges() : std::numeric_limits::max(); - const int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(slot_id, EQ::invbag::SLOT_BEGIN); - query = StringFormat("DELETE FROM inventory WHERE charid = %i AND slotid >= %i AND slotid < %i", - char_id, base_slot_id, (base_slot_id+10)); - results = QueryDatabase(query); - if (!results.Success()) { - return false; - } + const uint32 account_id = GetAccountIDByChar(char_id); - // @merth: need to delete augments here - return true; + auto e = SharedbankRepository::NewEntity(); + + e.account_id = account_id; + e.slot_id = slot_id; + e.item_id = inst->GetID(); + e.charges = charges; + e.color = inst->GetColor(); + e.augment_one = augment_ids[0]; + e.augment_two = augment_ids[1]; + e.augment_three = augment_ids[2]; + e.augment_four = augment_ids[3]; + e.augment_five = augment_ids[4]; + e.augment_six = augment_ids[5]; + e.custom_data = inst->GetCustomDataString(); + e.ornament_icon = inst->GetOrnamentationIcon(); + e.ornament_idfile = inst->GetOrnamentationIDFile(); + e.ornament_hero_model = inst->GetOrnamentHeroModel(); + e.guid = inst->GetSerialNumber(); + + const int replaced = SharedbankRepository::ReplaceOne(*this, e); + + // Save bag contents, if slot supports bag contents + if (inst->IsClassBag() && EQ::InventoryProfile::SupportsContainers(slot_id)) { + // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' + // messages through attrition (and the modded code in SaveInventory) + for ( + uint8 i = EQ::invbag::SLOT_BEGIN; + i < inst->GetItem()->BagSlots && i <= EQ::invbag::SLOT_END; + i++ + ) { + const EQ::ItemInstance* bag_inst = inst->GetItem(i); + SaveInventory(char_id, bag_inst, EQ::InventoryProfile::CalcSlotId(slot_id, i)); + } + } + + return replaced; } -bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id) { +bool SharedDatabase::DeleteInventorySlot(uint32 char_id, int16 slot_id) +{ + const int deleted = InventoryRepository::DeleteWhere( + *this, + fmt::format( + "`character_id` = {} AND `slot_id` = {}", + char_id, + slot_id + ) + ); - // Delete item - const uint32 account_id = GetAccountIDByChar(char_id); - std::string query = StringFormat("DELETE FROM sharedbank WHERE acctid=%i AND slotid=%i", account_id, slot_id); - auto results = QueryDatabase(query); - if (!results.Success()) { - return false; - } + if (!deleted) { + return false; + } // Delete bag slots, if need be - if (!EQ::InventoryProfile::SupportsContainers(slot_id)) - return true; + if (!EQ::InventoryProfile::SupportsContainers(slot_id)) { + return true; + } - const int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(slot_id, EQ::invbag::SLOT_BEGIN); - query = StringFormat("DELETE FROM sharedbank WHERE acctid = %i " - "AND slotid >= %i AND slotid < %i", - account_id, base_slot_id, (base_slot_id+10)); - results = QueryDatabase(query); - if (!results.Success()) { - return false; - } + const int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(slot_id, EQ::invbag::SLOT_BEGIN); - // @merth: need to delete augments here - return true; + return InventoryRepository::DeleteWhere( + *this, + fmt::format( + "`character_id` = {} AND `slot_id` BETWEEN {} AND {}", + char_id, + base_slot_id, + base_slot_id + (EQ::invbag::SLOT_COUNT - 1) + ) + ); +} + +bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id) +{ + const uint32 account_id = GetAccountIDByChar(char_id); + + const int deleted = SharedbankRepository::DeleteWhere( + *this, + fmt::format( + "`account_id` = {} AND `slot_id` = {}", + account_id, + slot_id + ) + ); + + if (!deleted) { + return false; + } + + if (!EQ::InventoryProfile::SupportsContainers(slot_id)) { + return true; + } + + const int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(slot_id, EQ::invbag::SLOT_BEGIN); + + return SharedbankRepository::DeleteWhere( + *this, + fmt::format( + "`account_id` = {} AND `slot_id` BETWEEN {} AND {}", + account_id, + base_slot_id, + base_slot_id + (EQ::invbag::SLOT_COUNT - 1) + ) + ); } @@ -552,96 +579,81 @@ bool SharedDatabase::SetStartingItems( // Retrieve shared bank inventory based on either account or character bool SharedDatabase::GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is_charid) { - std::string query; + const uint32 account_id = is_charid ? GetAccountIDByChar(id) : id; - if (is_charid) { - query = fmt::format( - "SELECT sb.slotid, sb.itemid, sb.charges, " - "sb.augslot1, sb.augslot2, sb.augslot3, " - "sb.augslot4, sb.augslot5, sb.augslot6, sb.custom_data " - "FROM sharedbank sb INNER JOIN character_data ch " - "ON ch.account_id = sb.acctid WHERE ch.id = {} ORDER BY sb.slotid", - id - ); - } else { - query = fmt::format( - "SELECT slotid, itemid, charges, " - "augslot1, augslot2, augslot3, " - "augslot4, augslot5, augslot6, custom_data " - "FROM sharedbank WHERE acctid = {} ORDER BY slotid", - id - ); - } - - auto results = QueryDatabase(query); - // If we have no results we still need to return true - if (!results.Success()) { + if (!account_id) { return false; } - for (auto row : results) { - int16 slot_id = static_cast(Strings::ToInt(row[0])); - uint32 item_id = Strings::ToUnsignedInt(row[1]); - const int16 charges = static_cast(Strings::ToInt(row[2])); + const auto& l = SharedbankRepository::GetWhere( + *this, + fmt::format( + "`account_id` = {}", + account_id + ) + ); - uint32 aug[EQ::invaug::SOCKET_COUNT]; - aug[0] = Strings::ToUnsignedInt(row[3]); - aug[1] = Strings::ToUnsignedInt(row[4]); - aug[2] = Strings::ToUnsignedInt(row[5]); - aug[3] = Strings::ToUnsignedInt(row[6]); - aug[4] = Strings::ToUnsignedInt(row[7]); - aug[5] = Strings::ToUnsignedInt(row[8]); + if (l.empty()) { + return true; + } - const EQ::ItemData *item = GetItem(item_id); + for (const auto& e : l) { + uint32 augment_ids[EQ::invaug::SOCKET_COUNT] = { + e.augment_one, + e.augment_two, + e.augment_three, + e.augment_four, + e.augment_five, + e.augment_six + }; + + const EQ::ItemData* item = GetItem(e.item_id); if (!item) { LogError( - "Warning: [{}] [{}] has an invalid item_id [{}] in inventory slot [{}]", - is_charid ? "charid" : "acctid", + "Warning: {} [{}] has an invalid item_id [{}] in slot_id [{}]", + is_charid ? "character_id" : "account_id", id, - item_id, - slot_id + e.item_id, + e.slot_id ); continue; } - auto inst = CreateBaseItem(item, charges); + EQ::ItemInstance* inst = CreateBaseItem(item, e.charges); if (!inst) { continue; } - if (inst && item->IsClassCommon()) { + if (item->IsClassCommon()) { for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { - if (aug[i]) { - inst->PutAugment(this, i, aug[i]); + if (augment_ids[i]) { + inst->PutAugment(this, i, augment_ids[i]); } } } - if (inst && row[9]) { - std::string data_str(row[9]); - inst->SetCustomDataString(data_str); + if (!e.custom_data.empty()) { + inst->SetCustomDataString(e.custom_data); } - // theoretically inst can be nullptr ... this would be very bad ... - const int16 put_slot_id = inv->PutItem(slot_id, *inst); + const int16 put_slot_id = inv->PutItem(e.slot_id, *inst); safe_delete(inst); - // Save ptr to item in inventory if (put_slot_id != INVALID_INDEX) { continue; } LogError( - "Warning: Invalid slot_id for item in shared bank inventory: [{}]=[{}], item_id=[{}], slot_id=[{}]", - is_charid ? "charid" : "acctid", + "Warning: Invalid slot_id for item in shared bank inventory for {} [{}] item_id [{}] slot_id [{}]", + is_charid ? "character_id" : "account_id", id, - item_id, - slot_id + e.item_id, + e.slot_id ); if (is_charid) { - SaveInventory(id, nullptr, slot_id); + SaveInventory(id, nullptr, e.slot_id); } } @@ -659,7 +671,7 @@ bool SharedDatabase::GetInventory(Client *c) EQ::InventoryProfile &inv = c->GetInv(); // Retrieve character inventory - auto results = InventoryRepository::GetWhere(*this, fmt::format("`charid` = '{}' ORDER BY `slotid`", char_id)); + auto results = InventoryRepository::GetWhere(*this, fmt::format("`character_id` = '{}' ORDER BY `slot_id`", char_id)); auto e_results = CharacterEvolvingItemsRepository::GetWhere( *this, fmt::format("`character_id` = '{}' AND `deleted_at` IS NULL", char_id) ); @@ -669,60 +681,57 @@ bool SharedDatabase::GetInventory(Client *c) return false; } - for (auto const &row: results) { + for (auto const& row: results) { if (row.guid != 0) { EQ::ItemInstance::AddGUIDToMap(row.guid); } } - const auto timestamps = GetItemRecastTimestamps(char_id); - auto cv_conflict = false; - const auto pmask = inv.GetLookup()->PossessionsBitmask; - const auto bank_size = inv.GetLookup()->InventoryTypeSize.Bank; + const auto timestamps = GetItemRecastTimestamps(char_id); + auto cv_conflict = false; + const auto pmask = inv.GetLookup()->PossessionsBitmask; + const auto bank_size = inv.GetLookup()->InventoryTypeSize.Bank; - std::vector queue{}; - for (auto &row: results) { - const int16 slot_id = row.slotid; - const uint32 item_id = row.itemid; + std::vector queue{ }; + for (auto& row: results) { + const int16 slot_id = row.slot_id; + const uint32 item_id = row.item_id; const uint16 charges = row.charges; const uint32 color = row.color; - const bool instnodrop = row.instnodrop; - const uint32 ornament_icon = row.ornamenticon; - const uint32 ornament_idfile = row.ornamentidfile; + const bool instnodrop = row.instnodrop; + const uint32 ornament_icon = row.ornament_icon; + const uint32 ornament_idfile = row.ornament_idfile; const uint32 ornament_hero_model = row.ornament_hero_model; - uint32 aug[EQ::invaug::SOCKET_COUNT]; - aug[0] = row.augslot1; - aug[1] = row.augslot2; - aug[2] = row.augslot3; - aug[3] = row.augslot4; - aug[4] = row.augslot5; - aug[5] = row.augslot6; + uint32 augment_ids[EQ::invaug::SOCKET_COUNT] = { + row.augment_one, + row.augment_two, + row.augment_three, + row.augment_four, + row.augment_five, + row.augment_six + }; - if (slot_id <= EQ::invslot::POSSESSIONS_END && slot_id >= EQ::invslot::POSSESSIONS_BEGIN) { + if (EQ::ValueWithin(slot_id, EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END)) { // Titanium thru UF check if (((static_cast(1) << slot_id) & pmask) == 0) { cv_conflict = true; continue; } - } - else if (slot_id <= EQ::invbag::GENERAL_BAGS_END && slot_id >= EQ::invbag::GENERAL_BAGS_BEGIN) { + } else if (EQ::ValueWithin(slot_id, EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END)) { // Titanium thru UF check - const auto parent_slot = EQ::invslot::GENERAL_BEGIN + ( - (slot_id - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT); + const auto parent_slot = EQ::invslot::GENERAL_BEGIN + ((slot_id - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT); if (((static_cast(1) << parent_slot) & pmask) == 0) { cv_conflict = true; continue; } - } - else if (slot_id <= EQ::invslot::BANK_END && slot_id >= EQ::invslot::BANK_BEGIN) { + } else if (EQ::ValueWithin(slot_id, EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END)) { // Titanium check if ((slot_id - EQ::invslot::BANK_BEGIN) >= bank_size) { cv_conflict = true; continue; } - } - else if (slot_id <= EQ::invbag::BANK_BAGS_END && slot_id >= EQ::invbag::BANK_BAGS_BEGIN) { + } else if (EQ::ValueWithin(slot_id, EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END)) { // Titanium check const auto parent_index = ((slot_id - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT); if (parent_index >= bank_size) { @@ -731,7 +740,7 @@ bool SharedDatabase::GetInventory(Client *c) } } - auto *item = GetItem(item_id); + auto* item = GetItem(item_id); if (!item) { LogError( "Warning: charid [{}] has an invalid item_id [{}] in inventory slot [{}]", @@ -742,7 +751,7 @@ bool SharedDatabase::GetInventory(Client *c) continue; } - auto *inst = CreateBaseItem(item, charges); + auto* inst = CreateBaseItem(item, charges); if (!inst) { continue; } @@ -755,8 +764,13 @@ bool SharedDatabase::GetInventory(Client *c) inst->SetOrnamentationIDFile(ornament_idfile); inst->SetOrnamentHeroModel(item->HerosForgeModel); - if (instnodrop || (inst->GetItem()->Attuneable && slot_id >= EQ::invslot::EQUIPMENT_BEGIN && slot_id <= - EQ::invslot::EQUIPMENT_END)) { + if ( + instnodrop || + ( + inst->GetItem()->Attuneable && + EQ::ValueWithin(slot_id, EQ::invslot::EQUIPMENT_BEGIN, EQ::invslot::EQUIPMENT_END) + ) + ) { inst->SetAttuned(true); } @@ -764,33 +778,29 @@ bool SharedDatabase::GetInventory(Client *c) inst->SetColor(color); } - if (charges == 0x7FFF) { + if (charges == std::numeric_limits::max()) { inst->SetCharges(-1); - } - else if (charges == 0 && inst->IsStackable()) { + } else if (charges == 0 && inst->IsStackable()) { // Stackable items need a minimum charge of 1 remain moveable. inst->SetCharges(1); - } - else { + } else { inst->SetCharges(charges); } if (item->RecastDelay) { if (item->RecastType != RECAST_TYPE_UNLINKED_ITEM && timestamps.count(item->RecastType)) { inst->SetRecastTimestamp(timestamps.at(item->RecastType)); - } - else if (item->RecastType == RECAST_TYPE_UNLINKED_ITEM && timestamps.count(item->ID)) { + } else if (item->RecastType == RECAST_TYPE_UNLINKED_ITEM && timestamps.count(item->ID)) { inst->SetRecastTimestamp(timestamps.at(item->ID)); - } - else { + } else { inst->SetRecastTimestamp(0); } } if (item->IsClassCommon()) { for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { - if (aug[i]) { - inst->PutAugment(this, i, aug[i]); + if (augment_ids[i]) { + inst->PutAugment(this, i, augment_ids[i]); } } } @@ -842,20 +852,10 @@ bool SharedDatabase::GetInventory(Client *c) } int16 put_slot_id; - if (slot_id >= 8000 && slot_id <= 8999) { + // this had || slot_id == EQ::invslot::slotCursor ??s + if (EQ::ValueWithin(slot_id, EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END)) { put_slot_id = inv.PushCursor(*inst); - } - else if (slot_id >= 3111 && slot_id <= 3179) { - // Admins: please report any occurrences of this error - LogError( - "Warning: Defunct location for item in inventory: charid={}, item_id={}, slot_id={} .. pushing to cursor...", - char_id, - item_id, - slot_id - ); - put_slot_id = inv.PushCursor(*inst); - } - else { + } else { put_slot_id = inv.PutItem(slot_id, *inst); } @@ -867,7 +867,7 @@ bool SharedDatabase::GetInventory(Client *c) // Save ptr to item in inventory if (put_slot_id == INVALID_INDEX) { LogError( - "Warning: Invalid slot_id for item in inventory: charid=[{}], item_id=[{}], slot_id=[{}]", + "Warning: Invalid slot_id for item in inventory for character_id [{}] item_id [{}] slot_id [{}]", char_id, item_id, slot_id @@ -876,7 +876,7 @@ bool SharedDatabase::GetInventory(Client *c) } if (cv_conflict) { - const std::string &char_name = GetCharName(char_id); + const std::string& char_name = GetCharName(char_id); LogError( "ClientVersion/Expansion conflict during inventory load at zone entry for [{}] (charid: [{}], inver: [{}], gmi: [{}])", char_name, @@ -896,94 +896,6 @@ bool SharedDatabase::GetInventory(Client *c) return GetSharedBank(char_id, &inv, true); } -// Overloaded: Retrieve character inventory based on account_id and character name (char select) -bool SharedDatabase::GetInventory(uint32 account_id, char *name, EQ::InventoryProfile *inv) // deprecated -{ - // Retrieve character inventory - const std::string query = - StringFormat("SELECT slotid, itemid, charges, color, augslot1, " - "augslot2, augslot3, augslot4, augslot5, augslot6, instnodrop, custom_data, ornamenticon, " - "ornamentidfile, ornament_hero_model " - "FROM inventory INNER JOIN character_data ch " - "ON ch.id = charid WHERE ch.name = '%s' AND ch.account_id = %i ORDER BY slotid", - name, account_id); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogError("If you got an error related to the 'instnodrop' field, run the " - "following SQL Queries:\nalter table inventory add instnodrop " - "tinyint(1) unsigned default 0 not null;\n"); - return false; - } - - for (auto& row = results.begin(); row != results.end(); ++row) { - int16 slot_id = Strings::ToInt(row[0]); - uint32 item_id = Strings::ToUnsignedInt(row[1]); - const int8 charges = Strings::ToInt(row[2]); - const uint32 color = Strings::ToUnsignedInt(row[3]); - - uint32 aug[EQ::invaug::SOCKET_COUNT]; - aug[0] = Strings::ToUnsignedInt(row[4]); - aug[1] = Strings::ToUnsignedInt(row[5]); - aug[2] = Strings::ToUnsignedInt(row[6]); - aug[3] = Strings::ToUnsignedInt(row[7]); - aug[4] = Strings::ToUnsignedInt(row[8]); - aug[5] = Strings::ToUnsignedInt(row[9]); - - const bool instnodrop = (row[10] && static_cast(Strings::ToUnsignedInt(row[10]))); - const uint32 ornament_icon = Strings::ToUnsignedInt(row[12]); - const uint32 ornament_idfile = Strings::ToUnsignedInt(row[13]); - uint32 ornament_hero_model = Strings::ToUnsignedInt(row[14]); - - const EQ::ItemData *item = GetItem(item_id); - if (!item) - continue; - - EQ::ItemInstance *inst = CreateBaseItem(item, charges); - - if (inst == nullptr) - continue; - - inst->SetAttuned(instnodrop); - - if (row[11]) { - std::string data_str(row[11]); - inst->SetCustomDataString(data_str); - } - - inst->SetOrnamentIcon(ornament_icon); - inst->SetOrnamentationIDFile(ornament_idfile); - inst->SetOrnamentHeroModel(item->HerosForgeModel); - - if (color > 0) - inst->SetColor(color); - - inst->SetCharges(charges); - - if (item->IsClassCommon()) { - for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { - if (aug[i]) - inst->PutAugment(this, i, aug[i]); - } - } - - int16 put_slot_id; - if (slot_id >= 8000 && slot_id <= 8999) - put_slot_id = inv->PushCursor(*inst); - else - put_slot_id = inv->PutItem(slot_id, *inst); - - safe_delete(inst); - - // Save ptr to item in inventory - if (put_slot_id == INVALID_INDEX) - LogError("Warning: Invalid slot_id for item in inventory: name={}, acctid={}, item_id={}, slot_id={}", - name, account_id, item_id, slot_id); - } - - // Retrieve shared inventory - return GetSharedBank(account_id, inv, false); -} - std::map SharedDatabase::GetItemRecastTimestamps(uint32 char_id) { std::map timers; @@ -1335,7 +1247,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ // Bag item.BagSize = static_cast(Strings::ToUnsignedInt(row[ItemField::bagsize])); - item.BagSlots = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::bagslots]), 0, 10)); // Will need to be changed from std::min to just use database value when bag slots are increased + item.BagSlots = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::bagslots]), 0, static_cast(EQ::invbag::SLOT_COUNT))); item.BagType = static_cast(Strings::ToUnsignedInt(row[ItemField::bagtype])); item.BagWR = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::bagwr]), 0, 100)); diff --git a/common/version.h b/common/version.h index e2e19372b..6eb990da6 100644 --- a/common/version.h +++ b/common/version.h @@ -42,7 +42,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9296 +#define CURRENT_BINARY_DATABASE_VERSION 9299 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054 #endif diff --git a/utils/scripts/generators/repository-generator.pl b/utils/scripts/generators/repository-generator.pl index 492bf3c96..396b1e875 100644 --- a/utils/scripts/generators/repository-generator.pl +++ b/utils/scripts/generators/repository-generator.pl @@ -142,7 +142,6 @@ foreach my $table_to_generate (@tables) { "guild_bank", "inventory_versions", "raid_leaders", - "sharedbank", "trader_audit", "eqtime", "db_version", diff --git a/world/client.cpp b/world/client.cpp index 1c4b61632..e75d8824d 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -2380,21 +2380,26 @@ bool Client::StoreCharacter( auto e = InventoryRepository::NewEntity(); - e.charid = character_id; + e.character_id = character_id; for (int16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invbag::BANK_BAGS_END;) { const auto inst = p_inventory_profile->GetItem(slot_id); if (inst) { - e.slotid = slot_id; - e.itemid = inst->GetItem()->ID; - e.charges = inst->GetCharges(); - e.color = inst->GetColor(); - e.augslot1 = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN); - e.augslot2 = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 1); - e.augslot3 = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 2); - e.augslot4 = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 3); - e.augslot5 = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 4); - e.augslot6 = inst->GetAugmentItemID(EQ::invaug::SOCKET_END); + e.slot_id = slot_id; + e.item_id = inst->GetItem()->ID; + e.charges = inst->GetCharges(); + e.color = inst->GetColor(); + e.augment_one = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN); + e.augment_two = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 1); + e.augment_three = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 2); + e.augment_four = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 3); + e.augment_five = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 4); + e.augment_six = inst->GetAugmentItemID(EQ::invaug::SOCKET_END); + e.instnodrop = inst->IsAttuned() ? 1 : 0; + e.ornament_icon = inst->GetOrnamentationIcon(); + e.ornament_idfile = inst->GetOrnamentationIDFile(); + e.ornament_hero_model = inst->GetOrnamentHeroModel(); + e.guid = inst->GetSerialNumber(); v.emplace_back(e); } diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 986843da5..6a82eba4a 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -26,6 +26,7 @@ #include #include "sof_char_create_data.h" #include "../common/repositories/character_instance_safereturns_repository.h" +#include "../common/repositories/inventory_repository.h" #include "../common/repositories/criteria/content_filter_criteria.h" #include "../common/zone_store.h" @@ -857,115 +858,90 @@ bool WorldDatabase::LoadCharacterCreateCombos() // this is a slightly modified version of SharedDatabase::GetInventory(...) for character select use-only bool WorldDatabase::GetCharSelInventory(uint32 account_id, char *name, EQ::InventoryProfile *inv) { - if (!account_id || !name || !inv) + if (!account_id || !name || !inv) { return false; + } - std::string query = StringFormat( - "SELECT" - " slotid," - " itemid," - " charges," - " color," - " augslot1," - " augslot2," - " augslot3," - " augslot4," - " augslot5," - " augslot6," - " instnodrop," - " custom_data," - " ornamenticon," - " ornamentidfile," - " ornament_hero_model " - "FROM" - " inventory " - "INNER JOIN" - " character_data ch " - "ON" - " ch.id = charid " - "WHERE" - " ch.name = '%s' " - "AND" - " ch.account_id = %i " - "AND" - " slotid >= %i " - "AND" - " slotid <= %i", - name, - account_id, - EQ::invslot::slotHead, - EQ::invslot::slotFeet + const uint32 character_id = GetCharacterID(name); + + if (!character_id) { + return false; + } + + const auto& l = InventoryRepository::GetWhere( + *this, + fmt::format( + "`character_id` = {} AND `slot_id` BETWEEN {} AND {}", + character_id, + EQ::invslot::slotHead, + EQ::invslot::slotFeet + ) ); - auto results = QueryDatabase(query); - if (!results.Success()) - return false; - for (auto row = results.begin(); row != results.end(); ++row) { - int16 slot_id = Strings::ToInt(row[0]); + if (l.empty()) { + return true; + } - switch (slot_id) { - case EQ::invslot::slotFace: - case EQ::invslot::slotEar2: - case EQ::invslot::slotNeck: - case EQ::invslot::slotShoulders: - case EQ::invslot::slotBack: - case EQ::invslot::slotFinger1: - case EQ::invslot::slotFinger2: - continue; - default: - break; + for (const auto& e : l) { + switch (e.slot_id) { + case EQ::invslot::slotFace: + case EQ::invslot::slotEar2: + case EQ::invslot::slotNeck: + case EQ::invslot::slotShoulders: + case EQ::invslot::slotBack: + case EQ::invslot::slotFinger1: + case EQ::invslot::slotFinger2: + continue; + default: + break; } - uint32 item_id = Strings::ToInt(row[1]); - int8 charges = Strings::ToInt(row[2]); - uint32 color = Strings::ToUnsignedInt(row[3]); - uint32 aug[EQ::invaug::SOCKET_COUNT]; - aug[0] = (uint32)Strings::ToInt(row[4]); - aug[1] = (uint32)Strings::ToInt(row[5]); - aug[2] = (uint32)Strings::ToInt(row[6]); - aug[3] = (uint32)Strings::ToInt(row[7]); - aug[4] = (uint32)Strings::ToInt(row[8]); - aug[5] = (uint32)Strings::ToInt(row[9]); + uint32 augment_ids[EQ::invaug::SOCKET_COUNT] = { + e.augment_one, + e.augment_two, + e.augment_three, + e.augment_four, + e.augment_five, + e.augment_six + }; - bool instnodrop = ((row[10] && (uint16)Strings::ToInt(row[10])) ? true : false); - uint32 ornament_icon = (uint32)Strings::ToUnsignedInt(row[12]); - uint32 ornament_idfile = (uint32)Strings::ToUnsignedInt(row[13]); - uint32 ornament_hero_model = (uint32)Strings::ToUnsignedInt(row[14]); - - const EQ::ItemData *item = content_db.GetItem(item_id); - if (!item) + const EQ::ItemData* item = content_db.GetItem(e.item_id); + if (!item) { continue; - - EQ::ItemInstance *inst = content_db.CreateBaseItem(item, charges); - - if (inst == nullptr) - continue; - - inst->SetAttuned(instnodrop); - - if (row[11]) { - std::string data_str(row[11]); - inst->SetCustomDataString(data_str); } - inst->SetOrnamentIcon(ornament_icon); - inst->SetOrnamentationIDFile(ornament_idfile); - inst->SetOrnamentHeroModel(item->HerosForgeModel); + EQ::ItemInstance *inst = content_db.CreateBaseItem(item, e.charges); - if (color > 0) - inst->SetColor(color); + if (!inst) { + continue; + } - inst->SetCharges(charges); + inst->SetCharges(e.charges); + + if (e.color > 0) { + inst->SetColor(e.color); + } if (item->IsClassCommon()) { for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { - if (aug[i]) - inst->PutAugment(this, i, aug[i]); + if (augment_ids[i]) { + inst->PutAugment(this, i, augment_ids[i]); + } } } - inv->PutItem(slot_id, *inst); + inst->SetAttuned(e.instnodrop); + + if (!e.custom_data.empty()) { + inst->SetCustomDataString(e.custom_data); + } + + inst->SetOrnamentIcon(e.ornament_icon); + inst->SetOrnamentationIDFile(e.ornament_idfile); + inst->SetOrnamentHeroModel(e.ornament_hero_model); + + inv->PutItem(e.slot_id, *inst); safe_delete(inst); } diff --git a/zone/client.cpp b/zone/client.cpp index de23acd0a..71afd1ee1 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -9210,7 +9210,7 @@ void Client::SetPrimaryWeaponOrnamentation(uint32 model_id) auto l = InventoryRepository::GetWhere( database, fmt::format( - "`charid` = {} AND `slotid` = {}", + "`character_id` = {} AND `slot_id` = {}", character_id, EQ::invslot::slotPrimary ) @@ -9222,7 +9222,7 @@ void Client::SetPrimaryWeaponOrnamentation(uint32 model_id) auto e = l.front(); - e.ornamentidfile = model_id; + e.ornament_idfile = model_id; const int updated = InventoryRepository::UpdateOne(database, e); @@ -9243,7 +9243,7 @@ void Client::SetSecondaryWeaponOrnamentation(uint32 model_id) auto l = InventoryRepository::GetWhere( database, fmt::format( - "`charid` = {} AND `slotid` = {}", + "`character_id` = {} AND `slot_id` = {}", character_id, EQ::invslot::slotSecondary ) @@ -9255,7 +9255,7 @@ void Client::SetSecondaryWeaponOrnamentation(uint32 model_id) auto e = l.front(); - e.ornamentidfile = model_id; + e.ornament_idfile = model_id; const int updated = InventoryRepository::UpdateOne(database, e); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 2955c6b75..901b16d40 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1666,11 +1666,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) m_pp.abilitySlotRefresh = 0; } -#ifdef _EQDEBUG - printf("Dumping inventory on load:\n"); - m_inv.dumpEntireInventory(); -#endif - /* Reset to max so they dont drown on zone in if its underwater */ m_pp.air_remaining = 60; /* Check for PVP Zone status*/ @@ -10762,8 +10757,7 @@ void Client::Handle_OP_MoveCoin(const EQApplicationPacket *app) void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) { - if (!CharacterID()) - { + if (!CharacterID()) { return; } @@ -10772,57 +10766,38 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) return; } - MoveItem_Struct* mi = (MoveItem_Struct*)app->pBuffer; - if (spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id)) - { - if (mi->from_slot != mi->to_slot && (mi->from_slot <= EQ::invslot::GENERAL_END || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) - { - const EQ::ItemInstance *itm_from = GetInv().GetItem(mi->from_slot); - const EQ::ItemInstance *itm_to = GetInv().GetItem(mi->to_slot); - auto message = fmt::format("Player issued a move item from {}(item id {}) to {}(item id {}) while casting {}.", + BenchTimer bench; + + MoveItem_Struct* mi = (MoveItem_Struct*) app->pBuffer; + if (spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id)) { + if (mi->from_slot != mi->to_slot && (mi->from_slot <= EQ::invslot::GENERAL_END || mi->from_slot > 39) && + IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) { + const EQ::ItemInstance* itm_from = GetInv().GetItem(mi->from_slot); + const EQ::ItemInstance* itm_to = GetInv().GetItem(mi->to_slot); + auto message = fmt::format( + "Player issued a move item from {}(item id {}) to {}(item id {}) while casting {}.", mi->from_slot, itm_from ? itm_from->GetID() : 0, mi->to_slot, itm_to ? itm_to->GetID() : 0, - casting_spell_id); - RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); + casting_spell_id + ); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{ .message = message }); Kick("Inventory desync"); // Kick client to prevent client and server from getting out-of-sync inventory slots return; } } - // Illegal bagslot usage checks. Currently, user only receives a message if this check is triggered. - bool mi_hack = false; - - if (mi->from_slot >= EQ::invbag::GENERAL_BAGS_BEGIN && mi->from_slot <= EQ::invbag::CURSOR_BAG_END) { - if (mi->from_slot >= EQ::invbag::CURSOR_BAG_BEGIN) { mi_hack = true; } - else { - int16 from_parent = m_inv.CalcSlotId(mi->from_slot); - if (!m_inv[from_parent]) { mi_hack = true; } - else if (!m_inv[from_parent]->IsClassBag()) { mi_hack = true; } - else if (m_inv.CalcBagIdx(mi->from_slot) >= m_inv[from_parent]->GetItem()->BagSlots) { mi_hack = true; } - } - } - - if (mi->to_slot >= EQ::invbag::GENERAL_BAGS_BEGIN && mi->to_slot <= EQ::invbag::CURSOR_BAG_END) { - if (mi->to_slot >= EQ::invbag::CURSOR_BAG_BEGIN) { mi_hack = true; } - else { - int16 to_parent = m_inv.CalcSlotId(mi->to_slot); - if (!m_inv[to_parent]) { mi_hack = true; } - else if (!m_inv[to_parent]->IsClassBag()) { mi_hack = true; } - else if (m_inv.CalcBagIdx(mi->to_slot) >= m_inv[to_parent]->GetItem()->BagSlots) { mi_hack = true; } - } - } - - if (mi_hack) { Message(Chat::Yellow, "Caution: Illegal use of inaccessible bag slots!"); } + database.TransactionBegin(); if (!SwapItem(mi) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) { SwapItemResync(mi); bool error = false; InterrogateInventory(this, false, true, false, error, false); - if (error) + if (error) { InterrogateInventory(this, true, false, true, error); + } } for (int slot : {mi->to_slot, mi->from_slot}) { @@ -10831,6 +10806,10 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) CharacterEvolvingItemsRepository::UpdateOne(database, item->GetEvolvingDetails()); } } + + database.TransactionCommit(); + + LogInventory("OP_MoveItem took [{}] ms", bench.elapsedMilliseconds()); } void Client::Handle_OP_MoveMultipleItems(const EQApplicationPacket *app) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 07158afa7..8fe3b5ff9 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -300,24 +300,30 @@ bool Client::Process() { } } - if (m_lazy_load_bank && m_lazy_load_sent_bank_slots <= EQ::invslot::SHARED_BANK_END) { - const EQ::ItemInstance *inst = nullptr; + int lazy_load_bank_slots = 0; + for (int i = 0; i < 5000; i++) { + if (m_lazy_load_bank && m_lazy_load_sent_bank_slots <= EQ::invslot::SHARED_BANK_END) { + const EQ::ItemInstance *inst = nullptr; - // Jump the gaps - if (m_lazy_load_sent_bank_slots < EQ::invslot::BANK_BEGIN) { - m_lazy_load_sent_bank_slots = EQ::invslot::BANK_BEGIN; - } - else if (m_lazy_load_sent_bank_slots > EQ::invslot::BANK_END && - m_lazy_load_sent_bank_slots < EQ::invslot::SHARED_BANK_BEGIN) { - m_lazy_load_sent_bank_slots = EQ::invslot::SHARED_BANK_BEGIN; - } - else { - m_lazy_load_sent_bank_slots++; - } + // Jump the gaps + if (m_lazy_load_sent_bank_slots < EQ::invslot::BANK_BEGIN) { + m_lazy_load_sent_bank_slots = EQ::invslot::BANK_BEGIN; + } + else if (m_lazy_load_sent_bank_slots > EQ::invslot::BANK_END && + m_lazy_load_sent_bank_slots < EQ::invslot::SHARED_BANK_BEGIN) { + m_lazy_load_sent_bank_slots = EQ::invslot::SHARED_BANK_BEGIN; + } + else { + m_lazy_load_sent_bank_slots++; + } - inst = m_inv[m_lazy_load_sent_bank_slots]; - if (inst) { - SendItemPacket(m_lazy_load_sent_bank_slots, inst, ItemPacketType::ItemPacketTrade); + inst = m_inv[m_lazy_load_sent_bank_slots]; + if (inst) { + SendItemPacket(m_lazy_load_sent_bank_slots, inst, ItemPacketType::ItemPacketTrade); + lazy_load_bank_slots++; + } + } else { + break; } } } @@ -776,65 +782,83 @@ void Client::BulkSendInventoryItems() EQ::OutBuffer ob; EQ::OutBuffer::pos_type last_pos = ob.tellp(); - // Possessions items - for (int16 slot_id = EQ::invslot::POSSESSIONS_BEGIN; slot_id <= EQ::invslot::POSSESSIONS_END; slot_id++) { + // Equipment items + for (int16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; slot_id++) { const EQ::ItemInstance* inst = m_inv[slot_id]; - if (!inst) + if (!inst) { continue; + } inst->Serialize(ob, slot_id); - if (ob.tellp() == last_pos) + if (ob.tellp() == last_pos) { LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id); + } last_pos = ob.tellp(); } - if (!RuleB(Inventory, LazyLoadBank)) { - // Bank items - for (int16 slot_id = EQ::invslot::BANK_BEGIN; slot_id <= EQ::invslot::BANK_END; slot_id++) { - const EQ::ItemInstance* inst = m_inv[slot_id]; - if (!inst) - continue; + // General items + for (int16 slot_id = EQ::invslot::GENERAL_BEGIN; slot_id <= EQ::invslot::GENERAL_END; slot_id++) { + const EQ::ItemInstance* inst = m_inv[slot_id]; + if (!inst) { + continue; + } - inst->Serialize(ob, slot_id); + inst->Serialize(ob, slot_id); - if (ob.tellp() == last_pos) - LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id); + if (ob.tellp() == last_pos) { + LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id); + } - last_pos = ob.tellp(); - } + last_pos = ob.tellp(); + } - // SharedBank items - for (int16 slot_id = EQ::invslot::SHARED_BANK_BEGIN; slot_id <= EQ::invslot::SHARED_BANK_END; slot_id++) { - const EQ::ItemInstance* inst = m_inv[slot_id]; - if (!inst) - continue; + if (!RuleB(Inventory, LazyLoadBank)) { + // Bank items + for (int16 slot_id = EQ::invslot::BANK_BEGIN; slot_id <= EQ::invslot::BANK_END; slot_id++) { + const EQ::ItemInstance* inst = m_inv[slot_id]; + if (!inst) { + continue; + } - inst->Serialize(ob, slot_id); + inst->Serialize(ob, slot_id); - if (ob.tellp() == last_pos) - LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id); + if (ob.tellp() == last_pos) { + LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id); + } - last_pos = ob.tellp(); - } - } + last_pos = ob.tellp(); + } - auto outapp = new EQApplicationPacket(OP_CharInventory); - outapp->size = ob.size(); - outapp->pBuffer = ob.detach(); - QueuePacket(outapp); - safe_delete(outapp); + // SharedBank items + for (int16 slot_id = EQ::invslot::SHARED_BANK_BEGIN; slot_id <= EQ::invslot::SHARED_BANK_END; slot_id++) { + const EQ::ItemInstance* inst = m_inv[slot_id]; + if (!inst) { + continue; + } + + inst->Serialize(ob, slot_id); + + if (ob.tellp() == last_pos) { + LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id); + } + + last_pos = ob.tellp(); + } + } + + auto outapp = new EQApplicationPacket(OP_CharInventory); + + outapp->size = ob.size(); + outapp->pBuffer = ob.detach(); + + QueuePacket(outapp); + safe_delete(outapp); } void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { const EQ::ItemData* handy_item = nullptr; - - uint32 merchant_slots = 80; //The max number of items passed in the transaction. - if (m_ClientVersionBit & EQ::versions::maskRoFAndLater) { // RoF+ can send 200 items - merchant_slots = 200; - } - const EQ::ItemData *item = nullptr; auto merchant_list = zone->merchanttable[merchant_id]; auto npc = entity_list.GetMobByNpcTypeID(npcid); @@ -846,6 +870,8 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { } } + const int16 merchant_slots = (m_ClientVersionBit & EQ::versions::maskRoFAndLater) ? EQ::invtype::MERCHANT_SIZE : 80; + auto temporary_merchant_list = zone->tmpmerchanttable[npcid]; uint32 slot_id = 1; uint8 handy_chance = 0; diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 4a0d8de09..6d2a92da3 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -845,7 +845,7 @@ LootItem *Corpse::GetItem(uint16 lootslot, LootItem **bag_item_data) // convert above code to for loop for (const auto &item: m_item_list) { - if (item->equip_slot >= bagstart && item->equip_slot < bagstart + 10) { + if (item->equip_slot >= bagstart && item->equip_slot < bagstart + EQ::invbag::SLOT_COUNT) { bag_item_data[item->equip_slot - bagstart] = item; } } @@ -1472,7 +1472,7 @@ void Corpse::LootCorpseItem(Client *c, const EQApplicationPacket *app) const EQ::ItemData *item = nullptr; EQ::ItemInstance *inst = nullptr; - LootItem *item_data = nullptr, *bag_item_data[10] = {}; + LootItem *item_data = nullptr, *bag_item_data[EQ::invbag::SLOT_COUNT] = {}; memset(bag_item_data, 0, sizeof(bag_item_data)); if (GetPlayerKillItem() > 1) { diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index af2d2eaf6..931f43338 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -278,25 +278,25 @@ int Perl__getinventoryslotid(std::string identifier) else if (identifier == "generalbags.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN; else if (identifier == "generalbags.end") result = EQ::invbag::GENERAL_BAGS_END; else if (identifier == "general1bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN; - else if (identifier == "general1bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 9; - else if (identifier == "general2bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 10; - else if (identifier == "general2bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 19; - else if (identifier == "general3bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 20; - else if (identifier == "general3bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 29; - else if (identifier == "general4bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 30; - else if (identifier == "general4bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 39; - else if (identifier == "general5bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 40; - else if (identifier == "general5bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 49; - else if (identifier == "general6bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 50; - else if (identifier == "general6bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 59; - else if (identifier == "general7bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 60; - else if (identifier == "general7bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 69; - else if (identifier == "general8bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 70; - else if (identifier == "general8bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 79; - else if (identifier == "general9bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 80; - else if (identifier == "general9bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 89; - else if (identifier == "general10bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + 90; - else if (identifier == "general10bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + 99; + else if (identifier == "general1bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT - 1); + else if (identifier == "general2bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + EQ::invbag::SLOT_COUNT; + else if (identifier == "general2bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 2) - 1); + else if (identifier == "general3bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 2); + else if (identifier == "general3bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 3) - 1); + else if (identifier == "general4bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 3); + else if (identifier == "general4bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 4) - 1); + else if (identifier == "general5bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 4); + else if (identifier == "general5bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 5) - 1); + else if (identifier == "general6bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 5); + else if (identifier == "general6bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 6) - 1); + else if (identifier == "general7bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 6); + else if (identifier == "general7bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 7) - 1); + else if (identifier == "general8bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 7); + else if (identifier == "general8bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 8) - 1); + else if (identifier == "general9bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 8); + else if (identifier == "general9bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 9) - 1); + else if (identifier == "general10bag.begin") result = EQ::invbag::GENERAL_BAGS_BEGIN + (EQ::invbag::SLOT_COUNT * 9); + else if (identifier == "general10bag.end") result = EQ::invbag::GENERAL_BAGS_BEGIN + ((EQ::invbag::SLOT_COUNT * 10) - 1); else if (identifier == "cursorbag.begin") result = EQ::invbag::CURSOR_BAG_BEGIN; else if (identifier == "cursorbag.end") result = EQ::invbag::CURSOR_BAG_END; else if (identifier == "bank.begin") result = EQ::invslot::BANK_BEGIN; diff --git a/zone/gm_commands/show/inventory.cpp b/zone/gm_commands/show/inventory.cpp index c2d22b2d9..2cffdc82f 100644 --- a/zone/gm_commands/show/inventory.cpp +++ b/zone/gm_commands/show/inventory.cpp @@ -310,7 +310,7 @@ void ShowInventory(Client *c, const Seperator *sep) Chat::White, fmt::format( "Slot {} | {} ({}){}", - (8000 + limboIndex), + (14000 + limboIndex), item_data->ID, linker.GenerateLink(), ( @@ -339,7 +339,7 @@ void ShowInventory(Client *c, const Seperator *sep) Chat::White, fmt::format( "Slot {} (Augment Slot {}) | {} ({}){}", - (8000 + limboIndex), + (14000 + limboIndex), augment_index, linker.GenerateLink(), item_data->ID, @@ -375,7 +375,7 @@ void ShowInventory(Client *c, const Seperator *sep) Chat::White, fmt::format( "Slot {} Bag Slot {} | {} ({}){}", - (8000 + limboIndex), + (14000 + limboIndex), sub_index, linker.GenerateLink(), item_data->ID, @@ -407,7 +407,7 @@ void ShowInventory(Client *c, const Seperator *sep) Chat::White, fmt::format( "Slot {} Bag Slot {} (Augment Slot {}) | {} ({}){}", - (8000 + limboIndex), + (14000 + limboIndex), sub_index, augment_index, linker.GenerateLink(), diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 07c2296cc..5d7bdf68f 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -1919,13 +1919,20 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return false; } //verify shared bank transactions in the database - if (src_inst && src_slot_id >= EQ::invslot::SHARED_BANK_BEGIN && src_slot_id <= EQ::invbag::SHARED_BANK_BAGS_END) { + if ( + src_inst && + ( + EQ::ValueWithin(src_slot_id, EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END) || + EQ::ValueWithin(src_slot_id, EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END) + ) + ) { if(!database.VerifyInventory(account_id, src_slot_id, src_inst)) { LogError("Player [{}] on account [{}] was found exploiting the shared bank.\n", GetName(), account_name); DeleteItemInInventory(dst_slot_id,0,true); return(false); } - if (src_slot_id >= EQ::invslot::SHARED_BANK_BEGIN && src_slot_id <= EQ::invslot::SHARED_BANK_END && src_inst->IsClassBag()){ + + if (EQ::ValueWithin(src_slot_id, EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END) && src_inst->IsClassBag()){ for (uint8 idx = EQ::invbag::SLOT_BEGIN; idx <= EQ::invbag::SLOT_END; idx++) { const EQ::ItemInstance* baginst = src_inst->GetItem(idx); if (baginst && !database.VerifyInventory(account_id, EQ::InventoryProfile::CalcSlotId(src_slot_id, idx), baginst)){ @@ -1934,13 +1941,21 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } } } - if (dst_inst && dst_slot_id >= EQ::invslot::SHARED_BANK_BEGIN && dst_slot_id <= EQ::invbag::SHARED_BANK_BAGS_END) { + + if ( + dst_inst && + ( + EQ::ValueWithin(dst_slot_id, EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END) || + EQ::ValueWithin(dst_slot_id, EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END) + ) + ) { if(!database.VerifyInventory(account_id, dst_slot_id, dst_inst)) { LogError("Player [{}] on account [{}] was found exploting the shared bank.\n", GetName(), account_name); DeleteItemInInventory(src_slot_id,0,true); return(false); } - if (dst_slot_id >= EQ::invslot::SHARED_BANK_BEGIN && dst_slot_id <= EQ::invslot::SHARED_BANK_END && dst_inst->IsClassBag()){ + + if (EQ::ValueWithin(dst_slot_id, EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END) && dst_inst->IsClassBag()){ for (uint8 idx = EQ::invbag::SLOT_BEGIN; idx <= EQ::invbag::SLOT_END; idx++) { const EQ::ItemInstance* baginst = dst_inst->GetItem(idx); if (baginst && !database.VerifyInventory(account_id, EQ::InventoryProfile::CalcSlotId(dst_slot_id, idx), baginst)){ @@ -1953,10 +1968,20 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Check for No Drop Hacks Mob* with = trade->With(); - if (((with && with->IsClient() && !with->CastToClient()->IsBecomeNPC() && dst_slot_id >= EQ::invslot::TRADE_BEGIN && dst_slot_id <= EQ::invslot::TRADE_END) || - (dst_slot_id >= EQ::invslot::SHARED_BANK_BEGIN && dst_slot_id <= EQ::invbag::SHARED_BANK_BAGS_END)) - && GetInv().CheckNoDrop(src_slot_id) - && !CanTradeFVNoDropItem()) { + if ( + ( + ( + with && + with->IsClient() && + !with->CastToClient()->IsBecomeNPC() && + EQ::ValueWithin(dst_slot_id, EQ::invslot::TRADE_BEGIN, EQ::invslot::TRADE_END) + ) || + EQ::ValueWithin(dst_slot_id, EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END) || + EQ::ValueWithin(dst_slot_id, EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END) + ) && + GetInv().CheckNoDrop(src_slot_id) && + !CanTradeFVNoDropItem() + ) { auto ndh_inst = m_inv[src_slot_id]; std::string ndh_item_data; if (ndh_inst == nullptr) { @@ -3626,7 +3651,7 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool if (cursor_itr == m_inv.cursor_cbegin()) continue; - instmap[8000 + limbo] = *cursor_itr; + instmap[EQ::invbag::CURSOR_BAG_BEGIN + limbo] = *cursor_itr; } // call InterrogateInventory_ for error check @@ -3729,11 +3754,12 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const EQ::ItemI // very basic error checking - can be elaborated upon if more in-depth testing is needed... if ( - (head >= EQ::invslot::EQUIPMENT_BEGIN && head <= EQ::invslot::EQUIPMENT_END) || - (head >= EQ::invslot::TRIBUTE_BEGIN && head <= EQ::invslot::TRIBUTE_END) || - (head >= EQ::invslot::GUILD_TRIBUTE_BEGIN && head <= EQ::invslot::GUILD_TRIBUTE_END) || - (head >= EQ::invslot::WORLD_BEGIN && head <= EQ::invslot::WORLD_END) || - (head >= 8000 && head <= 8101)) { + EQ::ValueWithin(head, EQ::invslot::EQUIPMENT_BEGIN, EQ::invslot::EQUIPMENT_END) || + EQ::ValueWithin(head, EQ::invslot::TRIBUTE_BEGIN, EQ::invslot::TRIBUTE_END) || + EQ::ValueWithin(head, EQ::invslot::GUILD_TRIBUTE_BEGIN, EQ::invslot::GUILD_TRIBUTE_END) || + EQ::ValueWithin(head, EQ::invslot::WORLD_BEGIN, EQ::invslot::WORLD_END) || + EQ::ValueWithin(head, EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END) + ) { switch (depth) { case 0: // requirement: inst is extant diff --git a/zone/zonedb.h b/zone/zonedb.h index ca0447758..28c224dbb 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -208,10 +208,10 @@ struct ZoneSpellsBlocked { }; struct TraderCharges_Struct { - uint32 ItemID[80]; - int32 SerialNumber[80]; - uint32 ItemCost[80]; - int32 Charges[80]; + uint32 ItemID[EQ::invtype::BAZAAR_SIZE]; + int32 SerialNumber[EQ::invtype::BAZAAR_SIZE]; + uint32 ItemCost[EQ::invtype::BAZAAR_SIZE]; + int32 Charges[EQ::invtype::BAZAAR_SIZE]; }; const int MaxMercStanceID = 9;