From 6cde08d073849504dc6e34bb5b5dfe192e9bf347 Mon Sep 17 00:00:00 2001 From: Mordred Date: Fri, 27 Jan 2023 11:13:57 +0100 Subject: [PATCH] Cleanup inside the player class. --- .../Network/PacketDef/Zone/ServerZoneDef.h | 22 +++- src/world/Actor/Player.cpp | 123 +----------------- src/world/Actor/Player.h | 9 +- src/world/Manager/AchievementMgr.cpp | 4 +- src/world/Manager/AchievementMgr.h | 9 +- src/world/Manager/HousingMgr.cpp | 95 +++++++++----- src/world/Manager/HousingMgr.h | 2 + src/world/Manager/PlayerMgr.cpp | 97 +++++++++++++- src/world/Manager/PlayerMgr.h | 2 + src/world/Manager/TerritoryMgr.cpp | 23 ++-- src/world/Manager/TerritoryMgr.h | 7 +- src/world/Task/MoveTerritoryTask.cpp | 10 +- 12 files changed, 216 insertions(+), 187 deletions(-) diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 1a5a1e12..c42fb030 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -2004,11 +2004,11 @@ struct FFXIVIpcEorzeaTimeOffset : FFXIVIpcBasePacket< TimeOffset > struct FFXIVIpcInterior : FFXIVIpcBasePacket< Interior > { - uint8_t Window; - uint8_t WindowColor; - uint8_t Door; - uint8_t DoorColor; - uint16_t Interior[10]; + uint16_t Window; + uint16_t WindowColor; + uint16_t Door; + uint16_t DoorColor; + uint32_t Interior[10]; }; struct FFXIVIpcHousingAuction : FFXIVIpcBasePacket< HousingAuction > @@ -2073,18 +2073,30 @@ struct FFXIVIpcEorzeaTimeOffset : FFXIVIpcBasePacket< TimeOffset > struct FFXIVIpcFurnitureListS : FFXIVIpcBasePacket< FurnitureListS > { Common::LandIdent LandId; + int8_t u1; //Outdoor -1 / Indoor 0 - probably indicator + uint8_t packetNum; + uint8_t packetTotal; + uint8_t u2; //Outdoor 0 / Indoor 100(?) Common::Furniture Furnitures[100]; }; struct FFXIVIpcFurnitureListM : FFXIVIpcBasePacket< FurnitureListM > { Common::LandIdent LandId; + int8_t u1; //Outdoor -1 / Indoor 0 - probably indicator + uint8_t packetNum; + uint8_t packetTotal; + uint8_t u2; //Outdoor 0 / Indoor 100(?) Common::Furniture Furnitures[150]; }; struct FFXIVIpcFurnitureListL : FFXIVIpcBasePacket< FurnitureListL > { Common::LandIdent LandId; + int8_t u1; //Outdoor -1 / Indoor 0 - probably indicator + uint8_t packetNum; + uint8_t packetTotal; + uint8_t u2; //Outdoor 0 / Indoor 100(?) Common::Furniture Furnitures[200]; }; diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 6a4a1322..f8e2d538 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -1526,86 +1526,6 @@ uint32_t Player::getPrevTerritoryTypeId() const return m_prevTerritoryTypeId; } -void Player::sendZonePackets() -{ - auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref(); - auto pZone = teriMgr.getTerritoryByGuId( getTerritoryId() ); - - auto initPacket = makeZonePacket< FFXIVIpcLogin >( getId() ); - initPacket->data().playerActorId = getId(); - queuePacket( initPacket ); - - sendInventory(); - - if( isLogin() ) - { - queuePacket( makeActorControlSelf( getId(), SetCharaGearParamUI, m_equipDisplayFlags, 1 ) ); - queuePacket( makeActorControlSelf( getId(), SetMaxGearSets, m_equippedMannequin ) ); - } - - // set flags, will be reset automatically by zoning ( only on client side though ) - //setStateFlag( PlayerStateFlag::BetweenAreas ); - //setStateFlag( PlayerStateFlag::BetweenAreas1 ); - - if( hasReward( Common::UnlockEntry::HuntingLog ) ) - sendHuntingLog(); - - sendStats(); - - // only initialize the UI if the player in fact just logged in. - if( isLogin() ) - { - auto contentFinderList = makeZonePacket< FFXIVIpcContentAttainFlags >( getId() ); - std::memset( &contentFinderList->data(), 0xFF, sizeof( contentFinderList->data() ) ); - - queuePacket( contentFinderList ); - - auto statusPacket = makePlayerSetup( *this ); - - queuePacket( statusPacket ); - - Service< World::Manager::PlayerMgr >::ref().onPlayerStatusUpdate( *this ); - - sendItemLevel(); - - clearSoldItems(); - } - - auto& housingMgr = Common::Service< HousingMgr >::ref(); - if( Sapphire::LandPtr pLand = housingMgr.getLandByOwnerId( getCharacterId() ) ) - { - uint32_t state = 0; - if( pLand->getHouse() ) - { - state |= LandFlags::CHARA_HOUSING_LAND_DATA_FLAG_HOUSE; - - // todo: remove this, debug for now - state |= LandFlags::CHARA_HOUSING_LAND_DATA_FLAG_AETHERYTE; - } - - setLandFlags( LandFlagsSlot::Private, state, pLand->getLandIdent() ); - } - - sendLandFlags(); - - queuePacket( makeInitZone( *this, *pZone ) ); - - pZone->onPlayerZoneIn( *this ); - - if( isLogin() ) - { - queuePacket( makeZonePacket< FFXIVIpcQuestRepeatFlags >( getId() ) ); - queuePacket( makeZonePacket< FFXIVIpcDailyQuests >( getId() ) ); - } - - if( getPartyId() != 0 ) - { - auto& partyMgr = Common::Service< World::Manager::PartyMgr >::ref(); - partyMgr.onMoveZone( *this ); - } - -} - void Player::setDirectorInitialized( bool isInitialized ) { m_directorInitialized = isInitialized; @@ -1760,44 +1680,6 @@ void Player::setLandFlags( uint8_t flagSlot, uint32_t landFlags, Common::LandIde m_charaLandData[ flagSlot ].landFlags = landFlags; } -void Player::sendLandFlags() -{ - auto landFlags = makeZonePacket< FFXIVIpcCharaHousing >( getId() ); - - landFlags->data().FcLands = m_charaLandData[ Common::LandFlagsSlot::FreeCompany ]; - landFlags->data().CharaLands = m_charaLandData[ Common::LandFlagsSlot::Private ]; - - queuePacket( landFlags ); -} - -void Player::sendLandFlagsSlot( Common::LandFlagsSlot slot ) -{ - auto landFlags = makeZonePacket< FFXIVIpcCharaHousingLandData >( getId() ); - - LandType type; - - switch( slot ) - { - case LandFlagsSlot::Private: - type = LandType::Private; - break; - - case LandFlagsSlot::FreeCompany: - type = LandType::FreeCompany; - break; - - default: - // todo: other/unsupported land types - return; - } - - landFlags->data().Index = static_cast< uint32_t >( type ); - landFlags->data().LandData.landId = m_charaLandData[ slot ].landId; - landFlags->data().LandData.landFlags = m_charaLandData[ slot ].landFlags; - - queuePacket( landFlags ); -} - Sapphire::Common::HuntingLogEntry& Player::getHuntingLogEntry( uint8_t index ) { assert( index < m_huntingLogEntries.size() ); @@ -2143,3 +2025,8 @@ void Player::updatePrevTerritory() m_prevRot = m_rot; } } + +const CharaLandData& Entity::Player::getCharaLandData( Common::LandFlagsSlot slot ) const +{ + return m_charaLandData[ slot ]; +} diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index 7a17aaa8..0b5b2a2b 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -582,8 +582,6 @@ namespace Sapphire::Entity /*! set the loading complete bool */ void setLoadingComplete( bool bComplete ); - void sendZonePackets(); - Common::ZoneingType getZoningType() const; void setZoningType( Common::ZoneingType zoneingType ); @@ -604,9 +602,6 @@ namespace Sapphire::Entity ////////////////////////////////////////////////////////////////////////////////////////////////////// void setLandFlags( uint8_t permissionSet, uint32_t landFlags, Common::LandIdent ident ); - void sendLandFlags(); - void sendLandFlagsSlot( Common::LandFlagsSlot slot ); - // Player Battle Handling ////////////////////////////////////////////////////////////////////////////////////////////////////// void initHateSlotQueue(); @@ -816,6 +811,8 @@ namespace Sapphire::Entity bool isConnected() const; void setConnected( bool isConnected ); + const Common::CharaLandData& getCharaLandData( Common::LandFlagsSlot slot ) const; + private: /*! queue a packet for the player */ void queuePacket( Network::Packets::FFXIVPacketBasePtr pPacket ); @@ -940,6 +937,8 @@ namespace Sapphire::Entity // housing info Common::CharaLandData m_charaLandData[2]{}; + private: + Common::ActiveLand m_activeLand{}; // gc info diff --git a/src/world/Manager/AchievementMgr.cpp b/src/world/Manager/AchievementMgr.cpp index 633ba67c..81a7d11d 100644 --- a/src/world/Manager/AchievementMgr.cpp +++ b/src/world/Manager/AchievementMgr.cpp @@ -169,12 +169,12 @@ Common::AchievementDataKey AchievementMgr::getKeyFromType( Common::Achievement:: return dataKey; } -const std::vector< uint32_t >& AchievementMgr::getAchievementIdByType( Common::Achievement::Type type ) const +std::vector< uint32_t > AchievementMgr::getAchievementIdByType( Common::Achievement::Type type ) const { return getAchievementIdByType( static_cast< uint32_t >( type ) ); } -const std::vector< uint32_t >& AchievementMgr::getAchievementIdByType( uint32_t type ) const +std::vector< uint32_t > AchievementMgr::getAchievementIdByType( uint32_t type ) const { auto it = m_achievementKeyCacheMap.find( type ); diff --git a/src/world/Manager/AchievementMgr.h b/src/world/Manager/AchievementMgr.h index 3c87c31d..88d7000d 100644 --- a/src/world/Manager/AchievementMgr.h +++ b/src/world/Manager/AchievementMgr.h @@ -77,8 +77,8 @@ namespace Sapphire::World::Manager AchievementKeyCache m_achievementKeyCacheMap; std::shared_ptr< Excel::ExcelStruct< Excel::Achievement > > getAchievementDetail( uint32_t achvId ) const; - const std::vector< uint32_t >& getAchievementIdByType( Common::Achievement::Type type ) const; - const std::vector< uint32_t >& getAchievementIdByType( uint32_t type ) const; + std::vector< uint32_t > getAchievementIdByType( Common::Achievement::Type type ) const; + std::vector< uint32_t > getAchievementIdByType( uint32_t type ) const; /// /// get a key for merged achievements (type:subtype) that have progress data @@ -125,7 +125,7 @@ namespace Sapphire::World::Manager auto achvExdData = pAchv->data(); - if( achvExdData.ConditionArg[ 1 ] <= achvDataList[ dataKey.u32 ] ) + if( achvExdData.ConditionArg[ 1 ] <= static_cast< int32_t >( achvDataList[ dataKey.u32 ] ) ) unlockAchievement( player, achvId ); } } @@ -157,9 +157,8 @@ namespace Sapphire::World::Manager auto achvExdData = pAchv->data(); - if( achvExdData.ConditionArg[ 1 ] <= achvDataList[ dataKey.u32 ] ) + if( achvExdData.ConditionArg[ 1 ] <= static_cast< int32_t >( achvDataList[ dataKey.u32 ] ) ) unlockAchievement( player, achvId ); - } } diff --git a/src/world/Manager/HousingMgr.cpp b/src/world/Manager/HousingMgr.cpp index a8607778..eff4b737 100644 --- a/src/world/Manager/HousingMgr.cpp +++ b/src/world/Manager/HousingMgr.cpp @@ -345,8 +345,7 @@ void HousingMgr::sendLandSignOwned( Entity::Player& player, const Common::LandId memcpy( &landInfoSignPacket->data().OwnerName, playerName.c_str(), playerName.size() ); - auto pSession = server.getSession( player.getCharacterId() ); - pSession->getZoneConnection()->queueOutPacket( landInfoSignPacket ); + server.queueForPlayer( player.getCharacterId(), landInfoSignPacket ); } void HousingMgr::sendLandSignFree( Entity::Player& player, const Common::LandIdent ident ) @@ -367,8 +366,7 @@ void HousingMgr::sendLandSignFree( Entity::Player& player, const Common::LandIde plotPricePacket->data().Price = land->getCurrentPrice(); plotPricePacket->data().Timer = land->getDevaluationTime(); - auto pSession = server.getSession( player.getCharacterId() ); - pSession->getZoneConnection()->queueOutPacket( plotPricePacket ); + server.queueForPlayer( player.getCharacterId(), plotPricePacket ); } LandPurchaseResult HousingMgr::purchaseLand( Entity::Player& player, HousingZone& zone, uint8_t plot, uint8_t state ) @@ -408,7 +406,7 @@ LandPurchaseResult HousingMgr::purchaseLand( Entity::Player& player, HousingZone player.setLandFlags( Common::LandFlagsSlot::Private, 0x00, pLand->getLandIdent() ); - player.sendLandFlagsSlot( Common::LandFlagsSlot::Private ); + sendLandFlagsSlot( player, Common::LandFlagsSlot::Private ); //pLand->setLandName( "Private Estate" + std::to_string( pHousing->getWardNum() ) + "-" + std::to_string( plot ) ); pLand->updateLandDb(); @@ -426,8 +424,6 @@ LandPurchaseResult HousingMgr::purchaseLand( Entity::Player& player, HousingZone bool HousingMgr::relinquishLand( Entity::Player& player, HousingZone& zone, uint8_t plot ) { auto& server = Common::Service< World::WorldServer >::ref(); - - auto pSession = server.getSession( player.getCharacterId() ); // TODO: Fix "permissions" being sent incorrectly // TODO: Add checks for land state before relinquishing @@ -439,7 +435,7 @@ bool HousingMgr::relinquishLand( Entity::Player& player, HousingZone& zone, uint if( !hasPermission( player, *pLand, 0 ) ) { auto msgPkt = makeActorControlSelf( player.getId(), ActorControl::LogMsg, 3304, 0 ); - pSession->getZoneConnection()->queueOutPacket( msgPkt ); + server.queueForPlayer( player.getCharacterId(), msgPkt ); return false; } @@ -448,7 +444,7 @@ bool HousingMgr::relinquishLand( Entity::Player& player, HousingZone& zone, uint if( pLand->getHouse() ) { auto msgPkt = makeActorControlSelf( player.getId(), ActorControl::LogMsg, 3315, 0 ); - pSession->getZoneConnection()->queueOutPacket( msgPkt ); + server.queueForPlayer( player.getCharacterId(), msgPkt ); return false; } @@ -462,11 +458,11 @@ bool HousingMgr::relinquishLand( Entity::Player& player, HousingZone& zone, uint player.setLandFlags( Common::LandFlagsSlot::Private, 0x00, ident ); - player.sendLandFlagsSlot( Common::LandFlagsSlot::Private ); + sendLandFlagsSlot( player, Common::LandFlagsSlot::Private ); auto screenMsgPkt2 = makeActorControlSelf( player.getId(), ActorControl::LogMsg, 3351, 0x1AA, pLand->getLandIdent().wardNum + 1, plot + 1 ); - pSession->getZoneConnection()->queueOutPacket( screenMsgPkt2 ); + server.queueForPlayer( player.getCharacterId(), screenMsgPkt2 ); zone.sendLandUpdate( plot ); return true; @@ -537,7 +533,7 @@ void HousingMgr::sendWardLandInfo( Entity::Player& player, uint8_t wardId, uint1 // todo: check if estate allows public entry } - pSession->getZoneConnection()->queueOutPacket( wardInfoPacket ); + server.queueForPlayer( player.getCharacterId(), wardInfoPacket ); } void HousingMgr::sendEstateGreeting( Entity::Player& player, const Common::LandIdent ident ) @@ -566,8 +562,7 @@ void HousingMgr::sendEstateGreeting( Entity::Player& player, const Common::LandI auto greeting = house->getHouseGreeting(); memcpy( &greetingPacket->data().Greeting, greeting.c_str(), greeting.size() ); - auto pSession = server.getSession( player.getCharacterId() ); - pSession->getZoneConnection()->queueOutPacket( greetingPacket ); + server.queueForPlayer( player.getCharacterId(), greetingPacket ); } bool HousingMgr::initHouseModels( Entity::Player& player, LandPtr land, uint32_t presetCatalogId ) @@ -575,12 +570,6 @@ bool HousingMgr::initHouseModels( Entity::Player& player, LandPtr land, uint32_t auto house = land->getHouse(); assert( house ); - auto itemMax = land->getInventoryItemMax(); - - // type, maxSize, tableName, isMultiStorage - // auto intContainer = make_ItemContainer( Common::InventoryType::HousingInteriorAppearance, itemMax.second, "houseiteminventory", true ); - // auto extContainer = make_ItemContainer( Common::InventoryType::HousingExteriorAppearance, itemMax.first, "houseiteminventory", true ); - // add containers to inv collection auto& houseInventory = getEstateInventory( house->getLandIdent() ); houseInventory[ Common::InventoryType::HousingInteriorAppearance ];// = intContainer; @@ -724,7 +713,7 @@ void HousingMgr::buildPresetEstate( Entity::Player& player, HousingZone& zone, u auto pSuccessBuildingPacket = makeActorControl( player.getId(), ActorControl::BuildPresetResponse, plotNum ); - pSession->getZoneConnection()->queueOutPacket( pSuccessBuildingPacket ); + server.queueForPlayer( player.getCharacterId(), pSuccessBuildingPacket ); pLand->updateLandDb(); @@ -734,7 +723,7 @@ void HousingMgr::buildPresetEstate( Entity::Player& player, HousingZone& zone, u eventMgr.playScene( player, 0x000B0095, 0, static_cast< uint32_t >( SET_BASE | HIDE_HOTBAR ), { 1, plotNum } ); player.setLandFlags( Common::LandFlagsSlot::Private, Common::HOUSING_LAND_STATUS::HOUSING_LAND_STATUS_BUILDHOUSE, ident ); - player.sendLandFlagsSlot( Common::LandFlagsSlot::Private ); + sendLandFlagsSlot( player, Common::LandFlagsSlot::Private ); zone.registerEstateEntranceEObj( plotNum ); } @@ -763,7 +752,7 @@ void HousingMgr::requestEstateRename( Entity::Player& player, const Common::Land landRenamePacket->data().LandId = ident; memcpy( &landRenamePacket->data().Name, house->getHouseName().c_str(), 20 ); - pSession->getZoneConnection()->queueOutPacket( landRenamePacket ); + server.queueForPlayer( player.getCharacterId(), landRenamePacket ); } void HousingMgr::requestEstateEditGreeting( Entity::Player& player, const Common::LandIdent ident ) @@ -792,7 +781,7 @@ void HousingMgr::requestEstateEditGreeting( Entity::Player& player, const Common estateGreetingPacket->data().LandId = ident; memcpy( &estateGreetingPacket->data().Greeting, house->getHouseGreeting().c_str(), sizeof( estateGreetingPacket->data().Greeting ) ); - pSession->getZoneConnection()->queueOutPacket( estateGreetingPacket ); + server.queueForPlayer( player.getCharacterId(), estateGreetingPacket ); } void HousingMgr::updateEstateGreeting( Entity::Player& player, const Common::LandIdent ident, const std::string& greeting ) @@ -846,7 +835,7 @@ void HousingMgr::requestEstateEditGuestAccess( Entity::Player& player, const Com packet->data().LandId = ident; packet->data().Welcome = land->getSharing(); - pSession->getZoneConnection()->queueOutPacket( packet ); + server.queueForPlayer( player.getCharacterId(), packet ); } Common::LandIdent HousingMgr::clientTriggerParamsToLandIdent( uint32_t param11, uint32_t param12, bool use16bits ) const @@ -1083,7 +1072,7 @@ void HousingMgr::reqPlaceHousingItem( Entity::Player& player, uint16_t landId, u status = placeInteriorItem( player, item ); if( status ) - pSession->getZoneConnection()->queueOutPacket( makeActorControlSelf( player.getId(), 0x3f3 ) ); + server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), 0x3f3 ) ); else PlayerMgr::sendUrgent( player, "An internal error occurred when placing the item." ); } @@ -1362,7 +1351,7 @@ bool HousingMgr::moveInternalItem( Entity::Player& player, Common::LandIdent ide // send confirmation to player uint32_t param1 = static_cast< uint32_t >( ( ident.landId << 16 ) | containerId ); - pSession->getZoneConnection()->queueOutPacket( makeActorControlSelf( player.getId(), ActorControl::HousingItemMoveConfirm, param1, slotIdx ) ); + server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), ActorControl::HousingItemMoveConfirm, param1, slotIdx ) ); return true; } @@ -1397,8 +1386,7 @@ bool HousingMgr::moveExternalItem( Entity::Player& player, Common::LandIdent ide terri.updateYardObjectPos( player, slot, static_cast< uint16_t >( ident.landId ), *item ); uint32_t param1 = static_cast< uint32_t >( ( ident.landId << 16 ) | Common::InventoryType::HousingExteriorPlacedItems ); - pSession->getZoneConnection()->queueOutPacket( makeActorControlSelf( player.getId(), ActorControl::HousingItemMoveConfirm, param1, slot ) ); - + server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), ActorControl::HousingItemMoveConfirm, param1, slot ) ); return true; } @@ -1637,7 +1625,7 @@ void HousingMgr::reqEstateExteriorRemodel( Entity::Player& player, uint16_t plot invMgr.sendInventoryContainer( player, it->second ); auto pkt = makeActorControlSelf( player.getId(), Network::ActorControl::ShowEstateExternalAppearanceUI, plot ); - pSession->getZoneConnection()->queueOutPacket( pkt ); + server.queueForPlayer( player.getCharacterId(), pkt ); } @@ -1677,7 +1665,7 @@ void HousingMgr::reqEstateInteriorRemodel( Entity::Player& player ) invMgr.sendInventoryContainer( player, it->second ); auto pkt = makeActorControlSelf( player.getId(), Network::ActorControl::ShowEstateInternalAppearanceUI ); - pSession->getZoneConnection()->queueOutPacket( pkt ); + server.queueForPlayer( player.getCharacterId(), pkt ); } bool HousingMgr::hasPermission( Entity::Player& player, Sapphire::Land& land, uint32_t permission ) @@ -1722,7 +1710,7 @@ void HousingMgr::removeHouse( Entity::Player& player, uint16_t plot ) if( !hasPermission( player, *pLand, 0 ) ) { auto msgPkt = makeActorControlSelf( player.getId(), ActorControl::LogMsg, 3305, 0 ); - pSession->getZoneConnection()->queueOutPacket( msgPkt ); + server.queueForPlayer( player.getCharacterId(), msgPkt ); return; } @@ -1758,7 +1746,7 @@ void HousingMgr::removeHouse( Entity::Player& player, uint16_t plot ) invMgr.sendInventoryContainer( player, interiorContainer ); invMgr.saveHousingContainer( land->getLandIdent(), interiorContainer ); - for( auto entry : changedContainerSet ) + for( auto& entry : changedContainerSet ) { invMgr.sendInventoryContainer( player, entry.second ); invMgr.saveHousingContainer( land->getLandIdent(), entry.second ); @@ -1776,3 +1764,44 @@ void HousingMgr::removeHouse( Entity::Player& player, uint16_t plot ) terri->removeEstateEntranceEObj( plot ); return; } + +void HousingMgr::sendLandFlagsSlot( Entity::Player& player, Common::LandFlagsSlot slot ) +{ + auto& server = Common::Service< World::WorldServer >::ref(); + auto landFlags = makeZonePacket< FFXIVIpcCharaHousingLandData >( player.getId() ); + + Common::LandType type; + + switch( slot ) + { + case Common::LandFlagsSlot::Private: + type = Common::LandType::Private; + break; + + case Common::LandFlagsSlot::FreeCompany: + type = Common::LandType::FreeCompany; + break; + + default: + // todo: other/unsupported land types + return; + } + + auto landData = player.getCharaLandData( slot ); + landFlags->data().Index = static_cast< uint32_t >( type ); + landFlags->data().LandData.landId = landData.landId; + landFlags->data().LandData.landFlags = landData.landFlags; + + server.queueForPlayer( player.getCharacterId(), landFlags ); +} + +void HousingMgr::sendLandFlags( Entity::Player& player ) +{ + auto landFlags = makeZonePacket< FFXIVIpcCharaHousing >( player.getId() ); + + landFlags->data().FcLands = player.getCharaLandData( Common::LandFlagsSlot::FreeCompany ); + landFlags->data().CharaLands = player.getCharaLandData( Common::LandFlagsSlot::Private ); + + auto& server = Common::Service< World::WorldServer >::ref(); + server.queueForPlayer( player.getCharacterId(), landFlags ); +} \ No newline at end of file diff --git a/src/world/Manager/HousingMgr.h b/src/world/Manager/HousingMgr.h index 9d0da9b3..65c521e2 100644 --- a/src/world/Manager/HousingMgr.h +++ b/src/world/Manager/HousingMgr.h @@ -98,6 +98,8 @@ namespace Sapphire::World::Manager void sendEstateGreeting( Entity::Player& player, const Common::LandIdent ident ); + void sendLandFlagsSlot( Entity::Player& player, Common::LandFlagsSlot slot ); + void sendLandFlags( Entity::Player& player ); /*! * @brief Updates the cached models on a house from the relevant apperance inventories. * Does not send the subsequent update to clients. diff --git a/src/world/Manager/PlayerMgr.cpp b/src/world/Manager/PlayerMgr.cpp index 1d295b4d..bba89828 100644 --- a/src/world/Manager/PlayerMgr.cpp +++ b/src/world/Manager/PlayerMgr.cpp @@ -5,9 +5,12 @@ #include #include +#include #include #include +#include +#include #include "Script/ScriptMgr.h" #include "WorldServer.h" @@ -20,7 +23,9 @@ #include #include #include "Network/PacketWrappers/ActorControlTargetPacket.h" +#include "Network/PacketWrappers/InitZonePacket.h" #include +#include "Network/PacketWrappers/PlayerSetupPacket.h" #include #include #include "Network/PacketWrappers/ServerNoticePacket.h" @@ -132,11 +137,10 @@ void PlayerMgr::onSendStats( Entity::Player& player ) statParams[ row->data().PacketIndex ] = player.getStatValue( static_cast< Common::BaseParam >( id ) ); } - auto& server = Common::Service< World::WorldServer >::ref(); - auto statPacket = makeZonePacket< FFXIVIpcBaseParam >( player.getId() ); memcpy( statPacket->data().Param, statParams.data(), sizeof( uint32_t ) * statParams.size() ); + auto& server = Common::Service< World::WorldServer >::ref(); server.queueForPlayer( player.getCharacterId(), statPacket ); } @@ -317,7 +321,7 @@ void PlayerMgr::onLogin( Entity::Player &player ) std::string msg; while( std::getline( ss, msg, ';' ) ) { - PlayerMgr::sendServerNotice( player, msg ); + sendServerNotice( player, msg ); } } @@ -327,6 +331,93 @@ void PlayerMgr::onDeath( Entity::Player &player ) scriptMgr.onPlayerDeath( player ); } +void PlayerMgr::onZone( Sapphire::Entity::Player& player ) +{ + auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref(); + auto& housingMgr = Common::Service< HousingMgr >::ref(); + auto& partyMgr = Common::Service< World::Manager::PartyMgr >::ref(); + auto& server = Common::Service< World::WorldServer >::ref(); + + auto pZone = teriMgr.getTerritoryByGuId( player.getTerritoryId() ); + if( !pZone ) + { + Logger::error( "Territory GuID#{} not found!", player.getTerritoryId() ); + return; + } + auto& teri = *pZone; + + auto initPacket = makeZonePacket< FFXIVIpcLogin >( player.getId() ); + initPacket->data().playerActorId = player.getId(); + + server.queueForPlayer( player.getCharacterId(), initPacket ); + + player.sendInventory(); + + if( player.isLogin() ) + { + server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), SetCharaGearParamUI, player.getEquipDisplayFlags(), 1 ) ); + server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), SetMaxGearSets, player.getMaxGearSets() ) ); + } + + // set flags, will be reset automatically by zoning ( only on client side though ) + //setStateFlag( PlayerStateFlag::BetweenAreas ); + //setStateFlag( PlayerStateFlag::BetweenAreas1 ); + + if( player.hasReward( Common::UnlockEntry::HuntingLog ) ) + player.sendHuntingLog(); + + player.sendStats(); + + // only initialize the UI if the player in fact just logged in. + if( player.isLogin() ) + { + auto contentFinderList = makeZonePacket< FFXIVIpcContentAttainFlags >( player.getId() ); + std::memset( &contentFinderList->data(), 0xFF, sizeof( contentFinderList->data() ) ); + + server.queueForPlayer( player.getCharacterId(), { contentFinderList, makePlayerSetup( player ) } ); + + onPlayerStatusUpdate( player ); + + player.sendItemLevel(); + + player.clearSoldItems(); + } + + if( Sapphire::LandPtr pLand = housingMgr.getLandByOwnerId( player.getCharacterId() ) ) + { + uint32_t state = 0; + if( pLand->getHouse() ) + { + state |= Common::LandFlags::CHARA_HOUSING_LAND_DATA_FLAG_HOUSE; + + // todo: remove this, debug for now + state |= Common::LandFlags::CHARA_HOUSING_LAND_DATA_FLAG_AETHERYTE; + } + + player.setLandFlags( Common::LandFlagsSlot::Private, state, pLand->getLandIdent() ); + } + + housingMgr.sendLandFlags( player ); + + server.queueForPlayer( player.getCharacterId(), makeInitZone( player, teri ) ); + + teri.onPlayerZoneIn( player ); + + if( player.isLogin() ) + { + server.queueForPlayer( player.getCharacterId(), + { + makeZonePacket< FFXIVIpcQuestRepeatFlags >( player.getId() ), + makeZonePacket< FFXIVIpcDailyQuests >( player.getId() ) + } ); + } + + if( player.getPartyId() != 0 ) + { + partyMgr.onMoveZone( player ); + } + +} ////////// Helper /////////// diff --git a/src/world/Manager/PlayerMgr.h b/src/world/Manager/PlayerMgr.h index 15e686a9..d000f70c 100644 --- a/src/world/Manager/PlayerMgr.h +++ b/src/world/Manager/PlayerMgr.h @@ -56,6 +56,8 @@ class PlayerMgr void onDeath( Sapphire::Entity::Player& player ); + void onZone( Sapphire::Entity::Player& player ); + //////////// Helpers static void sendServerNotice( Sapphire::Entity::Player& player, const std::string& message ); diff --git a/src/world/Manager/TerritoryMgr.cpp b/src/world/Manager/TerritoryMgr.cpp index 708e4453..695e9c6b 100644 --- a/src/world/Manager/TerritoryMgr.cpp +++ b/src/world/Manager/TerritoryMgr.cpp @@ -15,6 +15,7 @@ #include "TerritoryMgr.h" #include "HousingMgr.h" #include "WarpMgr.h" +#include "PlayerMgr.h" #include "Linkshell/Linkshell.h" #include "Territory/Land.h" @@ -585,13 +586,9 @@ TerritoryMgr::InstanceIdList TerritoryMgr::getInstanceContentIdList( uint16_t in return idList; } -bool TerritoryMgr::movePlayer( const TerritoryPtr& pZone, Entity::Player& player ) +bool TerritoryMgr::movePlayer( Sapphire::Territory& teri, Entity::Player& player ) { - if( !pZone ) - { - Logger::error( "Territory not found on this server." ); - return false; - } + auto& playerMgr = Common::Service< Manager::PlayerMgr >::ref(); auto pPrevZone = getTerritoryByGuId( player.getTerritoryId() ); @@ -599,8 +596,8 @@ bool TerritoryMgr::movePlayer( const TerritoryPtr& pZone, Entity::Player& player player.initSpawnIdQueue(); - player.setTerritoryTypeId( pZone->getTerritoryTypeId() ); - player.setTerritoryId( pZone->getGuId() ); + player.setTerritoryTypeId( teri.getTerritoryTypeId() ); + player.setTerritoryId( teri.getGuId() ); bool playerLoaded = player.isLoadingComplete(); @@ -610,13 +607,13 @@ bool TerritoryMgr::movePlayer( const TerritoryPtr& pZone, Entity::Player& player if( playerLoaded && pPrevZone ) pPrevZone->removeActor( player.getAsPlayer() ); - pZone->pushActor( player.getAsPlayer() ); + teri.pushActor( player.getAsPlayer() ); // map player to instanceId so it can be tracked. - m_playerIdToInstanceMap[ player.getId() ] = pZone->getGuId(); + m_playerIdToInstanceMap[ player.getId() ] = teri.getGuId(); - pZone->onBeforePlayerZoneIn( player ); - player.sendZonePackets(); + teri.onBeforePlayerZoneIn( player ); + playerMgr.onZone( player ); return true; } @@ -712,7 +709,7 @@ bool TerritoryMgr::joinWorld( Entity::Player& player ) return false; } - if( !movePlayer( pCurrZone, player ) ) + if( !movePlayer( *pCurrZone, player ) ) return false; return true; diff --git a/src/world/Manager/TerritoryMgr.h b/src/world/Manager/TerritoryMgr.h index 4ccc58c6..6d9c8c21 100644 --- a/src/world/Manager/TerritoryMgr.h +++ b/src/world/Manager/TerritoryMgr.h @@ -16,6 +16,11 @@ namespace Sapphire::Data using InstanceContentPtr = std::shared_ptr< InstanceContent >; } +namespace Sapphire +{ + class Territory; +} + namespace Sapphire::World::Manager { /*! @@ -132,7 +137,7 @@ namespace Sapphire::World::Manager TODO: Mind multiple instances?! */ TerritoryPtr getZoneByTerritoryTypeId( uint32_t territoryTypeId ) const; - bool movePlayer( const TerritoryPtr&, Entity::Player& player ); + bool movePlayer( Sapphire::Territory& teri, Entity::Player& player ); /*! returns an instancePtr if the player is still bound to an isntance */ TerritoryPtr getLinkedInstance( uint32_t playerId ) const; diff --git a/src/world/Task/MoveTerritoryTask.cpp b/src/world/Task/MoveTerritoryTask.cpp index c0e20ffe..0b30dec5 100644 --- a/src/world/Task/MoveTerritoryTask.cpp +++ b/src/world/Task/MoveTerritoryTask.cpp @@ -39,13 +39,19 @@ void MoveTerritoryTask::execute() if( m_warpInfo.m_targetTerritoryId != 0 ) pZone = teriMgr.getTerritoryByGuId( m_warpInfo.m_targetTerritoryId ); - if( !teriMgr.movePlayer( pZone, *pPlayer ) ) + if( !pZone ) + { + Logger::error( "Territory typeId#{} not found!", m_warpInfo.m_targetTerritoryId ); + return; + } + + if( !teriMgr.movePlayer( *pZone, *pPlayer ) ) { // todo: this will require proper handling, for now just return the player to their previous area pPlayer->setPos( pPlayer->getPrevPos(), false ); auto pZone1 = teriMgr.getZoneByTerritoryTypeId( pPlayer->getPrevTerritoryTypeId() ); - if( !teriMgr.movePlayer( pZone1, *pPlayer ) ) + if( !teriMgr.movePlayer( *pZone1, *pPlayer ) ) return; } }