1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-01 08:27:46 +00:00

items can be removed from the estate and moved to storeroom/inventory

This commit is contained in:
NotAdam 2018-12-28 11:49:12 +11:00
parent 3d9a90cbb7
commit 49c6049531
11 changed files with 142 additions and 34 deletions

View file

@ -216,7 +216,8 @@ enum ActorControlType : uint16_t
BuildPresetResponse = 0x3ED, BuildPresetResponse = 0x3ED,
/*! /*!
* param1 = object array index * param1 = u16 landid
* u16 slotid
*/ */
RemoveExteriorHousingItem = 0x3EF, RemoveExteriorHousingItem = 0x3EF,

View file

@ -41,7 +41,7 @@ struct FFXIVIpcClientTrigger :
/* 0004 */ uint32_t param11; /* 0004 */ uint32_t param11;
/* 0008 */ uint32_t param12; /* 0008 */ uint32_t param12;
/* 000C */ uint32_t param2; /* 000C */ uint32_t param2;
/* 0010 */ uint32_t housingParam; // todo: param4? /* 0010 */ uint32_t param4; // todo: really?
/* 0014 */ char unk_14[4]; /* 0014 */ char unk_14[4];
/* 0018 */ uint64_t param3; /* 0018 */ uint64_t param3;
}; };

View file

@ -365,9 +365,7 @@ namespace Sapphire::Entity
Common::GearModelSlot equipSlotToModelSlot( Common::GearSetSlot slot ); Common::GearModelSlot equipSlotToModelSlot( Common::GearSetSlot slot );
using InventoryContainerPair = std::pair< Common::InventoryType, uint8_t >; bool getFreeInventoryContainerSlot( Inventory::InventoryContainerPair& containerPair ) const;
bool getFreeInventoryContainerSlot( Entity::Player::InventoryContainerPair& containerPair ) const;
void insertInventoryItem( Common::InventoryType type, uint16_t slot, const Sapphire::ItemPtr item ); void insertInventoryItem( Common::InventoryType type, uint16_t slot, const Sapphire::ItemPtr item );

View file

