diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index e0c93e552..9bf88c0d3 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -6378,7 +6378,104 @@ CREATE INDEX idx_trader_active_transaction ON trader (active_transaction); )", .content_schema_update = false }, + ManifestEntry{ + .version = 9296, + .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`); +)" + }, + ManifestEntry{ + .version = 9297, + .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 +)" + }, + ManifestEntry{ + .version = 9298, + .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`; +)" + } // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ // .version = 9228, 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..603f4111b 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -1037,7 +1037,7 @@ int16 EQ::InventoryProfile::CalcSlotId(int16 bagslot_id, uint8 bagidx) { 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) { 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 2b52e081d..ce19c20cc 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -339,10 +339,10 @@ 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, 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") +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_CATEGORY_END() RULE_CATEGORY(Zone) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 679bffe9d..fea71e349 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 `slotid` 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); } } @@ -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_END, EQ::invslot::POSSESSIONS_BEGIN)) { // 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_END, EQ::invslot::BANK_BEGIN)) { // 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,9 @@ bool SharedDatabase::GetInventory(Client *c) } int16 put_slot_id; - if (slot_id >= 8000 && slot_id <= 8999) { + if (slot_id > EQ::invbag::TRADE_BAGS_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 +866,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 +875,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 +895,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 +1246,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 dec788622..4187eabe5 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 9295 +#define CURRENT_BINARY_DATABASE_VERSION 9298 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045 #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/zone/client.cpp b/zone/client.cpp index 1c577c08d..30e3be5d6 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -9203,7 +9203,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 ) @@ -9215,7 +9215,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); @@ -9236,7 +9236,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 ) @@ -9248,7 +9248,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 03aa87f10..7803b63e9 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -10748,8 +10748,7 @@ void Client::Handle_OP_MoveCoin(const EQApplicationPacket *app) void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) { - if (!CharacterID()) - { + if (!CharacterID()) { return; } @@ -10758,57 +10757,34 @@ 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 {}.", + 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!"); } - 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}) { diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 7a61db35e..919547b98 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -770,11 +770,12 @@ 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); @@ -784,7 +785,7 @@ void Client::BulkSendInventoryItems() last_pos = ob.tellp(); } - if (!RuleB(Inventory, LazyLoadBank)) { + 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]; @@ -823,12 +824,6 @@ void Client::BulkSendInventoryItems() 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); @@ -840,6 +835,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..2078f2bdd 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), + (EQ::invbag::CURSOR_BAG_BEGIN + 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), + (EQ::invbag::CURSOR_BAG_BEGIN + 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), + (EQ::invbag::CURSOR_BAG_BEGIN + 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), + (EQ::invbag::CURSOR_BAG_BEGIN + limboIndex), sub_index, augment_index, linker.GenerateLink(), diff --git a/zone/inventory.cpp b/zone/inventory.cpp index e031d5208..80e792d7f 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) { @@ -3624,7 +3649,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 @@ -3727,11 +3752,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;