2018-03-06 22:22:19 +01:00
|
|
|
#include <Common.h>
|
|
|
|
#include <Network/CommonNetwork.h>
|
|
|
|
#include <Network/GamePacketNew.h>
|
|
|
|
#include <Logging/Logger.h>
|
|
|
|
#include <Exd/ExdDataGenerated.h>
|
|
|
|
#include <Network/PacketContainer.h>
|
2018-06-23 21:38:04 +02:00
|
|
|
#include <Network/CommonActorControl.h>
|
2018-07-06 22:43:49 +10:00
|
|
|
#include <Network/PacketDef/Zone/ClientZoneDef.h>
|
2018-10-26 08:25:20 +02:00
|
|
|
#include <Util/Util.h>
|
2017-08-17 16:19:20 +02:00
|
|
|
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Zone/Zone.h"
|
|
|
|
#include "Zone/ZonePosition.h"
|
2018-11-04 23:47:10 +01:00
|
|
|
#include "Zone/HousingZone.h"
|
2018-11-11 14:27:39 +01:00
|
|
|
#include "Zone/HousingMgr.h"
|
2018-11-04 23:47:10 +01:00
|
|
|
#include "Zone/Land.h"
|
2017-12-08 15:38:25 +01:00
|
|
|
|
2018-03-02 07:22:25 -03:00
|
|
|
#include "Network/GameConnection.h"
|
2018-09-13 11:08:24 +01:00
|
|
|
|
|
|
|
#include "Network/PacketWrappers/ExaminePacket.h"
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Network/PacketWrappers/InitUIPacket.h"
|
|
|
|
#include "Network/PacketWrappers/PingPacket.h"
|
|
|
|
#include "Network/PacketWrappers/MoveActorPacket.h"
|
|
|
|
#include "Network/PacketWrappers/ChatPacket.h"
|
|
|
|
#include "Network/PacketWrappers/ServerNoticePacket.h"
|
|
|
|
#include "Network/PacketWrappers/ActorControlPacket142.h"
|
|
|
|
|
2018-01-28 11:16:34 +01:00
|
|
|
#include "DebugCommand/DebugCommandHandler.h"
|
2018-03-02 07:22:25 -03:00
|
|
|
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Event/EventHelper.h"
|
2018-03-02 07:22:25 -03:00
|
|
|
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Action/Action.h"
|
|
|
|
#include "Action/ActionTeleport.h"
|
2017-08-17 16:19:20 +02:00
|
|
|
|
2018-09-10 14:34:24 +01:00
|
|
|
|
2018-03-02 07:22:25 -03:00
|
|
|
#include "Session.h"
|
|
|
|
#include "ServerZone.h"
|
|
|
|
#include "Forwards.h"
|
|
|
|
#include "Framework.h"
|
2018-06-23 21:38:04 +02:00
|
|
|
#include <Network/PacketDef/Lobby/ServerLobbyDef.h>
|
2018-03-02 07:22:25 -03:00
|
|
|
|
2018-03-09 00:06:44 +01:00
|
|
|
extern Core::Framework g_fw;
|
2017-08-17 16:19:20 +02:00
|
|
|
|
|
|
|
using namespace Core::Common;
|
|
|
|
using namespace Core::Network::Packets;
|
|
|
|
using namespace Core::Network::Packets::Server;
|
2018-06-23 21:38:04 +02:00
|
|
|
using namespace Core::Network::ActorControl;
|
2017-08-17 16:19:20 +02:00
|
|
|
|
2018-09-10 15:01:13 +01:00
|
|
|
void examineHandler( Core::Entity::Player& player, uint32_t targetId )
|
|
|
|
{
|
|
|
|
using namespace Core;
|
|
|
|
|
|
|
|
auto pSession = g_fw.get< Core::ServerZone >()->getSession( targetId );
|
|
|
|
if( pSession )
|
|
|
|
{
|
2018-09-13 11:08:24 +01:00
|
|
|
auto pTarget = pSession->getPlayer();
|
|
|
|
if( pTarget )
|
2018-09-10 15:01:13 +01:00
|
|
|
{
|
2018-09-25 01:11:14 +10:00
|
|
|
if( pTarget->isActingAsGm() || pTarget->getZoneId() != player.getZoneId() )
|
|
|
|
{
|
|
|
|
player.queuePacket( makeActorControl142( player.getId(), ActorControlType::ExamineError ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-25 12:44:51 +11:00
|
|
|
player.queuePacket( std::make_shared< ExaminePacket >( player, pTarget ) );
|
2018-09-25 01:11:14 +10:00
|
|
|
}
|
2018-09-10 15:01:13 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-03 15:01:13 +02:00
|
|
|
void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket,
|
|
|
|
Entity::Player& player )
|
2017-08-17 16:19:20 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto pLog = g_fw.get< Logger >();
|
|
|
|
|
|
|
|
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;
|
2018-08-29 21:40:59 +02:00
|
|
|
|
|
|
|
pLog->debug( "[" + std::to_string( m_pSession->getId() ) + "] Incoming action: " +
|
2018-10-26 08:25:20 +02:00
|
|
|
Util::intToHexString( static_cast< uint32_t >( commandId & 0xFFFF ), 4 ) +
|
|
|
|
"\nparam1: " + Util::intToHexString( static_cast< uint64_t >( param1 & 0xFFFFFFFFFFFFFFF ), 16 ) +
|
|
|
|
"\nparam2: " + Util::intToHexString( static_cast< uint32_t >( param2 & 0xFFFFFFFF ), 8 ) +
|
|
|
|
"\nparam3: " + Util::intToHexString( static_cast< uint64_t >( param3 & 0xFFFFFFFFFFFFFFF ), 16 )
|
2018-08-29 21:40:59 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
//g_log.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 );
|
|
|
|
}
|
|
|
|
|
|
|
|
player.sendToInRangeSet( makeActorControl142( 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 );
|
|
|
|
|
|
|
|
player.sendToInRangeSet( makeActorControl142( 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::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();
|
|
|
|
break;
|
|
|
|
}
|
2018-09-10 14:34:24 +01:00
|
|
|
case ClientTriggerType::Examine:
|
|
|
|
{
|
|
|
|
uint32_t targetId = param11;
|
2018-09-10 15:01:13 +01:00
|
|
|
examineHandler( player, targetId );
|
|
|
|
break;
|
2018-09-10 14:34:24 +01:00
|
|
|
}
|
2018-08-29 21:40:59 +02:00
|
|
|
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;
|
|
|
|
}
|
2018-09-11 17:46:04 +01:00
|
|
|
case ClientTriggerType::CharaNameReq:
|
|
|
|
{
|
|
|
|
uint64_t targetContentId = param1;
|
|
|
|
// todo: look up player by content id
|
|
|
|
/*
|
|
|
|
auto packet = makeZonePacket< FFXIVIpcCharaNameReq >( player.getId() );
|
|
|
|
packet->data().contentId = targetContentId;
|
|
|
|
|
|
|
|
// lookup the name
|
|
|
|
|
|
|
|
strcpy( packet->data().name, name );
|
|
|
|
|
|
|
|
player.queuePacket( packet );
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
}
|
2018-08-29 21:40:59 +02:00
|
|
|
case ClientTriggerType::EmoteReq: // emote
|
|
|
|
{
|
|
|
|
uint64_t targetId = player.getTargetId();
|
|
|
|
uint32_t emoteId = param11;
|
|
|
|
bool isSilent = param2 == 1;
|
|
|
|
|
|
|
|
auto pExdData = g_fw.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 );
|
|
|
|
|
|
|
|
player.sendToInRangeSet( makeActorControl142( 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 );
|
|
|
|
auto pSetStatusPacket = makeActorControl142( 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 );
|
|
|
|
auto pSetStatusPacket = makeActorControl142( player.getId(), SetPose, param11, param12 );
|
|
|
|
player.sendToInRangeSet( pSetStatusPacket, true );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ClientTriggerType::PoseCancel: // cancel pose
|
|
|
|
{
|
|
|
|
player.setPose( param12 );
|
|
|
|
auto pSetStatusPacket = makeActorControl142( 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;
|
2018-08-29 21:40:59 +02:00
|
|
|
case ResurrectType::Return:
|
|
|
|
player.returnToHomepoint();
|
2018-03-15 03:13:20 +11:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
default:
|
2018-03-15 03:31:46 +11:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
case ClientTriggerType::FinishZoning: // Finish zoning
|
|
|
|
{
|
|
|
|
player.finishZoning();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ClientTriggerType::Teleport: // Teleport
|
|
|
|
{
|
|
|
|
|
|
|
|
player.teleportQuery( param11 );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ClientTriggerType::DyeItem: // Dye item
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ClientTriggerType::DirectorInitFinish: // Director init finish
|
|
|
|
{
|
|
|
|
player.getCurrentZone()->onInitDirector( player );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ClientTriggerType::DirectorSync: // Director init finish
|
|
|
|
{
|
|
|
|
player.getCurrentZone()->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 isnt in combat
|
|
|
|
player.exitInstance();
|
|
|
|
break;
|
|
|
|
}
|
2018-08-31 22:57:33 +10:00
|
|
|
case ClientTriggerType::AbandonQuest:
|
|
|
|
{
|
|
|
|
player.removeQuest( static_cast< uint16_t >( param1 ) );
|
2018-08-31 23:02:45 +10:00
|
|
|
break;
|
2018-08-31 22:57:33 +10:00
|
|
|
}
|
2018-11-12 08:32:30 +01:00
|
|
|
case ClientTriggerType::RequestHousingBuildPreset:
|
|
|
|
{
|
|
|
|
auto zone = player.getCurrentZone();
|
|
|
|
auto hZone = std::dynamic_pointer_cast< HousingZone >( zone );
|
|
|
|
if (!hZone)
|
|
|
|
return;
|
|
|
|
|
|
|
|
player.setActiveLand( param11, hZone->getWardNum() );
|
|
|
|
|
2018-11-15 22:30:59 +01:00
|
|
|
auto pShowBuildPresetUIPacket = makeActorControl142( player.getId(), ShowBuildPresetUI, param11 );
|
2018-11-12 08:32:30 +01:00
|
|
|
player.queuePacket( pShowBuildPresetUIPacket );
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2018-11-13 23:46:10 +01:00
|
|
|
case ClientTriggerType::RequestLandSignFree:
|
2018-11-04 23:47:10 +01:00
|
|
|
{
|
2018-11-13 23:46:10 +01:00
|
|
|
auto ward = static_cast< uint8_t >( ( param12 & 0xFF00 ) >> 8 );
|
|
|
|
auto plot = static_cast< uint8_t >( param12 & 0xFF );
|
2018-11-16 17:07:22 +01:00
|
|
|
auto territoryId = static_cast< uint16_t >( param11 & 0xFFFF );
|
|
|
|
|
2018-11-13 23:46:10 +01:00
|
|
|
auto pHousingMgr = g_fw.get< HousingMgr >();
|
2018-11-16 17:07:22 +01:00
|
|
|
pHousingMgr->sendLandSignFree( player, ward, plot, territoryId );
|
2018-11-04 23:47:10 +01:00
|
|
|
break;
|
|
|
|
}
|
2018-11-13 23:46:10 +01:00
|
|
|
case ClientTriggerType::RequestLandSignOwned:
|
2018-11-11 14:27:39 +01:00
|
|
|
{
|
2018-11-13 23:46:10 +01:00
|
|
|
auto ward = static_cast< uint8_t >( ( param12 & 0xFF00 ) >> 8 );
|
|
|
|
auto plot = static_cast< uint8_t >( param12 & 0xFF );
|
2018-11-16 17:07:22 +01:00
|
|
|
auto territoryId = static_cast< uint16_t >( param11 & 0xFFFF );
|
|
|
|
|
2018-11-13 23:46:10 +01:00
|
|
|
auto pHousingMgr = g_fw.get< HousingMgr >();
|
2018-11-16 17:07:22 +01:00
|
|
|
pHousingMgr->sendLandSignOwned( player, ward, plot, territoryId );
|
2018-11-11 14:27:39 +01:00
|
|
|
break;
|
|
|
|
}
|
2018-11-15 22:30:59 +01:00
|
|
|
case ClientTriggerType::RequestLandRelinquish:
|
|
|
|
{
|
|
|
|
auto ward = static_cast< uint8_t >( ( param12 & 0xFF00 ) >> 8 );
|
|
|
|
auto plot = static_cast< uint8_t >( param12 & 0xFF );
|
|
|
|
auto pHousingMgr = g_fw.get< HousingMgr >();
|
2018-11-16 17:07:22 +01:00
|
|
|
|
2018-11-15 22:30:59 +01:00
|
|
|
pLog->debug( "Request to relinquish plot " + std::to_string( plot ) );
|
|
|
|
// TODO: do stuff!
|
|
|
|
break;
|
|
|
|
}
|
2018-11-13 23:46:10 +01:00
|
|
|
case ClientTriggerType::RequestEstateRename:
|
2018-11-11 14:27:39 +01:00
|
|
|
{
|
2018-11-14 10:00:16 +01:00
|
|
|
// removed temporarly, there is no such thing as a LandName
|
|
|
|
/* auto landRenamePacket = makeZonePacket< Server::FFXIVIpcLandRename >( player.getId() );
|
2018-11-11 14:27:39 +01:00
|
|
|
|
|
|
|
uint8_t ward = ( param12 & 0xFF00 ) >> 8;
|
|
|
|
uint8_t plot = ( param12 & 0xFF );
|
|
|
|
|
|
|
|
auto zone = player.getCurrentZone();
|
|
|
|
|
|
|
|
auto hZone = std::dynamic_pointer_cast< HousingZone >( zone );
|
|
|
|
|
|
|
|
auto land = hZone->getLand( plot );
|
|
|
|
|
|
|
|
if( !land )
|
|
|
|
{
|
|
|
|
auto pHousingMgr = g_fw.get< HousingMgr >();
|
|
|
|
land = pHousingMgr->getLandByOwnerId( player.getId() );
|
|
|
|
}
|
|
|
|
|
|
|
|
landRenamePacket->data().landId = land->getLandId();
|
|
|
|
landRenamePacket->data().wardNum = land->getWardNum();
|
|
|
|
landRenamePacket->data().worldId = 67;
|
|
|
|
landRenamePacket->data().zoneId = land->getZoneId();
|
2018-11-11 14:53:19 +01:00
|
|
|
memcpy( &landRenamePacket->data().landName, land->getLandName().c_str(), 20 );
|
2018-11-11 14:27:39 +01:00
|
|
|
|
2018-11-14 10:00:16 +01:00
|
|
|
player.queuePacket( landRenamePacket ); */
|
2018-11-11 14:27:39 +01:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2018-11-07 09:05:03 +01:00
|
|
|
case ClientTriggerType::RequestHousingItemUI:
|
|
|
|
{
|
2018-11-11 14:27:39 +01:00
|
|
|
uint8_t ward = ( param12 & 0xFF00 ) >> 8;
|
|
|
|
uint8_t plot = ( param12 & 0xFF );
|
2018-11-08 22:19:26 +01:00
|
|
|
auto pShowHousingItemUIPacket = makeActorControl142( 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;
|
|
|
|
}
|
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
default:
|
|
|
|
{
|
|
|
|
pLog->debug( "[" + std::to_string( m_pSession->getId() ) + "] Unhandled action: " +
|
2018-10-26 08:25:20 +02:00
|
|
|
Util::intToHexString( static_cast< uint32_t >( commandId & 0xFFFF ), 4 ) );
|
2018-08-29 21:40:59 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-08-17 16:19:20 +02:00
|
|
|
}
|