@ -903,7 +903,7 @@ Sapphire::ItemPtr Sapphire::Entity::Player::dropInventoryItem( Sapphire::Common:
return item; return item;
} }
bool Sapphire::Entity::Player::getFreeInventoryContainerSlot( Entity::Player::InventoryContainerPair& containerPair ) const bool Sapphire::Entity::Player::getFreeInventoryContainerSlot( Inventory::InventoryContainerPair& containerPair ) const
{ {
for( auto bagId : { Bag0, Bag1, Bag2, Bag3 } ) for( auto bagId : { Bag0, Bag1, Bag2, Bag3 } )
{ {

View file

@ -37,6 +37,8 @@ TYPE_FORWARD( HousingInteriorTerritory );
namespace Inventory namespace Inventory
{ {
using InventoryContainerPair = std::pair< Common::InventoryType, uint8_t >;
using InventoryTypeList = std::vector< Common::InventoryType >;
TYPE_FORWARD( HousingItem ); TYPE_FORWARD( HousingItem );
} }

View file

@ -2,7 +2,9 @@
Sapphire::Inventory::HousingItem::HousingItem( uint64_t uId, uint32_t catalogId ) : Sapphire::Inventory::HousingItem::HousingItem( uint64_t uId, uint32_t catalogId ) :
Sapphire::Item( uId, catalogId, false ) Sapphire::Item( uId, catalogId, false )
{ } {
m_stackSize = 1;
}
uint16_t Sapphire::Inventory::HousingItem::getRot() const uint16_t Sapphire::Inventory::HousingItem::getRot() const
{ {

View file

@ -1092,7 +1092,6 @@ bool Sapphire::World::Manager::HousingMgr::placeInteriorItem( Entity::Player& pl
invMgr->saveItem( player, item ); invMgr->saveItem( player, item );
// resend container // resend container
// todo: unsure as to whether we need to resend every container or just the one we edit - we'll see how this goes
invMgr->sendInventoryContainer( player, container ); invMgr->sendInventoryContainer( player, container );
invMgr->saveHousingContainer( ident, container ); invMgr->saveHousingContainer( ident, container );
invMgr->updateHousingItemPosition( item ); invMgr->updateHousingItemPosition( item );
@ -1128,7 +1127,7 @@ void Sapphire::World::Manager::HousingMgr::sendInternalEstateInventoryBatch( Sap
// todo: perms check // todo: perms check
InventoryTypeList containerIds; Inventory::InventoryTypeList containerIds;
if( storeroom ) if( storeroom )
containerIds = m_internalStoreroomContainers; containerIds = m_internalStoreroomContainers;
@ -1297,7 +1296,7 @@ void Sapphire::World::Manager::HousingMgr::reqRemoveHousingItem( Sapphire::Entit
if( land->getOwnerId() != player.getId() ) if( land->getOwnerId() != player.getId() )
return; return;
removeExternalItem( player, *terri, containerId, slot, sendToStoreroom ); removeExternalItem( player, *terri, *land, slot, sendToStoreroom );
} }
} }
@ -1336,18 +1335,15 @@ bool Sapphire::World::Manager::HousingMgr::removeInternalItem( Entity::Player& p
if( !item ) if( !item )
return false; return false;
item->setStackSize( 1 );
if( !sendToStoreroom ) if( !sendToStoreroom )
{ {
// make sure the player has a free inv slot first // make sure the player has a free inv slot first
Entity::Player::InventoryContainerPair containerPair; Inventory::InventoryContainerPair containerPair;
if( !player.getFreeInventoryContainerSlot( containerPair ) ) if( !player.getFreeInventoryContainerSlot( containerPair ) )
return false; return false;
auto invMgr = g_fw.get< InventoryMgr >(); auto invMgr = g_fw.get< InventoryMgr >();
// remove it from housing inventory // remove it from housing inventory
container->removeItem( slotId ); container->removeItem( slotId );
invMgr->sendInventoryContainer( player, container ); invMgr->sendInventoryContainer( player, container );
@ -1358,20 +1354,108 @@ bool Sapphire::World::Manager::HousingMgr::removeInternalItem( Entity::Player& p
player.insertInventoryItem( containerPair.first, containerPair.second, item ); player.insertInventoryItem( containerPair.first, containerPair.second, item );
// todo: set item as bound/unsellable/untradable // todo: set item as bound/unsellable/untradable
}
else
{
ItemContainerPtr freeContainer;
Inventory::InventoryContainerPair freeSlotPair;
freeContainer = getFreeEstateInventorySlot( terri.getLandIdent(), freeSlotPair, m_internalStoreroomContainers );
if( !freeContainer )
return false;
auto invMgr = g_fw.get< InventoryMgr >();
container->removeItem( slotId );
invMgr->sendInventoryContainer( player, container );
invMgr->removeHousingItemPosition( *item );
invMgr->removeItemFromHousingContainer( terri.getLandIdent(), containerId, slotId );
freeContainer->setItem( slotId, item );
invMgr->sendInventoryContainer( player, freeContainer );
invMgr->saveHousingContainer( terri.getLandIdent(), freeContainer );
}
// despawn // despawn
auto arraySlot = ( containerIdx * 50 ) + slotId; auto arraySlot = ( containerIdx * 50 ) + slotId;
terri.removeHousingObject( arraySlot ); terri.removeHousingObject( arraySlot );
}
return true; return true;
} }
bool Sapphire::World::Manager::HousingMgr::removeExternalItem( Entity::Player& player, bool Sapphire::World::Manager::HousingMgr::removeExternalItem( Entity::Player& player, HousingZone& terri, Land& land,
HousingZone& terri, uint16_t slotId, bool sendToStoreroom )
uint16_t containerId, uint16_t slotId,
bool sendToStoreroom )
{ {
auto& containers = getEstateInventory( land.getLandIdent() );
auto& placedContainer = containers[ InventoryType::HousingExteriorPlacedItems ];
auto item = std::dynamic_pointer_cast< Inventory::HousingItem >( placedContainer->getItem( slotId ) );
if( !item )
return false;
auto invMgr = g_fw.get< InventoryMgr >();
if( sendToStoreroom )
{
auto& storeroomContainer = containers[ InventoryType::HousingExteriorStoreroom ];
auto freeSlot = storeroomContainer->getFreeSlot();
if( freeSlot == -1 )
return false;
placedContainer->removeItem( slotId );
invMgr->sendInventoryContainer( player, placedContainer );
invMgr->removeHousingItemPosition( *item );
invMgr->removeItemFromHousingContainer( land.getLandIdent(), placedContainer->getId(), slotId );
storeroomContainer->setItem( freeSlot, item );
invMgr->sendInventoryContainer( player, storeroomContainer );
invMgr->saveHousingContainer( land.getLandIdent(), storeroomContainer );
}
else
{
Inventory::InventoryContainerPair containerPair;
if( !player.getFreeInventoryContainerSlot( containerPair ) )
return false;
// remove from housing inv
placedContainer->removeItem( slotId );
invMgr->sendInventoryContainer( player, placedContainer );
invMgr->removeHousingItemPosition( *item );
invMgr->removeItemFromHousingContainer( land.getLandIdent(), placedContainer->getId(), slotId );
// add to player inv
player.insertInventoryItem( containerPair.first, containerPair.second, item );
}
terri.despawnYardObject( land.getLandIdent().landId, slotId );
return true;
}
Sapphire::ItemContainerPtr Sapphire::World::Manager::HousingMgr::getFreeEstateInventorySlot( Common::LandIdent ident,
Inventory::InventoryContainerPair& pair,
Inventory::InventoryTypeList bagList )
{
auto& estateContainers = getEstateInventory( ident );
for( auto bag : bagList )
{
auto needle = estateContainers.find( bag );
if( needle == estateContainers.end() )
continue;
auto container = needle->second;
auto freeSlot = container->getFreeSlot();
if( freeSlot == -1 )
continue;
pair = std::make_pair( bag, freeSlot );
return container;
}
return nullptr;
} }

View file

@ -66,8 +66,6 @@ namespace Sapphire::World::Manager
*/ */
using LandIdentToInventoryContainerMap = std::unordered_map< uint64_t, ContainerIdToContainerMap >; using LandIdentToInventoryContainerMap = std::unordered_map< uint64_t, ContainerIdToContainerMap >;
using InventoryTypeList = std::vector< Common::InventoryType >;
HousingMgr(); HousingMgr();
virtual ~HousingMgr(); virtual ~HousingMgr();
@ -176,6 +174,10 @@ namespace Sapphire::World::Manager
private: private:
ItemContainerPtr getFreeEstateInventorySlot( Common::LandIdent ident,
Inventory::InventoryContainerPair& pair,
Inventory::InventoryTypeList bagList );
/*! /*!
* *
* @param player * @param player
@ -192,13 +194,12 @@ namespace Sapphire::World::Manager
* *
* @param player * @param player
* @param terri * @param terri
* @param containerId
* @param slotId * @param slotId
* @param sendToStoreroom * @param sendToStoreroom
* @return * @return
*/ */
bool removeExternalItem( Entity::Player& player, HousingZone& terri, bool removeExternalItem( Entity::Player& player, HousingZone& terri, Land& land,
uint16_t containerId, uint16_t slotId, bool sendToStoreroom ); uint16_t slotId, bool sendToStoreroom );
/*! /*!
* @brief Processes the movement of an item placed in a HousingZone * @brief Processes the movement of an item placed in a HousingZone
@ -296,8 +297,8 @@ namespace Sapphire::World::Manager
LandSetLandCacheMap m_landCache; LandSetLandCacheMap m_landCache;
LandIdentToInventoryContainerMap m_estateInventories; LandIdentToInventoryContainerMap m_estateInventories;
InventoryTypeList m_internalPlacedItemContainers; Inventory::InventoryTypeList m_internalPlacedItemContainers;
InventoryTypeList m_internalStoreroomContainers; Inventory::InventoryTypeList m_internalStoreroomContainers;
std::array< std::pair< Common::InventoryType, Common::InventoryType >, 8 > m_containerMap; std::array< std::pair< Common::InventoryType, Common::InventoryType >, 8 > m_containerMap;

View file

@ -79,14 +79,14 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
const auto param12 = packet.data().param12; const auto param12 = packet.data().param12;
const auto param2 = packet.data().param2; const auto param2 = packet.data().param2;
const auto param3 = packet.data().param3; const auto param3 = packet.data().param3;
const auto housingParam = packet.data().housingParam; const auto param4 = packet.data().param4;
pLog->debug( "[" + std::to_string( m_pSession->getId() ) + "] Incoming action: " + pLog->debug( "[" + std::to_string( m_pSession->getId() ) + "] Incoming action: " +
Util::intToHexString( static_cast< uint32_t >( commandId & 0xFFFF ), 4 ) + Util::intToHexString( static_cast< uint32_t >( commandId & 0xFFFF ), 4 ) +
"\nparam1: " + Util::intToHexString( static_cast< uint64_t >( param1 & 0xFFFFFFFFFFFFFFF ), 16 ) + "\nparam1: " + Util::intToHexString( static_cast< uint64_t >( param1 & 0xFFFFFFFFFFFFFFF ), 16 ) +
"\nparam2: " + Util::intToHexString( static_cast< uint32_t >( param2 & 0xFFFFFFFF ), 8 ) + "\nparam2: " + Util::intToHexString( static_cast< uint32_t >( param2 & 0xFFFFFFFF ), 8 ) +
"\nparam3: " + Util::intToHexString( static_cast< uint64_t >( param3 & 0xFFFFFFFFFFFFFFF ), 16 ) + "\nparam3: " + Util::intToHexString( static_cast< uint64_t >( param3 & 0xFFFFFFFFFFFFFFF ), 16 ) +
"\nhousingParam: " + Util::intToHexString( static_cast< uint32_t >( housingParam & 0xFFFFFFFF ), 8 ) "\nparam4: " + Util::intToHexString( static_cast< uint32_t >( param4 & 0xFFFFFFFF ), 8 )
); );
@ -460,8 +460,8 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
{ {
auto housingMgr = g_fw.get< HousingMgr >(); auto housingMgr = g_fw.get< HousingMgr >();
auto slot = housingParam & 0xFF; auto slot = param4 & 0xFF;
auto sendToStoreroom = ( housingParam >> 16 ) != 0; auto sendToStoreroom = ( param4 >> 16 ) != 0;
//player, plot, containerId, slot, sendToStoreroom //player, plot, containerId, slot, sendToStoreroom
housingMgr->reqRemoveHousingItem( player, param12, param2, slot, sendToStoreroom ); housingMgr->reqRemoveHousingItem( player, param12, param2, slot, sendToStoreroom );

View file

@ -6,6 +6,8 @@
#include <Exd/ExdDataGenerated.h> #include <Exd/ExdDataGenerated.h>
#include <Network/GamePacketNew.h> #include <Network/GamePacketNew.h>
#include <Network/PacketDef/Zone/ServerZoneDef.h> #include <Network/PacketDef/Zone/ServerZoneDef.h>
#include <Network/PacketWrappers/ActorControlPacket143.h>
#include <Network/CommonActorControl.h>
#include "Actor/Player.h" #include "Actor/Player.h"
#include "Actor/Actor.h" #include "Actor/Actor.h"
@ -403,3 +405,20 @@ void Sapphire::HousingZone::updateYardObjectPos( Entity::Player& sourcePlayer, u
player.second->queuePacket( packet ); player.second->queuePacket( packet );
} }
} }
void Sapphire::HousingZone::despawnYardObject( uint16_t landId, uint16_t slot )
{
auto bounds = m_yardObjectArrayBounds[ landId ];
auto offset = bounds.first + slot;
auto yardMapIndex = landId <= 29 ? 0 : 1;
memset( &m_yardObjects[ yardMapIndex ][ offset ], 0x00, sizeof( Common::HousingObject ) );
for( const auto& player : m_playerMap )
{
auto param = ( landId << 16 ) | slot;
auto pkt = Server::makeActorControl143( player.second->getId(), Network::ActorControl::RemoveExteriorHousingItem, param );
player.second->queuePacket( pkt );
}
}

View file

@ -58,6 +58,7 @@ namespace Sapphire
void spawnYardObject( uint8_t landId, uint16_t slotId, Sapphire::Inventory::HousingItem& item ); void spawnYardObject( uint8_t landId, uint16_t slotId, Sapphire::Inventory::HousingItem& item );
void updateYardObjectPos( Entity::Player& sourcePlayer, uint16_t slot, uint16_t landId, void updateYardObjectPos( Entity::Player& sourcePlayer, uint16_t slot, uint16_t landId,
Inventory::HousingItem& item ); Inventory::HousingItem& item );
void despawnYardObject( uint16_t landId, uint16_t slot );
private: private:
using LandPtrMap = std::unordered_map< uint8_t, Sapphire::LandPtr >; using LandPtrMap = std::unordered_map< uint8_t, Sapphire::LandPtr >;