From 85501effedef0e0040905912152758232a9d8827 Mon Sep 17 00:00:00 2001 From: Mordred Date: Thu, 16 Feb 2023 08:24:39 +0100 Subject: [PATCH] Implemented a basic actionintegrity implementation, subject to be changed. Fixed replay packet sending. --- src/common/Network/CommonActorControl.h | 5 +- src/common/Network/GamePacket.h | 2 +- src/world/Action/EffectBuilder.cpp | 17 +++-- src/world/Actor/BNpc.cpp | 7 +- src/world/Actor/Chara.cpp | 4 +- src/world/Actor/GameObject.cpp | 12 ++++ src/world/Actor/GameObject.h | 2 + src/world/Actor/Player.cpp | 9 ++- src/world/Manager/DebugCommandMgr.cpp | 2 +- src/world/Manager/PlayerMgr.cpp | 6 +- .../Network/PacketWrappers/EffectPacket1.h | 5 ++ src/world/Session.cpp | 13 ++-- src/world/Task/ActionIntegrityTask.cpp | 65 +++++++++++++++++++ src/world/Task/ActionIntegrityTask.h | 31 +++++++++ src/world/Territory/Territory.cpp | 2 +- src/world/Territory/Territory.h | 2 +- 16 files changed, 160 insertions(+), 24 deletions(-) create mode 100644 src/world/Task/ActionIntegrityTask.cpp create mode 100644 src/world/Task/ActionIntegrityTask.h diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index 35cd5b7a..ade46b22 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -276,13 +276,14 @@ namespace Sapphire::Network::ActorControl HuntingLogSectionFinish = 0x21F, HuntingLogRankFinish = 0x220, - SetMaxGearSets = 0x320, - SetCharaGearParamUI = 0x260, + + SetConfigFlags = 0x260, ToggleWireframeRendering = 0x261, ExamineError = 0x2BF, + SetMaxGearSets = 0x320, GearSetEquipMsg = 0x321, SetBait = 0x325, // param1: bait ID diff --git a/src/common/Network/GamePacket.h b/src/common/Network/GamePacket.h index d74a5e93..589fa4a3 100644 --- a/src/common/Network/GamePacket.h +++ b/src/common/Network/GamePacket.h @@ -144,7 +144,7 @@ namespace Sapphire::Network::Packets */ void setSize( std::size_t packetSize ) { - m_segHdr.size = packetSize; + m_segHdr.size = static_cast< uint32_t >( packetSize ); } /** diff --git a/src/world/Action/EffectBuilder.cpp b/src/world/Action/EffectBuilder.cpp index b817e630..87a4e9b3 100644 --- a/src/world/Action/EffectBuilder.cpp +++ b/src/world/Action/EffectBuilder.cpp @@ -15,6 +15,9 @@ #include #include +#include +#include + using namespace Sapphire; using namespace Sapphire::World::Action; using namespace Sapphire::Network::Packets; @@ -110,7 +113,7 @@ void EffectBuilder::buildAndSendPackets( const std::vector< Entity::CharaPtr >& auto& teriMgr = Common::Service< Sapphire::World::Manager::TerritoryMgr >::ref(); auto zone = teriMgr.getZoneByTerritoryTypeId( m_sourceChara->getTerritoryTypeId() ); - auto globalSequence = zone ? zone->getNextEffectSequence() : 0; + auto globalSequence = zone ? zone->getNextEffectResultId() : 0; do // we want to send at least one packet even nothing is hit so other players can see { @@ -125,13 +128,13 @@ std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( const s auto remainingTargetCount = targetList.size(); auto& teriMgr = Common::Service< Sapphire::World::Manager::TerritoryMgr >::ref(); auto zone = teriMgr.getTerritoryByGuId( m_sourceChara->getTerritoryId() ); - auto globalSequence = zone->getNextEffectSequence(); + auto resultId = zone->getNextEffectResultId(); if( remainingTargetCount > 1 ) // use AoeEffect packets { auto effectPacket = std::make_shared< EffectPacket >( m_sourceChara->getId(), m_actionId ); effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) ); - effectPacket->setSequence( globalSequence, m_sequence ); + effectPacket->setSequence( resultId, m_sequence ); effectPacket->setTargetActor( targetList[ 0 ]->getId() ); uint8_t targetIndex = 0; @@ -153,6 +156,8 @@ std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( const s else { effectPacket->addTargetEffect( effect, result->getTarget()->getId() ); + auto& taskMgr = Common::Service< World::Manager::TaskMgr >::ref(); + taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( resultId, result->getTarget(), 1000 ) ); } zone->addEffectResult( std::move( result ) ); @@ -177,7 +182,7 @@ std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( const s auto effectPacket = std::make_shared< EffectPacket1 >( m_sourceChara->getId(), targetList[ 0 ]->getId(), m_actionId ); effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) ); - effectPacket->setSequence( globalSequence, m_sequence ); + effectPacket->setSequence( resultId, m_sequence ); for( auto it = m_actorEffectsMap.begin(); it != m_actorEffectsMap.end(); ) { @@ -197,6 +202,8 @@ std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( const s else { effectPacket->addTargetEffect( effect ); + auto& taskMgr = Common::Service< World::Manager::TaskMgr >::ref(); + taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( resultId, result->getTarget(), 1000 ) ); } zone->addEffectResult( std::move( result ) ); @@ -221,7 +228,7 @@ std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( const s effectPacket->data().DirTarget = Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ); effectPacket->data().Flag = Common::ActionEffectDisplayType::HideActionName; effectPacket->data().RequestId = m_sequence; - effectPacket->data().ResultId = globalSequence; + effectPacket->data().ResultId = resultId; m_actorEffectsMap.clear(); diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 954d036d..f682502e 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include using namespace Sapphire::Common; @@ -995,13 +996,17 @@ void Sapphire::Entity::BNpc::autoAttack( CharaPtr pTarget ) effectEntry.Arg0 = 3; effectEntry.Arg1 = 7; //effectEntry.Arg2 = 0x71; - effectPacket->setSequence( pZone->getNextEffectSequence() ); + auto resultId = pZone->getNextEffectResultId(); + effectPacket->setSequence( resultId ); effectPacket->addTargetEffect( effectEntry ); sendToInRangeSet( effectPacket ); pTarget->takeDamage( static_cast< uint16_t >( damage.first ) ); + auto& taskMgr = Common::Service< World::Manager::TaskMgr >::ref(); + taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( resultId, pTarget, 500 ) ); + } } diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index 51f8533e..524896d4 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -407,8 +407,6 @@ void Sapphire::Entity::Chara::takeDamage( uint32_t damage ) } else m_hp -= damage; - - sendStatusUpdate(); } /*! @@ -521,7 +519,7 @@ void Sapphire::Entity::Chara::addStatusEffect( StatusEffect::StatusEffectPtr pEf auto statusEffectAdd = makeZonePacket< FFXIVIpcActionIntegrity >( getId() ); - statusEffectAdd->data().ResultId = pZone->getNextEffectSequence(); + statusEffectAdd->data().ResultId = pZone->getNextEffectResultId(); statusEffectAdd->data().Target = pEffect->getTargetActorId(); statusEffectAdd->data().Hp = getHp(); statusEffectAdd->data().Mp = static_cast< uint16_t >( getMp() ); diff --git a/src/world/Actor/GameObject.cpp b/src/world/Actor/GameObject.cpp index fba59b34..b5778716 100644 --- a/src/world/Actor/GameObject.cpp +++ b/src/world/Actor/GameObject.cpp @@ -336,6 +336,18 @@ std::set< Sapphire::Entity::GameObjectPtr > Sapphire::Entity::GameObject::getInR return tempInRange; } +std::set< uint64_t > Sapphire::Entity::GameObject::getInRangePlayerIds( bool includeSelf ) +{ + std::set< uint64_t > playerIds; + for( auto& player : m_inRangePlayers ) + playerIds.insert( player->getCharacterId() ); + + if( isPlayer() && includeSelf ) + playerIds.insert( getAsPlayer()->getCharacterId() ); + + return playerIds; +} + uint32_t Sapphire::Entity::GameObject::getTerritoryTypeId() const { return m_territoryTypeId; diff --git a/src/world/Actor/GameObject.h b/src/world/Actor/GameObject.h index c8bc03e4..bc2d6203 100644 --- a/src/world/Actor/GameObject.h +++ b/src/world/Actor/GameObject.h @@ -111,6 +111,8 @@ namespace Sapphire::Entity std::set< GameObjectPtr > getInRangeActors( bool includeSelf = false ); + std::set< uint64_t > getInRangePlayerIds( bool includeSelf = false ); + //////////////////////////////////////////////////// CharaPtr getAsChara(); diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index d852f4c1..6f9d7fe3 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -44,6 +44,9 @@ #include "WorldServer.h" +#include +#include + using namespace Sapphire; using namespace Sapphire::Common; using namespace Sapphire::Network::Packets; @@ -1327,7 +1330,8 @@ void Player::autoAttack( CharaPtr pTarget ) //entry.Arg2 = 0x73; } - effectPacket->setSequence( pZone->getNextEffectSequence() ); + auto resultId = pZone->getNextEffectResultId(); + effectPacket->setResultId( resultId ); effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) ); effectPacket->addTargetEffect( entry ); @@ -1335,6 +1339,9 @@ void Player::autoAttack( CharaPtr pTarget ) sendToInRangeSet( effectPacket, true ); pTarget->takeDamage( static_cast< uint32_t >( damage.first ) ); + + auto& taskMgr = Common::Service< TaskMgr >::ref(); + taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( resultId, pTarget, 500 ) ); } diff --git a/src/world/Manager/DebugCommandMgr.cpp b/src/world/Manager/DebugCommandMgr.cpp index 6316f94c..4ff1ec2b 100644 --- a/src/world/Manager/DebugCommandMgr.cpp +++ b/src/world/Manager/DebugCommandMgr.cpp @@ -544,7 +544,7 @@ void DebugCommandMgr::add( char* data, Entity::Player& player, std::shared_ptr< effectPacket->addTargetEffect( entry, static_cast< uint64_t >( player.getId() ) ); - auto sequence = pCurrentZone->getNextEffectSequence(); + auto sequence = pCurrentZone->getNextEffectResultId(); effectPacket->setSequence( sequence ); // effectPacket->setAnimationId( param1 ); diff --git a/src/world/Manager/PlayerMgr.cpp b/src/world/Manager/PlayerMgr.cpp index acba59ad..598ae8a4 100644 --- a/src/world/Manager/PlayerMgr.cpp +++ b/src/world/Manager/PlayerMgr.cpp @@ -417,7 +417,7 @@ void PlayerMgr::onZone( Sapphire::Entity::Player& player ) server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), 0x16F, 5 ) ); // SalvageSkill server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), 0x16F, 6 ) ); // SalvageSkill server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), 0x16F, 7 ) ); // SalvageSkill - server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), SetCharaGearParamUI, player.getEquipDisplayFlags(), 1 ) ); + server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), SetConfigFlags, player.getEquipDisplayFlags(), 1 ) ); server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), SetMaxGearSets, player.getMaxGearSets() ) ); } @@ -425,13 +425,11 @@ void PlayerMgr::onZone( Sapphire::Entity::Player& player ) //setStateFlag( PlayerStateFlag::BetweenAreas ); //setStateFlag( PlayerStateFlag::BetweenAreas1 ); - if( player.hasReward( Common::UnlockEntry::HuntingLog ) ) - player.sendHuntingLog(); + player.sendHuntingLog(); if( player.isLogin() ) { player.sendItemLevel(); - server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), 0x39, 0 ) ); // unknown server.queueForPlayer( player.getCharacterId(), makePlayerSetup( player ) ); } diff --git a/src/world/Network/PacketWrappers/EffectPacket1.h b/src/world/Network/PacketWrappers/EffectPacket1.h index 67d467d7..c2279211 100644 --- a/src/world/Network/PacketWrappers/EffectPacket1.h +++ b/src/world/Network/PacketWrappers/EffectPacket1.h @@ -74,6 +74,11 @@ namespace Sapphire::Network::Packets::WorldPackets::Server m_data.ResultId = static_cast< uint32_t>( sequence ); } + void setResultId( uint32_t resultId ) + { + m_data.ResultId = static_cast< uint32_t>( resultId ); + } + private: uint8_t m_targetEffectCount{ 0 }; uint8_t m_sourceEffectCount{ 0 }; diff --git a/src/world/Session.cpp b/src/world/Session.cpp index 6f9ef99a..f4d9c947 100644 --- a/src/world/Session.cpp +++ b/src/world/Session.cpp @@ -149,9 +149,10 @@ void Sapphire::World::Session::startReplay( const std::string& path ) for( auto set : loadedSets ) { - m_replayCache.emplace_back( Common::Util::getTimeMs() + ( std::get< 0 >( set ) - startTime ), std::get< 1 >( set ) ); + uint64_t setTime = std::get< 0 >( set ); + m_replayCache.emplace_back( Common::Util::getTimeMs() + ( ( setTime - startTime ) / 1 ), std::get< 1 >( set ) ); - Logger::info( "Registering {0} for {1}", std::get< 1 >( set ), std::get< 0 >( set ) - startTime ); + Logger::info( "Registering {0} for {1}, oldTime {2}", std::get< 1 >( set ), setTime - startTime, setTime ); } PlayerMgr::sendDebug( *getPlayer(), "Registered {0} sets for replay" ), m_replayCache.size(); @@ -167,15 +168,19 @@ void Sapphire::World::Session::stopReplay() void Sapphire::World::Session::processReplay() { int at = 0; + test: for( const auto& set : m_replayCache ) { - if( std::get< 0 >( set ) <= Common::Util::getTimeMs() ) + if( (std::get< 0 >( set ) ) <= Common::Util::getTimeMs() ) { m_pZoneConnection->injectPacket( std::get< 1 >( set ), *getPlayer().get() ); m_replayCache.erase( m_replayCache.begin() + at ); - //g_framework.getLogger().info( "Sent for " + std::to_string( std::get< 0 >( set ) ) + ", left: " + std::to_string( m_replayCache.size() ) ); + + Logger::info( "Sent for {0}, left: {1}", std::get< 1 >( set ), std::to_string( m_replayCache.size() ) ); + goto test; } at++; + } if( m_replayCache.empty() ) diff --git a/src/world/Task/ActionIntegrityTask.cpp b/src/world/Task/ActionIntegrityTask.cpp new file mode 100644 index 00000000..e3273d19 --- /dev/null +++ b/src/world/Task/ActionIntegrityTask.cpp @@ -0,0 +1,65 @@ +#include "ActionIntegrityTask.h" + +#include +#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; + +ActionIntegrityTask::ActionIntegrityTask( uint32_t resultId, Entity::CharaPtr pTarget, uint64_t delayTime ) : Task( delayTime ) +{ + m_resultId = resultId; + m_pTarget = std::move( pTarget ); +} + +void ActionIntegrityTask::onQueue() +{ + Logger::debug( { __FUNCTION__ } ); +} + +void ActionIntegrityTask::execute() +{ + auto& server = Common::Service< WorldServer >::ref(); + + auto inRangePlayers = m_pTarget->getInRangePlayerIds( true ); + + if( inRangePlayers.empty() ) + return; + + auto integrityPacket = makeZonePacket< FFXIVIpcActionIntegrity >( 0 ); + auto& data = integrityPacket->data(); + integrityPacket->setSourceActor( m_pTarget->getId() ); + data.Hp = m_pTarget->getHp(); + data.HpMax = m_pTarget->getMaxHp(); + data.Mp = m_pTarget->getMp(); + data.MpMax = m_pTarget->getMaxMp(); + data.Tp = m_pTarget->getTp(); + data.ResultId = m_resultId; + data.Target = m_pTarget->getId(); + + + for( auto& charId : inRangePlayers ) + { + auto pPlayer = server.getPlayer( charId ); + Logger::debug( "Sending to {}", charId ); + integrityPacket->setTargetActor( pPlayer->getId() ); + + server.queueForPlayer( charId, integrityPacket ); + } + +} + +std::string ActionIntegrityTask::toString() +{ + return fmt::format( "ActionIntegrityTask: ResultId#{}, TargetId#{}, ElapsedTimeMs: {}", m_resultId, m_pTarget->getId(), getDelayTimeMs() ); +} + + diff --git a/src/world/Task/ActionIntegrityTask.h b/src/world/Task/ActionIntegrityTask.h new file mode 100644 index 00000000..0671c4a0 --- /dev/null +++ b/src/world/Task/ActionIntegrityTask.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include "Task.h" + +namespace Sapphire::World +{ + +class ActionIntegrityTask : public Task +{ +public: + ActionIntegrityTask( uint32_t resultId, Entity::CharaPtr pTarget, uint64_t delayTime ); + + void onQueue() override; + void execute() override; + std::string toString() override; + +private: + uint32_t m_resultId; + Entity::CharaPtr m_pTarget; +}; + +template< typename... Args > +std::shared_ptr< ActionIntegrityTask > makeActionIntegrityTask( Args... args ) +{ + return std::make_shared< ActionIntegrityTask >( args... ); +} + +} diff --git a/src/world/Territory/Territory.cpp b/src/world/Territory/Territory.cpp index 58dee781..a579e975 100644 --- a/src/world/Territory/Territory.cpp +++ b/src/world/Territory/Territory.cpp @@ -825,7 +825,7 @@ void Territory::updateSpawnPoints() } } -uint32_t Territory::getNextEffectSequence() +uint32_t Territory::getNextEffectResultId() { return m_effectCounter++; } diff --git a/src/world/Territory/Territory.h b/src/world/Territory/Territory.h index cdd6ff19..6a84570f 100644 --- a/src/world/Territory/Territory.h +++ b/src/world/Territory/Territory.h @@ -194,7 +194,7 @@ namespace Sapphire void updateSpawnPoints(); - uint32_t getNextEffectSequence(); + uint32_t getNextEffectResultId(); std::shared_ptr< World::Navi::NaviProvider > getNaviProvider();