From 06d6f4db30b6725b7d80f8bb7887a2619ccc67bb Mon Sep 17 00:00:00 2001 From: collett Date: Mon, 17 Jun 2024 02:14:12 +0900 Subject: [PATCH] remove WorldInteractionHandler as it turns out it's just another ClientTrigger. handler merged and values used by WorldInteractionHandler fit perfectly in ClientTriggerType(name picked up from 3.x). also update the packet and rename params to be more consistent --- src/common/Network/CommonActorControl.h | 12 +- src/common/Network/PacketDef/Ipcs.h | 3 +- .../Network/PacketDef/Zone/ClientZoneDef.h | 22 +- src/world/Actor/Player.cpp | 4 +- src/world/Actor/Player.h | 2 +- src/world/Network/GameConnection.cpp | 3 +- .../Network/Handlers/ClientTriggerHandler.cpp | 258 ++++++++++++------ src/world/Network/Handlers/PacketHandlers.cpp | 133 --------- 8 files changed, 189 insertions(+), 248 deletions(-) diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index 456d2fdf..76f1c510 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -382,11 +382,11 @@ namespace Sapphire::Network::ActorControl TitleList = 0x12F, UpdatedSeenHowTos = 0x132, - CutscenePlayed = 0x134, // param1 = cutscene id + CutscenePlayed = 0x134, // p1 = cutscene id AllotAttribute = 0x135, //ClearFieldMarkers = 0x13A, - CameraMode = 0x13A, // param11 (only read lowest byte), 1 = enable, 0 = disable + CameraMode = 0x13A, // p1 (only read lowest byte), 1 = enable, 0 = disable CharaNameReq = 0x13D, // requests character name by content id HuntingLogDetails = 0x194, @@ -397,10 +397,12 @@ namespace Sapphire::Network::ActorControl RequestChocoboInventory = 0x1C4, EmoteReq = 0x1F4, + EmoteWithWarp = 0x1F5, EmoteCancel = 0x1F6, PersistentEmoteCancel = 0x1F7, + EmoteCancelWithWarp = 0x1F8, /*! - * param2 = pose ID + * p2 = pose ID * 0 = idle pose 0 (just standing) * 1 = idle pose 1 * 2-4 = idle poses 2-4 @@ -430,9 +432,9 @@ namespace Sapphire::Network::ActorControl AchievementCritReq = 0x3E8, AchievementList = 0x3E9, - SetEstateLightingLevel = 0x40B, // param1 = light level 0 - 5 maps to UI val 5-0 + SetEstateLightingLevel = 0x40B, // p1 = light level 0 - 5 maps to UI val 5-0 RequestHousingBuildPreset = 0x44C, - RequestEstateExteriorRemodel = 0x044D, // param11 = land id + RequestEstateExteriorRemodel = 0x044D, // p1 = land id RequestEstateInteriorRemodel = 0x44E, RequestEstateHallRemoval = 0x44F, RequestBuildPreset = 0x450, // no idea what this is, it gets sent with BuildPresetHandler and has the plot id in param1 diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 44481fa1..4b0389ee 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -392,6 +392,7 @@ enum ClientZoneIpcType : ZoneLineHandler = 0x326, // updated 6.58 hotfix 2 ClientTrigger = 0x035C, // updated 6.58 hotfix 2 + ClientTriggerEnvironment = 0x0295, // updated 6.58 hotfix 2 DiscoveryHandler = 0x0129, // updated 6.58 hotfix 2 SkillHandler = 0x07C, // updated 6.58 hotfix 2 @@ -436,8 +437,6 @@ enum ClientZoneIpcType : UpdatePositionInstance = 0x0227, // updated 6.58 hotfix 2 PerformNoteHandler = 0x0243, // updated 5.58h - - WorldInteractionHandler = 0x0295, // updated 6.58 hotfix 2 Dive = 0x018C, // updated 6.30h }; diff --git a/src/common/Network/PacketDef/Zone/ClientZoneDef.h b/src/common/Network/PacketDef/Zone/ClientZoneDef.h index baa0944c..5bfcee7b 100644 --- a/src/common/Network/PacketDef/Zone/ClientZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ClientZoneDef.h @@ -37,12 +37,11 @@ struct FFXIVIpcClientTrigger : { /* 0000 */ uint16_t commandId; /* 0002 */ uint8_t unk_2[2]; - /* 0004 */ uint32_t param11; - /* 0008 */ uint32_t param12; - /* 000C */ uint32_t param2; - /* 0010 */ uint32_t param4; // todo: really? - /* 0014 */ uint32_t param5; - /* 0018 */ uint64_t param3; + /* 0004 */ uint32_t param1; + /* 0008 */ uint32_t param2; + /* 000C */ uint32_t param3; + /* 0010 */ uint32_t param4; + /* 0014 */ Common::FFXIVARR_POSITION3 position; }; struct FFXIVIpcUpdatePosition : @@ -351,17 +350,6 @@ struct FFXIVIpcFreeCompanyUpdateShortMessageHandler : uint16_t unknown2; }; -struct FFXIVIpcWorldInteractionHandler : - FFXIVIpcBasePacket< WorldInteractionHandler > -{ - uint32_t action; - uint32_t param1; - uint32_t param2; - uint32_t param3; - uint32_t param4; - Common::FFXIVARR_POSITION3 position; -}; - struct FFXIVIpcSocialInviteHandler : FFXIVIpcBasePacket< SocialInviteHandler > { diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index e104c28a..ff88d2ee 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -2020,10 +2020,10 @@ void Sapphire::Entity::Player::finishZoning() } } -void Sapphire::Entity::Player::emote( uint32_t emoteId, uint64_t targetId, bool isSilent ) +void Sapphire::Entity::Player::emote( uint32_t emoteId, uint64_t targetId, bool isSilent, uint32_t rotation ) { sendToInRangeSet( makeActorControlTarget( getId(), ActorControlType::Emote, - emoteId, 0, isSilent ? 1 : 0, 0, targetId ) ); + emoteId, 0, isSilent ? 1 : 0, rotation, targetId ) ); } void Sapphire::Entity::Player::emoteInterrupt() diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index ed53f3d1..ad96a2c0 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -791,7 +791,7 @@ namespace Sapphire::Entity /*! return true if the player is marked for zoning */ bool isMarkedForZoning() const; - void emote( uint32_t emoteId, uint64_t targetId, bool isSilent ); + void emote( uint32_t emoteId, uint64_t targetId, bool isSilent, uint32_t rotation = 0 ); void emoteInterrupt(); diff --git a/src/world/Network/GameConnection.cpp b/src/world/Network/GameConnection.cpp index 90e5d7cf..38c944dd 100644 --- a/src/world/Network/GameConnection.cpp +++ b/src/world/Network/GameConnection.cpp @@ -70,7 +70,7 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH setZoneHandler( ClientZoneIpcType::ReqExamineFcInfo, "ReqExamineFcInfo", &GameConnection::reqExamineFcInfo ); setZoneHandler( ClientZoneIpcType::ZoneLineHandler, "ZoneLineHandler", &GameConnection::zoneLineHandler ); setZoneHandler( ClientZoneIpcType::ClientTrigger, "ClientTrigger", &GameConnection::clientTriggerHandler ); - + setZoneHandler( ClientZoneIpcType::ClientTriggerEnvironment, "ClientTriggerEnvironment", &GameConnection::clientTriggerHandler ); setZoneHandler( ClientZoneIpcType::DiscoveryHandler, "DiscoveryHandler", &GameConnection::discoveryHandler ); setZoneHandler( ClientZoneIpcType::SkillHandler, "ActionHandler", &GameConnection::actionHandler ); @@ -137,7 +137,6 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH setZoneHandler( ClientZoneIpcType::MarketBoardRequestItemListings, "MarketBoardRequestItemListings", &GameConnection::marketBoardRequestItemListings ); - setZoneHandler( ClientZoneIpcType::WorldInteractionHandler, "WorldInteractionHandler", &GameConnection::worldInteractionhandler ); setZoneHandler( ClientZoneIpcType::Dive, "Dive", &GameConnection::diveHandler ); setZoneHandler( ClientZoneIpcType::InventoryEquipRecommendedItems, "InventoryEquipRecommendedItemsHandler", &GameConnection::inventoryEquipRecommendedItemsHandler ); diff --git a/src/world/Network/Handlers/ClientTriggerHandler.cpp b/src/world/Network/Handlers/ClientTriggerHandler.cpp index f43874ab..78409999 100644 --- a/src/world/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/world/Network/Handlers/ClientTriggerHandler.cpp @@ -8,8 +8,12 @@ #include #include +#include +#include + #include "Territory/Territory.h" #include "Territory/ZonePosition.h" +#include #include "Manager/HousingMgr.h" #include "Network/GameConnection.h" @@ -70,16 +74,15 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX const auto packet = ZoneChannelPacket< Client::FFXIVIpcClientTrigger >( inPacket ); const auto commandId = packet.data().commandId; - const auto param1 = *reinterpret_cast< const uint64_t* >( &packet.data().param11 ); - const auto param11 = packet.data().param11; - const auto param12 = packet.data().param12; - const auto param2 = packet.data().param2; - const auto param3 = packet.data().param3; - const auto param4 = packet.data().param4; - const auto param5 = packet.data().param5; + const auto p1u64 = *reinterpret_cast< const uint64_t* >( &packet.data().param1 ); + const auto p1 = packet.data().param1; + const auto p2 = packet.data().param2; + const auto p3 = packet.data().param3; + const auto p4 = packet.data().param4; + const auto pos = packet.data().position; - Logger::debug( "[{0}] Incoming action: {1:X} ( p1:{2:X} p2:{3:X} p3:{4:X} )", - m_pSession->getId(), commandId, param1, param2, param3 ); + Logger::debug( "[{0}] Type: {1:X} (p1u64:{2:X} p1:{3} p2:{4} p3:{5} p4:{6} x:{7} y:{8} z:{9}", + m_pSession->getId(), commandId, p1u64, p1, p2, p3, p4, pos.x, pos.y, pos.z ); //Logger::Log(LoggingSeverity::debug, "[" + std::to_string(m_pSession->getId()) + "] " + pInPacket->toString()); @@ -87,7 +90,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { case ClientTriggerType::ToggleSheathe: // Toggle sheathe { - if( param11 == 1 ) + if( p1 == 1 ) player.setStance( Common::Stance::Active ); else { @@ -95,13 +98,13 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX player.setAutoattack( false ); } - player.sendToInRangeSet( makeActorControl( player.getId(), 0, param11, 1 ) ); + player.sendToInRangeSet( makeActorControl( player.getId(), 0, p1, 1 ) ); break; } case ClientTriggerType::ToggleAutoAttack: // Toggle auto-attack { - if( param11 == 1 ) + if( p1 == 1 ) { player.setAutoattack( true ); player.setStance( Common::Stance::Active ); @@ -110,15 +113,15 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX player.setAutoattack( false ); // the client seems to ignore source actor of this packet and always set auto-attack on itself. causing everyone on screen take their weapons out - player.queuePacket( makeActorControl( player.getId(), 1, param11, 1 ) ); - //player.sendToInRangeSet( makeActorControl( player.getId(), 1, param11, 1 ) ); + player.queuePacket( makeActorControl( player.getId(), 1, p1, 1 ) ); + //player.sendToInRangeSet( makeActorControl( player.getId(), 1, p1, 1 ) ); break; } case ClientTriggerType::ChangeTarget: // Change target { - uint64_t targetId = param1; + uint64_t targetId = p1u64; player.changeTarget( targetId ); break; } @@ -129,7 +132,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } case ClientTriggerType::SpawnCompanionReq: { - player.spawnCompanion( static_cast< uint16_t >( param1 ) ); + player.spawnCompanion( static_cast< uint16_t >( p1 ) ); break; } case ClientTriggerType::DespawnCompanionReq: @@ -140,7 +143,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX case ClientTriggerType::RemoveStatusEffect: // Remove status (clicking it off) { // todo: check if status can be removed by client from exd - player.removeSingleStatusEffectById( static_cast< uint32_t >( param1 ) ); + player.removeSingleStatusEffectById( static_cast< uint32_t >( p1 ) ); break; } case ClientTriggerType::CastCancel: // Cancel cast @@ -151,7 +154,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } case ClientTriggerType::Examine: { - uint32_t targetId = param11; + uint32_t targetId = p1u64; examineHandler( player, targetId ); break; } @@ -161,7 +164,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } case ClientTriggerType::SetTitleReq: // Set player title { - player.setTitle( static_cast< uint16_t >( param1 ) ); + player.setTitle( static_cast< uint16_t >( p1 ) ); break; } case ClientTriggerType::TitleList: // Get title list @@ -171,13 +174,13 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } case ClientTriggerType::UpdatedSeenHowTos: // Update howtos seen { - uint32_t howToId = param11; + uint32_t howToId = p1; player.updateHowtosSeen( howToId ); break; } case ClientTriggerType::CharaNameReq: { - uint64_t targetContentId = param1; + uint64_t targetContentId = p1u64; // todo: look up player by content id /* auto packet = makeZonePacket< FFXIVIpcCharaNameReq >( player.getId() ); @@ -192,10 +195,11 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX break; } case ClientTriggerType::EmoteReq: // emote + case ClientTriggerType::EmoteWithWarp: { uint64_t targetId = player.getTargetId(); - uint32_t emoteId = param11; - bool isSilent = param2 == 1; + uint32_t emoteId = p1; + bool isSilent = p3 == 1; auto& exdData = Common::Service< Data::ExdDataGenerated >::ref(); auto emoteData = exdData.get< Data::Emote >( emoteId ); @@ -203,7 +207,23 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX if( !emoteData ) return; - player.emote( emoteId, targetId, isSilent ); + if( commandId == ClientTriggerType::EmoteWithWarp ) + { + player.setPos( packet.data().position ); + player.setRot( Util::floatFromUInt16Rot( p4 ) ); + if( player.hasInRangeActor() ) + { + auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() ); + setpos->data().r16 = p4; + setpos->data().waitForLoad = 18; + setpos->data().x = packet.data().position.x; + setpos->data().y = packet.data().position.y; + setpos->data().z = packet.data().position.z; + player.sendToInRangeSet( setpos, false ); + } + } + + player.emote( emoteId, targetId, isSilent, commandId == ClientTriggerType::EmoteWithWarp ? p4 : 0 ); bool isPersistent = emoteData->emoteMode != 0; @@ -213,10 +233,6 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX player.setAutoattack( false ); player.setPersistentEmote( emoteData->emoteMode ); player.setStatus( Common::ActorStatus::EmoteMode ); - - player.sendToInRangeSet( makeActorControl( player.getId(), ActorControlType::SetStatus, - static_cast< uint8_t >( Common::ActorStatus::EmoteMode ), - emoteData->hasCancelEmote ? 1 : 0 ), true ); } if( emoteData->drawsWeapon ) @@ -226,38 +242,52 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX break; } - case ClientTriggerType::EmoteCancel: // emote - { - player.emoteInterrupt(); - break; - } + case ClientTriggerType::EmoteCancel: // emote cancel case ClientTriggerType::PersistentEmoteCancel: // cancel persistent emote + case ClientTriggerType::EmoteCancelWithWarp: { - player.setPersistentEmote( 0 ); + if( commandId == ClientTriggerType::EmoteCancelWithWarp ) + { + player.setPos( packet.data().position ); + if( player.hasInRangeActor() ) + { + auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() ); + setpos->data().r16 = p2; + setpos->data().waitForLoad = 18; + setpos->data().x = packet.data().position.x; + setpos->data().y = packet.data().position.y; + setpos->data().z = packet.data().position.z; + player.sendToInRangeSet( setpos, false ); + } + } player.emoteInterrupt(); - player.setStatus( Common::ActorStatus::Idle ); - auto pSetStatusPacket = makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) ); - player.sendToInRangeSet( pSetStatusPacket ); + if( player.getPersistentEmote() ) + { + player.setPersistentEmote( 0 ); + player.setStatus( Common::ActorStatus::Idle ); + auto pSetStatusPacket = makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) ); + player.sendToInRangeSet( pSetStatusPacket ); + } break; } case ClientTriggerType::PoseChange: // change pose case ClientTriggerType::PoseReapply: // reapply pose { - player.setPose( static_cast< uint8_t >( param12 ) ); - auto pSetStatusPacket = makeActorControl( player.getId(), SetPose, param11, param12 ); + player.setPose( static_cast< uint8_t >( p2 ) ); + auto pSetStatusPacket = makeActorControl( player.getId(), SetPose, p1, p2 ); player.sendToInRangeSet( pSetStatusPacket, true ); break; } case ClientTriggerType::PoseCancel: // cancel pose { - player.setPose( static_cast< uint8_t >( param12 ) ); - auto pSetStatusPacket = makeActorControl( player.getId(), SetPose, param11, param12 ); + player.setPose( static_cast< uint8_t >( p2 ) ); + auto pSetStatusPacket = makeActorControl( player.getId(), SetPose, p1, p2 ); player.sendToInRangeSet( pSetStatusPacket, false ); break; } case ClientTriggerType::Return: // return dead / accept raise { - switch( static_cast < ResurrectType >( param1 ) ) + switch( static_cast < ResurrectType >( p1 ) ) { case ResurrectType::RaiseSpell: // todo: handle raise case (set position to raiser, apply weakness status, set hp/mp/tp as well as packet) @@ -280,16 +310,16 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX case ClientTriggerType::Teleport: // Teleport { - player.teleportQuery( static_cast< uint16_t >( param11 ) ); + player.teleportQuery( static_cast< uint16_t >( p1 ) ); break; } case ClientTriggerType::DyeItem: // Dye item { - // param11 = item to dye container - // param12 = item to dye slot - // param2 = dye bag container - // param4 = dye bag slot - player.setDyeingInfo( param11, param12, param2, param4 ); + // p1 = item to dye container + // p2 = item to dye slot + // p3 = dye bag container + // p4 = dye bag slot + player.setDyeingInfo( p1, p2, p3, p4 ); break; } case ClientTriggerType::DirectorInitFinish: // Director init finish @@ -315,7 +345,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } case ClientTriggerType::AbandonQuest: { - player.removeQuest( static_cast< uint16_t >( param1 ) ); + player.removeQuest( static_cast< uint16_t >( p1 ) ); break; } case ClientTriggerType::RequestHousingBuildPreset: @@ -325,9 +355,9 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX if (!hZone) return; - player.setActiveLand( static_cast< uint8_t >( param11 ), hZone->getWardNum() ); + player.setActiveLand( static_cast< uint8_t >( p1 ), hZone->getWardNum() ); - auto pShowBuildPresetUIPacket = makeActorControl( player.getId(), ShowBuildPresetUI, param11 ); + auto pShowBuildPresetUIPacket = makeActorControl( player.getId(), ShowBuildPresetUI, p1 ); player.queuePacket( pShowBuildPresetUIPacket ); break; @@ -336,7 +366,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12 ); + auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2 ); housingMgr.sendLandSignFree( player, ident ); break; @@ -345,7 +375,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12, false ); + auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2, false ); housingMgr.sendLandSignOwned( player, ident ); break; @@ -354,7 +384,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - housingMgr.sendWardLandInfo( player, static_cast< uint8_t >( param12 ), static_cast< uint8_t >( param11 ) ); + housingMgr.sendWardLandInfo( player, static_cast< uint8_t >( p2 ), static_cast< uint8_t >( p1 ) ); break; } @@ -362,7 +392,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto plot = static_cast< uint8_t >( param12 & 0xFF ); + auto plot = static_cast< uint8_t >( p2 & 0xFF ); housingMgr.relinquishLand( player, plot ); break; @@ -371,7 +401,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12 ); + auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2 ); housingMgr.requestEstateRename( player, ident ); break; @@ -380,7 +410,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12 ); + auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2 ); housingMgr.requestEstateEditGreeting( player, ident ); break; @@ -389,7 +419,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12 ); + auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2 ); housingMgr.requestEstateEditGuestAccess( player, ident ); break; @@ -397,13 +427,13 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX case ClientTriggerType::RequestHousingItemUI: { // close ui - if( param11 == 1 ) + if( p1 == 1 ) break; - // param12 is 0 when inside a house + // p2 is 0 when inside a house - uint8_t ward = ( param12 >> 16 ) & 0xFF; - uint8_t plot = ( param12 & 0xFF ); + uint8_t ward = ( p2 >> 16 ) & 0xFF; + uint8_t plot = ( p2 & 0xFF ); auto pShowHousingItemUIPacket = makeActorControl( player.getId(), ShowHousingItemUI, 0, plot ); player.queuePacket( pShowHousingItemUIPacket ); @@ -416,19 +446,19 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto ident = housingMgr.clientTriggerParamsToLandIdent( param11, param12 ); + auto ident = housingMgr.clientTriggerParamsToLandIdent( p1, p2 ); housingMgr.sendEstateGreeting( player, ident ); break; } case ClientTriggerType::RequestLandInventory: { - uint8_t plot = ( param12 & 0xFF ); + uint8_t plot = ( p2 & 0xFF ); auto& housingMgr = Common::Service< HousingMgr >::ref(); uint16_t inventoryType = Common::InventoryType::HousingExteriorPlacedItems; - if( param2 == 1 ) + if( p3 == 1 ) inventoryType = Common::InventoryType::HousingExteriorStoreroom; housingMgr.sendEstateInventory( player, inventoryType, plot ); @@ -439,10 +469,10 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - // param1 = 1 - storeroom - // param1 = 0 - placed items + // p1 = 1 - storeroom + // p1 = 0 - placed items - if( param1 == 1 ) + if( p1 == 1 ) housingMgr.sendInternalEstateInventoryBatch( player, true ); else housingMgr.sendInternalEstateInventoryBatch( player ); @@ -453,11 +483,11 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - auto slot = param4 & 0xFF; - auto sendToStoreroom = ( param4 >> 16 ) != 0; + auto slot = p4 & 0xFF; + auto sendToStoreroom = ( p4 >> 16 ) != 0; //player, plot, containerId, slot, sendToStoreroom - housingMgr.reqRemoveHousingItem( player, static_cast< uint16_t >( param12 ), static_cast< uint16_t >( param2 ), static_cast< uint8_t >( slot ), sendToStoreroom ); + housingMgr.reqRemoveHousingItem( player, static_cast< uint16_t >( p2 ), static_cast< uint16_t >( p3 ), static_cast< uint8_t >( slot ), sendToStoreroom ); break; } @@ -465,7 +495,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - housingMgr.reqEstateExteriorRemodel( player, static_cast< uint16_t >( param11 ) ); + housingMgr.reqEstateExteriorRemodel( player, static_cast< uint16_t >( p1 ) ); break; } @@ -481,16 +511,16 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX { auto& housingMgr = Common::Service< HousingMgr >::ref(); - housingMgr.removeHouse( player, static_cast< uint16_t >( param11 ) ); + housingMgr.removeHouse( player, static_cast< uint16_t >( p1 ) ); break; } case ClientTriggerType::UpdateEstateGuestAccess: { - auto canTeleport = ( param2 & 0xFF ) == 1; - auto unk1 = ( param2 >> 8 & 0xFF ) == 1; // todo: related to fc? or unused? - auto privateEstateAccess = ( param2 >> 16 & 0xFF ) == 1; - auto unk = ( param2 >> 24 & 0xFF ) == 1; // todo: related to fc? or unused? + auto canTeleport = ( p3 & 0xFF ) == 1; + auto unk1 = ( p3 >> 8 & 0xFF ) == 1; // todo: related to fc? or unused? + auto privateEstateAccess = ( p3 >> 16 & 0xFF ) == 1; + auto unk = ( p3 >> 24 & 0xFF ) == 1; // todo: related to fc? or unused? player.sendDebug( "can teleport: {0}, unk: {1}, privateEstateAccess: {2}, unk: {3}", canTeleport, unk1, privateEstateAccess, unk ); @@ -498,36 +528,34 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } case ClientTriggerType::RequestEventBattle: { - auto packet = makeActorControlSelf( player.getId(), ActorControl::EventBattleDialog, 0, param12, param2 ); + auto packet = makeActorControlSelf( player.getId(), ActorControl::EventBattleDialog, 0, p2, p3 ); player.queuePacket( packet ); - - player.sendDebug( "event battle p1: {0}, p11: {1}, p12: {2}, p2: {3}, p3: {4}, p4: {5}, p5: {6}", param1, param11, param12, param2, param3, param4, param5 ); break; } case ClientTriggerType::CutscenePlayed: { - player.sendDebug( "cutscene: {}", param1 ); + player.sendDebug( "cutscene: {}", p1 ); break; } case ClientTriggerType::OpenPerformInstrumentUI: { - //param11 = instrument, 0 = end - player.sendDebug( "perform: {}", param11 ); - if( param11 == 0 ) + //p1 = instrument, 0 = end + player.sendDebug( "perform: {}", p1 ); + if( p1 == 0 ) { player.sendToInRangeSet( makeActorControl( player.getId(), ActorControl::SetStatus, 1, 0, 0, 0 ), true ); player.unsetStateFlag( PlayerStateFlag::Performing ); } else { - player.sendToInRangeSet( makeActorControl( player.getId(), ActorControl::SetStatus, 16, param11, 0, 0 ), true ); + player.sendToInRangeSet( makeActorControl( player.getId(), ActorControl::SetStatus, 16, p1, 0, 0 ), true ); player.setStateFlag( PlayerStateFlag::Performing ); } break; } case ClientTriggerType::CameraMode: { - if( ( param11 & 0xFF ) == 1 ) + if( ( p1 & 0xFF ) == 1 ) { player.setOnlineStatusMask( player.getOnlineStatusMask() | 0x0000000000040000 ); } @@ -537,6 +565,64 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX } break; } + case 0x25E: // coming out from water (no 3.x name) + case 0xD1: // underwater town portal (3.x NEWBIE_TELEPO_INQUIRY) + { + auto p = makeZonePacket< FFXIVIpcPrepareZoning >( player.getId() ); + p->data().targetZone = player.getCurrentTerritory()->getTerritoryTypeId(); + p->data().param4 = commandId == 0xD1 ? 14 : 227; + p->data().hideChar = commandId == 0xD1 ? 2 : 1; + p->data().fadeOut = commandId == 0xD1 ? 24 : 25; + p->data().fadeOutTime = 1; + p->data().unknown = commandId == 0xD1 ? 4 : 6; + auto x = pos.x; + auto y = pos.y; + auto z = pos.z; + auto rot = player.getRot(); + if( commandId == 0xD1 ) + { + auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref(); + auto exit = instanceObjectCache.getExitRange( p->data().targetZone, p1 ); + if( exit ) + { + player.sendDebug( "exitRange {0} found!", p1 ); + auto destZone = exit->data.destTerritoryType; + if( destZone == 0 ) + destZone = p->data().targetZone; + else + p->data().targetZone = destZone; + auto pop = instanceObjectCache.getPopRange( destZone, exit->data.destInstanceObjectId ); + if( pop ) + { + player.sendDebug( "popRange {0} found!", exit->data.destInstanceObjectId ); + x = pop->header.transform.translation.x; + y = pop->header.transform.translation.y; + z = pop->header.transform.translation.z; + //rot = pop->header.transform.rotation.y; all x/y/z not correct, maybe we don't need it since we have to be facing the portal anyway? + } + else + { + player.sendUrgent( "popRange {0} not found in {1}!", exit->data.destInstanceObjectId, destZone ); + } + } + else + { + player.sendUrgent( "exitRange {0} not found in {1}!", p1, p->data().targetZone ); + } + } + player.queuePacket( p ); + player.setPos( x, y, z, true ); + player.setRot( rot ); + auto setPos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() ); + setPos->data().r16 = Common::Util::floatToUInt16Rot( player.getRot() ); + setPos->data().x = x; + setPos->data().y = y; + setPos->data().z = z; + setPos->data().waitForLoad = commandId == 0xD1 ? 24 : 25; + setPos->data().unknown1 = 0; + player.queuePacket( setPos ); // this packet needs a delay of 0.8 second to wait for the client finishing its water animation otherwise it looks odd. + break; + } default: { Logger::debug( "[{0}] Unhandled action: {1:04X}", m_pSession->getId(), commandId ); diff --git a/src/world/Network/Handlers/PacketHandlers.cpp b/src/world/Network/Handlers/PacketHandlers.cpp index 68d01fb2..f0a5c5fc 100644 --- a/src/world/Network/Handlers/PacketHandlers.cpp +++ b/src/world/Network/Handlers/PacketHandlers.cpp @@ -805,139 +805,6 @@ void Sapphire::Network::GameConnection::marketBoardRequestItemListings( const Pa marketMgr.requestItemListings( player, packet.data().itemCatalogId ); } -void Sapphire::Network::GameConnection::worldInteractionhandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, - Entity::Player& player ) -{ - const auto packet = ZoneChannelPacket< Client::FFXIVIpcWorldInteractionHandler >( inPacket ); - auto action = packet.data().action; - player.sendDebug( "WorldInteraction {}", action ); - switch( action ) - { - case 0x1F5: // emote - { - auto emote = packet.data().param1; - if( emote == 0x32 || emote == 0x33 ) // "/sit" - { - auto param4 = packet.data().param4; - auto& exdData = Common::Service< Data::ExdDataGenerated >::ref(); - auto emoteData = exdData.get< Data::Emote >( emote ); - - if( !emoteData ) - break; - - player.setPos( packet.data().position ); - player.setRot( Util::floatFromUInt16Rot( param4 ) ); - if( emote == 0x32 && player.hasInRangeActor() ) - { - auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() ); - setpos->data().r16 = param4; - setpos->data().waitForLoad = 18; - setpos->data().x = packet.data().position.x; - setpos->data().y = packet.data().position.y; - setpos->data().z = packet.data().position.z; - player.sendToInRangeSet( setpos, false ); - } - player.sendToInRangeSet( makeActorControlTarget( player.getId(), ActorControl::ActorControlType::Emote, emote, 0, 0, param4, 0xE0000000 ), true ); - - if( emote == 0x32 && emoteData->emoteMode != 0 ) - { - player.setStance( Common::Stance::Passive ); - player.setAutoattack( false ); - player.setPersistentEmote( emoteData->emoteMode ); - player.setStatus( Common::ActorStatus::EmoteMode ); - } - } - break; - } - case 0x1F8: - { - if( player.getPersistentEmote() > 0 ) - { - auto param2 = packet.data().param2; - - player.setPos( packet.data().position ); - if( player.hasInRangeActor() ) - { - auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() ); - setpos->data().r16 = param2; - setpos->data().waitForLoad = 18; - setpos->data().x = packet.data().position.x; - setpos->data().y = packet.data().position.y; - setpos->data().z = packet.data().position.z; - player.sendToInRangeSet( setpos, false ); - } - - player.setPersistentEmote( 0 ); - player.emoteInterrupt(); - player.setStatus( Common::ActorStatus::Idle ); - auto pSetStatusPacket = makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) ); - player.sendToInRangeSet( pSetStatusPacket ); - } - break; - } - case 0x25E: // coming out from water - case 0xD1: // underwater town portal - { - auto p = makeZonePacket< FFXIVIpcPrepareZoning >( player.getId() ); - p->data().targetZone = player.getCurrentTerritory()->getTerritoryTypeId(); - p->data().param4 = action == 0xD1 ? 14 : 227; - p->data().hideChar = action == 0xD1 ? 2 : 1; - p->data().fadeOut = action == 0xD1 ? 24 : 25; - p->data().fadeOutTime = 1; - p->data().unknown = action == 0xD1 ? 4 : 6; - auto x = packet.data().position.x; - auto y = packet.data().position.y; - auto z = packet.data().position.z; - auto rot = player.getRot(); - if( action == 0xD1 ) - { - auto exitRange = packet.data().param1; - - auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref(); - auto exit = instanceObjectCache.getExitRange( p->data().targetZone, exitRange ); - if( exit ) - { - player.sendDebug( "exitRange {0} found!", exitRange ); - auto destZone = exit->data.destTerritoryType; - if( destZone == 0 ) - destZone = p->data().targetZone; - else - p->data().targetZone = destZone; - auto pop = instanceObjectCache.getPopRange( destZone, exit->data.destInstanceObjectId ); - if( pop ) - { - player.sendDebug( "popRange {0} found!", exit->data.destInstanceObjectId ); - x = pop->header.transform.translation.x; - y = pop->header.transform.translation.y; - z = pop->header.transform.translation.z; - //rot = pop->header.transform.rotation.y; all x/y/z not correct, maybe we don't need it since we have to be facing the portal anyway? - } - else - { - player.sendUrgent( "popRange {0} not found in {1}!", exit->data.destInstanceObjectId, destZone ); - } - } - else - { - player.sendUrgent( "exitRange {0} not found in {1}!", exitRange, p->data().targetZone ); - } - } - player.queuePacket( p ); - player.setPos( x, y, z, true ); - player.setRot( rot ); - auto setPos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() ); - setPos->data().r16 = Common::Util::floatToUInt16Rot( player.getRot() ); - setPos->data().x = x; - setPos->data().y = y; - setPos->data().z = z; - setPos->data().waitForLoad = action == 0xD1 ? 24 : 25; - setPos->data().unknown1 = 0; - player.queuePacket( setPos ); // this packet needs a delay of 0.8 second to wait for the client finishing its water animation otherwise it looks odd. - break; - } - } -} - void Sapphire::Network::GameConnection::diveHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) { const auto packetIn = ZoneChannelPacket< Client::FFXIVIpcDive >( inPacket );