1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-02 16:57:47 +00:00

Implemented a basic actionintegrity implementation, subject to be changed.

Fixed replay packet sending.
This commit is contained in:
Mordred 2023-02-16 08:24:39 +01:00
parent 0167367eeb
commit 85501effed
16 changed files with 160 additions and 24 deletions

View file

@ -276,13 +276,14 @@ namespace Sapphire::Network::ActorControl
HuntingLogSectionFinish = 0x21F, HuntingLogSectionFinish = 0x21F,
HuntingLogRankFinish = 0x220, HuntingLogRankFinish = 0x220,
SetMaxGearSets = 0x320,
SetCharaGearParamUI = 0x260,
SetConfigFlags = 0x260,
ToggleWireframeRendering = 0x261, ToggleWireframeRendering = 0x261,
ExamineError = 0x2BF, ExamineError = 0x2BF,
SetMaxGearSets = 0x320,
GearSetEquipMsg = 0x321, GearSetEquipMsg = 0x321,
SetBait = 0x325, // param1: bait ID SetBait = 0x325, // param1: bait ID

View file

@ -144,7 +144,7 @@ namespace Sapphire::Network::Packets
*/ */
void setSize( std::size_t packetSize ) void setSize( std::size_t packetSize )
{ {
m_segHdr.size = packetSize; m_segHdr.size = static_cast< uint32_t >( packetSize );
} }
/** /**

View file

@ -15,6 +15,9 @@
#include <Manager/TerritoryMgr.h> #include <Manager/TerritoryMgr.h>
#include <Service.h> #include <Service.h>
#include <Manager/TaskMgr.h>
#include <Task/ActionIntegrityTask.h>
using namespace Sapphire; using namespace Sapphire;
using namespace Sapphire::World::Action; using namespace Sapphire::World::Action;
using namespace Sapphire::Network::Packets; 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& teriMgr = Common::Service< Sapphire::World::Manager::TerritoryMgr >::ref();
auto zone = teriMgr.getZoneByTerritoryTypeId( m_sourceChara->getTerritoryTypeId() ); 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 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 remainingTargetCount = targetList.size();
auto& teriMgr = Common::Service< Sapphire::World::Manager::TerritoryMgr >::ref(); auto& teriMgr = Common::Service< Sapphire::World::Manager::TerritoryMgr >::ref();
auto zone = teriMgr.getTerritoryByGuId( m_sourceChara->getTerritoryId() ); auto zone = teriMgr.getTerritoryByGuId( m_sourceChara->getTerritoryId() );
auto globalSequence = zone->getNextEffectSequence(); auto resultId = zone->getNextEffectResultId();
if( remainingTargetCount > 1 ) // use AoeEffect packets if( remainingTargetCount > 1 ) // use AoeEffect packets
{ {
auto effectPacket = std::make_shared< EffectPacket >( m_sourceChara->getId(), m_actionId ); auto effectPacket = std::make_shared< EffectPacket >( m_sourceChara->getId(), m_actionId );
effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) ); effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) );
effectPacket->setSequence( globalSequence, m_sequence ); effectPacket->setSequence( resultId, m_sequence );
effectPacket->setTargetActor( targetList[ 0 ]->getId() ); effectPacket->setTargetActor( targetList[ 0 ]->getId() );
uint8_t targetIndex = 0; uint8_t targetIndex = 0;
@ -153,6 +156,8 @@ std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( const s
else else
{ {
effectPacket->addTargetEffect( effect, result->getTarget()->getId() ); 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 ) ); 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 ); auto effectPacket = std::make_shared< EffectPacket1 >( m_sourceChara->getId(), targetList[ 0 ]->getId(), m_actionId );
effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) ); 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(); ) for( auto it = m_actorEffectsMap.begin(); it != m_actorEffectsMap.end(); )
{ {
@ -197,6 +202,8 @@ std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( const s
else else
{ {
effectPacket->addTargetEffect( effect ); 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 ) ); 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().DirTarget = Common::Util::floatToUInt16Rot( m_sourceChara->getRot() );
effectPacket->data().Flag = Common::ActionEffectDisplayType::HideActionName; effectPacket->data().Flag = Common::ActionEffectDisplayType::HideActionName;
effectPacket->data().RequestId = m_sequence; effectPacket->data().RequestId = m_sequence;
effectPacket->data().ResultId = globalSequence; effectPacket->data().ResultId = resultId;
m_actorEffectsMap.clear(); m_actorEffectsMap.clear();

View file

@ -37,6 +37,7 @@
#include <Task/RemoveBNpcTask.h> #include <Task/RemoveBNpcTask.h>
#include <Task/FadeBNpcTask.h> #include <Task/FadeBNpcTask.h>
#include <Task/DelayedEmnityTask.h> #include <Task/DelayedEmnityTask.h>
#include <Task/ActionIntegrityTask.h>
#include <Service.h> #include <Service.h>
using namespace Sapphire::Common; using namespace Sapphire::Common;
@ -995,13 +996,17 @@ void Sapphire::Entity::BNpc::autoAttack( CharaPtr pTarget )
effectEntry.Arg0 = 3; effectEntry.Arg0 = 3;
effectEntry.Arg1 = 7; effectEntry.Arg1 = 7;
//effectEntry.Arg2 = 0x71; //effectEntry.Arg2 = 0x71;
effectPacket->setSequence( pZone->getNextEffectSequence() ); auto resultId = pZone->getNextEffectResultId();
effectPacket->setSequence( resultId );
effectPacket->addTargetEffect( effectEntry ); effectPacket->addTargetEffect( effectEntry );
sendToInRangeSet( effectPacket ); sendToInRangeSet( effectPacket );
pTarget->takeDamage( static_cast< uint16_t >( damage.first ) ); pTarget->takeDamage( static_cast< uint16_t >( damage.first ) );
auto& taskMgr = Common::Service< World::Manager::TaskMgr >::ref();
taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( resultId, pTarget, 500 ) );
} }
} }

View file

@ -407,8 +407,6 @@ void Sapphire::Entity::Chara::takeDamage( uint32_t damage )
} }
else else
m_hp -= damage; m_hp -= damage;
sendStatusUpdate();
} }
/*! /*!
@ -521,7 +519,7 @@ void Sapphire::Entity::Chara::addStatusEffect( StatusEffect::StatusEffectPtr pEf
auto statusEffectAdd = makeZonePacket< FFXIVIpcActionIntegrity >( getId() ); auto statusEffectAdd = makeZonePacket< FFXIVIpcActionIntegrity >( getId() );
statusEffectAdd->data().ResultId = pZone->getNextEffectSequence(); statusEffectAdd->data().ResultId = pZone->getNextEffectResultId();
statusEffectAdd->data().Target = pEffect->getTargetActorId(); statusEffectAdd->data().Target = pEffect->getTargetActorId();
statusEffectAdd->data().Hp = getHp(); statusEffectAdd->data().Hp = getHp();
statusEffectAdd->data().Mp = static_cast< uint16_t >( getMp() ); statusEffectAdd->data().Mp = static_cast< uint16_t >( getMp() );

View file

@ -336,6 +336,18 @@ std::set< Sapphire::Entity::GameObjectPtr > Sapphire::Entity::GameObject::getInR
return tempInRange; 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 uint32_t Sapphire::Entity::GameObject::getTerritoryTypeId() const
{ {
return m_territoryTypeId; return m_territoryTypeId;

View file

@ -111,6 +111,8 @@ namespace Sapphire::Entity
std::set< GameObjectPtr > getInRangeActors( bool includeSelf = false ); std::set< GameObjectPtr > getInRangeActors( bool includeSelf = false );
std::set< uint64_t > getInRangePlayerIds( bool includeSelf = false );
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
CharaPtr getAsChara(); CharaPtr getAsChara();

View file

@ -44,6 +44,9 @@
#include "WorldServer.h" #include "WorldServer.h"
#include <Manager/TaskMgr.h>
#include <Task/ActionIntegrityTask.h>
using namespace Sapphire; using namespace Sapphire;
using namespace Sapphire::Common; using namespace Sapphire::Common;
using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets;
@ -1327,7 +1330,8 @@ void Player::autoAttack( CharaPtr pTarget )
//entry.Arg2 = 0x73; //entry.Arg2 = 0x73;
} }
effectPacket->setSequence( pZone->getNextEffectSequence() ); auto resultId = pZone->getNextEffectResultId();
effectPacket->setResultId( resultId );
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) ); effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
effectPacket->addTargetEffect( entry ); effectPacket->addTargetEffect( entry );
@ -1335,6 +1339,9 @@ void Player::autoAttack( CharaPtr pTarget )
sendToInRangeSet( effectPacket, true ); sendToInRangeSet( effectPacket, true );
pTarget->takeDamage( static_cast< uint32_t >( damage.first ) ); pTarget->takeDamage( static_cast< uint32_t >( damage.first ) );
auto& taskMgr = Common::Service< TaskMgr >::ref();
taskMgr.queueTask( Sapphire::World::makeActionIntegrityTask( resultId, pTarget, 500 ) );
} }

View file

@ -544,7 +544,7 @@ void DebugCommandMgr::add( char* data, Entity::Player& player, std::shared_ptr<
effectPacket->addTargetEffect( entry, static_cast< uint64_t >( player.getId() ) ); effectPacket->addTargetEffect( entry, static_cast< uint64_t >( player.getId() ) );
auto sequence = pCurrentZone->getNextEffectSequence(); auto sequence = pCurrentZone->getNextEffectResultId();
effectPacket->setSequence( sequence ); effectPacket->setSequence( sequence );
// effectPacket->setAnimationId( param1 ); // effectPacket->setAnimationId( param1 );

View file

@ -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, 5 ) ); // SalvageSkill
server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), 0x16F, 6 ) ); // 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(), 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() ) ); 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::BetweenAreas );
//setStateFlag( PlayerStateFlag::BetweenAreas1 ); //setStateFlag( PlayerStateFlag::BetweenAreas1 );
if( player.hasReward( Common::UnlockEntry::HuntingLog ) ) player.sendHuntingLog();
player.sendHuntingLog();
if( player.isLogin() ) if( player.isLogin() )
{ {
player.sendItemLevel(); player.sendItemLevel();
server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), 0x39, 0 ) ); // unknown
server.queueForPlayer( player.getCharacterId(), makePlayerSetup( player ) ); server.queueForPlayer( player.getCharacterId(), makePlayerSetup( player ) );
} }

View file

@ -74,6 +74,11 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
m_data.ResultId = static_cast< uint32_t>( sequence ); m_data.ResultId = static_cast< uint32_t>( sequence );
} }
void setResultId( uint32_t resultId )
{
m_data.ResultId = static_cast< uint32_t>( resultId );
}
private: private:
uint8_t m_targetEffectCount{ 0 }; uint8_t m_targetEffectCount{ 0 };
uint8_t m_sourceEffectCount{ 0 }; uint8_t m_sourceEffectCount{ 0 };

View file

@ -149,9 +149,10 @@ void Sapphire::World::Session::startReplay( const std::string& path )
for( auto set : loadedSets ) 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(); 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() void Sapphire::World::Session::processReplay()
{ {
int at = 0; int at = 0;
test:
for( const auto& set : m_replayCache ) 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_pZoneConnection->injectPacket( std::get< 1 >( set ), *getPlayer().get() );
m_replayCache.erase( m_replayCache.begin() + at ); 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++; at++;
} }
if( m_replayCache.empty() ) if( m_replayCache.empty() )

View file

@ -0,0 +1,65 @@
#include "ActionIntegrityTask.h"
#include <Logging/Logger.h>
#include <Actor/Player.h>
#include <Actor/Chara.h>
#include <WorldServer.h>
#include <Service.h>
#include <Network/PacketWrappers/WarpPacket.h>
#include <utility>
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() );
}

View file

@ -0,0 +1,31 @@
#pragma once
#include <cstdint>
#include <string>
#include <ForwardsZone.h>
#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... );
}
}

View file

@ -825,7 +825,7 @@ void Territory::updateSpawnPoints()
} }
} }
uint32_t Territory::getNextEffectSequence() uint32_t Territory::getNextEffectResultId()
{ {
return m_effectCounter++; return m_effectCounter++;
} }

View file

@ -194,7 +194,7 @@ namespace Sapphire
void updateSpawnPoints(); void updateSpawnPoints();
uint32_t getNextEffectSequence(); uint32_t getNextEffectResultId();
std::shared_ptr< World::Navi::NaviProvider > getNaviProvider(); std::shared_ptr< World::Navi::NaviProvider > getNaviProvider();