mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-15 15:07:45 +00:00
housing inventories work, parts are loaded from db now
plus a shitload of cleanup and refactoring
This commit is contained in:
parent
50ddcbb180
commit
2c426b5059
12 changed files with 303 additions and 123 deletions
|
@ -527,13 +527,15 @@ CREATE TABLE `landset` (
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||||
|
|
||||||
CREATE TABLE `houseiteminventory` (
|
CREATE TABLE `houseiteminventory` (
|
||||||
`LandIdent` BIGINT(20) UNSIGNED NOT NULL,
|
`LandIdent` BIGINT(20) UNSIGNED NOT NULL,
|
||||||
`ContainerId` INT(10) UNSIGNED NOT NULL,
|
`ContainerId` INT(10) UNSIGNED NOT NULL,
|
||||||
`ItemId` INT(20) NOT NULL,
|
`SlotId` INT(10) UNSIGNED NOT NULL,
|
||||||
`SlotId` INT(10) UNSIGNED NOT NULL,
|
`ItemId` INT(20) NOT NULL,
|
||||||
INDEX `landIdent` (`landIdent`)
|
PRIMARY KEY (`LandIdent`, `ContainerId`, `SlotId`),
|
||||||
|
INDEX `landIdent` (`LandIdent`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE `spawngroup` (
|
CREATE TABLE `spawngroup` (
|
||||||
`id` int(10) NOT NULL AUTO_INCREMENT,
|
`id` int(10) NOT NULL AUTO_INCREMENT,
|
||||||
`territoryTypeId` int(5) NOT NULL,
|
`territoryTypeId` int(5) NOT NULL,
|
||||||
|
|
|
@ -248,7 +248,7 @@ namespace Sapphire::Common
|
||||||
|
|
||||||
// housing exterior containers
|
// housing exterior containers
|
||||||
HousingOutdoorPlacedItems = 25001,
|
HousingOutdoorPlacedItems = 25001,
|
||||||
HousingOutdoorAppearance = 25000,
|
HousingExteriorAppearance = 25000,
|
||||||
HousingOutdoorStoreroom = 27000,
|
HousingOutdoorStoreroom = 27000,
|
||||||
|
|
||||||
|
|
||||||
|
@ -769,7 +769,7 @@ namespace Sapphire::Common
|
||||||
MountSkill = 0xD,
|
MountSkill = 0xD,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum HousePartSlot
|
enum HouseExteriorSlot
|
||||||
{
|
{
|
||||||
ExteriorRoof,
|
ExteriorRoof,
|
||||||
ExteriorWall,
|
ExteriorWall,
|
||||||
|
|
|
@ -172,7 +172,7 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements()
|
||||||
|
|
||||||
/// ITEM GLOBAL
|
/// ITEM GLOBAL
|
||||||
prepareStatement( CHARA_ITEMGLOBAL_INS,
|
prepareStatement( CHARA_ITEMGLOBAL_INS,
|
||||||
"INSERT INTO charaglobalitem ( CharacterId, ItemId, catalogId, UPDATE_DATE ) VALUES ( ?, ?, ?, NOW() );",
|
"INSERT INTO charaglobalitem ( CharacterId, ItemId, catalogId, stack, UPDATE_DATE ) VALUES ( ?, ?, ?, ?, NOW() );",
|
||||||
CONNECTION_BOTH );
|
CONNECTION_BOTH );
|
||||||
|
|
||||||
/// BNPC TEMPLATES
|
/// BNPC TEMPLATES
|
||||||
|
@ -222,6 +222,17 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements()
|
||||||
"ON land.HouseId = house.HouseId;",
|
"ON land.HouseId = house.HouseId;",
|
||||||
CONNECTION_SYNC );
|
CONNECTION_SYNC );
|
||||||
|
|
||||||
|
prepareStatement( LAND_INV_UP,
|
||||||
|
"INSERT INTO houseiteminventory ( LandIdent, ContainerId, SlotId, ItemId ) "
|
||||||
|
"VALUES ( ?, ?, ?, ? ) "
|
||||||
|
"ON DUPLICATE KEY UPDATE ItemId = ?;",
|
||||||
|
CONNECTION_BOTH );
|
||||||
|
|
||||||
|
prepareStatement( LAND_INV_DEL,
|
||||||
|
"DELETE FROM houseiteminventory "
|
||||||
|
"WHERE LandIdent = ? AND ContainerId = ? AND SlotId = ?;",
|
||||||
|
CONNECTION_BOTH );
|
||||||
|
|
||||||
/*prepareStatement( LAND_INS,
|
/*prepareStatement( LAND_INS,
|
||||||
"INSERT INTO land ( LandSetId ) VALUES ( ? );",
|
"INSERT INTO land ( LandSetId ) VALUES ( ? );",
|
||||||
CONNECTION_BOTH );
|
CONNECTION_BOTH );
|
||||||
|
|
|
@ -91,13 +91,13 @@ bool Sapphire::World::Manager::HousingMgr::loadEstateInventories()
|
||||||
while( res->next() )
|
while( res->next() )
|
||||||
{
|
{
|
||||||
//uint64_t uId, uint32_t catalogId, uint64_t model1, uint64_t model2, bool isHq
|
//uint64_t uId, uint32_t catalogId, uint64_t model1, uint64_t model2, bool isHq
|
||||||
uint64_t ident = res->getUInt64( "LandIdent" );
|
auto ident = res->getUInt64( "LandIdent" );
|
||||||
uint16_t containerId = res->getUInt16( "ContainerId" );
|
auto containerId = res->getUInt16( "ContainerId" );
|
||||||
uint64_t itemId = res->getUInt64( "ItemId" );
|
auto itemId = res->getUInt64( "ItemId" );
|
||||||
uint16_t slot = res->getUInt16( "SlotId" );
|
auto slot = res->getUInt16( "SlotId" );
|
||||||
uint32_t catalogId = res->getUInt( "catalogId" );
|
auto catalogId = res->getUInt( "catalogId" );
|
||||||
uint8_t stain = res->getUInt8( "stain" );
|
auto stain = res->getUInt8( "stain" );
|
||||||
uint64_t characterId = res->getUInt64( "CharacterId" );
|
auto characterId = res->getUInt64( "CharacterId" );
|
||||||
|
|
||||||
auto item = make_Item( itemId, catalogId, 0, 0, 0 );
|
auto item = make_Item( itemId, catalogId, 0, 0, 0 );
|
||||||
item->setStain( stain );
|
item->setStain( stain );
|
||||||
|
@ -162,6 +162,17 @@ void Sapphire::World::Manager::HousingMgr::loadLandCache()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t Sapphire::World::Manager::HousingMgr::getNextHouseId()
|
||||||
|
{
|
||||||
|
auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >();
|
||||||
|
auto pQR = pDb->query( "SELECT MAX( HouseId ) FROM house" );
|
||||||
|
|
||||||
|
if( !pQR->next() )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return pQR->getUInt64( 1 ) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t Sapphire::World::Manager::HousingMgr::toLandSetId( uint16_t territoryTypeId, uint8_t wardId ) const
|
uint32_t Sapphire::World::Manager::HousingMgr::toLandSetId( uint16_t territoryTypeId, uint8_t wardId ) const
|
||||||
{
|
{
|
||||||
return ( static_cast< uint32_t >( territoryTypeId ) << 16 ) | wardId;
|
return ( static_cast< uint32_t >( territoryTypeId ) << 16 ) | wardId;
|
||||||
|
@ -430,6 +441,86 @@ void Sapphire::World::Manager::HousingMgr::sendEstateGreeting( Entity::Player& p
|
||||||
player.queuePacket( greetingPacket );
|
player.queuePacket( greetingPacket );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Sapphire::World::Manager::HousingMgr::initHouseModels( Entity::Player& player, LandPtr land, uint32_t presetCatalogId )
|
||||||
|
{
|
||||||
|
auto house = land->getHouse();
|
||||||
|
assert( house );
|
||||||
|
|
||||||
|
auto itemMax = land->getInventoryItemMax();
|
||||||
|
|
||||||
|
// type, maxSize, tableName, isMultiStorage
|
||||||
|
auto intContainer = make_ItemContainer( InventoryType::HousingInteriorAppearance, itemMax.second, "houseiteminventory", true );
|
||||||
|
auto extContainer = make_ItemContainer( InventoryType::HousingExteriorAppearance, itemMax.first, "houseiteminventory", true );
|
||||||
|
|
||||||
|
// add containers to inv collection
|
||||||
|
auto& houseInventory = getEstateInventory( house->getLandIdent() );
|
||||||
|
houseInventory[ InventoryType::HousingInteriorAppearance ] = intContainer;
|
||||||
|
houseInventory[ InventoryType::HousingExteriorAppearance ] = extContainer;
|
||||||
|
|
||||||
|
auto exdData = g_fw.get< Sapphire::Data::ExdDataGenerated >();
|
||||||
|
auto preset = exdData->get< Sapphire::Data::HousingPreset >( getItemAdditionalData( presetCatalogId ) );
|
||||||
|
if( !preset )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// high iq shit
|
||||||
|
auto invMap = std::map< uint16_t, std::map< uint32_t, int32_t > >
|
||||||
|
{
|
||||||
|
// external
|
||||||
|
{
|
||||||
|
InventoryType::HousingExteriorAppearance,
|
||||||
|
{
|
||||||
|
{ HouseExteriorSlot::ExteriorRoof, preset->exteriorRoof },
|
||||||
|
{ HouseExteriorSlot::ExteriorWall, preset->exteriorWall },
|
||||||
|
{ HouseExteriorSlot::ExteriorWindow, preset->exteriorWindow },
|
||||||
|
{ HouseExteriorSlot::ExteriorDoor, preset->exteriorDoor }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// internal
|
||||||
|
{
|
||||||
|
InventoryType::HousingInteriorAppearance,
|
||||||
|
{
|
||||||
|
// lobby/middle floor
|
||||||
|
{ HousingInteriorSlot::InteriorWall, preset->interiorWall },
|
||||||
|
{ HousingInteriorSlot::InteriorFloor, preset->interiorFlooring },
|
||||||
|
{ HousingInteriorSlot::InteriorLight, preset->interiorLighting },
|
||||||
|
|
||||||
|
// attic
|
||||||
|
{ HousingInteriorSlot::InteriorWall_Attic, preset->otherFloorWall },
|
||||||
|
{ HousingInteriorSlot::InteriorFloor_Attic, preset->otherFloorFlooring },
|
||||||
|
{ HousingInteriorSlot::InteriorLight_Attic, preset->otherFloorLighting },
|
||||||
|
|
||||||
|
// basement
|
||||||
|
{ HousingInteriorSlot::InteriorWall_Basement, preset->basementWall },
|
||||||
|
{ HousingInteriorSlot::InteriorFloor_Basement, preset->basementFlooring },
|
||||||
|
{ HousingInteriorSlot::InteriorLight_Basement, preset->basementLighting },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto invMgr = g_fw.get< InventoryMgr >();
|
||||||
|
|
||||||
|
// create and link items
|
||||||
|
for( auto& destContainer : invMap )
|
||||||
|
{
|
||||||
|
auto container = houseInventory[ destContainer.first ];
|
||||||
|
|
||||||
|
for( auto& item : destContainer.second )
|
||||||
|
{
|
||||||
|
auto pItem = invMgr->createItem( player, item.second );
|
||||||
|
|
||||||
|
container->setItem( item.first, pItem );
|
||||||
|
}
|
||||||
|
|
||||||
|
invMgr->saveHousingContainer( land->getLandIdent(), container );
|
||||||
|
}
|
||||||
|
|
||||||
|
// lift off
|
||||||
|
updateHouseModels( house );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Sapphire::World::Manager::HousingMgr::buildPresetEstate( Entity::Player& player, uint8_t plotNum, uint32_t presetItem )
|
void Sapphire::World::Manager::HousingMgr::buildPresetEstate( Entity::Player& player, uint8_t plotNum, uint32_t presetItem )
|
||||||
{
|
{
|
||||||
auto hZone = std::dynamic_pointer_cast< HousingZone >( player.getCurrentZone() );
|
auto hZone = std::dynamic_pointer_cast< HousingZone >( player.getCurrentZone() );
|
||||||
|
@ -447,7 +538,15 @@ void Sapphire::World::Manager::HousingMgr::buildPresetEstate( Entity::Player& pl
|
||||||
|
|
||||||
// todo: check if permit is in inventory and remove one
|
// todo: check if permit is in inventory and remove one
|
||||||
|
|
||||||
if( !pLand->setPreset( presetItem ) )
|
// create house
|
||||||
|
auto ident = pLand->getLandIdent();
|
||||||
|
auto house = make_House( getNextHouseId(), pLand->getLandSetId(), ident,
|
||||||
|
"Estate #" + std::to_string( ident.landId + 1 ), "" );
|
||||||
|
|
||||||
|
pLand->setHouse( house );
|
||||||
|
|
||||||
|
// create inventory items
|
||||||
|
if( !initHouseModels( player, pLand, presetItem ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pLand->setState( HouseState::privateHouse );
|
pLand->setState( HouseState::privateHouse );
|
||||||
|
@ -465,7 +564,7 @@ void Sapphire::World::Manager::HousingMgr::buildPresetEstate( Entity::Player& pl
|
||||||
player.eventStart( player.getId(), 0x000B0095, Event::EventHandler::EventType::Housing, 1, 1 );
|
player.eventStart( player.getId(), 0x000B0095, Event::EventHandler::EventType::Housing, 1, 1 );
|
||||||
player.playScene( 0x000B0095, 0, SET_BASE | HIDE_HOTBAR , 0, 1, plotNum, nullptr );
|
player.playScene( 0x000B0095, 0, SET_BASE | HIDE_HOTBAR , 0, 1, plotNum, nullptr );
|
||||||
|
|
||||||
player.setLandFlags( LandFlagsSlot::Private, EstateBuilt, pLand->getLandIdent() );
|
player.setLandFlags( LandFlagsSlot::Private, EstateBuilt, ident );
|
||||||
player.sendLandFlagsSlot( LandFlagsSlot::Private );
|
player.sendLandFlagsSlot( LandFlagsSlot::Private );
|
||||||
|
|
||||||
hZone->registerHouseEntranceEObj( plotNum );
|
hZone->registerHouseEntranceEObj( plotNum );
|
||||||
|
@ -647,11 +746,7 @@ Sapphire::World::Manager::HousingMgr::LandIdentToInventoryContainerMap&
|
||||||
Sapphire::World::Manager::HousingMgr::ContainerIdToContainerMap&
|
Sapphire::World::Manager::HousingMgr::ContainerIdToContainerMap&
|
||||||
Sapphire::World::Manager::HousingMgr::getEstateInventory( uint64_t ident )
|
Sapphire::World::Manager::HousingMgr::getEstateInventory( uint64_t ident )
|
||||||
{
|
{
|
||||||
auto map = m_estateInventories.find( ident );
|
return m_estateInventories[ ident ];
|
||||||
|
|
||||||
assert( map != m_estateInventories.end() );
|
|
||||||
|
|
||||||
return map->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Sapphire::World::Manager::HousingMgr::ContainerIdToContainerMap&
|
Sapphire::World::Manager::HousingMgr::ContainerIdToContainerMap&
|
||||||
|
@ -662,26 +757,19 @@ Sapphire::World::Manager::HousingMgr::ContainerIdToContainerMap&
|
||||||
return getEstateInventory( u64ident );
|
return getEstateInventory( u64ident );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sapphire::World::Manager::HousingMgr::updateHouseModelsFromDb( Sapphire::HousePtr house )
|
void Sapphire::World::Manager::HousingMgr::updateHouseModels( Sapphire::HousePtr house )
|
||||||
{
|
{
|
||||||
assert( house );
|
assert( house );
|
||||||
|
|
||||||
auto getItemData = []( uint32_t itemId )
|
auto& containers = getEstateInventory( house->getLandIdent() );
|
||||||
{
|
|
||||||
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
|
|
||||||
auto info = pExdData->get< Sapphire::Data::Item >( itemId );
|
|
||||||
return info->additionalData;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto containers = getEstateInventory( house->getLandIdent() );
|
auto extContainer = containers.find( static_cast< uint16_t >( InventoryType::HousingExteriorAppearance ) );
|
||||||
|
|
||||||
auto extContainer = containers.find( static_cast< uint16_t >( InventoryType::HousingOutdoorAppearance ) );
|
|
||||||
if( extContainer != containers.end() )
|
if( extContainer != containers.end() )
|
||||||
{
|
{
|
||||||
for( auto& item : extContainer->second->getItemMap() )
|
for( auto& item : extContainer->second->getItemMap() )
|
||||||
{
|
{
|
||||||
house->setExteriorModel( static_cast< Common::HousePartSlot >( item.first ),
|
house->setExteriorModel( static_cast< Common::HouseExteriorSlot >( item.first ),
|
||||||
getItemData( item.second->getId() ), item.second->getStain() );
|
getItemAdditionalData( item.second->getId() ), item.second->getStain() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -695,7 +783,7 @@ void Sapphire::World::Manager::HousingMgr::updateHouseModelsFromDb( Sapphire::Ho
|
||||||
for( auto& item : intContainer->second->getItemMap() )
|
for( auto& item : intContainer->second->getItemMap() )
|
||||||
{
|
{
|
||||||
house->setInteriorModel( static_cast< Common::HousingInteriorSlot >( item.first ),
|
house->setInteriorModel( static_cast< Common::HousingInteriorSlot >( item.first ),
|
||||||
getItemData( item.second->getId() ) );
|
getItemAdditionalData( item.second->getId() ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -703,3 +791,10 @@ void Sapphire::World::Manager::HousingMgr::updateHouseModelsFromDb( Sapphire::Ho
|
||||||
g_fw.get< Logger >()->error( "Plot " + std::to_string( house->getLandIdent().landId ) + " has an invalid inventory configuration for indoor appearance." );
|
g_fw.get< Logger >()->error( "Plot " + std::to_string( house->getLandIdent().landId ) + " has an invalid inventory configuration for indoor appearance." );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t Sapphire::World::Manager::HousingMgr::getItemAdditionalData( uint32_t catalogId )
|
||||||
|
{
|
||||||
|
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
|
||||||
|
auto info = pExdData->get< Sapphire::Data::Item >( catalogId );
|
||||||
|
return info->additionalData;
|
||||||
|
}
|
|
@ -18,6 +18,10 @@ namespace Sapphire::World::Manager
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Structure that is generated and filled on world launch. Used to store housing data during init
|
||||||
|
* so we don't need to query them individually.
|
||||||
|
*/
|
||||||
struct LandCacheEntry
|
struct LandCacheEntry
|
||||||
{
|
{
|
||||||
// land table
|
// land table
|
||||||
|
@ -97,7 +101,7 @@ namespace Sapphire::World::Manager
|
||||||
*
|
*
|
||||||
* @param house The house to update the models for
|
* @param house The house to update the models for
|
||||||
*/
|
*/
|
||||||
void updateHouseModelsFromDb( HousePtr house );
|
void updateHouseModels( HousePtr house );
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Sends the house inventory for the specified type to a player.
|
* @brief Sends the house inventory for the specified type to a player.
|
||||||
|
@ -131,10 +135,39 @@ namespace Sapphire::World::Manager
|
||||||
* @return A map containing container ids to ItemContainerPtr
|
* @return A map containing container ids to ItemContainerPtr
|
||||||
*/
|
*/
|
||||||
ContainerIdToContainerMap& getEstateInventory( Common::LandIdent ident );
|
ContainerIdToContainerMap& getEstateInventory( Common::LandIdent ident );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets up inventories and spawns the base items for the house appearance
|
||||||
|
* @param land The house to update
|
||||||
|
*/
|
||||||
|
bool initHouseModels( Entity::Player& player, LandPtr land, uint32_t presetCatalogId );
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*!
|
||||||
|
* @brief Gets the next available house id
|
||||||
|
* @return The next available house id
|
||||||
|
*/
|
||||||
|
uint64_t getNextHouseId();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Loads all the land entries from the database and caches them to speed up housing territory init
|
||||||
|
*/
|
||||||
void loadLandCache();
|
void loadLandCache();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Loads all the inventories for every estate on the world and sets up their containers
|
||||||
|
* @return True if it was successful
|
||||||
|
*/
|
||||||
bool loadEstateInventories();
|
bool loadEstateInventories();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Gets the additionalData field from item.exd for an item
|
||||||
|
* @param catalogId The item id to lookup in item.exd
|
||||||
|
* @return The additionalData field from item.exd
|
||||||
|
*/
|
||||||
|
uint32_t getItemAdditionalData( uint32_t catalogId );
|
||||||
|
|
||||||
LandSetLandCacheMap m_landCache;
|
LandSetLandCacheMap m_landCache;
|
||||||
LandIdentToInventoryContainerMap m_estateInventories;
|
LandIdentToInventoryContainerMap m_estateInventories;
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,17 @@
|
||||||
#include "Actor/Player.h"
|
#include "Actor/Player.h"
|
||||||
#include "Inventory/ItemContainer.h"
|
#include "Inventory/ItemContainer.h"
|
||||||
#include "Inventory/Item.h"
|
#include "Inventory/Item.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>
|
||||||
|
|
||||||
|
#include <Database/DatabaseDef.h>
|
||||||
|
#include <Exd/ExdDataGenerated.h>
|
||||||
|
|
||||||
|
#include "Framework.h"
|
||||||
|
|
||||||
|
extern Sapphire::Framework g_fw;
|
||||||
|
|
||||||
using namespace Sapphire::Network::Packets;
|
using namespace Sapphire::Network::Packets;
|
||||||
|
|
||||||
void Sapphire::World::Manager::InventoryMgr::sendInventoryContainer( Sapphire::Entity::Player& player,
|
void Sapphire::World::Manager::InventoryMgr::sendInventoryContainer( Sapphire::Entity::Player& player,
|
||||||
|
@ -55,4 +63,63 @@ void Sapphire::World::Manager::InventoryMgr::sendInventoryContainer( Sapphire::E
|
||||||
containerInfoPacket->data().containerId = container->getId();
|
containerInfoPacket->data().containerId = container->getId();
|
||||||
|
|
||||||
player.queuePacket( containerInfoPacket );
|
player.queuePacket( containerInfoPacket );
|
||||||
|
}
|
||||||
|
|
||||||
|
Sapphire::ItemPtr Sapphire::World::Manager::InventoryMgr::createItem( Entity::Player& player,
|
||||||
|
uint32_t catalogId, uint32_t quantity )
|
||||||
|
{
|
||||||
|
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
|
||||||
|
auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >();
|
||||||
|
auto itemInfo = pExdData->get< Sapphire::Data::Item >( catalogId );
|
||||||
|
|
||||||
|
if( !itemInfo )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto item = make_Item( Items::Util::getNextUId(), catalogId,
|
||||||
|
itemInfo->modelMain, itemInfo->modelSub );
|
||||||
|
|
||||||
|
item->setStackSize( std::max< uint32_t >( 1, quantity ) );
|
||||||
|
|
||||||
|
auto stmt = pDb->getPreparedStatement( Db::CHARA_ITEMGLOBAL_INS );
|
||||||
|
|
||||||
|
stmt->setUInt( 1, player.getId() );
|
||||||
|
stmt->setUInt( 2, item->getUId() );
|
||||||
|
stmt->setUInt( 3, item->getId() );
|
||||||
|
stmt->setUInt( 4, item->getStackSize() );
|
||||||
|
|
||||||
|
pDb->execute( stmt );
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sapphire::World::Manager::InventoryMgr::saveHousingContainer( Common::LandIdent ident,
|
||||||
|
Sapphire::ItemContainerPtr container )
|
||||||
|
{
|
||||||
|
auto u64ident = *reinterpret_cast< uint64_t* >( &ident );
|
||||||
|
|
||||||
|
for( auto& item : container->getItemMap() )
|
||||||
|
{
|
||||||
|
saveHousingContainerItem( u64ident, container->getId(), item.first, item.second->getUId() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sapphire::World::Manager::InventoryMgr::saveHousingContainerItem( uint64_t ident,
|
||||||
|
uint16_t containerId, uint16_t slotId,
|
||||||
|
uint64_t itemId )
|
||||||
|
{
|
||||||
|
auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >();
|
||||||
|
|
||||||
|
auto stmt = pDb->getPreparedStatement( Db::LAND_INV_UP );
|
||||||
|
// 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 );
|
||||||
|
|
||||||
|
pDb->execute( stmt );
|
||||||
}
|
}
|
|
@ -9,7 +9,56 @@ namespace Sapphire::World::Manager
|
||||||
class InventoryMgr
|
class InventoryMgr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/*!
|
||||||
|
* @brief Sends an item container to a player
|
||||||
|
*
|
||||||
|
* This does no checks on the container itself. You can send another players inventory to a different
|
||||||
|
* player if you so wish - not that you should
|
||||||
|
*
|
||||||
|
* Automagically manages inventory packet sequencing.
|
||||||
|
*
|
||||||
|
* @param player The player to send the container to
|
||||||
|
* @param container The container to send to the player
|
||||||
|
*/
|
||||||
void sendInventoryContainer( Sapphire::Entity::Player& player, Sapphire::ItemContainerPtr container );
|
void sendInventoryContainer( Sapphire::Entity::Player& player, Sapphire::ItemContainerPtr container );
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Creates an item, saves it to the global item table and returns a ptr to the created item
|
||||||
|
* @param player The player that will 'own' the item
|
||||||
|
* @param catalogId The ID for the item, see item.exd
|
||||||
|
* @param quantity how much item to make
|
||||||
|
* @return An ItemPtr to the newly created item
|
||||||
|
*/
|
||||||
|
Sapphire::ItemPtr createItem( Entity::Player& player, uint32_t catalogId, uint32_t quantity = 1 );
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Commits a housing containers contents to the db
|
||||||
|
* @param ident The identity of the owner of the container
|
||||||
|
* @param container The container to save to the db
|
||||||
|
*/
|
||||||
|
void saveHousingContainer( Common::LandIdent ident, Sapphire::ItemContainerPtr container );
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Update an item in the db
|
||||||
|
* @param item The item to commit to the db
|
||||||
|
*/
|
||||||
|
void updateItem( Sapphire::ItemPtr item );
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*!
|
||||||
|
* @brief Saves an individual item to the db.
|
||||||
|
*
|
||||||
|
* This will create a new row in the event the slot doesn't exist in the db, otherwise this
|
||||||
|
* will overwrite the itemid in the existing row.
|
||||||
|
*
|
||||||
|
* @param ident
|
||||||
|
* @param containerId
|
||||||
|
* @param slotId
|
||||||
|
* @param itemId
|
||||||
|
*/
|
||||||
|
void saveHousingContainerItem( uint64_t ident,
|
||||||
|
uint16_t containerId, uint16_t slotId,
|
||||||
|
uint64_t itemId );
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,12 +87,12 @@ void Sapphire::House::setHouseName( const std::string& name )
|
||||||
updateHouseDb();
|
updateHouseDb();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sapphire::House::setExteriorModel( Sapphire::Common::HousePartSlot slot, uint32_t modelId, uint16_t stain )
|
void Sapphire::House::setExteriorModel( Sapphire::Common::HouseExteriorSlot slot, uint32_t modelId, uint16_t stain )
|
||||||
{
|
{
|
||||||
m_exteriorModelCache[ slot ] = std::make_pair( modelId, stain );
|
m_exteriorModelCache[ slot ] = std::make_pair( modelId, stain );
|
||||||
}
|
}
|
||||||
|
|
||||||
Sapphire::House::HousePart Sapphire::House::getExteriorModel( Sapphire::Common::HousePartSlot slot )
|
Sapphire::House::HousePart Sapphire::House::getExteriorModel( Sapphire::Common::HouseExteriorSlot slot )
|
||||||
{
|
{
|
||||||
return m_exteriorModelCache[ slot ];
|
return m_exteriorModelCache[ slot ];
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,8 @@ namespace Sapphire
|
||||||
void setHouseGreeting( const std::string& greeting );
|
void setHouseGreeting( const std::string& greeting );
|
||||||
|
|
||||||
//functions
|
//functions
|
||||||
void setExteriorModel( Common::HousePartSlot slot, uint32_t modelId, uint16_t stain );
|
void setExteriorModel( Common::HouseExteriorSlot slot, uint32_t modelId, uint16_t stain );
|
||||||
HousePart getExteriorModel( Common::HousePartSlot slot );
|
HousePart getExteriorModel( Common::HouseExteriorSlot slot );
|
||||||
|
|
||||||
void setInteriorModel( Common::HousingInteriorSlot slot, uint32_t modelId );
|
void setInteriorModel( Common::HousingInteriorSlot slot, uint32_t modelId );
|
||||||
uint32_t getInteriorModel( Common::HousingInteriorSlot slot );
|
uint32_t getInteriorModel( Common::HousingInteriorSlot slot );
|
||||||
|
|
|
@ -85,7 +85,7 @@ bool Sapphire::HousingZone::init()
|
||||||
{
|
{
|
||||||
auto house = make_House( entry.m_houseId, m_landSetId, land->getLandIdent(), entry.m_estateName, entry.m_estateComment );
|
auto house = make_House( entry.m_houseId, m_landSetId, land->getLandIdent(), entry.m_estateName, entry.m_estateComment );
|
||||||
|
|
||||||
housingMgr->updateHouseModelsFromDb( house );
|
housingMgr->updateHouseModels( house );
|
||||||
land->setHouse( house );
|
land->setHouse( house );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,25 +88,6 @@ void Sapphire::Land::init( Common::LandType type, uint8_t size, uint8_t state, u
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// init item containers
|
|
||||||
// auto setupContainer = [ this ]( InventoryType type, uint16_t maxSize )
|
|
||||||
// {
|
|
||||||
// m_landInventoryMap[ type ] = make_ItemContainer( type, maxSize, "houseiteminventory", true, true );
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// setupContainer( InventoryType::HousingOutdoorAppearance, 8 );
|
|
||||||
// setupContainer( InventoryType::HousingOutdoorPlacedItems, m_maxPlacedExternalItems );
|
|
||||||
// setupContainer( InventoryType::HousingOutdoorStoreroom, m_maxPlacedExternalItems );
|
|
||||||
//
|
|
||||||
// setupContainer( InventoryType::HousingInteriorAppearance, 9 );
|
|
||||||
//
|
|
||||||
// // nb: so we're going to store these internally in one container because SE is fucked in the head
|
|
||||||
// // but when an inventory is requested, we will split them into groups of 50
|
|
||||||
// setupContainer( InventoryType::HousingInteriorPlacedItems1, m_maxPlacedInternalItems );
|
|
||||||
// setupContainer( InventoryType::HousingInteriorStoreroom1, m_maxPlacedInternalItems );
|
|
||||||
//
|
|
||||||
// loadItemContainerContents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Sapphire::Land::convertItemIdToHousingItemId( uint32_t itemId )
|
uint32_t Sapphire::Land::convertItemIdToHousingItemId( uint32_t itemId )
|
||||||
|
@ -281,68 +262,7 @@ void Sapphire::Land::update( uint32_t currTime )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Sapphire::Land::getNextHouseId()
|
Sapphire::Land::InvMaxItemsPair Sapphire::Land::getInventoryItemMax() const
|
||||||
{
|
{
|
||||||
auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >();
|
return std::make_pair( m_maxPlacedExternalItems, m_maxPlacedInternalItems );
|
||||||
auto pQR = pDb->query( "SELECT MAX( HouseId ) FROM house" );
|
|
||||||
|
|
||||||
if( !pQR->next() )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return pQR->getUInt( 1 ) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Sapphire::Land::setPreset( uint32_t itemId )
|
|
||||||
{
|
|
||||||
auto housingItemId = convertItemIdToHousingItemId( itemId );
|
|
||||||
|
|
||||||
auto exdData = g_fw.get< Sapphire::Data::ExdDataGenerated >();
|
|
||||||
if( !exdData )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto housingPreset = exdData->get< Sapphire::Data::HousingPreset >( housingItemId );
|
|
||||||
if( !housingPreset )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if( !getHouse() )
|
|
||||||
{
|
|
||||||
// todo: i guess we'd create a house here?
|
|
||||||
auto newId = getNextHouseId();
|
|
||||||
|
|
||||||
m_pHouse = make_House( newId, getLandSetId(), getLandIdent(), "Estate #" + std::to_string( m_landIdent.landId + 1 ), "" );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// getHouse()->setHouseModel( Common::HousePartSlot::ExteriorRoof,
|
|
||||||
// convertItemIdToHousingItemId( housingPreset->exteriorRoof ) );
|
|
||||||
// getHouse()->setHouseModel( Common::HousePartSlot::ExteriorWall,
|
|
||||||
// convertItemIdToHousingItemId( housingPreset->exteriorWall ) );
|
|
||||||
// getHouse()->setHouseModel( Common::HousePartSlot::ExteriorWindow,
|
|
||||||
// convertItemIdToHousingItemId( housingPreset->exteriorWindow ) );
|
|
||||||
// getHouse()->setHouseModel( Common::HousePartSlot::ExteriorDoor,
|
|
||||||
// convertItemIdToHousingItemId( housingPreset->exteriorDoor ) );
|
|
||||||
//
|
|
||||||
// getHouse()->setHouseInteriorModel( Common::HousingInteriorSlot::InteriorWall,
|
|
||||||
// convertItemIdToHousingItemId( housingPreset->interiorWall ) );
|
|
||||||
// getHouse()->setHouseInteriorModel( Common::HousingInteriorSlot::InteriorFloor,
|
|
||||||
// convertItemIdToHousingItemId( housingPreset->interiorFlooring ) );
|
|
||||||
// getHouse()->setHouseInteriorModel( Common::HousingInteriorSlot::InteriorLight,
|
|
||||||
// convertItemIdToHousingItemId( housingPreset->interiorLighting ) );
|
|
||||||
// getHouse()->setHouseInteriorModel( Common::HousingInteriorSlot::InteriorWall_Attic,
|
|
||||||
// convertItemIdToHousingItemId( housingPreset->otherFloorWall ) );
|
|
||||||
// getHouse()->setHouseInteriorModel( Common::HousingInteriorSlot::InteriorFloor_Attic,
|
|
||||||
// convertItemIdToHousingItemId( housingPreset->otherFloorFlooring ) );
|
|
||||||
// getHouse()->setHouseInteriorModel( Common::HousingInteriorSlot::InteriorLight_Attic,
|
|
||||||
// convertItemIdToHousingItemId( housingPreset->otherFloorLighting ) );
|
|
||||||
// getHouse()->setHouseInteriorModel( Common::HousingInteriorSlot::InteriorWall_Basement,
|
|
||||||
// convertItemIdToHousingItemId( housingPreset->basementWall ) );
|
|
||||||
// getHouse()->setHouseInteriorModel( Common::HousingInteriorSlot::InteriorFloor_Basement,
|
|
||||||
// convertItemIdToHousingItemId( housingPreset->basementFlooring ) );
|
|
||||||
// getHouse()->setHouseInteriorModel( Common::HousingInteriorSlot::InteriorLight_Basement,
|
|
||||||
// convertItemIdToHousingItemId( housingPreset->basementLighting ) );
|
|
||||||
// getHouse()->setHouseInteriorModel( Common::HousingInteriorSlot::InteriorLight_Mansion,
|
|
||||||
// convertItemIdToHousingItemId( housingPreset->mansionLighting ) );
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
|
@ -20,6 +20,7 @@ namespace Sapphire
|
||||||
void init( Common::LandType type, uint8_t size, uint8_t state, uint32_t currentPrice, uint64_t ownerId, uint64_t houseId );
|
void init( Common::LandType type, uint8_t size, uint8_t state, uint32_t currentPrice, uint64_t ownerId, uint64_t houseId );
|
||||||
|
|
||||||
using LandInventoryMap = std::unordered_map< uint16_t, ItemContainerPtr >;
|
using LandInventoryMap = std::unordered_map< uint16_t, ItemContainerPtr >;
|
||||||
|
using InvMaxItemsPair = std::pair< uint16_t, uint16_t >;
|
||||||
|
|
||||||
//Primary state
|
//Primary state
|
||||||
void setSize( uint8_t size );
|
void setSize( uint8_t size );
|
||||||
|
@ -61,6 +62,8 @@ namespace Sapphire
|
||||||
void setLandTag( uint8_t slot, uint8_t tag );
|
void setLandTag( uint8_t slot, uint8_t tag );
|
||||||
uint8_t getLandTag( uint8_t slot );
|
uint8_t getLandTag( uint8_t slot );
|
||||||
|
|
||||||
|
InvMaxItemsPair getInventoryItemMax() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t convertItemIdToHousingItemId( uint32_t itemId );
|
uint32_t convertItemIdToHousingItemId( uint32_t itemId );
|
||||||
uint32_t getNextHouseId();
|
uint32_t getNextHouseId();
|
||||||
|
|
Loading…
Add table
Reference in a new issue