mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-25 22:17:45 +00:00
add external housing object placing
This commit is contained in:
parent
e58014174c
commit
d3301b0b9f
18 changed files with 300 additions and 23 deletions
|
@ -236,6 +236,17 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements()
|
||||||
"WHERE LandIdent = ? AND ContainerId = ? AND SlotId = ?;",
|
"WHERE LandIdent = ? AND ContainerId = ? AND SlotId = ?;",
|
||||||
CONNECTION_BOTH );
|
CONNECTION_BOTH );
|
||||||
|
|
||||||
|
prepareStatement( LAND_INV_UP_ITEMPOS,
|
||||||
|
"INSERT INTO landplaceditems ( ItemId, PosX, PosY, PosZ, Rotation ) "
|
||||||
|
"VALUES ( ?, ?, ?, ?, ? ) "
|
||||||
|
"ON DUPLICATE KEY UPDATE PosX = ?, PosY = ?, PosZ = ?, Rotation = ?;",
|
||||||
|
CONNECTION_BOTH );
|
||||||
|
|
||||||
|
prepareStatement( LAND_INV_DEL_ITEMPOS,
|
||||||
|
"DELETE FROM landplaceditems "
|
||||||
|
"WHERE ItemId = ?;",
|
||||||
|
CONNECTION_BOTH );
|
||||||
|
|
||||||
/*prepareStatement( LAND_INS,
|
/*prepareStatement( LAND_INS,
|
||||||
"INSERT INTO land ( LandSetId ) VALUES ( ? );",
|
"INSERT INTO land ( LandSetId ) VALUES ( ? );",
|
||||||
CONNECTION_BOTH );
|
CONNECTION_BOTH );
|
||||||
|
|
|
@ -91,6 +91,8 @@ namespace Sapphire::Db
|
||||||
LAND_INV_SEL_HOUSE,
|
LAND_INV_SEL_HOUSE,
|
||||||
LAND_INV_DEL,
|
LAND_INV_DEL,
|
||||||
LAND_INV_UP,
|
LAND_INV_UP,
|
||||||
|
LAND_INV_UP_ITEMPOS,
|
||||||
|
LAND_INV_DEL_ITEMPOS,
|
||||||
|
|
||||||
|
|
||||||
MAX_STATEMENTS
|
MAX_STATEMENTS
|
||||||
|
|
|
@ -294,6 +294,8 @@ namespace Sapphire::Network::Packets
|
||||||
|
|
||||||
InventoryModifyHandler = 0x0142, // updated 4.4
|
InventoryModifyHandler = 0x0142, // updated 4.4
|
||||||
|
|
||||||
|
ReqPlaceHousingItem = 0x145, // updated 4.4
|
||||||
|
|
||||||
BuildPresetHandler = 0x014A, // updated 4.4
|
BuildPresetHandler = 0x014A, // updated 4.4
|
||||||
TalkEventHandler = 0x014B, // updated 4.4
|
TalkEventHandler = 0x014B, // updated 4.4
|
||||||
EmoteEventHandler = 0x014C, // updated 4.4
|
EmoteEventHandler = 0x014C, // updated 4.4
|
||||||
|
@ -311,6 +313,7 @@ namespace Sapphire::Network::Packets
|
||||||
|
|
||||||
LandRenameHandler = 0x0171, // updated 4.4
|
LandRenameHandler = 0x0171, // updated 4.4
|
||||||
HousingUpdateHouseGreeting = 0x0172, // updated 4.4
|
HousingUpdateHouseGreeting = 0x0172, // updated 4.4
|
||||||
|
HousingUpdateObjectRotation = 0x0173, // updated 4.4
|
||||||
|
|
||||||
SetSharedEstateSettings = 0x0177, // updated 4.4
|
SetSharedEstateSettings = 0x0177, // updated 4.4
|
||||||
|
|
||||||
|
|
|
@ -240,6 +240,22 @@ struct FFXIVIpcMarketBoardRequestItemListings :
|
||||||
/* 0004 */ uint32_t padding;
|
/* 0004 */ uint32_t padding;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FFXIVIpcReqPlaceHousingItem :
|
||||||
|
FFXIVIpcBasePacket< ReqPlaceHousingItem >
|
||||||
|
{
|
||||||
|
/* 0000 */ uint16_t landId; // 0 when plot 0 or inside an estate
|
||||||
|
/* 0002 */ uint16_t unknown1;
|
||||||
|
/* 0004 */ uint32_t unknown2;
|
||||||
|
/* 0008 */ uint16_t sourceInvContainerId;
|
||||||
|
/* 000A */ uint16_t sourceInvSlotId;
|
||||||
|
|
||||||
|
/* 000C */ Common::FFXIVARR_POSITION3 position;
|
||||||
|
/* 0018 */ float rotation;
|
||||||
|
|
||||||
|
/* 001C */ uint32_t unknown3; // always 1?
|
||||||
|
/* 0020 */ uint32_t unknown4[2]; // always 0 it looks like
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1684,11 +1684,7 @@ struct FFXIVIpcYardObjectSpawn : FFXIVIpcBasePacket<YardObjectSpawn>
|
||||||
uint8_t landSetId;
|
uint8_t landSetId;
|
||||||
uint8_t objectArray;
|
uint8_t objectArray;
|
||||||
uint16_t unknown1;
|
uint16_t unknown1;
|
||||||
uint32_t itemId;
|
Common::YardObject object;
|
||||||
uint16_t itemRotation;
|
|
||||||
uint16_t pos_x;
|
|
||||||
uint16_t pos_y;
|
|
||||||
uint16_t pos_z;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FFXIVIpcYardObjectMove : FFXIVIpcBasePacket<YardObjectMove>
|
struct FFXIVIpcYardObjectMove : FFXIVIpcBasePacket<YardObjectMove>
|
||||||
|
|
|
@ -919,6 +919,8 @@ namespace Sapphire::Entity
|
||||||
void setActiveLand( uint8_t land, uint8_t ward );
|
void setActiveLand( uint8_t land, uint8_t ward );
|
||||||
Common::ActiveLand getActiveLand() const;
|
Common::ActiveLand getActiveLand() const;
|
||||||
|
|
||||||
|
Sapphire::ItemPtr dropInventoryItem( Common::InventoryType type, uint16_t slotId );
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
|
@ -754,7 +754,7 @@ void Sapphire::Entity::Player::swapItem( uint16_t fromInventoryId, uint8_t fromS
|
||||||
void Sapphire::Entity::Player::discardItem( uint16_t fromInventoryId, uint8_t fromSlotId )
|
void Sapphire::Entity::Player::discardItem( uint16_t fromInventoryId, uint8_t fromSlotId )
|
||||||
{
|
{
|
||||||
// i am not entirely sure how this should be generated or if it even is important for us...
|
// i am not entirely sure how this should be generated or if it even is important for us...
|
||||||
uint32_t transactionId = 1;
|
uint32_t transactionId = getNextInventorySequence();
|
||||||
|
|
||||||
auto fromItem = m_storageMap[ fromInventoryId ]->getItem( fromSlotId );
|
auto fromItem = m_storageMap[ fromInventoryId ]->getItem( fromSlotId );
|
||||||
|
|
||||||
|
@ -869,3 +869,36 @@ uint32_t Sapphire::Entity::Player::getNextInventorySequence()
|
||||||
{
|
{
|
||||||
return m_inventorySequence++;
|
return m_inventorySequence++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Sapphire::ItemPtr Sapphire::Entity::Player::dropInventoryItem( Sapphire::Common::InventoryType type, uint16_t slotId )
|
||||||
|
{
|
||||||
|
auto& container = m_storageMap[ type ];
|
||||||
|
|
||||||
|
auto item = container->getItem( slotId );
|
||||||
|
if( !item )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// unlink item
|
||||||
|
container->removeItem( slotId );
|
||||||
|
updateContainer( type, slotId, nullptr );
|
||||||
|
|
||||||
|
auto seq = getNextInventorySequence();
|
||||||
|
|
||||||
|
// send inv update
|
||||||
|
auto invTransPacket = makeZonePacket< FFXIVIpcInventoryTransaction >( getId() );
|
||||||
|
invTransPacket->data().transactionId = seq;
|
||||||
|
invTransPacket->data().ownerId = getId();
|
||||||
|
invTransPacket->data().storageId = type;
|
||||||
|
invTransPacket->data().catalogId = item->getId();
|
||||||
|
invTransPacket->data().stackSize = item->getStackSize();
|
||||||
|
invTransPacket->data().slotId = slotId;
|
||||||
|
invTransPacket->data().type = 7;
|
||||||
|
queuePacket( invTransPacket );
|
||||||
|
|
||||||
|
auto invTransFinPacket = makeZonePacket< FFXIVIpcInventoryTransactionFinish >( getId() );
|
||||||
|
invTransFinPacket->data().transactionId = seq;
|
||||||
|
invTransFinPacket->data().transactionId1 = seq;
|
||||||
|
queuePacket( invTransFinPacket );
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
|
@ -12,12 +12,12 @@
|
||||||
extern Sapphire::Framework g_fw;
|
extern Sapphire::Framework g_fw;
|
||||||
|
|
||||||
Sapphire::ItemContainer::ItemContainer( uint16_t storageId, uint16_t maxSize, const std::string& tableName,
|
Sapphire::ItemContainer::ItemContainer( uint16_t storageId, uint16_t maxSize, const std::string& tableName,
|
||||||
bool isMultiStorage, bool isPersistentStorage ) :
|
bool isMultiStorage, bool removeItemOnContainerRemoval ) :
|
||||||
m_id( storageId ),
|
m_id( storageId ),
|
||||||
m_size( maxSize ),
|
m_size( maxSize ),
|
||||||
m_tableName( tableName ),
|
m_tableName( tableName ),
|
||||||
m_bMultiStorage( isMultiStorage ),
|
m_bMultiStorage( isMultiStorage ),
|
||||||
m_isPersistentStorage( isPersistentStorage )
|
m_removeItemOnContainerRemove( removeItemOnContainerRemoval )
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ void Sapphire::ItemContainer::removeItem( uint16_t slotId )
|
||||||
|
|
||||||
if( it != m_itemMap.end() )
|
if( it != m_itemMap.end() )
|
||||||
{
|
{
|
||||||
if( m_isPersistentStorage )
|
if( m_removeItemOnContainerRemove )
|
||||||
pDb->execute( "DELETE FROM charaglobalitem WHERE itemId = " + std::to_string( it->second->getUId() ) );
|
pDb->execute( "DELETE FROM charaglobalitem WHERE itemId = " + std::to_string( it->second->getUId() ) );
|
||||||
|
|
||||||
m_itemMap.erase( it );
|
m_itemMap.erase( it );
|
||||||
|
@ -118,7 +118,7 @@ bool Sapphire::ItemContainer::isMultiStorage() const
|
||||||
|
|
||||||
bool Sapphire::ItemContainer::isPersistentStorage() const
|
bool Sapphire::ItemContainer::isPersistentStorage() const
|
||||||
{
|
{
|
||||||
return m_isPersistentStorage;
|
return m_removeItemOnContainerRemove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace Sapphire
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ItemContainer( uint16_t storageId, uint16_t maxSize, const std::string& tableName, bool isMultiStorage,
|
ItemContainer( uint16_t storageId, uint16_t maxSize, const std::string& tableName, bool isMultiStorage,
|
||||||
bool isPersistentStorage = true );
|
bool removeItemOnContainerRemoval = true );
|
||||||
|
|
||||||
~ItemContainer();
|
~ItemContainer();
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ namespace Sapphire
|
||||||
uint16_t m_size;
|
uint16_t m_size;
|
||||||
std::string m_tableName;
|
std::string m_tableName;
|
||||||
bool m_bMultiStorage;
|
bool m_bMultiStorage;
|
||||||
bool m_isPersistentStorage;
|
bool m_removeItemOnContainerRemove;
|
||||||
ItemMap m_itemMap;
|
ItemMap m_itemMap;
|
||||||
Entity::PlayerPtr m_pOwner;
|
Entity::PlayerPtr m_pOwner;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "InventoryMgr.h"
|
#include "InventoryMgr.h"
|
||||||
#include "Inventory/HousingItem.h"
|
#include "Inventory/HousingItem.h"
|
||||||
#include "Inventory/ItemContainer.h"
|
#include "Inventory/ItemContainer.h"
|
||||||
|
#include "Util/UtilMath.h"
|
||||||
|
|
||||||
using namespace Sapphire::Common;
|
using namespace Sapphire::Common;
|
||||||
using namespace Sapphire::Network;
|
using namespace Sapphire::Network;
|
||||||
|
@ -216,7 +217,7 @@ void Sapphire::World::Manager::HousingMgr::initLandCache()
|
||||||
|
|
||||||
auto makeContainer = [ &containers ]( Common::InventoryType type, uint16_t size )
|
auto makeContainer = [ &containers ]( Common::InventoryType type, uint16_t size )
|
||||||
{
|
{
|
||||||
containers[ type ] = make_ItemContainer( type, size, "houseiteminventory", true );
|
containers[ type ] = make_ItemContainer( type, size, "houseiteminventory", false );
|
||||||
};
|
};
|
||||||
|
|
||||||
uint16_t count = 0;
|
uint16_t count = 0;
|
||||||
|
@ -901,7 +902,7 @@ uint32_t Sapphire::World::Manager::HousingMgr::getItemAdditionalData( uint32_t c
|
||||||
|
|
||||||
bool Sapphire::World::Manager::HousingMgr::isPlacedItemsInventory( Sapphire::Common::InventoryType type )
|
bool Sapphire::World::Manager::HousingMgr::isPlacedItemsInventory( Sapphire::Common::InventoryType type )
|
||||||
{
|
{
|
||||||
return type == InventoryType::HousingExteriorPlacedItems ||
|
return type == InventoryType::HousingExteriorPlacedItems ||
|
||||||
type == InventoryType::HousingInteriorPlacedItems1 ||
|
type == InventoryType::HousingInteriorPlacedItems1 ||
|
||||||
type == InventoryType::HousingInteriorPlacedItems2 ||
|
type == InventoryType::HousingInteriorPlacedItems2 ||
|
||||||
type == InventoryType::HousingInteriorPlacedItems3 ||
|
type == InventoryType::HousingInteriorPlacedItems3 ||
|
||||||
|
@ -909,3 +910,118 @@ bool Sapphire::World::Manager::HousingMgr::isPlacedItemsInventory( Sapphire::Com
|
||||||
type == InventoryType::HousingInteriorPlacedItems5 ||
|
type == InventoryType::HousingInteriorPlacedItems5 ||
|
||||||
type == InventoryType::HousingInteriorPlacedItems6;
|
type == InventoryType::HousingInteriorPlacedItems6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sapphire::World::Manager::HousingMgr::reqPlaceHousingItem( Sapphire::Entity::Player& player, uint16_t landId,
|
||||||
|
uint16_t containerId, uint16_t slotId,
|
||||||
|
Sapphire::Common::FFXIVARR_POSITION3 pos,
|
||||||
|
float rotation )
|
||||||
|
{
|
||||||
|
// retail process is:
|
||||||
|
// - unlink item from current container
|
||||||
|
// - add it to destination container
|
||||||
|
// - resend container
|
||||||
|
// - send spawn packet
|
||||||
|
// - send actrl 3f3, all params are 0
|
||||||
|
|
||||||
|
LandPtr land;
|
||||||
|
bool isOutside = false;
|
||||||
|
|
||||||
|
// inside housing territory
|
||||||
|
if( auto zone = std::dynamic_pointer_cast< HousingZone >( player.getCurrentZone() ) )
|
||||||
|
{
|
||||||
|
land = zone->getLand( landId );
|
||||||
|
|
||||||
|
isOutside = true;
|
||||||
|
}
|
||||||
|
// inside house
|
||||||
|
else if( auto zone = std::dynamic_pointer_cast< Territory::Housing::HousingInteriorTerritory >( player.getCurrentZone() ) )
|
||||||
|
{
|
||||||
|
// todo: this whole process is retarded and needs to be fixed
|
||||||
|
// perhaps maintain a list of estates by ident inside housingmgr?
|
||||||
|
auto ident = zone->getIdent();
|
||||||
|
auto landSet = toLandSetId( ident.territoryTypeId, ident.wardNum );
|
||||||
|
|
||||||
|
land = getHousingZoneByLandSetId( landSet )->getLand( landId );
|
||||||
|
}
|
||||||
|
// wtf?
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !land )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// todo: add proper permissions checks
|
||||||
|
if( land->getOwnerId() != player.getId() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
player.sendDebug( "got item place request: ");
|
||||||
|
player.sendDebug( " - item: c: " + std::to_string( containerId ) + ", s: " + std::to_string( slotId ) );
|
||||||
|
|
||||||
|
// unlink item
|
||||||
|
Inventory::HousingItemPtr item;
|
||||||
|
|
||||||
|
if( containerId == InventoryType::Bag0 ||
|
||||||
|
containerId == InventoryType::Bag1 ||
|
||||||
|
containerId == InventoryType::Bag2 ||
|
||||||
|
containerId == InventoryType::Bag3 )
|
||||||
|
{
|
||||||
|
auto tmpItem = player.dropInventoryItem( static_cast< Common::InventoryType >( containerId ), slotId );
|
||||||
|
|
||||||
|
item = Inventory::make_HousingItem( tmpItem->getUId(), tmpItem->getId() );
|
||||||
|
|
||||||
|
// set params
|
||||||
|
item->setPos( pos );
|
||||||
|
item->setRot( Util::floatToUInt16Rot( rotation ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
player.sendUrgent( "The inventory you are using to place an item is not supported." );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ident = land->getLandIdent();
|
||||||
|
|
||||||
|
if( isOutside )
|
||||||
|
{
|
||||||
|
if( !placeExternalItem( player, item, ident ) )
|
||||||
|
player.sendUrgent( "An internal error occurred when placing the item." );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
player.sendUrgent( "you can't place internal items (yet)" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Sapphire::World::Manager::HousingMgr::placeExternalItem( Entity::Player& player,
|
||||||
|
Inventory::HousingItemPtr item,
|
||||||
|
Common::LandIdent ident )
|
||||||
|
{
|
||||||
|
auto invMgr = g_fw.get< InventoryMgr >();
|
||||||
|
|
||||||
|
auto& container = getEstateInventory( ident )[ InventoryType::HousingExteriorPlacedItems ];
|
||||||
|
|
||||||
|
auto freeSlot = container->getFreeSlot();
|
||||||
|
|
||||||
|
// todo: what happens when this fails? at the moment the player will just lose the item
|
||||||
|
if( freeSlot == -1 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// add item to inv
|
||||||
|
container->setItem( freeSlot, item );
|
||||||
|
|
||||||
|
// we need to save the item again as removing it from the container on the player will remove it from charaglobalitem
|
||||||
|
// todo: this needs to be handled a bit better as it might be possible to overwrite another item that is created in the meantime
|
||||||
|
invMgr->saveItem( player, item );
|
||||||
|
|
||||||
|
invMgr->sendInventoryContainer( player, container );
|
||||||
|
invMgr->saveHousingContainer( ident, container );
|
||||||
|
invMgr->updateHousingItemPosition( item );
|
||||||
|
|
||||||
|
// add to zone and spawn
|
||||||
|
auto zone = std::dynamic_pointer_cast< HousingZone >( player.getCurrentZone() );
|
||||||
|
|
||||||
|
zone->spawnYardObject( ident.landId, freeSlot, item );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -146,8 +146,13 @@ namespace Sapphire::World::Manager
|
||||||
*/
|
*/
|
||||||
bool initHouseModels( Entity::Player& player, LandPtr land, uint32_t presetCatalogId );
|
bool initHouseModels( Entity::Player& player, LandPtr land, uint32_t presetCatalogId );
|
||||||
|
|
||||||
|
void reqPlaceHousingItem( Entity::Player& player, uint16_t landId, uint16_t containerId, uint16_t slotId,
|
||||||
|
Common::FFXIVARR_POSITION3 pos, float rotation );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
bool placeExternalItem( Entity::Player& player, Inventory::HousingItemPtr item, Common::LandIdent ident );
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Creates a house and saves the minimum amount required to persist a house through restarts.
|
* @brief Creates a house and saves the minimum amount required to persist a house through restarts.
|
||||||
*
|
*
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <Common.h>
|
#include <Common.h>
|
||||||
#include "Actor/Player.h"
|
#include "Actor/Player.h"
|
||||||
#include "Inventory/ItemContainer.h"
|
#include "Inventory/ItemContainer.h"
|
||||||
#include "Inventory/Item.h"
|
#include "Inventory/HousingItem.h"
|
||||||
#include "Inventory/ItemUtil.h"
|
#include "Inventory/ItemUtil.h"
|
||||||
#include <Network/PacketDef/Zone/ServerZoneDef.h>
|
#include <Network/PacketDef/Zone/ServerZoneDef.h>
|
||||||
#include <Network/GamePacketNew.h>
|
#include <Network/GamePacketNew.h>
|
||||||
|
@ -79,14 +79,7 @@ Sapphire::ItemPtr Sapphire::World::Manager::InventoryMgr::createItem( Entity::Pl
|
||||||
|
|
||||||
item->setStackSize( std::max< uint32_t >( 1, quantity ) );
|
item->setStackSize( std::max< uint32_t >( 1, quantity ) );
|
||||||
|
|
||||||
auto stmt = pDb->getPreparedStatement( Db::CHARA_ITEMGLOBAL_INS );
|
saveItem( player, item );
|
||||||
|
|
||||||
stmt->setUInt( 1, player.getId() );
|
|
||||||
stmt->setUInt64( 2, item->getUId() );
|
|
||||||
stmt->setUInt( 3, item->getId() );
|
|
||||||
stmt->setUInt( 4, item->getStackSize() );
|
|
||||||
|
|
||||||
pDb->directExecute( stmt );
|
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
@ -122,3 +115,42 @@ void Sapphire::World::Manager::InventoryMgr::saveHousingContainerItem( uint64_t
|
||||||
|
|
||||||
pDb->execute( stmt );
|
pDb->execute( stmt );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sapphire::World::Manager::InventoryMgr::updateHousingItemPosition( Sapphire::Inventory::HousingItemPtr item )
|
||||||
|
{
|
||||||
|
auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >();
|
||||||
|
|
||||||
|
auto stmt = pDb->getPreparedStatement( Db::LAND_INV_UP_ITEMPOS );
|
||||||
|
// ItemId, PosX, PosY, PosZ, Rotation, PosX, PosY, PosZ, Rotation
|
||||||
|
|
||||||
|
auto pos = item->getPos();
|
||||||
|
auto rot = item->getRot();
|
||||||
|
|
||||||
|
stmt->setUInt64( 1, item->getUId() );
|
||||||
|
|
||||||
|
stmt->setDouble( 2, pos.x );
|
||||||
|
stmt->setDouble( 3, pos.y );
|
||||||
|
stmt->setDouble( 4, pos.z );
|
||||||
|
|
||||||
|
stmt->setInt( 5, rot );
|
||||||
|
|
||||||
|
stmt->setDouble( 6, pos.x );
|
||||||
|
stmt->setDouble( 7, pos.y );
|
||||||
|
stmt->setDouble( 8, pos.z );
|
||||||
|
stmt->setInt( 9, rot );
|
||||||
|
|
||||||
|
pDb->execute( stmt );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sapphire::World::Manager::InventoryMgr::saveItem( Sapphire::Entity::Player& player, Sapphire::ItemPtr item )
|
||||||
|
{
|
||||||
|
auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >();
|
||||||
|
auto stmt = pDb->getPreparedStatement( Db::CHARA_ITEMGLOBAL_INS );
|
||||||
|
|
||||||
|
stmt->setUInt( 1, player.getId() );
|
||||||
|
stmt->setUInt64( 2, item->getUId() );
|
||||||
|
stmt->setUInt( 3, item->getId() );
|
||||||
|
stmt->setUInt( 4, item->getStackSize() );
|
||||||
|
|
||||||
|
pDb->directExecute( stmt );
|
||||||
|
}
|
|
@ -44,6 +44,19 @@ namespace Sapphire::World::Manager
|
||||||
*/
|
*/
|
||||||
void updateItem( Sapphire::ItemPtr item );
|
void updateItem( Sapphire::ItemPtr item );
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Updates the position/rotation of a housing object
|
||||||
|
* @param item The item to update
|
||||||
|
*/
|
||||||
|
void updateHousingItemPosition( Sapphire::Inventory::HousingItemPtr item );
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Saves an item to the global item table
|
||||||
|
* @param player The player which owns the item
|
||||||
|
* @param item The item to save
|
||||||
|
*/
|
||||||
|
void saveItem( Entity::Player& player, ItemPtr item );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
* @brief Saves an individual item to the db.
|
* @brief Saves an individual item to the db.
|
||||||
|
|
|
@ -88,6 +88,7 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH
|
||||||
setZoneHandler( ClientZoneIpcType::LandRenameHandler, "LandRenameHandler", &GameConnection::landRenameHandler );
|
setZoneHandler( ClientZoneIpcType::LandRenameHandler, "LandRenameHandler", &GameConnection::landRenameHandler );
|
||||||
setZoneHandler( ClientZoneIpcType::HousingUpdateHouseGreeting, "HousingUpdateHouseGreeting",
|
setZoneHandler( ClientZoneIpcType::HousingUpdateHouseGreeting, "HousingUpdateHouseGreeting",
|
||||||
&GameConnection::housingUpdateGreetingHandler );
|
&GameConnection::housingUpdateGreetingHandler );
|
||||||
|
setZoneHandler( ClientZoneIpcType::ReqPlaceHousingItem, "ReqPlaceHousingItem", &GameConnection::reqPlaceHousingItem );
|
||||||
|
|
||||||
setZoneHandler( ClientZoneIpcType::TalkEventHandler, "EventHandlerTalk", &GameConnection::eventHandlerTalk );
|
setZoneHandler( ClientZoneIpcType::TalkEventHandler, "EventHandlerTalk", &GameConnection::eventHandlerTalk );
|
||||||
setZoneHandler( ClientZoneIpcType::EmoteEventHandler, "EventHandlerEmote", &GameConnection::eventHandlerEmote );
|
setZoneHandler( ClientZoneIpcType::EmoteEventHandler, "EventHandlerEmote", &GameConnection::eventHandlerEmote );
|
||||||
|
|
|
@ -171,6 +171,8 @@ namespace Sapphire::Network
|
||||||
|
|
||||||
DECLARE_HANDLER( tellHandler );
|
DECLARE_HANDLER( tellHandler );
|
||||||
|
|
||||||
|
DECLARE_HANDLER( reqPlaceHousingItem );
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -705,3 +705,14 @@ void Sapphire::Network::GameConnection::housingUpdateGreetingHandler( const Pack
|
||||||
|
|
||||||
pHousingMgr->updateEstateGreeting( player, packet.data().ident, std::string( packet.data().greeting ) );
|
pHousingMgr->updateEstateGreeting( player, packet.data().ident, std::string( packet.data().greeting ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sapphire::Network::GameConnection::reqPlaceHousingItem( const Packets::FFXIVARR_PACKET_RAW& inPacket,
|
||||||
|
Entity::Player& player )
|
||||||
|
{
|
||||||
|
auto housingMgr = g_fw.get< HousingMgr >();
|
||||||
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcReqPlaceHousingItem >( inPacket );
|
||||||
|
const auto& data = packet.data();
|
||||||
|
|
||||||
|
housingMgr->reqPlaceHousingItem( player, data.landId, data.sourceInvContainerId, data.sourceInvSlotId,
|
||||||
|
data.position, data.rotation );
|
||||||
|
}
|
|
@ -354,3 +354,36 @@ void Sapphire::HousingZone::updateYardObjects( Sapphire::Common::LandIdent ident
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sapphire::HousingZone::spawnYardObject( uint8_t landId, uint16_t slotId, Inventory::HousingItemPtr item )
|
||||||
|
{
|
||||||
|
auto bounds = m_yardObjectArrayBounds[ landId ];
|
||||||
|
auto offset = bounds.first + slotId;
|
||||||
|
|
||||||
|
Common::YardObject obj {};
|
||||||
|
|
||||||
|
obj.itemId = item->getAdditionalData();
|
||||||
|
obj.itemRotation = item->getRot();
|
||||||
|
|
||||||
|
auto pos = item->getPos();
|
||||||
|
|
||||||
|
obj.pos_x = Util::floatToUInt16( pos.x );
|
||||||
|
obj.pos_y = Util::floatToUInt16( pos.y );
|
||||||
|
obj.pos_z = Util::floatToUInt16( pos.z );
|
||||||
|
|
||||||
|
// link obj
|
||||||
|
uint8_t yardMapIndex = landId <= 29 ? 0 : 1;
|
||||||
|
m_yardObjects[ yardMapIndex ][ offset ] = obj;
|
||||||
|
|
||||||
|
// spawn obj in zone
|
||||||
|
for( const auto& player : m_playerMap )
|
||||||
|
{
|
||||||
|
auto packet = makeZonePacket< Server::FFXIVIpcYardObjectSpawn >( player.second->getId() );
|
||||||
|
|
||||||
|
packet->data().landSetId = landId;
|
||||||
|
packet->data().objectArray = slotId;
|
||||||
|
packet->data().object = obj;
|
||||||
|
|
||||||
|
player.second->queuePacket( packet );
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,6 +55,7 @@ namespace Sapphire
|
||||||
Entity::EventObjectPtr registerEstateEntranceEObj( uint8_t landId );
|
Entity::EventObjectPtr registerEstateEntranceEObj( uint8_t landId );
|
||||||
|
|
||||||
void updateYardObjects( Common::LandIdent ident );
|
void updateYardObjects( Common::LandIdent ident );
|
||||||
|
void spawnYardObject( uint8_t landId, uint16_t slotId, Sapphire::Inventory::HousingItemPtr item );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using LandPtrMap = std::unordered_map< uint8_t, Sapphire::LandPtr >;
|
using LandPtrMap = std::unordered_map< uint8_t, Sapphire::LandPtr >;
|
||||||
|
|
Loading…
Add table
Reference in a new issue