From ade63f917092d2beb45c7f8c4440f856e0e6ba09 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Sun, 12 Aug 2018 22:30:18 +1000 Subject: [PATCH 1/3] fix item splitting --- .../Network/PacketDef/Zone/ClientZoneDef.h | 6 +++--- .../sapphire_zone/Actor/PlayerInventory.cpp | 18 ++++++++++++------ .../sapphire_zone/Script/NativeScriptApi.h | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/common/Network/PacketDef/Zone/ClientZoneDef.h b/src/common/Network/PacketDef/Zone/ClientZoneDef.h index 3b77195f..b7cd1b32 100644 --- a/src/common/Network/PacketDef/Zone/ClientZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ClientZoneDef.h @@ -153,9 +153,7 @@ struct FFXIVIpcInventoryModifyHandler : FFXIVIpcBasePacket< InventoryModifyHandl { /* 0000 */ uint32_t seq; /* 0004 */ Common::InventoryOperation action; - /* 0005 */ char pad_0005[3]; - /* 0008 */ uint16_t splitCount; // todo: check packet handler in game and see if this is sent as a u16 or u32 - /* 000A */ char pad_000A[2]; + /* 0005 */ char pad_0005[7]; /* 000C */ uint16_t fromContainer; /* 000E */ char pad_000E[2]; /* 0010 */ uint8_t fromSlot; @@ -163,6 +161,8 @@ struct FFXIVIpcInventoryModifyHandler : FFXIVIpcBasePacket< InventoryModifyHandl /* 0020 */ uint16_t toContainer; /* 0022 */ char pad_0022[2]; /* 0024 */ uint8_t toSlot; + /* 0025 */ uint8_t pad_0025[3]; + /* 0028 */ uint32_t splitCount; }; } diff --git a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp index e55db651..bce81ff2 100644 --- a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp @@ -533,16 +533,19 @@ int16_t Core::Entity::Player::addItem( uint16_t inventoryId, int8_t slotId, uint " WHERE storageId = " + std::to_string( inventoryId ) + " AND CharacterId = " + std::to_string( getId() ) ); + if( !slient ) + { + auto invUpdate = boost::make_shared< UpdateInventorySlotPacket >( getId(), + rSlotId, + inventoryId, + *item ); - auto invUpdate = boost::make_shared< UpdateInventorySlotPacket >( getId(), - rSlotId, - inventoryId, - *item ); - queuePacket( invUpdate ); + queuePacket( invUpdate ); - if( !silent ) queuePacket( boost::make_shared< ActorControlPacket143 >( getId(), ItemObtainIcon, catalogId, item->getStackSize() ) ); + } + } @@ -613,6 +616,9 @@ bool Core::Entity::Player::updateContainer( uint16_t storageId, uint8_t slotId, void Core::Entity::Player::splitItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot, uint16_t itemCount ) { + if( itemCount == 0 ) + return; + auto fromItem = m_storageMap[fromInventoryId]->getItem( fromSlotId ); if( !fromItem ) return; diff --git a/src/servers/sapphire_zone/Script/NativeScriptApi.h b/src/servers/sapphire_zone/Script/NativeScriptApi.h index cf6393cb..7a300f29 100644 --- a/src/servers/sapphire_zone/Script/NativeScriptApi.h +++ b/src/servers/sapphire_zone/Script/NativeScriptApi.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "Forwards.h" #ifdef _MSC_VER From 8a2b47255419836fa6440c1245529f76da9766db Mon Sep 17 00:00:00 2001 From: NotAdam Date: Sun, 12 Aug 2018 22:53:21 +1000 Subject: [PATCH 2/3] additem returns an itemptr, handin item container --- .../Scripts/opening/OpeningGridania.cpp | 25 +++++++--------- src/servers/Scripts/opening/OpeningLimsa.cpp | 25 +++++++--------- src/servers/Scripts/opening/OpeningUldah.cpp | 25 +++++++--------- src/servers/sapphire_zone/Actor/Player.h | 4 +-- .../sapphire_zone/Actor/PlayerInventory.cpp | 29 +++++++++++-------- .../sapphire_zone/Inventory/ItemContainer.cpp | 13 +++++++-- .../sapphire_zone/Inventory/ItemContainer.h | 5 +++- .../Network/Handlers/GMCommandHandlers.cpp | 2 +- 8 files changed, 64 insertions(+), 64 deletions(-) diff --git a/src/servers/Scripts/opening/OpeningGridania.cpp b/src/servers/Scripts/opening/OpeningGridania.cpp index 32791779..25ce7e31 100644 --- a/src/servers/Scripts/opening/OpeningGridania.cpp +++ b/src/servers/Scripts/opening/OpeningGridania.cpp @@ -30,27 +30,22 @@ private: auto callback = [this]( Entity::Player& player, const Event::SceneResult& result ) { auto questionAnswer = result.param2; - int16_t rSlotId; + + uint16_t itemId = 0; switch( questionAnswer ) { - case 1: rSlotId = player.addItem( Common::InventoryType::ArmoryRing, -1, 4423, 1, false, true ); break; - case 2: rSlotId = player.addItem( Common::InventoryType::ArmoryRing, -1, 4424, 1, false, true ); break; - case 3: rSlotId = player.addItem( Common::InventoryType::ArmoryRing, -1, 4425, 1, false, true ); break; - case 4: rSlotId = player.addItem( Common::InventoryType::ArmoryRing, -1, 4426, 1, false, true ); break; - default: rSlotId = player.addItem( Common::InventoryType::ArmoryRing, -1, 4426, 1, false, true ); break; + case 1: itemId = 4423; break; + case 2: itemId = 4424; break; + case 3: itemId = 4425; break; + case 4: itemId = 4426; break; + default: itemId = 4426; break; } - if( rSlotId != -1 ) - { - auto pItem = player.getItemAt( Common::InventoryType::ArmoryRing, rSlotId ); + auto item = player.addItem( Common::InventoryType::ArmoryRing, -1, itemId, 1, false, true ); - player.sendDebug( std::to_string( rSlotId ) ); - - if( pItem ) - player.equipItem( Common::EquipSlot::Ring2, pItem, true ); - - } + if( item ) + player.equipItem( Common::EquipSlot::Ring2, item, true ); player.setOpeningSequence( 1 ); Scene00001( player ); diff --git a/src/servers/Scripts/opening/OpeningLimsa.cpp b/src/servers/Scripts/opening/OpeningLimsa.cpp index 43000624..71983122 100644 --- a/src/servers/Scripts/opening/OpeningLimsa.cpp +++ b/src/servers/Scripts/opening/OpeningLimsa.cpp @@ -45,27 +45,22 @@ private: auto callback = [this]( Entity::Player& player, const Event::SceneResult& result ) { auto questionAnswer = result.param2; - int16_t rSlotId; + + uint16_t itemId = 0; switch( questionAnswer ) { - case 1: rSlotId = player.addItem( Common::InventoryType::ArmoryRing, -1, 4423, 1, false, true ); break; - case 2: rSlotId = player.addItem( Common::InventoryType::ArmoryRing, -1, 4424, 1, false, true ); break; - case 3: rSlotId = player.addItem( Common::InventoryType::ArmoryRing, -1, 4425, 1, false, true ); break; - case 4: rSlotId = player.addItem( Common::InventoryType::ArmoryRing, -1, 4426, 1, false, true ); break; - default: rSlotId = player.addItem( Common::InventoryType::ArmoryRing, -1, 4426, 1, false, true ); break; + case 1: itemId = 4423; break; + case 2: itemId = 4424; break; + case 3: itemId = 4425; break; + case 4: itemId = 4426; break; + default: itemId = 4426; break; } - if( rSlotId != -1 ) - { - auto pItem = player.getItemAt( Common::InventoryType::ArmoryRing, rSlotId ); + auto item = player.addItem( Common::InventoryType::ArmoryRing, -1, itemId, 1, false, true ); - player.sendDebug( std::to_string( rSlotId ) ); - - if( pItem ) - player.equipItem( Common::EquipSlot::Ring2, pItem, true ); - - } + if( item ) + player.equipItem( Common::EquipSlot::Ring2, item, true ); player.setOpeningSequence( 1 ); Scene00001( player ); diff --git a/src/servers/Scripts/opening/OpeningUldah.cpp b/src/servers/Scripts/opening/OpeningUldah.cpp index eb7cc2a2..7c3529ea 100644 --- a/src/servers/Scripts/opening/OpeningUldah.cpp +++ b/src/servers/Scripts/opening/OpeningUldah.cpp @@ -31,27 +31,22 @@ private: auto callback = [this]( Entity::Player& player, const Event::SceneResult& result ) { auto questionAnswer = result.param2; - int16_t rSlotId; + + uint16_t itemId = 0; switch( questionAnswer ) { - case 1: rSlotId = player.addItem( Common::InventoryType::ArmoryRing, -1, 4423, 1, false, true ); break; - case 2: rSlotId = player.addItem( Common::InventoryType::ArmoryRing, -1, 4424, 1, false, true ); break; - case 3: rSlotId = player.addItem( Common::InventoryType::ArmoryRing, -1, 4425, 1, false, true ); break; - case 4: rSlotId = player.addItem( Common::InventoryType::ArmoryRing, -1, 4426, 1, false, true ); break; - default: rSlotId = player.addItem( Common::InventoryType::ArmoryRing, -1, 4426, 1, false, true ); break; + case 1: itemId = 4423; break; + case 2: itemId = 4424; break; + case 3: itemId = 4425; break; + case 4: itemId = 4426; break; + default: itemId = 4426; break; } - if( rSlotId != -1 ) - { - auto pItem = player.getItemAt( Common::InventoryType::ArmoryRing, rSlotId ); + auto item = player.addItem( Common::InventoryType::ArmoryRing, -1, itemId, 1, false, true ); - player.sendDebug( std::to_string( rSlotId ) ); - - if( pItem ) - player.equipItem( Common::EquipSlot::Ring2, pItem, true ); - - } + if( item ) + player.equipItem( Common::EquipSlot::Ring2, item, true ); player.setOpeningSequence( 1 ); Scene00001( player ); diff --git a/src/servers/sapphire_zone/Actor/Player.h b/src/servers/sapphire_zone/Actor/Player.h index 268ab9f9..5376b655 100644 --- a/src/servers/sapphire_zone/Actor/Player.h +++ b/src/servers/sapphire_zone/Actor/Player.h @@ -612,7 +612,7 @@ public: bool loadInventory(); InvSlotPairVec getSlotsOfItemsInInventory( uint32_t catalogId ); InvSlotPair getFreeBagSlot(); - int16_t addItem( uint16_t inventoryId, int8_t slotId, uint32_t catalogId, uint16_t quantity = 1, bool isHq = false, bool silent = false ); + Core::ItemPtr addItem( uint16_t inventoryId, int8_t slotId, uint32_t catalogId, uint16_t quantity = 1, bool isHq = false, bool slient = false ); void moveItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot ); void swapItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot ); void discardItem( uint16_t fromInventoryId, uint8_t fromSlotId ); @@ -760,7 +760,7 @@ private: // content finder info uint32_t m_cfPenaltyUntil; // unix time - uint8_t m_mount; + uint32_t m_mount; uint32_t m_emoteMode; uint8_t m_pose; diff --git a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp index bce81ff2..df89ec1d 100644 --- a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp @@ -45,8 +45,8 @@ using namespace Core::Network::ActorControl; void Core::Entity::Player::initInventory() { - auto setupContainer = [this]( InventoryType type, uint8_t maxSize, const std::string& tableName, bool isMultiStorage ) - { m_storageMap[type] = make_ItemContainer( type, maxSize, tableName, isMultiStorage ); }; + auto setupContainer = [this]( InventoryType type, uint8_t maxSize, const std::string& tableName, bool isMultiStorage, bool isPersistentStorage = true ) + { m_storageMap[type] = make_ItemContainer( type, maxSize, tableName, isMultiStorage, isPersistentStorage ); }; // main bags setupContainer( Bag0, 34, "charaiteminventory", true ); @@ -102,6 +102,10 @@ void Core::Entity::Player::initInventory() //soul crystals - 13 setupContainer( ArmorySoulCrystal, 34, "charaiteminventory", true ); + // item hand in container + // non-persistent container, will not save its contents + setupContainer( HandIn, 10, "", true, false ); + loadInventory(); } @@ -321,7 +325,7 @@ bool Core::Entity::Player::tryAddItem( uint16_t catalogId, uint32_t quantity ) for( uint16_t i = 0; i < 4; i++ ) { - if( addItem( i, -1, catalogId, quantity ) != -1 ) + if( addItem( i, -1, catalogId, quantity ) ) return true; } return false; @@ -445,6 +449,9 @@ void Core::Entity::Player::writeInventory( InventoryType type ) auto storage = m_storageMap[type]; + if( storage->isPersistentStorage() ) + return; + std::string query = "UPDATE " + storage->getTableName() + " SET "; for( int32_t i = 0; i <= storage->getMaxSize(); i++ ) @@ -488,7 +495,7 @@ bool Core::Entity::Player::isObtainable( uint32_t catalogId, uint8_t quantity ) } -int16_t Core::Entity::Player::addItem( uint16_t inventoryId, int8_t slotId, uint32_t catalogId, uint16_t quantity, bool isHq, bool silent ) +Core::ItemPtr Core::Entity::Player::addItem( uint16_t inventoryId, int8_t slotId, uint32_t catalogId, uint16_t quantity, bool isHq, bool silent ) { auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >(); auto pExdData = g_fw.get< Data::ExdDataGenerated >(); @@ -497,7 +504,7 @@ int16_t Core::Entity::Player::addItem( uint16_t inventoryId, int8_t slotId, uint // if item data doesn't exist or it's a blank field if( !itemInfo || itemInfo->levelItem == 0 ) { - return -1; + return nullptr; } int8_t rSlotId = -1; @@ -515,7 +522,7 @@ int16_t Core::Entity::Player::addItem( uint16_t inventoryId, int8_t slotId, uint rSlotId = freeSlot.second; if( rSlotId == -1 ) - return -1; + return nullptr; } auto item = createItem( catalogId, quantity ); @@ -533,7 +540,7 @@ int16_t Core::Entity::Player::addItem( uint16_t inventoryId, int8_t slotId, uint " WHERE storageId = " + std::to_string( inventoryId ) + " AND CharacterId = " + std::to_string( getId() ) ); - if( !slient ) + if( !silent ) { auto invUpdate = boost::make_shared< UpdateInventorySlotPacket >( getId(), rSlotId, @@ -549,7 +556,7 @@ int16_t Core::Entity::Player::addItem( uint16_t inventoryId, int8_t slotId, uint } - return rSlotId; + return item; } @@ -634,12 +641,10 @@ void Core::Entity::Player::splitItem( uint16_t fromInventoryId, uint8_t fromSlot // todo: correct invalid move? again, not sure what retail does here return; - auto newSlot = addItem( toInventoryId, toSlot, fromItem->getId(), itemCount, fromItem->isHq(), true ); - if( newSlot == -1 ) + auto newItem = addItem( toInventoryId, toSlot, fromItem->getId(), itemCount, fromItem->isHq(), true ); + if( !newItem ) return; - auto newItem = m_storageMap[toInventoryId]->getItem( static_cast< uint8_t >( newSlot ) ); - fromItem->setStackSize( fromItem->getStackSize() - itemCount ); updateContainer( fromInventoryId, fromSlotId, fromItem ); diff --git a/src/servers/sapphire_zone/Inventory/ItemContainer.cpp b/src/servers/sapphire_zone/Inventory/ItemContainer.cpp index e9a4d28d..88b81425 100644 --- a/src/servers/sapphire_zone/Inventory/ItemContainer.cpp +++ b/src/servers/sapphire_zone/Inventory/ItemContainer.cpp @@ -11,11 +11,12 @@ extern Core::Framework g_fw; -Core::ItemContainer::ItemContainer( uint16_t storageId, uint8_t maxSize, const std::string& tableName, bool isMultiStorage ) : +Core::ItemContainer::ItemContainer( uint16_t storageId, uint8_t maxSize, const std::string& tableName, bool isMultiStorage, bool isPersistentStorage ) : m_id( storageId ), m_size( maxSize ), m_tableName( tableName ), - m_bMultiStorage( isMultiStorage ) + m_bMultiStorage( isMultiStorage ), + m_isPersistentStorage( isPersistentStorage ) { } @@ -43,7 +44,8 @@ void Core::ItemContainer::removeItem( uint8_t slotId ) if( it != m_itemMap.end() ) { - pDb->execute( "DELETE FROM charaglobalitem WHERE itemId = " + std::to_string( it->second->getUId() ) ); + if( m_isPersistentStorage ) + pDb->execute( "DELETE FROM charaglobalitem WHERE itemId = " + std::to_string( it->second->getUId() ) ); m_itemMap.erase( it ); @@ -113,4 +115,9 @@ bool Core::ItemContainer::isMultiStorage() const return m_bMultiStorage; } +bool Core::ItemContainer::isPersistentStorage() const +{ + return m_isPersistentStorage; +} + diff --git a/src/servers/sapphire_zone/Inventory/ItemContainer.h b/src/servers/sapphire_zone/Inventory/ItemContainer.h index 0d0334bf..09a35c26 100644 --- a/src/servers/sapphire_zone/Inventory/ItemContainer.h +++ b/src/servers/sapphire_zone/Inventory/ItemContainer.h @@ -16,7 +16,7 @@ namespace Core { public: - ItemContainer( uint16_t storageId, uint8_t maxSize, const std::string& tableName, bool isMultiStorage ); + ItemContainer( uint16_t storageId, uint8_t maxSize, const std::string& tableName, bool isMultiStorage, bool isPersistentStorage = true ); ~ItemContainer(); uint16_t getId() const; @@ -40,12 +40,15 @@ namespace Core std::string getTableName() const; bool isMultiStorage() const; + + bool isPersistentStorage() const; private: uint16_t m_id; uint8_t m_size; std::string m_tableName; bool m_bMultiStorage; + bool m_isPersistentStorage; ItemMap m_itemMap; Entity::PlayerPtr m_pOwner; }; diff --git a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp index f009e69d..0a81a927 100644 --- a/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/GMCommandHandlers.cpp @@ -324,7 +324,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::FFXIVARR_PACKET_R } if( !targetPlayer->addItem( -1, param1, quantity ) ) - player.sendUrgent( "Item " + std::to_string( param1 ) + " not found..." ); + player.sendUrgent( "Item " + std::to_string( param1 ) + " could not be added to inventory." ); break; } case GmCommand::Gil: From 05585ac24b5425f697cf55687980629f1ee8425e Mon Sep 17 00:00:00 2001 From: NotAdam Date: Sun, 12 Aug 2018 23:04:23 +1000 Subject: [PATCH 3/3] missed a ! during refactoring, oops --- src/servers/sapphire_zone/Actor/PlayerInventory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp index df89ec1d..44ec57ab 100644 --- a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp @@ -449,7 +449,7 @@ void Core::Entity::Player::writeInventory( InventoryType type ) auto storage = m_storageMap[type]; - if( storage->isPersistentStorage() ) + if( !storage->isPersistentStorage() ) return; std::string query = "UPDATE " + storage->getTableName() + " SET ";