mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-01 00:27:44 +00:00
items can be removed from the estate and moved to storeroom/inventory
This commit is contained in:
parent
3d9a90cbb7
commit
49c6049531
11 changed files with 142 additions and 34 deletions
|
@ -216,7 +216,8 @@ enum ActorControlType : uint16_t
|
|||
BuildPresetResponse = 0x3ED,
|
||||
|
||||
/*!
|
||||
* param1 = object array index
|
||||
* param1 = u16 landid
|
||||
* u16 slotid
|
||||
*/
|
||||
RemoveExteriorHousingItem = 0x3EF,
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ struct FFXIVIpcClientTrigger :
|
|||
/* 0004 */ uint32_t param11;
|
||||
/* 0008 */ uint32_t param12;
|
||||
/* 000C */ uint32_t param2;
|
||||
/* 0010 */ uint32_t housingParam; // todo: param4?
|
||||
/* 0010 */ uint32_t param4; // todo: really?
|
||||
/* 0014 */ char unk_14[4];
|
||||
/* 0018 */ uint64_t param3;
|
||||
};
|
||||
|
|
|
@ -365,9 +365,7 @@ namespace Sapphire::Entity
|
|||
|
||||
Common::GearModelSlot equipSlotToModelSlot( Common::GearSetSlot slot );
|
||||
|
||||
using InventoryContainerPair = std::pair< Common::InventoryType, uint8_t >;
|
||||
|
||||
bool getFreeInventoryContainerSlot( Entity::Player::InventoryContainerPair& containerPair ) const;
|
||||
bool getFreeInventoryContainerSlot( Inventory::InventoryContainerPair& containerPair ) const;
|
||||
|
||||
void insertInventoryItem( Common::InventoryType type, uint16_t slot, const Sapphire::ItemPtr item );
|
||||
|
||||
|
|
|
@ -903,7 +903,7 @@ Sapphire::ItemPtr Sapphire::Entity::Player::dropInventoryItem( Sapphire::Common:
|
|||
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 } )
|
||||
{
|
||||
|
|
|
@ -37,6 +37,8 @@ TYPE_FORWARD( HousingInteriorTerritory );
|
|||
|
||||
namespace Inventory
|
||||
{
|
||||
using InventoryContainerPair = std::pair< Common::InventoryType, uint8_t >;
|
||||
using InventoryTypeList = std::vector< Common::InventoryType >;
|
||||
TYPE_FORWARD( HousingItem );
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
Sapphire::Inventory::HousingItem::HousingItem( uint64_t uId, uint32_t catalogId ) :
|
||||
Sapphire::Item( uId, catalogId, false )
|
||||
{ }
|
||||
{
|
||||
m_stackSize = 1;
|
||||
}
|
||||
|
||||
uint16_t Sapphire::Inventory::HousingItem::getRot() const
|
||||
{
|
||||
|
|
|
@ -1092,7 +1092,6 @@ bool Sapphire::World::Manager::HousingMgr::placeInteriorItem( Entity::Player& pl
|
|||
invMgr->saveItem( player, item );
|
||||
|
||||
// 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->saveHousingContainer( ident, container );
|
||||
invMgr->updateHousingItemPosition( item );
|
||||
|
@ -1128,7 +1127,7 @@ void Sapphire::World::Manager::HousingMgr::sendInternalEstateInventoryBatch( Sap
|
|||
|
||||
// todo: perms check
|
||||
|
||||
InventoryTypeList containerIds;
|
||||
Inventory::InventoryTypeList containerIds;
|
||||
|
||||
if( storeroom )
|
||||
containerIds = m_internalStoreroomContainers;
|
||||
|
@ -1297,7 +1296,7 @@ void Sapphire::World::Manager::HousingMgr::reqRemoveHousingItem( Sapphire::Entit
|
|||
if( land->getOwnerId() != player.getId() )
|
||||
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 )
|
||||
return false;
|
||||
|
||||
item->setStackSize( 1 );
|
||||
|
||||
if( !sendToStoreroom )
|
||||
{
|
||||
// make sure the player has a free inv slot first
|
||||
Entity::Player::InventoryContainerPair containerPair;
|
||||
Inventory::InventoryContainerPair containerPair;
|
||||
if( !player.getFreeInventoryContainerSlot( containerPair ) )
|
||||
return false;
|
||||
|
||||
auto invMgr = g_fw.get< InventoryMgr >();
|
||||
|
||||
|
||||
// remove it from housing inventory
|
||||
container->removeItem( slotId );
|
||||
invMgr->sendInventoryContainer( player, container );
|
||||
|
@ -1358,20 +1354,108 @@ bool Sapphire::World::Manager::HousingMgr::removeInternalItem( Entity::Player& p
|
|||
player.insertInventoryItem( containerPair.first, containerPair.second, item );
|
||||
|
||||
// todo: set item as bound/unsellable/untradable
|
||||
|
||||
// despawn
|
||||
auto arraySlot = ( containerIdx * 50 ) + slotId;
|
||||
|
||||
terri.removeHousingObject( arraySlot );
|
||||
}
|
||||
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
|
||||
auto arraySlot = ( containerIdx * 50 ) + slotId;
|
||||
terri.removeHousingObject( arraySlot );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sapphire::World::Manager::HousingMgr::removeExternalItem( Entity::Player& player,
|
||||
HousingZone& terri,
|
||||
uint16_t containerId, uint16_t slotId,
|
||||
bool sendToStoreroom )
|
||||
bool Sapphire::World::Manager::HousingMgr::removeExternalItem( Entity::Player& player, HousingZone& terri, Land& land,
|
||||
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;
|
||||
}
|
|
@ -66,8 +66,6 @@ namespace Sapphire::World::Manager
|
|||
*/
|
||||
using LandIdentToInventoryContainerMap = std::unordered_map< uint64_t, ContainerIdToContainerMap >;
|
||||
|
||||
using InventoryTypeList = std::vector< Common::InventoryType >;
|
||||
|
||||
HousingMgr();
|
||||
virtual ~HousingMgr();
|
||||
|
||||
|
@ -176,6 +174,10 @@ namespace Sapphire::World::Manager
|
|||
|
||||
private:
|
||||
|
||||
ItemContainerPtr getFreeEstateInventorySlot( Common::LandIdent ident,
|
||||
Inventory::InventoryContainerPair& pair,
|
||||
Inventory::InventoryTypeList bagList );
|
||||
|
||||
/*!
|
||||
*
|
||||
* @param player
|
||||
|
@ -192,13 +194,12 @@ namespace Sapphire::World::Manager
|
|||
*
|
||||
* @param player
|
||||
* @param terri
|
||||
* @param containerId
|
||||
* @param slotId
|
||||
* @param sendToStoreroom
|
||||
* @return
|
||||
*/
|
||||
bool removeExternalItem( Entity::Player& player, HousingZone& terri,
|
||||
uint16_t containerId, uint16_t slotId, bool sendToStoreroom );
|
||||
bool removeExternalItem( Entity::Player& player, HousingZone& terri, Land& land,
|
||||
uint16_t slotId, bool sendToStoreroom );
|
||||
|
||||
/*!
|
||||
* @brief Processes the movement of an item placed in a HousingZone
|
||||
|
@ -296,8 +297,8 @@ namespace Sapphire::World::Manager
|
|||
LandSetLandCacheMap m_landCache;
|
||||
LandIdentToInventoryContainerMap m_estateInventories;
|
||||
|
||||
InventoryTypeList m_internalPlacedItemContainers;
|
||||
InventoryTypeList m_internalStoreroomContainers;
|
||||
Inventory::InventoryTypeList m_internalPlacedItemContainers;
|
||||
Inventory::InventoryTypeList m_internalStoreroomContainers;
|
||||
|
||||
std::array< std::pair< Common::InventoryType, Common::InventoryType >, 8 > m_containerMap;
|
||||
|
||||
|
|
|
@ -79,14 +79,14 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
const auto param12 = packet.data().param12;
|
||||
const auto param2 = packet.data().param2;
|
||||
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: " +
|
||||
Util::intToHexString( static_cast< uint32_t >( commandId & 0xFFFF ), 4 ) +
|
||||
"\nparam1: " + Util::intToHexString( static_cast< uint64_t >( param1 & 0xFFFFFFFFFFFFFFF ), 16 ) +
|
||||
"\nparam2: " + Util::intToHexString( static_cast< uint32_t >( param2 & 0xFFFFFFFF ), 8 ) +
|
||||
"\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 slot = housingParam & 0xFF;
|
||||
auto sendToStoreroom = ( housingParam >> 16 ) != 0;
|
||||
auto slot = param4 & 0xFF;
|
||||
auto sendToStoreroom = ( param4 >> 16 ) != 0;
|
||||
|
||||
//player, plot, containerId, slot, sendToStoreroom
|
||||
housingMgr->reqRemoveHousingItem( player, param12, param2, slot, sendToStoreroom );
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include <Exd/ExdDataGenerated.h>
|
||||
#include <Network/GamePacketNew.h>
|
||||
#include <Network/PacketDef/Zone/ServerZoneDef.h>
|
||||
#include <Network/PacketWrappers/ActorControlPacket143.h>
|
||||
#include <Network/CommonActorControl.h>
|
||||
|
||||
#include "Actor/Player.h"
|
||||
#include "Actor/Actor.h"
|
||||
|
@ -402,4 +404,21 @@ void Sapphire::HousingZone::updateYardObjectPos( Entity::Player& sourcePlayer, u
|
|||
|
||||
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 );
|
||||
}
|
||||
}
|
|
@ -58,6 +58,7 @@ namespace Sapphire
|
|||
void spawnYardObject( uint8_t landId, uint16_t slotId, Sapphire::Inventory::HousingItem& item );
|
||||
void updateYardObjectPos( Entity::Player& sourcePlayer, uint16_t slot, uint16_t landId,
|
||||
Inventory::HousingItem& item );
|
||||
void despawnYardObject( uint16_t landId, uint16_t slot );
|
||||
|
||||
private:
|
||||
using LandPtrMap = std::unordered_map< uint8_t, Sapphire::LandPtr >;
|
||||
|
|
Loading…
Add table
Reference in a new issue