diff --git a/src/tools/quest_parser/main.cpp b/src/tools/quest_parser/main.cpp index 1f2371ba..2d72c88d 100644 --- a/src/tools/quest_parser/main.cpp +++ b/src/tools/quest_parser/main.cpp @@ -595,7 +595,7 @@ int main( int argc, char** argv ) { std::string entry( §ion[ offset ] ); - offset += entry.size() + 1; + offset += static_cast< uint32_t >( entry.size() + 1 ); if( entry.size() > 3 && entry.find_first_not_of( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_-" ) == diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 6808d6e6..2efaad7c 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -19,6 +19,7 @@ #include "Manager/RNGMgr.h" #include "Manager/PlayerMgr.h" #include "Manager/PartyMgr.h" +#include "Manager/WarpMgr.h" #include "Territory/Territory.h" #include "Territory/InstanceContent.h" @@ -86,7 +87,6 @@ Sapphire::Entity::Player::Player() : m_id = 0; m_currentStance = Stance::Passive; m_onlineStatus = 0; - m_queuedZoneing = nullptr; m_status = ActorStatus::Idle; m_invincibilityType = InvincibilityType::InvincibilityNone; m_radius = 1.f; @@ -402,7 +402,8 @@ void Sapphire::Entity::Player::sendStats() void Sapphire::Entity::Player::teleport( uint16_t aetheryteId, uint8_t type ) { auto& exdData = Common::Service< Data::ExdData >::ref(); - auto& terriMgr = Common::Service< TerritoryMgr >::ref(); + auto& teriMgr = Common::Service< TerritoryMgr >::ref(); + auto& warpMgr = Common::Service< WarpMgr >::ref(); auto aetherData = exdData.getRow< Excel::Aetheryte >( aetheryteId ); @@ -411,8 +412,6 @@ void Sapphire::Entity::Player::teleport( uint16_t aetheryteId, uint8_t type ) const auto& data = aetherData->data(); - setStateFlag( PlayerStateFlag::BetweenAreas ); - auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref(); auto pop = instanceObjectCache.getPopRange( data.TerritoryType, data.PopRange[ 0 ] ); @@ -441,35 +440,41 @@ void Sapphire::Entity::Player::teleport( uint16_t aetheryteId, uint8_t type ) aetherytePlace->getString( aetherytePlace->data().Text.SGL ), data.TerritoryType ); + // if it is a teleport in the same zone, we want to do warp instead of moveTerri + bool sameTerritory = getTerritoryTypeId() == data.TerritoryType; + + WarpType warpType; // TODO: this should be simplified and a type created in server_common/common.h. - if( type == 1 ) // teleport + if( type == 1 || type == 2 ) // teleport { - //prepareZoning( data.TerritoryType, true, 1, 0 ); // TODO: Really? - sendToInRangeSet( makeActorControl( getId(), WarpStart, Common::WarpType::WARP_TYPE_TELEPO ), true ); - sendToInRangeSet( makeActorControl( getId(), ActorDespawnEffect, 0x04 ) ); - setZoningType( Common::ZoneingType::Teleport ); - } - else if( type == 2 ) // aethernet - { - //prepareZoning( data.TerritoryType, true, 1, 112 ); - sendToInRangeSet( makeActorControl( getId(), WarpStart, Common::WarpType::WARP_TYPE_TELEPO ), true ); - sendToInRangeSet( makeActorControl( getId(), ActorDespawnEffect, 0x04 ) ); + warpType = WarpType::WARP_TYPE_TELEPO; setZoningType( Common::ZoneingType::Teleport ); } else if( type == 3 ) // return { - //prepareZoning( data.TerritoryType, true, 1, 111 ); - sendToInRangeSet( makeActorControl( getId(), WarpStart, Common::WarpType::WARP_TYPE_HOME_POINT ), true ); - sendToInRangeSet( makeActorControl( getId(), ActorDespawnEffect, 0x03 ) ); + warpType = WarpType::WARP_TYPE_HOME_POINT; setZoningType( Common::ZoneingType::Return ); } - m_queuedZoneing = std::make_shared< QueuedZoning >( data.TerritoryType, 0, pos, Util::getTimeMs(), rot ); + if( sameTerritory ) + warpMgr.requestWarp( *this, warpType, pos, rot ); + else + { + auto pTeri = teriMgr.getZoneByTerritoryTypeId( data.TerritoryType ); + if( !pTeri ) + return; + warpMgr.requestMoveTerritory( *this, warpType, pTeri->getGuId(), pos, rot ); + } } void Sapphire::Entity::Player::forceZoneing( uint32_t zoneId ) { - m_queuedZoneing = std::make_shared< QueuedZoning >( zoneId, 0, getPos(), Util::getTimeMs(), 0.f ); + auto& teriMgr = Common::Service< TerritoryMgr >::ref(); + auto& warpMgr = Common::Service< WarpMgr >::ref(); + auto pTeri = teriMgr.getZoneByTerritoryTypeId( zoneId ); + if( !pTeri ) + return; + warpMgr.requestMoveTerritory( *this, WarpType::WARP_TYPE_NORMAL, pTeri->getGuId(), getPos(), getRot() ); } void Sapphire::Entity::Player::performZoning( uint16_t territoryTypeId, uint32_t territoryId, const Common::FFXIVARR_POSITION3& pos, float rotation ) @@ -478,7 +483,7 @@ void Sapphire::Entity::Player::performZoning( uint16_t territoryTypeId, uint32_t setRot( rotation ); auto& teriMgr = Common::Service< TerritoryMgr >::ref(); - m_onEnterEventDone = false; + setOnEnterEventDone( false ); TerritoryPtr pZone; if( territoryId != 0 ) @@ -499,35 +504,10 @@ void Sapphire::Entity::Player::performZoning( uint16_t territoryTypeId, uint32_t } } -bool Sapphire::Entity::Player::setInstance( uint32_t territoryId, Common::FFXIVARR_POSITION3 pos ) -{ - auto& teriMgr = Common::Service< TerritoryMgr >::ref(); - auto instance = teriMgr.getTerritoryByGuId( territoryId ); - - m_onEnterEventDone = false; - if( !instance ) - return false; - - // zoning within the same zone won't cause the prev data to be overwritten - if( instance->getTerritoryTypeId() != m_territoryTypeId ) - { - auto pZone = teriMgr.getTerritoryByGuId( getTerritoryId() ); - m_prevTerritoryTypeId = pZone->getTerritoryTypeId(); - m_prevTerritoryId = getTerritoryId(); - m_prevPos = m_pos; - m_prevRot = m_rot; - } - - m_queuedZoneing = std::make_shared< QueuedZoning >( instance->getTerritoryTypeId(), territoryId, m_pos, Util::getTimeMs(), m_rot ); - - m_pos = pos; - return true; -} - bool Sapphire::Entity::Player::exitInstance() { auto& teriMgr = Common::Service< TerritoryMgr >::ref(); - auto pZone = teriMgr.getTerritoryByGuId( getTerritoryId() ); + auto& warpMgr = Common::Service< WarpMgr >::ref(); resetHp(); resetMp(); @@ -537,7 +517,7 @@ bool Sapphire::Entity::Player::exitInstance() m_territoryTypeId = m_prevTerritoryTypeId; m_territoryId = m_prevTerritoryId; - m_queuedZoneing = std::make_shared< QueuedZoning >( m_territoryTypeId, getTerritoryId(), m_pos, Util::getTimeMs(), m_rot ); + warpMgr.requestMoveTerritory( *this, WarpType::WARP_TYPE_CONTENT_END_RETURN, m_prevTerritoryId, m_prevPos, m_prevRot ); return true; } @@ -691,8 +671,9 @@ void Sapphire::Entity::Player::resetDiscovery() void Sapphire::Entity::Player::changePosition( float x, float y, float z, float o ) { + auto& warpMgr = Common::Service< WarpMgr >::ref(); Common::FFXIVARR_POSITION3 pos{ x, y, z }; - m_queuedZoneing = std::make_shared< QueuedZoning >( getTerritoryTypeId(), 0, pos, Util::getTimeMs(), o ); + warpMgr.requestWarp( *this, Common::WARP_TYPE_NORMAL, pos, getRot() ); } void Sapphire::Entity::Player::setSystemActionUnlocked( Common::UnlockEntry unlockId ) @@ -1046,24 +1027,6 @@ void Sapphire::Entity::Player::unsetStateFlag( Common::PlayerStateFlag flag ) void Sapphire::Entity::Player::update( uint64_t tickCount ) { - // a zoning is pending, lets do it - if( m_queuedZoneing && ( tickCount - m_queuedZoneing->m_queueTime ) > 800 ) - { - Common::FFXIVARR_POSITION3 targetPos = m_queuedZoneing->m_targetPosition; - if( getTerritoryTypeId() != m_queuedZoneing->m_targetTerritoryTypeId ) - { - Logger::debug( "{}_{}", m_queuedZoneing->m_targetTerritoryTypeId, m_queuedZoneing->m_targetTerritoryId ); - performZoning( m_queuedZoneing->m_targetTerritoryTypeId, m_queuedZoneing->m_targetTerritoryId, targetPos, m_queuedZoneing->m_targetRotation ); - } - else - { - setPos( targetPos ); - sendToInRangeSet( makeWarp( *this, WARP_TYPE_TELEPO, targetPos, m_queuedZoneing->m_targetRotation ), true ); - } - m_queuedZoneing.reset(); - return; - } - if( m_hp <= 0 && m_status != ActorStatus::Dead ) die(); @@ -2198,3 +2161,16 @@ void Sapphire::Entity::Player::setConnected( bool isConnected ) { m_bIsConnected = isConnected; } + +void Sapphire::Entity::Player::updatePrevTerritory() +{ + auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref(); + + if( teriMgr.isDefaultTerritory( getTerritoryTypeId() ) ) + { + m_prevTerritoryTypeId = getTerritoryTypeId(); + m_prevTerritoryId = getTerritoryId(); + m_prevPos = m_pos; + m_prevRot = m_rot; + } +} diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index fb32e16f..99c262f8 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -18,25 +18,6 @@ namespace Sapphire::Entity { - struct QueuedZoning - { - uint16_t m_targetTerritoryTypeId; - uint32_t m_targetTerritoryId; - Common::FFXIVARR_POSITION3 m_targetPosition; - float m_targetRotation; - uint64_t m_queueTime; - - QueuedZoning( uint16_t targetZone, uint32_t targetTerritoryId, const Common::FFXIVARR_POSITION3& targetPosition, - uint64_t queuedTime, float targetRotation ) : - m_targetTerritoryTypeId( targetZone ), - m_targetTerritoryId( targetTerritoryId ), - m_targetPosition( targetPosition ), - m_queueTime( queuedTime ), - m_targetRotation( targetRotation ) - { - } - }; - /** Class representing the Player * Inheriting from Actor * @@ -189,13 +170,13 @@ namespace Sapphire::Entity /*! return the current amount of crystals of type */ uint32_t getCrystal( uint8_t type ) const; - void updateModels( Common::GearSetSlot equipSlotId, const Sapphire::Item& item ); + void updateModels( Common::GearSetSlot equipSlotId, const Item& item ); Common::GearModelSlot equipSlotToModelSlot( Common::GearSetSlot slot ); bool getFreeInventoryContainerSlot( Inventory::InventoryContainerPair& containerPair ) const; - void insertInventoryItem( Common::InventoryType type, uint16_t slot, const Sapphire::ItemPtr item ); + void insertInventoryItem( Common::InventoryType type, uint16_t slot, const ItemPtr item ); /*! * Collect real item handins from container @@ -304,15 +285,14 @@ namespace Sapphire::Entity /*! return current online status depending on current state / activity */ Common::OnlineStatus getOnlineStatus() const; - /*! sets the players instance & initiates zoning process */ - bool setInstance( uint32_t territoryId, Sapphire::Common::FFXIVARR_POSITION3 pos ); - /*! returns the player to their position before zoning into an instance */ bool exitInstance(); /*! gets the players territoryTypeId */ uint32_t getPrevTerritoryTypeId() const; + void updatePrevTerritory(); + void forceZoneing( uint32_t zoneId ); /*! change position, sends update too */ @@ -625,7 +605,7 @@ namespace Sapphire::Entity const std::map< uint32_t, uint8_t >& getActorIdToHateSlotMap(); - Sapphire::Entity::GameObjectPtr lookupTargetById( uint64_t targetId ); + Entity::GameObjectPtr lookupTargetById( uint64_t targetId ); bool isLogin() const; @@ -730,7 +710,7 @@ namespace Sapphire::Entity InvSlotPair getFreeBagSlot(); - Sapphire::ItemPtr addItem( uint32_t catalogId, uint32_t quantity = 1, bool isHq = false, bool slient = false, bool canMerge = true ); + ItemPtr addItem( uint32_t catalogId, uint32_t quantity = 1, bool isHq = false, bool slient = false, bool canMerge = true ); void moveItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot ); @@ -781,7 +761,7 @@ namespace Sapphire::Entity void setActiveLand( uint8_t land, uint8_t ward ); Common::ActiveLand getActiveLand() const; - Sapphire::ItemPtr dropInventoryItem( Common::InventoryType storageId, uint8_t slotId ); + ItemPtr dropInventoryItem( Common::InventoryType storageId, uint8_t slotId ); ////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -823,7 +803,7 @@ namespace Sapphire::Entity /*! queue a packet for the player */ void queuePacket( Network::Packets::FFXIVPacketBasePtr pPacket ); - using InventoryMap = std::map< uint16_t, Sapphire::ItemContainerPtr >; + using InventoryMap = std::map< uint16_t, ItemContainerPtr >; uint64_t m_lastDBWrite; @@ -928,7 +908,6 @@ namespace Sapphire::Entity bool m_bNewAdventurer{}; uint64_t m_onlineStatus; uint64_t m_onlineStatusCustom; - std::shared_ptr< QueuedZoning > m_queuedZoneing; // search info char m_searchMessage[193]{}; // searchmessage to show in profile diff --git a/src/world/Manager/TerritoryMgr.cpp b/src/world/Manager/TerritoryMgr.cpp index 1e42999e..058f44af 100644 --- a/src/world/Manager/TerritoryMgr.cpp +++ b/src/world/Manager/TerritoryMgr.cpp @@ -15,7 +15,7 @@ #include "Territory/QuestBattle.h" #include "TerritoryMgr.h" #include "HousingMgr.h" - +#include "WarpMgr.h" #include "Linkshell/Linkshell.h" #include "Territory/Land.h" @@ -658,8 +658,8 @@ void TerritoryMgr::createAndJoinQuestBattle( Entity::Player& player, uint16_t qu if( !qb ) return; - //player.setInstance( qb->getGuId(), { 0, 0, 0 } ); - + auto& warpMgr = Common::Service< WarpMgr >::ref(); + warpMgr.requestMoveTerritory( player, Common::WARP_TYPE_INSTANCE_CONTENT, qb->getGuId(), { 0, 0, 0 }, 0 ); } bool TerritoryMgr::joinWorld( Entity::Player& player ) diff --git a/src/world/Manager/WarpMgr.cpp b/src/world/Manager/WarpMgr.cpp index 451374ff..beca7fe3 100644 --- a/src/world/Manager/WarpMgr.cpp +++ b/src/world/Manager/WarpMgr.cpp @@ -3,6 +3,76 @@ #include "TaskMgr.h" #include "WarpMgr.h" +#include "TerritoryMgr.h" + +#include + +#include "Task/MoveTerritoryTask.h" +#include "Task/WarpTask.h" +#include +#include "Territory/Territory.h" +#include "Network/PacketWrappers/ActorControlSelfPacket.h" +#include "Network/PacketWrappers/ActorControlPacket.h" +#include "Network/PacketWrappers/WarpPacket.h" +#include "Actor/Player.h" using namespace Sapphire::World::Manager; using namespace Sapphire::World; +using namespace Sapphire; +using namespace Sapphire::Common; +using namespace Sapphire::Network::ActorControl; +using namespace Sapphire::Network::Packets; +using namespace Sapphire::Network::Packets::WorldPackets::Server; + +void WarpMgr::requestMoveTerritory( Entity::Player& player, Common::WarpType warpType, + uint32_t targetTerritoryId, Common::FFXIVARR_POSITION3 targetPos, float targetRot ) +{ + m_entityIdToWarpInfoMap[ player.getId() ] = { targetTerritoryId, warpType, targetPos, targetRot }; + + auto& teriMgr = Common::Service< TerritoryMgr >::ref(); + auto& server = Common::Service< WorldServer >::ref(); + + auto pTeri = teriMgr.getTerritoryByGuId( targetTerritoryId ); + if( !pTeri ) + return; + + player.updatePrevTerritory(); + + player.sendToInRangeSet( makeActorControl( player.getId(), WarpStart, warpType, 1, pTeri->getTerritoryTypeId() ), true ); + player.sendToInRangeSet( makeActorControl( player.getId(), ActorDespawnEffect, warpType ) ); + player.setStateFlag( PlayerStateFlag::BetweenAreas ); + + auto moveTerritoryPacket = makeZonePacket< FFXIVIpcMoveTerritory >( player.getId() ); + moveTerritoryPacket->data().index = -1; + moveTerritoryPacket->data().territoryType = pTeri->getTerritoryTypeId(); + moveTerritoryPacket->data().zoneId = player.getTerritoryTypeId(); + moveTerritoryPacket->data().worldId = server.getWorldId(); + moveTerritoryPacket->data().worldId1 = server.getWorldId(); + moveTerritoryPacket->data().landId = -1; + moveTerritoryPacket->data().landSetId = -1; + moveTerritoryPacket->data().landTerritoryId = -1; + strcpy( moveTerritoryPacket->data().worldName, "Sapphire" ); + server.queueForPlayer( player.getCharacterId(), moveTerritoryPacket ); + + // create warp task + auto& taskMgr = Common::Service< TaskMgr >::ref(); + taskMgr.queueTask( makeMoveTerritoryTask( player, warpType, targetTerritoryId, targetPos, targetRot, 2000 ) ); +} + +void WarpMgr::finishWarp( Entity::Player& player ) +{ + +} + +void WarpMgr::requestWarp( Entity::Player& player, Common::WarpType warpType, Common::FFXIVARR_POSITION3 targetPos, float targetRot ) +{ + m_entityIdToWarpInfoMap[ player.getId() ] = { 0, warpType, targetPos, targetRot }; + auto& teriMgr = Common::Service< TerritoryMgr >::ref(); + auto& server = Common::Service< WorldServer >::ref(); + + player.sendToInRangeSet( makeActorControl( player.getId(), WarpStart, warpType, 1, player.getTerritoryTypeId(), 1 ), true ); + player.sendToInRangeSet( makeActorControl( player.getId(), ActorDespawnEffect, warpType ) ); + + auto& taskMgr = Common::Service< TaskMgr >::ref(); + taskMgr.queueTask( makeWarpTask( player, warpType, targetPos, targetRot, 1000 ) ); +} diff --git a/src/world/Manager/WarpMgr.h b/src/world/Manager/WarpMgr.h index 5964dac6..7b05b812 100644 --- a/src/world/Manager/WarpMgr.h +++ b/src/world/Manager/WarpMgr.h @@ -11,17 +11,22 @@ namespace Sapphire::World::Manager struct WarpInfo { - uint32_t targetTerritoryId; + uint32_t m_targetTerritoryId; Common::WarpType m_warpType; + Common::FFXIVARR_POSITION3 m_targetPos; + float m_targetRot; }; class WarpMgr { public: WarpMgr() = default; + void requestMoveTerritory( Entity::Player& player, Common::WarpType warpType, uint32_t targetTerritoryId, Common::FFXIVARR_POSITION3 targetPos, float targetRot ); + void requestWarp( Entity::Player& player, Common::WarpType warpType, Common::FFXIVARR_POSITION3 targetPos, float targetRot ); + void finishWarp( Entity::Player& player ); private: - std::unordered_map< uint32_t, std::shared_ptr< WarpInfo > > m_entityIdToWarpInfoMap; + std::unordered_map< uint32_t, WarpInfo > m_entityIdToWarpInfoMap; }; diff --git a/src/world/Network/Handlers/GMCommandHandlers.cpp b/src/world/Network/Handlers/GMCommandHandlers.cpp index a9af4df6..56d197e6 100644 --- a/src/world/Network/Handlers/GMCommandHandlers.cpp +++ b/src/world/Network/Handlers/GMCommandHandlers.cpp @@ -14,6 +14,7 @@ #include "Manager/TerritoryMgr.h" #include "Manager/PlayerMgr.h" +#include "Manager/WarpMgr.h" #include "Territory/Territory.h" #include "Territory/InstanceContent.h" @@ -471,6 +472,7 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR case GmCommand::Teri: { auto& teriMgr = Common::Service< TerritoryMgr >::ref(); + auto& warpMgr = Common::Service< WarpMgr >::ref(); if( auto instance = teriMgr.getTerritoryByGuId( param1 ) ) { PlayerMgr::sendDebug( player, "Found instance: {0}, id#{1}", instance->getName(), param1 ); @@ -485,8 +487,7 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR PlayerMgr::sendUrgent( player, "Player not bound! ( run !instance bind first ) {0}", param1 ); break; } - - player.setInstance( param1, { 0, 0, 0 } ); + warpMgr.requestMoveTerritory( player, WarpType::WARP_TYPE_INSTANCE_CONTENT, param1, { 0.f, 0.f, 0.f }, 0.f ); } else if( !teriMgr.isValidTerritory( param1 ) ) { diff --git a/src/world/Network/Handlers/PacketHandlers.cpp b/src/world/Network/Handlers/PacketHandlers.cpp index 42be9069..db84ce36 100644 --- a/src/world/Network/Handlers/PacketHandlers.cpp +++ b/src/world/Network/Handlers/PacketHandlers.cpp @@ -50,6 +50,7 @@ #include "Manager/LinkshellMgr.h" #include "Manager/PartyMgr.h" #include "Manager/PlayerMgr.h" +#include "Manager/WarpMgr.h" #include "Action/Action.h" @@ -337,27 +338,17 @@ void Sapphire::Network::GameConnection::zoneJumpHandler( const Packets::FFXIVARR pPopRange->header.transform.rotation.z, rotation ); - server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), WarpStart, - Common::WarpType::WARP_TYPE_EXIT_RANGE, player.getId(), 0x01, targetZone ) ); - - auto moveTerritoryPacket = makeZonePacket< FFXIVIpcMoveTerritory >( player.getId() ); - moveTerritoryPacket->data().index = -1; - moveTerritoryPacket->data().territoryType = targetZone; - moveTerritoryPacket->data().zoneId = player.getTerritoryTypeId(); - moveTerritoryPacket->data().worldId = server.getWorldId(); - moveTerritoryPacket->data().worldId1 = server.getWorldId(); - moveTerritoryPacket->data().landId = -1; - moveTerritoryPacket->data().landSetId = -1; - moveTerritoryPacket->data().landTerritoryId = -1; - strcpy( moveTerritoryPacket->data().worldName, "Sapphire" ); - server.queueForPlayer( player.getCharacterId(), moveTerritoryPacket ); - } } PlayerMgr::sendDebug( player, "Walking ZoneLine#{0}", exitBoxId ); + auto pTargetTeri = teriMgr.getZoneByTerritoryTypeId( targetZone ); + if( !pTargetTeri ) + return; + + auto& warpMgr = Common::Service< WarpMgr >::ref(); + warpMgr.requestMoveTerritory( player, Common::WARP_TYPE_EXIT_RANGE, pTargetTeri->getGuId(), targetPos, rotation ); - player.performZoning( targetZone, 0, targetPos, rotation ); } diff --git a/src/world/Network/PacketWrappers/WarpPacket.h b/src/world/Network/PacketWrappers/WarpPacket.h index c375dfe6..8162d92f 100644 --- a/src/world/Network/PacketWrappers/WarpPacket.h +++ b/src/world/Network/PacketWrappers/WarpPacket.h @@ -6,6 +6,7 @@ #include #include #include +#include namespace Sapphire::Network::Packets::WorldPackets::Server { @@ -16,14 +17,14 @@ namespace Sapphire::Network::Packets::WorldPackets::Server class WarpPacket : public ZoneChannelPacket< FFXIVIpcWarp > { public: - WarpPacket( Entity::Player& player, Common::WarpType warpType, Common::FFXIVARR_POSITION3& targetPos, float rotation ) : - ZoneChannelPacket< FFXIVIpcWarp >( player.getId(), player.getId() ) + WarpPacket( uint32_t playerId, Common::WarpType warpType, Common::FFXIVARR_POSITION3& targetPos, float rotation ) : + ZoneChannelPacket< FFXIVIpcWarp >( playerId, playerId ) { - initialize( player, warpType, targetPos, rotation ); + initialize( warpType, targetPos, rotation ); }; private: - void initialize( Entity::Player& player, Common::WarpType warpType, Common::FFXIVARR_POSITION3& targetPos, float rotation ) + void initialize( Common::WarpType warpType, Common::FFXIVARR_POSITION3& targetPos, float rotation ) { m_data.Dir = Sapphire::Common::Util::floatToUInt16Rot( rotation ); m_data.Type = warpType; diff --git a/src/world/Task/MoveTerritoryTask.cpp b/src/world/Task/MoveTerritoryTask.cpp new file mode 100644 index 00000000..c0e20ffe --- /dev/null +++ b/src/world/Task/MoveTerritoryTask.cpp @@ -0,0 +1,58 @@ +#include "MoveTerritoryTask.h" + +#include +#include +#include +#include + +#include + +using namespace Sapphire::World; +using namespace Sapphire::World::Manager; + +MoveTerritoryTask::MoveTerritoryTask( Entity::Player& player, Common::WarpType warpType, + uint32_t targetTerritoryId, Common::FFXIVARR_POSITION3 targetPos, float targetRot, uint64_t delayTime ) : Task( delayTime ) +{ + m_playerId = player.getId(); + m_warpInfo = { targetTerritoryId, warpType, targetPos, targetRot }; +} + +void MoveTerritoryTask::onQueue() +{ + Logger::debug( { __FUNCTION__ } ); +} + +void MoveTerritoryTask::execute() +{ + auto& server = Common::Service< WorldServer >::ref(); + auto pPlayer = server.getPlayer( m_playerId ); + if( !pPlayer ) + return; + + pPlayer->setPos( m_warpInfo.m_targetPos, false ); + pPlayer->setRot( m_warpInfo.m_targetRot ); + + auto& teriMgr = Common::Service< TerritoryMgr >::ref(); + pPlayer->setOnEnterEventDone( false ); + + TerritoryPtr pZone; + if( m_warpInfo.m_targetTerritoryId != 0 ) + pZone = teriMgr.getTerritoryByGuId( m_warpInfo.m_targetTerritoryId ); + + 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 ) ) + return; + } +} + +std::string MoveTerritoryTask::toString() +{ + return fmt::format( "MoveTerritoryTask: Player#{}, TerritoryId#{}, ElapsedTimeMs: {}", m_playerId, m_warpInfo.m_targetTerritoryId, getDelayTimeMs() ); +} + + diff --git a/src/world/Task/MoveTerritoryTask.h b/src/world/Task/MoveTerritoryTask.h new file mode 100644 index 00000000..b7d88b12 --- /dev/null +++ b/src/world/Task/MoveTerritoryTask.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include +#include "Task.h" +#include "Manager/WarpMgr.h" + +namespace Sapphire::World +{ + +class MoveTerritoryTask : public Task +{ +public: + MoveTerritoryTask( Entity::Player& player, Common::WarpType warpType, + uint32_t targetTerritoryId, Common::FFXIVARR_POSITION3 targetPos, float targetRot, uint64_t delayTime ); + + void onQueue() override; + void execute() override; + std::string toString() override; + +private: + Manager::WarpInfo m_warpInfo; + uint32_t m_playerId; + +}; + +template< typename... Args > +std::shared_ptr< MoveTerritoryTask > makeMoveTerritoryTask( Args... args ) +{ + return std::make_shared< MoveTerritoryTask >( args... ); +} + +} diff --git a/src/world/Task/WarpTask.cpp b/src/world/Task/WarpTask.cpp new file mode 100644 index 00000000..c0c33a42 --- /dev/null +++ b/src/world/Task/WarpTask.cpp @@ -0,0 +1,44 @@ +#include "WarpTask.h" + +#include +#include +#include +#include +#include + +#include + +using namespace Sapphire::World; +using namespace Sapphire::World::Manager; +using namespace Sapphire::Network::Packets; +using namespace Sapphire::Network::Packets::WorldPackets::Server; + +WarpTask::WarpTask( Entity::Player& player, Common::WarpType warpType, + Common::FFXIVARR_POSITION3 targetPos, float targetRot, uint64_t delayTime ) : Task( delayTime ) +{ + m_playerId = player.getId(); + m_warpInfo = { 0, warpType, targetPos, targetRot }; +} + +void WarpTask::onQueue() +{ + Logger::debug( { __FUNCTION__ } ); +} + +void WarpTask::execute() +{ + auto& server = Common::Service< WorldServer >::ref(); + auto pPlayer = server.getPlayer( m_playerId ); + if( !pPlayer ) + return; + + pPlayer->setPos( m_warpInfo.m_targetPos, false ); + pPlayer->sendToInRangeSet( makeWarp( pPlayer->getId(), m_warpInfo.m_warpType, m_warpInfo.m_targetPos, m_warpInfo.m_targetRot ), true ); +} + +std::string WarpTask::toString() +{ + return fmt::format( "WarpTask: Player#{}, TerritoryId#{}, ElapsedTimeMs: {}", m_playerId, m_warpInfo.m_targetTerritoryId, getDelayTimeMs() ); +} + + diff --git a/src/world/Task/WarpTask.h b/src/world/Task/WarpTask.h new file mode 100644 index 00000000..512bccb9 --- /dev/null +++ b/src/world/Task/WarpTask.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include +#include "Task.h" +#include "Manager/WarpMgr.h" + +namespace Sapphire::World +{ + +class WarpTask : public Task +{ +public: + WarpTask( Entity::Player& player, Common::WarpType warpType, + Common::FFXIVARR_POSITION3 targetPos, float targetRot, uint64_t delayTime ); + + void onQueue() override; + void execute() override; + std::string toString() override; + +private: + Manager::WarpInfo m_warpInfo; + uint32_t m_playerId; + +}; + +template< typename... Args > +std::shared_ptr< WarpTask > makeWarpTask( Args... args ) +{ + return std::make_shared< WarpTask >( args... ); +} + +} diff --git a/src/world/WorldServer.cpp b/src/world/WorldServer.cpp index 8a5f8059..56d190e8 100644 --- a/src/world/WorldServer.cpp +++ b/src/world/WorldServer.cpp @@ -47,6 +47,7 @@ #include "Manager/PartyMgr.h" #include "Manager/FriendListMgr.h" #include "Manager/BlacklistMgr.h" +#include "Manager/WarpMgr.h" #include "ContentFinder/ContentFinder.h" @@ -247,6 +248,7 @@ void WorldServer::run( int32_t argc, char* argv[] ) auto pBlacklistMgr = std::make_shared< Manager::BlacklistMgr >(); auto contentFinder = std::make_shared< ContentFinder >(); auto taskMgr = std::make_shared< Manager::TaskMgr >(); + auto warpMgr = std::make_shared< Manager::WarpMgr >(); Common::Service< DebugCommandMgr >::set( pDebugCom ); Common::Service< Manager::PlayerMgr >::set( pPlayerMgr ); @@ -260,6 +262,7 @@ void WorldServer::run( int32_t argc, char* argv[] ) Common::Service< Manager::BlacklistMgr >::set( pBlacklistMgr ); Common::Service< ContentFinder >::set( contentFinder ); Common::Service< Manager::TaskMgr >::set( taskMgr ); + Common::Service< Manager::WarpMgr >::set( warpMgr ); Logger::info( "World server running on {0}:{1}", m_ip, m_port );