2018-12-18 22:59:01 +11:00
|
|
|
#include "InventoryMgr.h"
|
|
|
|
|
|
|
|
#include <Common.h>
|
|
|
|
#include "Actor/Player.h"
|
|
|
|
#include "Inventory/ItemContainer.h"
|
2018-12-26 18:11:18 +11:00
|
|
|
#include "Inventory/HousingItem.h"
|
2018-12-29 13:05:13 +11:00
|
|
|
#include "Manager/ItemMgr.h"
|
2018-12-18 22:59:01 +11:00
|
|
|
#include <Network/PacketDef/Zone/ServerZoneDef.h>
|
2019-03-08 15:34:38 +01:00
|
|
|
#include <Network/GamePacket.h>
|
2018-12-18 22:59:01 +11:00
|
|
|
|
2018-12-23 19:13:30 +11:00
|
|
|
#include <Database/DatabaseDef.h>
|
2021-11-27 00:53:57 +01:00
|
|
|
#include <Exd/ExdData.h>
|
2020-03-01 01:00:57 +11:00
|
|
|
#include <Service.h>
|
2018-12-23 19:13:30 +11:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
#include "WorldServer.h"
|
|
|
|
#include "Session.h"
|
|
|
|
#include "Network/GameConnection.h"
|
|
|
|
|
2022-01-27 21:08:43 +01:00
|
|
|
using namespace Sapphire;
|
|
|
|
using namespace Sapphire::World::Manager;
|
2021-11-27 00:53:57 +01:00
|
|
|
using namespace Sapphire::Network;
|
2018-12-18 22:59:01 +11:00
|
|
|
using namespace Sapphire::Network::Packets;
|
2021-11-27 00:53:57 +01:00
|
|
|
using namespace Sapphire::Network::Packets::WorldPackets::Server;
|
2018-12-18 22:59:01 +11:00
|
|
|
|
2022-01-27 21:08:43 +01:00
|
|
|
void InventoryMgr::sendInventoryContainer( Entity::Player& player, ItemContainerPtr container )
|
2018-12-18 22:59:01 +11:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& server = Common::Service< World::WorldServer >::ref();
|
|
|
|
auto pSession = server.getSession( player.getCharacterId() );
|
|
|
|
|
2018-12-20 20:41:16 +11:00
|
|
|
auto sequence = player.getNextInventorySequence();
|
2018-12-18 22:59:01 +11:00
|
|
|
auto pMap = container->getItemMap();
|
|
|
|
|
|
|
|
for( auto itM = pMap.begin(); itM != pMap.end(); ++itM )
|
|
|
|
{
|
|
|
|
if( !itM->second )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if( container->getId() == Common::InventoryType::Currency || container->getId() == Common::InventoryType::Crystal )
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto currencyInfoPacket = makeZonePacket< FFXIVIpcGilItem >( player.getId() );
|
|
|
|
currencyInfoPacket->data().contextId = sequence;
|
|
|
|
currencyInfoPacket->data().item.catalogId = itM->second->getId();
|
|
|
|
currencyInfoPacket->data().item.subquarity = 1;
|
|
|
|
currencyInfoPacket->data().item.stack = itM->second->getStackSize();
|
|
|
|
currencyInfoPacket->data().item.storageId = container->getId();
|
|
|
|
currencyInfoPacket->data().item.containerIndex = 0;
|
|
|
|
|
|
|
|
server.queueForPlayer( player.getCharacterId(), currencyInfoPacket );
|
2018-12-18 22:59:01 +11:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto itemInfoPacket = makeZonePacket< FFXIVIpcNormalItem >( player.getId() );
|
|
|
|
itemInfoPacket->data().contextId = sequence;
|
|
|
|
itemInfoPacket->data().item.storageId = container->getId();
|
|
|
|
itemInfoPacket->data().item.containerIndex = itM->first;
|
|
|
|
itemInfoPacket->data().item.stack = itM->second->getStackSize();
|
|
|
|
itemInfoPacket->data().item.catalogId = itM->second->getId();
|
|
|
|
itemInfoPacket->data().item.durability = itM->second->getDurability();
|
|
|
|
// itemInfoPacket->data().spiritBond = itM->second->getSpiritbond();
|
|
|
|
// itemInfoPacket->data().reservedFlag = itM->second->getReservedFlag();
|
|
|
|
// todo: not sure if correct flag?
|
|
|
|
itemInfoPacket->data().item.flags = static_cast< uint8_t >( itM->second->isHq() ? 1 : 0 );
|
|
|
|
itemInfoPacket->data().item.stain = itM->second->getStain();
|
|
|
|
|
|
|
|
server.queueForPlayer( player.getCharacterId(), itemInfoPacket );
|
2018-12-18 22:59:01 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto itemSizePacket = makeZonePacket< FFXIVIpcItemSize >( player.getId() );
|
|
|
|
itemSizePacket->data().contextId = sequence;
|
|
|
|
itemSizePacket->data().size = container->getEntryCount();
|
|
|
|
itemSizePacket->data().storageId = container->getId();
|
2018-12-18 22:59:01 +11:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
server.queueForPlayer( player.getCharacterId(), itemSizePacket );
|
2018-12-23 19:13:30 +11:00
|
|
|
}
|
|
|
|
|
2022-01-27 21:08:43 +01:00
|
|
|
ItemPtr InventoryMgr::createItem( Entity::Player& player, uint32_t catalogId, uint32_t quantity )
|
2018-12-23 19:13:30 +11:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& pExdData = Common::Service< Data::ExdData >::ref();
|
2022-01-27 21:08:43 +01:00
|
|
|
auto& itemMgr = Common::Service< ItemMgr >::ref();
|
2022-01-27 21:24:54 +01:00
|
|
|
auto itemInfo = pExdData.getRow< Excel::Item >( catalogId );
|
2018-12-23 19:13:30 +11:00
|
|
|
|
|
|
|
if( !itemInfo )
|
|
|
|
return nullptr;
|
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
auto item = make_Item( itemMgr.getNextUId(), catalogId );
|
2018-12-23 19:13:30 +11:00
|
|
|
|
|
|
|
item->setStackSize( std::max< uint32_t >( 1, quantity ) );
|
|
|
|
|
2018-12-26 18:11:18 +11:00
|
|
|
saveItem( player, item );
|
2018-12-23 19:13:30 +11:00
|
|
|
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
2022-01-27 21:08:43 +01:00
|
|
|
void InventoryMgr::saveHousingContainer( Common::LandIdent ident, ItemContainerPtr container )
|
2018-12-23 19:13:30 +11:00
|
|
|
{
|
|
|
|
auto u64ident = *reinterpret_cast< uint64_t* >( &ident );
|
|
|
|
|
|
|
|
for( auto& item : container->getItemMap() )
|
|
|
|
{
|
|
|
|
saveHousingContainerItem( u64ident, container->getId(), item.first, item.second->getUId() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-27 21:08:43 +01:00
|
|
|
void InventoryMgr::removeItemFromHousingContainer( Common::LandIdent ident, uint16_t containerId, uint16_t slotId )
|
2018-12-28 02:17:29 +11:00
|
|
|
{
|
2020-03-01 01:00:57 +11:00
|
|
|
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
|
2018-12-28 02:17:29 +11:00
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
auto stmt = db.getPreparedStatement( Db::LAND_INV_DEL );
|
2018-12-28 02:17:29 +11:00
|
|
|
|
|
|
|
auto u64ident = *reinterpret_cast< uint64_t* >( &ident );
|
|
|
|
|
|
|
|
stmt->setUInt64( 1, u64ident );
|
|
|
|
stmt->setUInt( 2, containerId );
|
|
|
|
stmt->setUInt( 3, slotId );
|
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
db.directExecute( stmt );
|
2018-12-28 02:17:29 +11:00
|
|
|
}
|
|
|
|
|
2022-01-27 21:08:43 +01:00
|
|
|
void InventoryMgr::saveHousingContainerItem( uint64_t ident, uint16_t containerId, uint16_t slotId, uint64_t itemId )
|
2018-12-23 19:13:30 +11:00
|
|
|
{
|
2020-03-01 01:00:57 +11:00
|
|
|
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
|
2018-12-23 19:13:30 +11:00
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
auto stmt = db.getPreparedStatement( Db::LAND_INV_UP );
|
2018-12-23 19:13:30 +11:00
|
|
|
// LandIdent, ContainerId, SlotId, ItemId, ItemId
|
|
|
|
|
|
|
|
stmt->setUInt64( 1, ident );
|
|
|
|
stmt->setUInt( 2, containerId );
|
|
|
|
stmt->setUInt( 3, slotId );
|
|
|
|
stmt->setUInt64( 4, itemId );
|
|
|
|
|
|
|
|
// see query, we have to pass itemid in twice
|
|
|
|
// the second time is for the ON DUPLICATE KEY UPDATE condition
|
|
|
|
stmt->setUInt64( 5, itemId );
|
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
db.directExecute( stmt );
|
2018-12-26 18:11:18 +11:00
|
|
|
}
|
|
|
|
|
2022-01-27 21:08:43 +01:00
|
|
|
void InventoryMgr::updateHousingItemPosition( Inventory::HousingItemPtr item )
|
2018-12-26 18:11:18 +11:00
|
|
|
{
|
2020-03-01 01:00:57 +11:00
|
|
|
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
|
2018-12-26 18:11:18 +11:00
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
auto stmt = db.getPreparedStatement( Db::LAND_INV_UP_ITEMPOS );
|
2018-12-26 18:11:18 +11:00
|
|
|
// ItemId, PosX, PosY, PosZ, Rotation, PosX, PosY, PosZ, Rotation
|
|
|
|
|
|
|
|
auto pos = item->getPos();
|
2022-01-27 18:35:19 -03:00
|
|
|
|
|
|
|
auto posX = static_cast< uint32_t >( pos.x );
|
|
|
|
auto posY = static_cast< uint32_t >( pos.y );
|
|
|
|
auto posZ = static_cast< uint32_t >( pos.z );
|
|
|
|
|
|
|
|
auto rot = static_cast< int32_t >( item->getRot() );
|
2018-12-26 18:11:18 +11:00
|
|
|
|
|
|
|
stmt->setUInt64( 1, item->getUId() );
|
|
|
|
|
2022-01-27 18:35:19 -03:00
|
|
|
stmt->setUInt( 2, posX );
|
|
|
|
stmt->setUInt( 3, posY );
|
|
|
|
stmt->setUInt( 4, posZ );
|
2021-11-27 00:53:57 +01:00
|
|
|
stmt->setInt( 5, rot );
|
2021-02-06 05:18:26 +09:00
|
|
|
|
2022-01-27 18:35:19 -03:00
|
|
|
stmt->setUInt( 6, posX );
|
|
|
|
stmt->setUInt( 7, posY );
|
|
|
|
stmt->setUInt( 8, posZ );
|
2021-11-27 00:53:57 +01:00
|
|
|
stmt->setInt( 9, rot );
|
2018-12-26 18:11:18 +11:00
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
db.execute( stmt );
|
2018-12-26 18:11:18 +11:00
|
|
|
}
|
|
|
|
|
2022-01-27 21:08:43 +01:00
|
|
|
void InventoryMgr::removeHousingItemPosition( Inventory::HousingItem& item )
|
2018-12-28 02:17:29 +11:00
|
|
|
{
|
2020-03-01 01:00:57 +11:00
|
|
|
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
|
2018-12-28 02:17:29 +11:00
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
auto stmt = db.getPreparedStatement( Db::LAND_INV_DEL_ITEMPOS );
|
2018-12-28 02:17:29 +11:00
|
|
|
|
|
|
|
stmt->setUInt64( 1, item.getUId() );
|
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
db.directExecute( stmt );
|
2018-12-28 02:17:29 +11:00
|
|
|
}
|
|
|
|
|
2022-01-27 21:08:43 +01:00
|
|
|
void InventoryMgr::saveItem( Entity::Player& player, ItemPtr item )
|
2018-12-26 18:11:18 +11:00
|
|
|
{
|
2020-03-01 01:00:57 +11:00
|
|
|
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
|
|
|
|
auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_INS );
|
2018-12-26 18:11:18 +11:00
|
|
|
|
|
|
|
stmt->setUInt( 1, player.getId() );
|
|
|
|
stmt->setUInt64( 2, item->getUId() );
|
|
|
|
stmt->setUInt( 3, item->getId() );
|
|
|
|
stmt->setUInt( 4, item->getStackSize() );
|
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
db.directExecute( stmt );
|
2019-03-08 15:34:38 +01:00
|
|
|
}
|