diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index 0f0eda35..8d6e9ea1 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -215,6 +215,15 @@ enum ActorControlType : uint16_t ShowBuildPresetUI = 0x3E9, BuildPresetResponse = 0x3ED, + /*! + * param1 = identity shit + * u16 1 - container id + * u16 2 - plot id + * param2 = item shit + * u16 1 - slot + */ + HousingItemMoveConfirm = 0x3F9, + /*! * param1 = outdoor furnishings * u8 0 - relocation available, 1 = available diff --git a/src/common/Network/PacketDef/Zone/ClientZoneDef.h b/src/common/Network/PacketDef/Zone/ClientZoneDef.h index 011fd400..d42e21ed 100644 --- a/src/common/Network/PacketDef/Zone/ClientZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ClientZoneDef.h @@ -261,7 +261,7 @@ struct FFXIVIpcHousingUpdateObjectPosition : { /* 0000 */ Common::LandIdent ident; /* 0008 */ uint16_t slot; - /* 000A */ uint16_t containerId; + /* 000A */ uint16_t unk; /* 000C */ Common::FFXIVARR_POSITION3 pos; /* 0018 */ float rotation; diff --git a/src/world/Manager/HousingMgr.cpp b/src/world/Manager/HousingMgr.cpp index c41094ca..3713c83f 100644 --- a/src/world/Manager/HousingMgr.cpp +++ b/src/world/Manager/HousingMgr.cpp @@ -1149,7 +1149,6 @@ void Sapphire::World::Manager::HousingMgr::sendInternalEstateInventoryBatch( Sap void Sapphire::World::Manager::HousingMgr::reqMoveHousingItem( Entity::Player& player, Common::LandIdent ident, uint16_t slot, - uint16_t container, Common::FFXIVARR_POSITION3 pos, float rot ) { auto landSet = toLandSetId( ident.territoryTypeId, ident.wardNum ); @@ -1162,6 +1161,75 @@ void Sapphire::World::Manager::HousingMgr::reqMoveHousingItem( Entity::Player& p if( land->getOwnerId() != player.getId() ) return; - // update item in db + // todo: what happens when either of these fail? how does the server let the client know that the moment failed + // as is, if it does fail, the client will be locked and unable to move any item until reentering the territory + if( auto terri = std::dynamic_pointer_cast< Territory::Housing::HousingInteriorTerritory >( player.getCurrentZone() ) ) + { + moveInternalItem( player, ident, *terri, slot, pos, rot ); + } + else if( auto terri = std::dynamic_pointer_cast< HousingZone >( player.getCurrentZone() ) ) + { + moveExternalItem( player, ident, slot, pos, rot ); + } +} +bool Sapphire::World::Manager::HousingMgr::moveInternalItem( Entity::Player& player, Common::LandIdent ident, + Territory::Housing::HousingInteriorTerritory& terri, uint16_t slot, + Common::FFXIVARR_POSITION3 pos, float rot ) +{ + auto containerIdx = static_cast< uint16_t >( slot / 50 ); + auto slotIdx = slot % 50; + + uint16_t containerId = 0; + try + { + containerId = m_internalPlacedItemContainers.at( containerIdx ); + } + catch( const std::out_of_range& ex ) + { + return false; + } + + auto& containers = getEstateInventory( ident ); + + auto needle = containers.find( containerId ); + if( needle == containers.end() ) + return false; + + auto container = needle->second; + + auto item = std::dynamic_pointer_cast< Inventory::HousingItem >( container->getItem( slotIdx ) ); + if( !item ) + return false; + + item->setPos( { + Util::floatToUInt16( pos.x ), + Util::floatToUInt16( pos.y ), + Util::floatToUInt16( pos.z ) + } ); + + item->setRot( Util::floatToUInt16Rot( rot ) ); + + // save + auto invMgr = g_fw.get< InventoryMgr >(); + invMgr->updateHousingItemPosition( item ); + + terri.updateObjectPosition( slot, item->getPos(), item->getRot() ); + + // send confirmation to player + uint32_t param1 = ( ident.landId << 16 ) | containerId; + + player.queuePacket( Server::makeActorControl143( player.getId(), ActorControl::HousingItemMoveConfirm, param1, slotIdx ) ); + + // todo: update it for other players?? + + return true; +} + +bool Sapphire::World::Manager::HousingMgr::moveExternalItem( Entity::Player& player, + Common::LandIdent ident, uint16_t slot, + Common::FFXIVARR_POSITION3 pos, float rot ) +{ + + return true; } \ No newline at end of file diff --git a/src/world/Manager/HousingMgr.h b/src/world/Manager/HousingMgr.h index 14ca5009..9fe6dd42 100644 --- a/src/world/Manager/HousingMgr.h +++ b/src/world/Manager/HousingMgr.h @@ -167,11 +167,44 @@ namespace Sapphire::World::Manager void reqMoveHousingItem( Entity::Player& player, Common::LandIdent ident, uint16_t slot, - uint16_t container, Common::FFXIVARR_POSITION3 pos, float rot ); + Common::FFXIVARR_POSITION3 pos, float rot ); private: + /*! + * @brief Processes the movement of an item placed in a HousingZone + * + * This assumes that the player has permission to move the item. + * + * @param player The player who placed the item + * @param ident The ident of the land that the item belongs to + * @param containerIdx The index of the container + * @param slot The slot of the item + * @param pos The new position + * @param rot The new rotation + * @return + */ + bool moveExternalItem( Entity::Player& player, Common::LandIdent ident, uint16_t slot, + Common::FFXIVARR_POSITION3 pos, float rot ); + + /*! + * @brief Processes the movement of an item placed inside a HousingInteriorTerritory + * + * This assumes that the player has permission to move the item. + * + * @param player The player who placed the item + * @param ident The ident of the land that the item belongs to + * @param slot The index of the container + * @param slotIdx The slot of the item + * @param pos The new position + * @param rot The new rotation + * @return + */ + bool moveInternalItem( Entity::Player& player, Common::LandIdent ident, + Territory::Housing::HousingInteriorTerritory& terri, uint16_t slot, + Common::FFXIVARR_POSITION3 pos, float rot ); + /*! * @brief Processes the spawning and linking of a newly placed housing item for external items * @param player The player who is placing the item diff --git a/src/world/Network/Handlers/PacketHandlers.cpp b/src/world/Network/Handlers/PacketHandlers.cpp index daab3cdb..3dc5b303 100644 --- a/src/world/Network/Handlers/PacketHandlers.cpp +++ b/src/world/Network/Handlers/PacketHandlers.cpp @@ -725,6 +725,6 @@ void Sapphire::Network::GameConnection::reqMoveHousingItem( const Packets::FFXIV const auto packet = ZoneChannelPacket< Client::FFXIVIpcHousingUpdateObjectPosition >( inPacket ); const auto& data = packet.data(); - housingMgr->reqMoveHousingItem( player, data.ident, data.slot, data.containerId, data.pos, data.rotation ); + housingMgr->reqMoveHousingItem( player, data.ident, data.slot, data.pos, data.rotation ); } \ No newline at end of file diff --git a/src/world/Territory/Housing/HousingInteriorTerritory.cpp b/src/world/Territory/Housing/HousingInteriorTerritory.cpp index bba2adaf..60e147c7 100644 --- a/src/world/Territory/Housing/HousingInteriorTerritory.cpp +++ b/src/world/Territory/Housing/HousingInteriorTerritory.cpp @@ -183,4 +183,16 @@ void Sapphire::World::Territory::Housing::HousingInteriorTerritory::spawnYardObj player.second->queuePacket( objectSpawnPkt ); } +} + +void Sapphire::World::Territory::Housing::HousingInteriorTerritory::updateObjectPosition( uint16_t slot, + Sapphire::Common::FFXIVARR_POSITION3_U16 pos, + uint16_t rot ) +{ + auto& obj = m_yardObjects[ slot ]; + + obj.pos = pos; + obj.itemRotation = rot; + + // todo: how does this update on other clients? } \ No newline at end of file diff --git a/src/world/Territory/Housing/HousingInteriorTerritory.h b/src/world/Territory/Housing/HousingInteriorTerritory.h index 07c69040..d928cd27 100644 --- a/src/world/Territory/Housing/HousingInteriorTerritory.h +++ b/src/world/Territory/Housing/HousingInteriorTerritory.h @@ -26,6 +26,7 @@ namespace Sapphire::World::Territory::Housing void updateYardObjects(); void spawnYardObject( uint8_t containerIdx, uint16_t slot, uint16_t containerType, Inventory::HousingItemPtr item ); + void updateObjectPosition( uint16_t slot, Common::FFXIVARR_POSITION3_U16 pos, uint16_t rot ); private: Common::LandIdent m_landIdent;