1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-22 20:57:46 +00:00
sapphire/src/world/Network/Handlers/ClientTriggerHandler.cpp

504 lines
15 KiB
C++
Raw Normal View History

2018-03-06 22:22:19 +01:00
#include <Common.h>
#include <Network/CommonNetwork.h>
2019-03-08 15:34:38 +01:00
#include <Network/GamePacket.h>
2018-03-06 22:22:19 +01:00
#include <Logging/Logger.h>
#include <Exd/ExdDataGenerated.h>
#include <Network/PacketContainer.h>
#include <Network/CommonActorControl.h>
#include <Network/PacketDef/Zone/ClientZoneDef.h>
2018-10-26 08:25:20 +02:00
#include <Util/Util.h>
2019-07-21 22:33:33 +10:00
#include "Territory/Territory.h"
#include "Territory/ZonePosition.h"
#include "Manager/HousingMgr.h"
#include "Network/GameConnection.h"
#include "Network/PacketWrappers/ExaminePacket.h"
#include "Network/PacketWrappers/PlayerSetupPacket.h"
#include "Network/PacketWrappers/PingPacket.h"
#include "Network/PacketWrappers/MoveActorPacket.h"
#include "Network/PacketWrappers/ChatPacket.h"
#include "Network/PacketWrappers/ServerNoticePacket.h"
#include "Network/PacketWrappers/ActorControlPacket.h"
#include "Manager/DebugCommandMgr.h"
2018-12-23 03:53:08 +01:00
#include "Manager/EventMgr.h"
#include "Action/Action.h"
#include "Session.h"
2018-11-20 21:32:13 +01:00
#include "ServerMgr.h"
#include "Forwards.h"
#include "Framework.h"
#include <Network/PacketDef/Lobby/ServerLobbyDef.h>
using namespace Sapphire::Common;
using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::Server;
using namespace Sapphire::Network::ActorControl;
using namespace Sapphire::World::Manager;
2018-12-23 03:53:08 +01:00
void examineHandler( Sapphire::FrameworkPtr pFw, Sapphire::Entity::Player& player, uint32_t targetId )
{
using namespace Sapphire;
2018-12-23 03:53:08 +01:00
auto pSession = pFw->get< World::ServerMgr >()->getSession( targetId );
if( pSession )
{
auto pTarget = pSession->getPlayer();
if( pTarget )
{
if( pTarget->isActingAsGm() || pTarget->getZoneId() != player.getZoneId() )
{
2019-10-09 18:42:25 +02:00
player.queuePacket( makeActorControl( player.getId(), ActorControlType::ExamineError ) );
}
else
{
2018-10-25 12:44:51 +11:00
player.queuePacket( std::make_shared< ExaminePacket >( player, pTarget ) );
}
}
}
}
2018-12-23 03:53:08 +01:00
void Sapphire::Network::GameConnection::clientTriggerHandler( FrameworkPtr pFw,
const Packets::FFXIVARR_PACKET_RAW& inPacket,
Entity::Player& player )
{
2019-07-29 22:22:45 +10:00
const auto packet = ZoneChannelPacket< Client::FFXIVIpcClientTrigger >( inPacket );
2018-10-14 23:31:52 +11:00
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;
Logger::debug( "[{0}] Incoming action: {1:X} ( p1:{2:X} p2:{3:X} p3:{4:X} )",
m_pSession->getId(), commandId, param1, param2, param3 );
//Logger::Log(LoggingSeverity::debug, "[" + std::to_string(m_pSession->getId()) + "] " + pInPacket->toString());
switch( commandId )
{
case ClientTriggerType::ToggleSheathe: // Toggle sheathe
{
if( param11 == 1 )
player.setStance( Common::Stance::Active );
else
{
player.setStance( Common::Stance::Passive );
player.setAutoattack( false );
}
2019-10-09 18:42:25 +02:00
player.sendToInRangeSet( makeActorControl( player.getId(), 0, param11, 1 ) );
break;
}
case ClientTriggerType::ToggleAutoAttack: // Toggle auto-attack
{
if( param11 == 1 )
{
player.setAutoattack( true );
player.setStance( Common::Stance::Active );
}
else
player.setAutoattack( false );
2019-10-09 18:42:25 +02:00
player.sendToInRangeSet( makeActorControl( player.getId(), 1, param11, 1 ) );
break;
}
case ClientTriggerType::ChangeTarget: // Change target
{
uint64_t targetId = param1;
player.changeTarget( targetId );
break;
}
case ClientTriggerType::DismountReq:
{
player.dismount();
break;
}
case ClientTriggerType::SpawnCompanionReq:
{
player.spawnCompanion( param1 );
break;
}
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 ) );
break;
}
case ClientTriggerType::CastCancel: // Cancel cast
{
if( player.getCurrentAction() )
player.getCurrentAction()->setInterrupted( Common::ActionInterruptType::RegularInterrupt );
break;
}
case ClientTriggerType::Examine:
{
uint32_t targetId = param11;
2018-12-23 03:53:08 +01:00
examineHandler( pFw, player, targetId );
break;
}
case ClientTriggerType::MarkPlayer: // Mark player
{
break;
}
case ClientTriggerType::SetTitleReq: // Set player title
{
player.setTitle( static_cast< uint16_t >( param1 ) );
break;
}
case ClientTriggerType::TitleList: // Get title list
{
player.sendTitleList();
break;
}
case ClientTriggerType::UpdatedSeenHowTos: // Update howtos seen
{
uint32_t howToId = param11;
player.updateHowtosSeen( howToId );
break;
}
case ClientTriggerType::CharaNameReq:
{
uint64_t targetContentId = param1;
// todo: look up player by content id
/*
2019-07-29 22:22:45 +10:00
auto packet = makeZonePacket< FFXIVIpcCharaNameReq >( player.getId() );
packet->data().contentId = targetContentId;
// lookup the name
strcpy( packet->data().name, name );
player.queuePacket( packet );
*/
break;
}
case ClientTriggerType::EmoteReq: // emote
{
uint64_t targetId = player.getTargetId();
uint32_t emoteId = param11;
bool isSilent = param2 == 1;
2018-12-23 03:53:08 +01:00
auto pExdData = pFw->get< Data::ExdDataGenerated >();
auto emoteData = pExdData->get< Data::Emote >( emoteId );
if( !emoteData )
return;
player.emote( emoteId, targetId, isSilent );
bool isPersistent = emoteData->emoteMode != 0;
if( isPersistent )
{
player.setStance( Common::Stance::Passive );
player.setAutoattack( false );
player.setPersistentEmote( emoteData->emoteMode );
player.setStatus( Common::ActorStatus::EmoteMode );
2019-10-09 18:42:25 +02:00
player.sendToInRangeSet( makeActorControl( player.getId(), ActorControlType::SetStatus,
static_cast< uint8_t >( Common::ActorStatus::EmoteMode ),
emoteData->hasCancelEmote ? 1 : 0 ), true );
}
if( emoteData->drawsWeapon )
{
player.setStance( Common::Stance::Active );
}
break;
}
case ClientTriggerType::EmoteCancel: // emote
{
player.emoteInterrupt();
break;
}
case ClientTriggerType::PersistentEmoteCancel: // cancel persistent emote
{
player.setPersistentEmote( 0 );
player.emoteInterrupt();
player.setStatus( Common::ActorStatus::Idle );
2019-10-09 18:42:25 +02:00
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( param12 );
2019-10-09 18:42:25 +02:00
auto pSetStatusPacket = makeActorControl( player.getId(), SetPose, param11, param12 );
player.sendToInRangeSet( pSetStatusPacket, true );
break;
}
case ClientTriggerType::PoseCancel: // cancel pose
{
player.setPose( param12 );
2019-10-09 18:42:25 +02:00
auto pSetStatusPacket = makeActorControl( player.getId(), SetPose, param11, param12 );
player.sendToInRangeSet( pSetStatusPacket, true );
break;
}
case ClientTriggerType::Return: // return dead / accept raise
{
switch( static_cast < ResurrectType >( param1 ) )
{
case ResurrectType::RaiseSpell:
// todo: handle raise case (set position to raiser, apply weakness status, set hp/mp/tp as well as packet)
player.returnToHomepoint();
2018-03-15 03:13:20 +11:00
break;
case ResurrectType::Return:
player.returnToHomepoint();
2018-03-15 03:13:20 +11:00
break;
default:
2018-03-15 03:31:46 +11:00
break;
}
}
case ClientTriggerType::FinishZoning: // Finish zoning
{
player.finishZoning();
break;
}
case ClientTriggerType::Teleport: // Teleport
{
2019-02-08 21:20:53 +11:00
player.teleportQuery( param11 );
break;
}
case ClientTriggerType::DyeItem: // Dye item
{
// param11 = item to dye container
// param12 = item to dye slot
// param2 = dye bag container
// param4 = dye bag slot
break;
}
case ClientTriggerType::DirectorInitFinish: // Director init finish
{
player.getCurrentTerritory()->onInitDirector( player );
break;
}
case ClientTriggerType::DirectorSync: // Director init finish
{
player.getCurrentTerritory()->onDirectorSync( player );
break;
}
case ClientTriggerType::EnterTerritoryEventFinished:// this may still be something else. I think i have seen it elsewhere
{
player.setOnEnterEventDone( true );
break;
}
case ClientTriggerType::RequestInstanceLeave:
{
// todo: apply cf penalty if applicable, make sure player isn't in combat
player.exitInstance();
break;
}
case ClientTriggerType::AbandonQuest:
{
player.removeQuest( static_cast< uint16_t >( param1 ) );
2018-08-31 23:02:45 +10:00
break;
}
case ClientTriggerType::RequestHousingBuildPreset:
{
auto zone = player.getCurrentTerritory();
auto hZone = std::dynamic_pointer_cast< HousingZone >( zone );
if (!hZone)
return;
player.setActiveLand( param11, hZone->getWardNum() );
2019-10-09 18:42:25 +02:00
auto pShowBuildPresetUIPacket = makeActorControl( player.getId(), ShowBuildPresetUI, param11 );
player.queuePacket( pShowBuildPresetUIPacket );
break;
}
case ClientTriggerType::RequestLandSignFree:
2018-11-04 23:47:10 +01:00
{
2018-12-23 03:53:08 +01:00
auto pHousingMgr = pFw->get< HousingMgr >();
2018-12-05 16:55:14 +11:00
auto ident = pHousingMgr->clientTriggerParamsToLandIdent( param11, param12 );
pHousingMgr->sendLandSignFree( player, ident );
2018-11-04 23:47:10 +01:00
break;
}
case ClientTriggerType::RequestLandSignOwned:
2018-11-11 14:27:39 +01:00
{
2018-12-23 03:53:08 +01:00
auto pHousingMgr = pFw->get< HousingMgr >();
2018-12-05 16:55:14 +11:00
auto ident = pHousingMgr->clientTriggerParamsToLandIdent( param11, param12, false );
2018-12-05 16:55:14 +11:00
pHousingMgr->sendLandSignOwned( player, ident );
2018-11-11 14:27:39 +01:00
break;
}
case ClientTriggerType::RequestWardLandInfo:
{
2018-12-23 03:53:08 +01:00
auto pHousingMgr = pFw->get< HousingMgr >();
if( !pHousingMgr )
break;
pHousingMgr->sendWardLandInfo( player, param12, param11 );
break;
}
case ClientTriggerType::RequestLandRelinquish:
{
auto plot = static_cast< uint8_t >( param12 & 0xFF );
2018-12-23 03:53:08 +01:00
auto pHousingMgr = pFw->get< HousingMgr >();
2018-11-17 01:16:44 +01:00
pHousingMgr->relinquishLand( player, plot );
break;
}
case ClientTriggerType::RequestEstateRename:
2018-11-11 14:27:39 +01:00
{
2018-12-23 03:53:08 +01:00
auto pHousingMgr = pFw->get< HousingMgr >();
if( !pHousingMgr )
break;
2018-11-11 14:27:39 +01:00
2018-12-05 16:55:14 +11:00
auto ident = pHousingMgr->clientTriggerParamsToLandIdent( param11, param12 );
pHousingMgr->requestEstateRename( player, ident );
2018-11-11 14:27:39 +01:00
break;
}
case ClientTriggerType::RequestEstateEditGreeting:
{
2018-12-23 03:53:08 +01:00
auto pHousingMgr = pFw->get< HousingMgr >();
if( !pHousingMgr )
break;
2018-12-05 16:55:14 +11:00
auto ident = pHousingMgr->clientTriggerParamsToLandIdent( param11, param12 );
pHousingMgr->requestEstateEditGreeting( player, ident );
break;
}
2018-11-29 00:19:37 +11:00
case ClientTriggerType::RequestEstateEditGuestAccessSettings:
{
2018-12-23 03:53:08 +01:00
auto pHousingMgr = pFw->get< HousingMgr >();
2018-11-29 00:19:37 +11:00
if( !pHousingMgr )
break;
2018-12-05 16:55:14 +11:00
auto ident = pHousingMgr->clientTriggerParamsToLandIdent( param11, param12 );
pHousingMgr->requestEstateEditGuestAccess( player, ident );
2018-11-29 00:19:37 +11:00
break;
}
2018-11-07 09:05:03 +01:00
case ClientTriggerType::RequestHousingItemUI:
{
// close ui
if( param11 == 1 )
break;
// param12 is 0 when inside a house
uint8_t ward = ( param12 >> 16 ) & 0xFF;
2018-11-11 14:27:39 +01:00
uint8_t plot = ( param12 & 0xFF );
2019-10-09 18:42:25 +02:00
auto pShowHousingItemUIPacket = makeActorControl( player.getId(), ShowHousingItemUI, 0, plot );
2018-11-07 09:05:03 +01:00
2018-11-07 09:27:57 +01:00
player.queuePacket( pShowHousingItemUIPacket );
2018-11-07 09:05:03 +01:00
//TODO: show item housing container
break;
}
case ClientTriggerType::RequestEstateGreeting:
{
2018-12-23 03:53:08 +01:00
auto housingMgr = pFw->get< HousingMgr >();
if( !housingMgr )
break;
2018-12-05 16:55:14 +11:00
auto ident = housingMgr->clientTriggerParamsToLandIdent( param11, param12 );
housingMgr->sendEstateGreeting( player, ident );
break;
}
case ClientTriggerType::RequestLandInventory:
{
uint8_t plot = ( param12 & 0xFF );
2018-12-23 03:53:08 +01:00
auto housingMgr = pFw->get< HousingMgr >();
if( !housingMgr )
break;
uint16_t inventoryType = Common::InventoryType::HousingExteriorPlacedItems;
if( param2 == 1 )
inventoryType = Common::InventoryType::HousingExteriorStoreroom;
2018-12-22 11:33:21 +11:00
housingMgr->sendEstateInventory( player, inventoryType, plot );
break;
}
case ClientTriggerType::RequestEstateInventory:
{
2018-12-23 03:53:08 +01:00
auto housingMgr = pFw->get< HousingMgr >();
if( !housingMgr )
break;
// param1 = 1 - storeroom
// param1 = 0 - placed items
2018-12-27 00:36:47 +11:00
if( param1 == 1 )
housingMgr->sendInternalEstateInventoryBatch( player, true );
else
housingMgr->sendInternalEstateInventoryBatch( player );
break;
}
case ClientTriggerType::RequestHousingItemRemove:
{
2018-12-29 13:05:13 +11:00
auto housingMgr = m_pFw->get< HousingMgr >();
auto slot = param4 & 0xFF;
auto sendToStoreroom = ( param4 >> 16 ) != 0;
//player, plot, containerId, slot, sendToStoreroom
housingMgr->reqRemoveHousingItem( player, param12, param2, slot, sendToStoreroom );
break;
}
case ClientTriggerType::RequestEstateExteriorRemodel:
{
2018-12-29 13:05:13 +11:00
auto housingMgr = m_pFw->get< HousingMgr >();
housingMgr->reqEstateExteriorRemodel( player, param11 );
break;
}
case ClientTriggerType::RequestEstateInteriorRemodel:
{
2018-12-29 13:05:13 +11:00
auto housingMgr = m_pFw->get< HousingMgr >();
housingMgr->reqEstateInteriorRemodel( player );
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?
2019-01-05 12:32:10 +01:00
player.sendDebug( "can teleport: {0}, unk: {1}, privateEstateAccess: {2}, unk: {3}",
canTeleport, unk1, privateEstateAccess, unk );
break;
}
2018-11-07 09:05:03 +01:00
default:
{
Logger::debug( "[{0}] Unhandled action: {1:04X}", m_pSession->getId(), commandId );
break;
}
}
}