diff --git a/src/common/Logging/Logger.cpp b/src/common/Logging/Logger.cpp index 1a599551..c051e946 100644 --- a/src/common/Logging/Logger.cpp +++ b/src/common/Logging/Logger.cpp @@ -58,6 +58,11 @@ namespace Sapphire spdlog::get( "logger" )->error( text ); } + void Logger::warn( const std::string& text ) + { + spdlog::get( "logger" )->warn( text ); + } + void Logger::info( const std::string& text ) { spdlog::get( "logger" )->info( text ); @@ -73,4 +78,9 @@ namespace Sapphire spdlog::get( "logger" )->critical( text ); } + void Logger::trace( const std::string& text ) + { + spdlog::get( "logger" )->trace( text ); + } + } diff --git a/src/common/Logging/Logger.h b/src/common/Logging/Logger.h index 876fadc3..b716e319 100644 --- a/src/common/Logging/Logger.h +++ b/src/common/Logging/Logger.h @@ -20,12 +20,16 @@ namespace Sapphire static void error( const std::string& text ); + static void warn( const std::string& text ); + static void info( const std::string& text ); static void debug( const std::string& text ); static void fatal( const std::string& text ); + static void trace( const std::string& text ); + }; } diff --git a/src/common/Network/PacketDef/Zone/ClientZoneDef.h b/src/common/Network/PacketDef/Zone/ClientZoneDef.h index 12b452dd..e096fa8a 100644 --- a/src/common/Network/PacketDef/Zone/ClientZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ClientZoneDef.h @@ -253,7 +253,7 @@ struct FFXIVIpcReqPlaceHousingItem : /* 000C */ Common::FFXIVARR_POSITION3 position; /* 0018 */ float rotation; - /* 001C */ uint32_t unknown3; // always 1? + /* 001C */ uint32_t shouldPlaceItem; // 1 if placing an item, 0 if placing in store /* 0020 */ uint32_t unknown4[2]; // always 0 it looks like }; diff --git a/src/world/Manager/HousingMgr.cpp b/src/world/Manager/HousingMgr.cpp index 1d3d079b..8badd385 100644 --- a/src/world/Manager/HousingMgr.cpp +++ b/src/world/Manager/HousingMgr.cpp @@ -416,11 +416,10 @@ bool Sapphire::World::Manager::HousingMgr::relinquishLand( Entity::Player& playe auto pLand = pHousing->getLand( plot ); auto plotMaxPrice = pLand->getCurrentPrice(); - auto landOwnerId = pLand->getOwnerId(); // can't relinquish when you are not the owner // TODO: actually use permissions here for FC houses - if( landOwnerId != player.getId() ) + if( !hasPermission( player, *pLand, 0 ) ) { auto msgPkt = makeActorControl143( player.getId(), ActorControl::LogMsg, 3304, 0 ); player.queuePacket( msgPkt ); @@ -664,8 +663,7 @@ void Sapphire::World::Manager::HousingMgr::buildPresetEstate( Entity::Player& pl if( !pLand ) return; - // todo: when doing FC houses, look up the type from the original purchase and check perms from FC and set state accordingly - if( pLand->getOwnerId() != player.getId() ) + if( !hasPermission( player, *pLand, 0 ) ) return; // create house @@ -763,8 +761,7 @@ void Sapphire::World::Manager::HousingMgr::updateEstateGreeting( Entity::Player& if( !land ) return; - // todo: implement proper permissions checks - if( land->getOwnerId() != player.getId() ) + if( !hasPermission( player, *land, 0 ) ) return; auto house = land->getHouse(); @@ -789,8 +786,7 @@ void Sapphire::World::Manager::HousingMgr::requestEstateEditGuestAccess( Entity: if( !land ) return; - // todo: add proper permission check - if( land->getOwnerId() != player.getId() ) + if( !hasPermission( player, *land, 0 ) ) return; auto packet = makeZonePacket< Server::FFXIVIpcHousingShowEstateGuestAccess >( player.getId() ); @@ -854,8 +850,7 @@ void Sapphire::World::Manager::HousingMgr::sendEstateInventory( Entity::Player& if( !targetLand ) return; - // todo: add proper permissions checks - if( targetLand->getOwnerId() != player.getId() ) + if( !hasPermission( player, *targetLand, 0 ) ) return; auto& containers = getEstateInventory( targetLand->getLandIdent() ); @@ -993,12 +988,11 @@ void Sapphire::World::Manager::HousingMgr::reqPlaceHousingItem( Sapphire::Entity if( !land ) return; - // todo: add proper permissions checks - if( land->getOwnerId() != player.getId() ) + if( !hasPermission( player, *land, 0 ) ) return; // todo: check item position and make sure it's not outside the plot - // retail uses a radius based check + // anecdotal evidence on reddit seems to imply retail uses a radius based check // unlink item Inventory::HousingItemPtr item; @@ -1009,6 +1003,8 @@ void Sapphire::World::Manager::HousingMgr::reqPlaceHousingItem( Sapphire::Entity containerId == InventoryType::Bag3 ) { auto tmpItem = player.dropInventoryItem( static_cast< Common::InventoryType >( containerId ), slotId ); + if( !tmpItem ) + return; item = Inventory::make_HousingItem( tmpItem->getUId(), tmpItem->getId(), framework() ); @@ -1042,6 +1038,76 @@ void Sapphire::World::Manager::HousingMgr::reqPlaceHousingItem( Sapphire::Entity player.sendUrgent( "An internal error occurred when placing the item." ); } +void Sapphire::World::Manager::HousingMgr::reqPlaceItemInStore( Sapphire::Entity::Player& player, uint16_t landId, + uint16_t containerId, uint16_t slotId ) +{ + LandPtr land; + bool isOutside = false; + + if( auto zone = std::dynamic_pointer_cast< HousingZone >( player.getCurrentZone() ) ) + { + land = zone->getLand( landId ); + isOutside = true; + } + 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->getLandIdent(); + auto landSet = toLandSetId( ident.territoryTypeId, ident.wardNum ); + + land = getHousingZoneByLandSetId( landSet )->getLand( ident.landId ); + } + + if( !hasPermission( player, *land, 0 ) ) + return; + + auto invMgr = framework()->get< InventoryMgr >(); + auto ident = land->getLandIdent(); + auto& containers = getEstateInventory( ident ); + + if( isOutside ) + { + auto& container = containers[ InventoryType::HousingExteriorStoreroom ]; + + auto freeSlot = container->getFreeSlot(); + if( freeSlot == -1 ) + return; + + auto item = player.dropInventoryItem( static_cast< Common::InventoryType >( containerId ), slotId ); + if( !item ) + return; + + container->setItem( freeSlot, item ); + invMgr->sendInventoryContainer( player, container ); + invMgr->saveHousingContainer( ident, container ); + } + else + { + for( auto houseContainer : m_internalStoreroomContainers ) + { + auto needle = containers.find( houseContainer ); + if( needle == containers.end() ) + continue; + + auto container = needle->second; + auto freeSlot = container->getFreeSlot(); + if( freeSlot == -1 ) + { + continue; + } + + auto item = player.dropInventoryItem( static_cast< Common::InventoryType >( containerId ), slotId ); + if( !item ) + return; + + container->setItem( freeSlot, item ); + invMgr->sendInventoryContainer( player, container ); + invMgr->saveHousingContainer( ident, container ); + } + } +} + bool Sapphire::World::Manager::HousingMgr::placeExternalItem( Entity::Player& player, Inventory::HousingItemPtr item, Common::LandIdent ident ) @@ -1107,9 +1173,6 @@ bool Sapphire::World::Manager::HousingMgr::placeInteriorItem( Entity::Player& pl // 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 invMgr->sendInventoryContainer( player, container ); invMgr->saveHousingContainer( ident, container ); @@ -1176,8 +1239,7 @@ void Sapphire::World::Manager::HousingMgr::reqMoveHousingItem( Entity::Player& p if( !land ) return; - // todo: proper perms checks - if( land->getOwnerId() != player.getId() ) + if( !hasPermission( player, *land, 0 ) ) return; // todo: what happens when either of these fail? how does the server let the client know that the moment failed @@ -1250,8 +1312,7 @@ bool Sapphire::World::Manager::HousingMgr::moveExternalItem( Entity::Player& pla { auto land = terri.getLand( ident.landId ); - // todo: add proper perms check - if( land->getOwnerId() != player.getId() ) + if( !hasPermission( player, *land, 0 ) ) return false; auto& containers = getEstateInventory( ident ); @@ -1298,8 +1359,7 @@ void Sapphire::World::Manager::HousingMgr::reqRemoveHousingItem( Sapphire::Entit if( !land ) return; - // todo: proper perms checks - if( land->getOwnerId() != player.getId() ) + if( !hasPermission( player, *land, 0 ) ) return; removeInternalItem( player, *terri, containerId, slot, sendToStoreroom ); @@ -1310,7 +1370,7 @@ void Sapphire::World::Manager::HousingMgr::reqRemoveHousingItem( Sapphire::Entit if( !land ) return; - if( land->getOwnerId() != player.getId() ) + if( !hasPermission( player, *land, 0 ) ) return; auto containerType = static_cast< Common::InventoryType >( containerId ); @@ -1419,11 +1479,13 @@ bool Sapphire::World::Manager::HousingMgr::removeExternalItem( Entity::Player& p if( !item ) return false; + bool shouldDespawnItem = containerType != InventoryType::HousingExteriorStoreroom; + auto invMgr = framework()->get< InventoryMgr >(); if( sendToStoreroom ) { - auto& storeroomContainer = containers[ InventoryType::HousingExteriorStoreroom ]; + auto& storeroomContainer = containers[ containerType ]; auto freeSlot = storeroomContainer->getFreeSlot(); if( freeSlot == -1 ) @@ -1431,8 +1493,8 @@ bool Sapphire::World::Manager::HousingMgr::removeExternalItem( Entity::Player& p sourceContainer->removeItem( slotId ); invMgr->sendInventoryContainer( player, sourceContainer ); - invMgr->removeHousingItemPosition( *item ); invMgr->removeItemFromHousingContainer( land.getLandIdent(), sourceContainer->getId(), slotId ); + invMgr->removeHousingItemPosition( *item ); storeroomContainer->setItem( freeSlot, item ); invMgr->sendInventoryContainer( player, storeroomContainer ); @@ -1454,7 +1516,8 @@ bool Sapphire::World::Manager::HousingMgr::removeExternalItem( Entity::Player& p player.insertInventoryItem( containerPair.first, containerPair.second, item ); } - terri.despawnYardObject( land.getLandIdent().landId, slotId ); + if( shouldDespawnItem ) + terri.despawnYardObject( land.getLandIdent().landId, slotId ); return true; } @@ -1495,8 +1558,7 @@ void Sapphire::World::Manager::HousingMgr::reqEstateExteriorRemodel( Sapphire::E if( !land ) return; - // todo: proper perms checks - if( land->getOwnerId() != player.getId() ) + if( !hasPermission( player, *land, 0 ) ) return; auto& inv = getEstateInventory( land->getLandIdent() ); @@ -1526,8 +1588,7 @@ void Sapphire::World::Manager::HousingMgr::reqEstateInteriorRemodel( Sapphire::E if( !land ) return; - // todo: proper perms checks - if( land->getOwnerId() != player.getId() ) + if( !hasPermission( player, *land, 0 ) ) return; auto& inv = getEstateInventory( land->getLandIdent() ); @@ -1541,4 +1602,16 @@ void Sapphire::World::Manager::HousingMgr::reqEstateInteriorRemodel( Sapphire::E auto pkt = Server::makeActorControl143( player.getId(), Network::ActorControl::ShowEstateInternalAppearanceUI ); player.queuePacket( pkt ); +} + +bool Sapphire::World::Manager::HousingMgr::hasPermission( Sapphire::Entity::Player& player, Sapphire::Land& land, + uint32_t permission ) +{ + // todo: proper perms checks pls + if( land.getOwnerId() == player.getId() ) + return true; + + // todo: check perms here + + return false; } \ No newline at end of file diff --git a/src/world/Manager/HousingMgr.h b/src/world/Manager/HousingMgr.h index 4f2a6898..deb6c099 100644 --- a/src/world/Manager/HousingMgr.h +++ b/src/world/Manager/HousingMgr.h @@ -159,6 +159,8 @@ namespace Sapphire::World::Manager void reqPlaceHousingItem( Entity::Player& player, uint16_t landId, uint16_t containerId, uint16_t slotId, Common::FFXIVARR_POSITION3 pos, float rotation ); + void reqPlaceItemInStore( Entity::Player& player, uint16_t landId, uint16_t containerId, uint16_t slotId ); + /*! * @brief Returns the equivalent YardObject for a HousingItem * @param item The item to convert into a YardObject @@ -179,6 +181,8 @@ namespace Sapphire::World::Manager void reqEstateInteriorRemodel( Entity::Player& player ); + bool hasPermission( Entity::Player& player, Land& land, uint32_t permission ); + private: ItemContainerPtr getFreeEstateInventorySlot( Common::LandIdent ident, diff --git a/src/world/Network/Handlers/PacketHandlers.cpp b/src/world/Network/Handlers/PacketHandlers.cpp index a41ed334..fa6543bf 100644 --- a/src/world/Network/Handlers/PacketHandlers.cpp +++ b/src/world/Network/Handlers/PacketHandlers.cpp @@ -731,8 +731,14 @@ void Sapphire::Network::GameConnection::reqPlaceHousingItem( FrameworkPtr pFw, 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 ); + if( data.shouldPlaceItem == 1 ) + { + housingMgr->reqPlaceHousingItem( player, data.landId, data.sourceInvContainerId, data.sourceInvSlotId, + data.position, data.rotation ); + } + else + housingMgr->reqPlaceItemInStore( player, data.landId, data.sourceInvContainerId, data.sourceInvSlotId ); + } void Sapphire::Network::GameConnection::reqMoveHousingItem( FrameworkPtr pFw,