diff --git a/bin/sql/schema/schema.sql b/bin/sql/schema/schema.sql index 83d777fd..cdaa247e 100644 --- a/bin/sql/schema/schema.sql +++ b/bin/sql/schema/schema.sql @@ -566,9 +566,9 @@ CREATE TABLE `zonepositions` ( CREATE TABLE `landplaceditems` ( `ItemId` INT(20) UNSIGNED NOT NULL, - `PosX` FLOAT NOT NULL, - `PosY` FLOAT NOT NULL, - `PosZ` FLOAT NOT NULL, + `PosX` INT(10) NOT NULL, + `PosY` INT(10) NOT NULL, + `PosZ` INT(10) NOT NULL, `Rotation` INT(10) NOT NULL, PRIMARY KEY (`ItemId`) ) diff --git a/src/common/Common.h b/src/common/Common.h index 5fb1a59c..8a86bde6 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -26,6 +26,13 @@ namespace Sapphire::Common float z; }; + struct FFXIVARR_POSITION3_U16 + { + uint16_t x; + uint16_t y; + uint16_t z; + }; + struct ActiveLand { uint8_t ward; @@ -848,9 +855,7 @@ namespace Sapphire::Common { uint32_t itemId; uint16_t itemRotation; - uint16_t pos_x; - uint16_t pos_y; - uint16_t pos_z; + Common::FFXIVARR_POSITION3_U16 pos; }; enum HouseSize : uint8_t diff --git a/src/world/Inventory/HousingItem.cpp b/src/world/Inventory/HousingItem.cpp index 3ab655e2..265c26de 100644 --- a/src/world/Inventory/HousingItem.cpp +++ b/src/world/Inventory/HousingItem.cpp @@ -14,12 +14,12 @@ void Sapphire::Inventory::HousingItem::setRot( uint16_t rot ) m_rotation = rot; } -Sapphire::Common::FFXIVARR_POSITION3 Sapphire::Inventory::HousingItem::getPos() const +Sapphire::Common::FFXIVARR_POSITION3_U16 Sapphire::Inventory::HousingItem::getPos() const { return m_position; } -void Sapphire::Inventory::HousingItem::setPos( Sapphire::Common::FFXIVARR_POSITION3 pos ) +void Sapphire::Inventory::HousingItem::setPos( Sapphire::Common::FFXIVARR_POSITION3_U16 pos ) { m_position = pos; } \ No newline at end of file diff --git a/src/world/Inventory/HousingItem.h b/src/world/Inventory/HousingItem.h index d1536834..d4fbe368 100644 --- a/src/world/Inventory/HousingItem.h +++ b/src/world/Inventory/HousingItem.h @@ -14,11 +14,11 @@ namespace Sapphire::Inventory void setRot( uint16_t rot ); uint16_t getRot() const; - void setPos( Common::FFXIVARR_POSITION3 pos ); - Common::FFXIVARR_POSITION3 getPos() const; + void setPos( Common::FFXIVARR_POSITION3_U16 pos ); + Common::FFXIVARR_POSITION3_U16 getPos() const; private: - Common::FFXIVARR_POSITION3 m_position; + Common::FFXIVARR_POSITION3_U16 m_position; uint16_t m_rotation; }; } diff --git a/src/world/Manager/HousingMgr.cpp b/src/world/Manager/HousingMgr.cpp index 91ccc0f7..a9593901 100644 --- a/src/world/Manager/HousingMgr.cpp +++ b/src/world/Manager/HousingMgr.cpp @@ -120,12 +120,12 @@ bool Sapphire::World::Manager::HousingMgr::loadEstateInventories() if( isPlacedItemsInventory( static_cast< Common::InventoryType >( containerId ) ) ) { item->setPos( { - res->getFloat( "PosX" ), - res->getFloat( "PosY" ), - res->getFloat( "PosZ" ) + res->getUInt16( "PosX" ), + res->getUInt16( "PosY" ), + res->getUInt16( "PosZ" ) } ); - item->setRot( res->getUInt( "Rotation" ) ); + item->setRot( res->getUInt16( "Rotation" ) ); } ContainerIdToContainerMap& estateInv = m_estateInventories[ ident ]; @@ -800,7 +800,7 @@ void Sapphire::World::Manager::HousingMgr::sendEstateInventory( Entity::Player& if( !internalZone ) return; - auto ident = internalZone->getIdent(); + auto ident = internalZone->getLandIdent(); auto landSetId = toLandSetId( ident.territoryTypeId, ident.wardNum ); auto exteriorZone = getHousingZoneByLandSetId( landSetId ); @@ -933,12 +933,16 @@ void Sapphire::World::Manager::HousingMgr::reqPlaceHousingItem( Sapphire::Entity isOutside = true; } - // inside house - else if( auto zone = std::dynamic_pointer_cast< Territory::Housing::HousingInteriorTerritory >( player.getCurrentZone() ) ) + // otherwise, inside a house. landId is 0 when inside a plot + else if( landId == 0 ) { + auto zone = std::dynamic_pointer_cast< Territory::Housing::HousingInteriorTerritory >( player.getCurrentZone() ); + if( !zone ) + return; + // 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 ident = zone->getLandIdent(); auto landSet = toLandSetId( ident.territoryTypeId, ident.wardNum ); land = getHousingZoneByLandSetId( landSet )->getLand( landId ); @@ -954,9 +958,6 @@ void Sapphire::World::Manager::HousingMgr::reqPlaceHousingItem( Sapphire::Entity 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; @@ -970,7 +971,12 @@ void Sapphire::World::Manager::HousingMgr::reqPlaceHousingItem( Sapphire::Entity item = Inventory::make_HousingItem( tmpItem->getUId(), tmpItem->getId() ); // set params - item->setPos( pos ); + item->setPos( { + Util::floatToUInt16( pos.x ), + Util::floatToUInt16( pos.y ), + Util::floatToUInt16( pos.z ) + } ); + item->setRot( Util::floatToUInt16Rot( rotation ) ); } else @@ -1020,8 +1026,62 @@ bool Sapphire::World::Manager::HousingMgr::placeExternalItem( Entity::Player& pl // add to zone and spawn auto zone = std::dynamic_pointer_cast< HousingZone >( player.getCurrentZone() ); + assert( zone ); zone->spawnYardObject( ident.landId, freeSlot, item ); + return true; +} + +bool Sapphire::World::Manager::HousingMgr::placeInteriorItem( Entity::Player& player, + Inventory::HousingItemPtr item ) +{ + auto invMgr = g_fw.get< InventoryMgr >(); + + auto containers = { + InventoryType::HousingInteriorPlacedItems1, + InventoryType::HousingInteriorPlacedItems2, + InventoryType::HousingInteriorPlacedItems3, + InventoryType::HousingInteriorPlacedItems4, + InventoryType::HousingInteriorPlacedItems5, + InventoryType::HousingInteriorPlacedItems6, + InventoryType::HousingInteriorPlacedItems7, + InventoryType::HousingInteriorPlacedItems8, + }; + + auto zone = std::dynamic_pointer_cast< Territory::Housing::HousingInteriorTerritory >( player.getCurrentZone() ); + assert( zone ); + + auto ident = zone->getLandIdent(); + + // find first free container + uint8_t containerIdx = 0; + for( auto containerId : containers ) + { + auto& container = getEstateInventory( ident )[ containerId ]; + + auto freeSlot = container->getFreeSlot(); + if( freeSlot == -1 ) + { + containerIdx++; + continue; + } + + // have a free slot + container->setItem( freeSlot, item ); + + // todo: see comment above in placeExternalItem where the same func is called + 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 ); + + break; + } + + return true; } \ No newline at end of file diff --git a/src/world/Manager/HousingMgr.h b/src/world/Manager/HousingMgr.h index a4291814..f9191c06 100644 --- a/src/world/Manager/HousingMgr.h +++ b/src/world/Manager/HousingMgr.h @@ -151,8 +151,23 @@ namespace Sapphire::World::Manager private: + /*! + * @brief Processes the spawning and linking of a newly placed housing item for external items + * @param player The player who is placing the item + * @param item The item that we're placing + * @param ident The land that is going to own the item + * @return true if the item was placed successfully, false if there's no free container slots to place it + */ bool placeExternalItem( Entity::Player& player, Inventory::HousingItemPtr item, Common::LandIdent ident ); + /*! + * @brief Processing the spawning and linking of a newly placed item for interior items + * @param player The player who is placing the item + * @param item The item that we're placing + * @return true if the item was placed successfully, false if there's no free spots to place it + */ + bool placeInteriorItem( Entity::Player& player, Inventory::HousingItemPtr item ); + /*! * @brief Creates a house and saves the minimum amount required to persist a house through restarts. * diff --git a/src/world/Manager/InventoryMgr.cpp b/src/world/Manager/InventoryMgr.cpp index 4aacb24d..f5b59620 100644 --- a/src/world/Manager/InventoryMgr.cpp +++ b/src/world/Manager/InventoryMgr.cpp @@ -128,15 +128,14 @@ void Sapphire::World::Manager::InventoryMgr::updateHousingItemPosition( Sapphire stmt->setUInt64( 1, item->getUId() ); - stmt->setDouble( 2, pos.x ); - stmt->setDouble( 3, pos.y ); - stmt->setDouble( 4, pos.z ); - + stmt->setUInt( 2, pos.x ); + stmt->setUInt( 3, pos.y ); + stmt->setUInt( 4, pos.z ); stmt->setInt( 5, rot ); - stmt->setDouble( 6, pos.x ); - stmt->setDouble( 7, pos.y ); - stmt->setDouble( 8, pos.z ); + stmt->setUInt( 6, pos.x ); + stmt->setUInt( 7, pos.y ); + stmt->setUInt( 8, pos.z ); stmt->setInt( 9, rot ); pDb->execute( stmt ); diff --git a/src/world/Territory/Housing/HousingInteriorTerritory.cpp b/src/world/Territory/Housing/HousingInteriorTerritory.cpp index f7487ee6..f1044efa 100644 --- a/src/world/Territory/Housing/HousingInteriorTerritory.cpp +++ b/src/world/Territory/Housing/HousingInteriorTerritory.cpp @@ -105,7 +105,7 @@ uint32_t Housing::HousingInteriorTerritory::getLastActivityTime() const return m_lastActivityTime; } -const Common::LandIdent Housing::HousingInteriorTerritory::getIdent() const +const Common::LandIdent Housing::HousingInteriorTerritory::getLandIdent() const { return m_landIdent; } \ No newline at end of file diff --git a/src/world/Territory/Housing/HousingInteriorTerritory.h b/src/world/Territory/Housing/HousingInteriorTerritory.h index f8287df8..153e3604 100644 --- a/src/world/Territory/Housing/HousingInteriorTerritory.h +++ b/src/world/Territory/Housing/HousingInteriorTerritory.h @@ -20,7 +20,7 @@ namespace Sapphire::World::Territory::Housing uint32_t getLastActivityTime() const; - const Common::LandIdent getIdent() const; + const Common::LandIdent getLandIdent() const; private: Common::LandIdent m_landIdent; diff --git a/src/world/Territory/HousingZone.cpp b/src/world/Territory/HousingZone.cpp index a1bbfb6d..414e927a 100644 --- a/src/world/Territory/HousingZone.cpp +++ b/src/world/Territory/HousingZone.cpp @@ -142,7 +142,7 @@ bool Sapphire::HousingZone::init() auto& externalContainer = inventory[ InventoryType::HousingExteriorPlacedItems ]; auto arrayBounds = m_yardObjectArrayBounds[ entry.m_landId ]; - uint8_t yardMapIndex = entry.m_landId <= 29 ? 0 : 1; + auto yardMapIndex = entry.m_landId <= 29 ? 0 : 1; for( auto& item : externalContainer->getItemMap() ) { @@ -151,14 +151,9 @@ bool Sapphire::HousingZone::init() auto housingItem = std::dynamic_pointer_cast< Inventory::HousingItem >( item.second ); assert( housingItem ); - auto pos = housingItem->getPos(); - obj.itemId = housingItem->getAdditionalData(); obj.itemRotation = housingItem->getRot(); - - obj.pos_x = Util::floatToUInt16( pos.x ); - obj.pos_y = Util::floatToUInt16( pos.y ); - obj.pos_z = Util::floatToUInt16( pos.z ); + obj.pos = housingItem->getPos(); auto idx = item.first + arrayBounds.first; m_yardObjects[ yardMapIndex ][ idx ] = obj; @@ -365,14 +360,10 @@ void Sapphire::HousingZone::spawnYardObject( uint8_t landId, uint16_t slotId, In 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 ); + obj.pos = item->getPos(); // link obj - uint8_t yardMapIndex = landId <= 29 ? 0 : 1; + auto yardMapIndex = landId <= 29 ? 0 : 1; m_yardObjects[ yardMapIndex ][ offset ] = obj; // spawn obj in zone @@ -381,7 +372,7 @@ void Sapphire::HousingZone::spawnYardObject( uint8_t landId, uint16_t slotId, In auto packet = makeZonePacket< Server::FFXIVIpcYardObjectSpawn >( player.second->getId() ); packet->data().landSetId = landId; - packet->data().objectArray = slotId; + packet->data().objectArray = static_cast< uint8_t >( slotId ); packet->data().object = obj; player.second->queuePacket( packet );