2018-03-06 22:22:19 +01:00
|
|
|
#include <Common.h>
|
2019-02-06 11:12:29 +01:00
|
|
|
#include <Vector3.cpp>
|
2018-03-06 22:22:19 +01:00
|
|
|
#include <Network/CommonNetwork.h>
|
2019-03-08 15:34:38 +01:00
|
|
|
#include <Network/GamePacket.h>
|
2018-06-23 21:38:04 +02:00
|
|
|
#include <Network/CommonActorControl.h>
|
2018-03-06 22:22:19 +01:00
|
|
|
#include <Logging/Logger.h>
|
|
|
|
#include <Network/PacketContainer.h>
|
|
|
|
#include <Network/PacketDef/Chat/ServerChatDef.h>
|
|
|
|
#include <Database/DatabaseDef.h>
|
2018-07-07 00:10:16 +02:00
|
|
|
#include <Util/Util.h>
|
2018-03-09 10:19:38 +01:00
|
|
|
|
2019-10-21 23:24:26 +02:00
|
|
|
#include <datReader/DatCategories/bg/LgbTypes.h>
|
2020-01-06 20:19:42 +11:00
|
|
|
#include <datReader/DatCategories/bg/lgb.h>
|
2019-10-21 23:24:26 +02:00
|
|
|
|
2018-02-28 10:26:03 +01:00
|
|
|
#include <unordered_map>
|
2018-07-06 23:36:50 +10:00
|
|
|
#include <Network/PacketDef/Zone/ClientZoneDef.h>
|
2018-07-07 00:10:16 +02:00
|
|
|
#include <Logging/Logger.h>
|
2020-02-29 22:30:10 +11:00
|
|
|
#include <Service.h>
|
2018-07-07 00:10:16 +02:00
|
|
|
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Network/GameConnection.h"
|
|
|
|
|
2019-07-21 22:33:33 +10:00
|
|
|
#include "Territory/Territory.h"
|
2018-12-01 00:27:16 +11:00
|
|
|
#include "Territory/HousingZone.h"
|
|
|
|
#include "Territory/Land.h"
|
|
|
|
#include "Territory/House.h"
|
2019-10-21 23:24:26 +02:00
|
|
|
#include "Territory/InstanceObjectCache.h"
|
2017-12-08 15:38:25 +01:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
#include "Linkshell/Linkshell.h"
|
|
|
|
|
2019-06-20 14:48:24 +10:00
|
|
|
#include "Network/PacketWrappers/PlayerSetupPacket.h"
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Network/PacketWrappers/PingPacket.h"
|
|
|
|
#include "Network/PacketWrappers/MoveActorPacket.h"
|
|
|
|
#include "Network/PacketWrappers/ChatPacket.h"
|
|
|
|
#include "Network/PacketWrappers/ServerNoticePacket.h"
|
2019-10-09 18:14:53 +02:00
|
|
|
#include "Network/PacketWrappers/ActorControlPacket.h"
|
|
|
|
#include "Network/PacketWrappers/ActorControlSelfPacket.h"
|
|
|
|
#include "Network/PacketWrappers/ActorControlTargetPacket.h"
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Network/PacketWrappers/EventStartPacket.h"
|
|
|
|
#include "Network/PacketWrappers/EventFinishPacket.h"
|
|
|
|
#include "Network/PacketWrappers/PlayerStateFlagsPacket.h"
|
|
|
|
|
2018-12-22 22:25:03 +01:00
|
|
|
#include "Manager/DebugCommandMgr.h"
|
2018-12-23 03:53:08 +01:00
|
|
|
#include "Manager/EventMgr.h"
|
2018-12-31 23:20:36 +11:00
|
|
|
#include "Manager/MarketMgr.h"
|
2019-01-19 21:20:23 -02:00
|
|
|
#include "Manager/TerritoryMgr.h"
|
|
|
|
#include "Manager/HousingMgr.h"
|
|
|
|
#include "Manager/RNGMgr.h"
|
2021-11-27 00:53:57 +01:00
|
|
|
#include "Manager/ChatChannelMgr.h"
|
|
|
|
#include "Manager/QuestMgr.h"
|
|
|
|
#include "Manager/LinkshellMgr.h"
|
|
|
|
#include "Manager/PartyMgr.h"
|
|
|
|
#include "Manager/PlayerMgr.h"
|
2018-03-02 07:22:25 -03:00
|
|
|
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Action/Action.h"
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-03-02 07:22:25 -03:00
|
|
|
#include "Session.h"
|
2021-11-27 00:53:57 +01:00
|
|
|
#include "WorldServer.h"
|
2018-03-02 07:22:25 -03:00
|
|
|
#include "Forwards.h"
|
2017-10-27 00:10:13 +02:00
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
using namespace Sapphire::Common;
|
|
|
|
using namespace Sapphire::Network::Packets;
|
2021-11-27 00:53:57 +01:00
|
|
|
using namespace Sapphire::Network::Packets::WorldPackets::Server;
|
|
|
|
using namespace Sapphire::Network::Packets::WorldPackets::Client;
|
|
|
|
using namespace Sapphire::Network::Packets::WorldPackets;
|
2018-11-29 16:55:48 +01:00
|
|
|
using namespace Sapphire::Network::ActorControl;
|
2018-12-01 00:27:16 +11:00
|
|
|
using namespace Sapphire::World::Manager;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::setProfileHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2019-07-29 22:22:45 +10:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcSetSearchInfo >( inPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
player.setOnlineStatusCustomMask( packet.data().OnlineStatus );
|
|
|
|
const auto status = player.getOnlineStatusCustomMask() | player.getOnlineStatusMask();
|
|
|
|
const auto selectRegion = packet.data().Region;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
player.setSearchInfo( selectRegion, 0, packet.data().SearchComment );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
if( player.isNewAdventurer() && !( status & ( static_cast< uint64_t >( 1 ) << static_cast< uint8_t >( OnlineStatus::NewAdventurer ) ) ) )
|
2018-08-29 21:40:59 +02:00
|
|
|
// mark player as not new adventurer anymore
|
|
|
|
player.setNewAdventurer( false );
|
2021-11-27 00:53:57 +01:00
|
|
|
else if( status & ( static_cast< uint64_t >( 1 ) << static_cast< uint8_t >( OnlineStatus::NewAdventurer ) ) )
|
2018-08-29 21:40:59 +02:00
|
|
|
// mark player as new adventurer
|
|
|
|
player.setNewAdventurer( true );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2019-07-29 22:22:45 +10:00
|
|
|
auto statusPacket = makeZonePacket< FFXIVIpcSetOnlineStatus >( player.getId() );
|
2018-08-29 21:40:59 +02:00
|
|
|
statusPacket->data().onlineStatusFlags = status;
|
|
|
|
queueOutPacket( statusPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto searchInfoPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcSetProfileResult >( player.getId() );
|
|
|
|
searchInfoPacket->data().OnlineStatus = status;
|
|
|
|
searchInfoPacket->data().Region = player.getSearchSelectRegion();
|
|
|
|
searchInfoPacket->data().SelectClassID = packet.data().SelectClassID;
|
|
|
|
searchInfoPacket->data().CurrentSelectClassID = packet.data().CurrentSelectClassID;
|
|
|
|
strcpy( searchInfoPacket->data().SearchComment, player.getSearchMessage() );
|
2018-08-29 21:40:59 +02:00
|
|
|
queueOutPacket( searchInfoPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2019-10-09 18:42:25 +02:00
|
|
|
player.sendToInRangeSet( makeActorControl( player.getId(), SetStatusIcon,
|
|
|
|
static_cast< uint8_t >( player.getOnlineStatus() ) ), true );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::getProfileHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto searchInfoPacket = makeZonePacket< FFXIVIpcGetProfileResult >( player.getId() );
|
|
|
|
searchInfoPacket->data().OnlineStatus = player.getOnlineStatusMask() | player.getOnlineStatusCustomMask();
|
|
|
|
searchInfoPacket->data().Region = player.getSearchSelectRegion();
|
|
|
|
strcpy( searchInfoPacket->data().SearchComment, player.getSearchMessage() );
|
2018-08-29 21:40:59 +02:00
|
|
|
queueOutPacket( searchInfoPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::getSearchCommentHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2018-09-10 14:34:24 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
auto targetId = *reinterpret_cast< const uint32_t* >( &inPacket.data[ 0x10 ] );
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& server = Common::Service< World::WorldServer >::ref();
|
2022-01-12 22:28:39 +01:00
|
|
|
auto pPlayer = server.getPlayer( targetId );
|
2018-09-10 14:34:24 +01:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
Logger::debug( "getSearchCommentHandler: {0}", targetId );
|
2018-09-10 14:34:24 +01:00
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
if( pPlayer )
|
2018-09-10 14:34:24 +01:00
|
|
|
{
|
2022-01-12 22:28:39 +01:00
|
|
|
if( pPlayer->isActingAsGm() || pPlayer->getTerritoryTypeId() != player.getTerritoryTypeId() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// retail sends the requester's id as both (isForSelf)
|
|
|
|
auto searchInfoPacket = makeZonePacket< FFXIVIpcExamineSearchComment >( player.getId() );
|
|
|
|
searchInfoPacket->data().charId = targetId;
|
|
|
|
strcpy( searchInfoPacket->data().searchComment, pPlayer->getSearchMessage() );
|
|
|
|
server.queueForPlayer( player.getCharacterId(), searchInfoPacket );
|
2018-09-10 14:34:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::reqExamineFcInfo( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2018-09-10 14:34:24 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
auto targetId = *reinterpret_cast< const uint32_t* >( &inPacket.data[ 0x18 ] );
|
2020-02-29 22:30:10 +11:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& server = Common::Service< World::WorldServer >::ref();
|
2022-01-12 22:28:39 +01:00
|
|
|
auto pPlayer = server.getPlayer( targetId );
|
2018-09-10 14:34:24 +01:00
|
|
|
|
2019-01-04 22:37:01 +11:00
|
|
|
Logger::debug( "reqExamineFcInfo: {0}", targetId );
|
2018-09-10 14:34:24 +01:00
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
if( pPlayer )
|
2018-09-10 14:34:24 +01:00
|
|
|
{
|
2022-01-12 22:28:39 +01:00
|
|
|
if( pPlayer->isActingAsGm() || pPlayer->getTerritoryTypeId() != player.getTerritoryTypeId() )
|
|
|
|
return;
|
2018-09-10 14:34:24 +01:00
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
// retail sends the requester's id as both (isForSelf)
|
|
|
|
auto examineFcInfoPacket = makeZonePacket< FFXIVIpcExamineFreeCompanyInfo >( player.getId() );
|
|
|
|
examineFcInfoPacket->data().charId = targetId;
|
|
|
|
// todo: populate with fc info
|
2018-09-25 01:11:14 +10:00
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
server.queueForPlayer( player.getCharacterId(), examineFcInfoPacket );
|
2018-09-10 14:34:24 +01:00
|
|
|
}
|
2022-01-12 22:28:39 +01:00
|
|
|
|
2018-09-10 14:34:24 +01:00
|
|
|
}
|
|
|
|
|
2021-12-04 21:53:04 +01:00
|
|
|
void Sapphire::Network::GameConnection::joinChatChannelHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2021-11-27 00:53:57 +01:00
|
|
|
{
|
|
|
|
const auto joinChannelPacket = ZoneChannelPacket< Client::FFXIVIpcJoinChatChannel >( inPacket );
|
|
|
|
const uint64_t channelIdReq = joinChannelPacket.data().ChannelID;
|
|
|
|
|
|
|
|
auto& chatChannelMgr = Common::Service< ChatChannelMgr >::ref();
|
|
|
|
|
|
|
|
if( !chatChannelMgr.isChannelValid( joinChannelPacket.data().ChannelID ) )
|
|
|
|
return Logger::warn( "Failed to join chat channel - Invalid chat channel specified!" );
|
|
|
|
|
|
|
|
chatChannelMgr.addPlayerToChannel( joinChannelPacket.data().ChannelID, player );
|
|
|
|
|
|
|
|
auto chatChannelResultPacket = makeZonePacket< FFXIVIpcChatChannelResult >( player.getId() );
|
|
|
|
|
|
|
|
chatChannelResultPacket->data().ChannelID = channelIdReq;
|
|
|
|
chatChannelResultPacket->data().TargetCharacterID = player.getId();
|
|
|
|
chatChannelResultPacket->data().CommunityID = player.getCharacterId();
|
|
|
|
chatChannelResultPacket->data().UpPacketNo = 0; // todo: define behavior
|
|
|
|
chatChannelResultPacket->data().Result = 0; // todo: define behavior
|
|
|
|
|
|
|
|
queueOutPacket( chatChannelResultPacket );
|
|
|
|
|
|
|
|
auto joinChannelResultPacket = makeChatPacket< Packets::Server::FFXIVJoinChannelResult >( player.getId() );
|
|
|
|
|
|
|
|
joinChannelResultPacket->data().channelID = channelIdReq;
|
|
|
|
joinChannelResultPacket->data().characterID = player.getId();
|
|
|
|
joinChannelResultPacket->data().result = 0;
|
|
|
|
|
|
|
|
auto& server = Common::Service< World::WorldServer >::ref();
|
|
|
|
auto pSession = server.getSession( player.getCharacterId() );
|
|
|
|
|
|
|
|
if( !pSession )
|
|
|
|
{
|
|
|
|
Logger::error( std::string( __FUNCTION__ ) + ": Session not found for player#{}", player.getCharacterId() );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pSession->getChatConnection()->queueOutPacket( joinChannelResultPacket );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::moveHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
// if the player is marked for zoning we no longer want to update his pos
|
|
|
|
if( player.isMarkedForZoning() )
|
|
|
|
return;
|
|
|
|
|
2019-07-29 22:22:45 +10:00
|
|
|
const auto updatePositionPacket = ZoneChannelPacket< Client::FFXIVIpcUpdatePosition >( inPacket );
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& data = updatePositionPacket.data();
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2019-02-06 08:49:57 +01:00
|
|
|
bool bPosChanged = true;
|
2021-11-27 00:53:57 +01:00
|
|
|
if( data.pos.x == player.getPos().x && data.pos.y == player.getPos().y && data.pos.z == player.getPos().z )
|
2019-02-06 08:49:57 +01:00
|
|
|
bPosChanged = false;
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
//if( !bPosChanged && player.getRot() == data.rotation )
|
2019-02-06 08:49:57 +01:00
|
|
|
//return;
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
player.setRot( data.dir );
|
|
|
|
player.setPos( { data.pos.x, data.pos.y, data.pos.z } );
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2022-01-14 12:51:37 +01:00
|
|
|
if( player.getCurrentAction() && bPosChanged && player.getCurrentAction()->getCastTimeRest() > 500 )
|
2019-02-10 21:21:34 +11:00
|
|
|
player.getCurrentAction()->setInterrupted( Common::ActionInterruptType::RegularInterrupt );
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto clientAnimationType = data.flag;
|
|
|
|
auto animationState = data.flag;
|
|
|
|
auto animationType = data.flag2;
|
2022-01-05 20:56:02 -03:00
|
|
|
auto animColType = data.flag2;
|
2021-11-27 00:53:57 +01:00
|
|
|
auto headRotation = data.flag_unshared;
|
2019-02-06 18:51:51 +01:00
|
|
|
uint8_t orgAnimationType = animationType;
|
2019-02-06 09:27:30 +01:00
|
|
|
uint8_t unknownRotation = 0;
|
2019-02-06 08:49:57 +01:00
|
|
|
uint16_t animationSpeed = MoveSpeed::Walk;
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2019-02-06 08:49:57 +01:00
|
|
|
animationType |= clientAnimationType;
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2019-02-06 09:38:31 +01:00
|
|
|
if( animationType & MoveType::Strafing )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2019-02-06 08:49:57 +01:00
|
|
|
if( animationType & MoveType::Walking )
|
|
|
|
headRotation = 0xFF;
|
|
|
|
else if( headRotation < 0x7F )
|
|
|
|
headRotation += 0x7F;
|
|
|
|
else if( headRotation > 0x7F )
|
|
|
|
headRotation -= 0x7F;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2019-02-06 08:49:57 +01:00
|
|
|
if( animationType == MoveType::Running )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2019-02-06 08:49:57 +01:00
|
|
|
headRotation = 0x7F;
|
|
|
|
animationSpeed = MoveSpeed::Run;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2019-02-06 09:27:30 +01:00
|
|
|
if( animationType & MoveType::Jumping )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2022-01-05 20:56:02 -03:00
|
|
|
|
|
|
|
if( animColType == MoveState::LeaveCollision )
|
2019-02-06 18:51:51 +01:00
|
|
|
{
|
|
|
|
if( orgAnimationType & clientAnimationType )
|
|
|
|
animationType += 0x10;
|
|
|
|
else
|
|
|
|
animationType += 0x04;
|
|
|
|
}
|
2022-01-05 20:56:02 -03:00
|
|
|
|
|
|
|
if( animColType == MoveState::LeaveCollision || animColType == MoveState::StartFalling )
|
2019-02-06 18:51:51 +01:00
|
|
|
{
|
2022-01-05 20:56:02 -03:00
|
|
|
player.setFalling( true, { data.pos.x, data.pos.y, data.pos.z } );
|
2019-02-06 18:51:51 +01:00
|
|
|
}
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
|
2022-01-05 20:56:02 -03:00
|
|
|
if( animColType == MoveState::EnterCollision )
|
|
|
|
{
|
|
|
|
animationType = 2;
|
|
|
|
player.setFalling( false, { data.pos.x, data.pos.y, data.pos.z } );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( player.isFalling() )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2019-02-06 08:49:57 +01:00
|
|
|
animationType += 0x10;
|
2019-02-06 09:27:30 +01:00
|
|
|
unknownRotation = 0x7F;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
uint64_t currentTime = Util::getTimeMs();
|
2018-07-07 00:10:16 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
player.m_lastMoveTime = currentTime;
|
2019-02-06 08:49:57 +01:00
|
|
|
player.m_lastMoveflag = animationType;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2022-01-05 20:56:02 -03:00
|
|
|
// if no one is in range, don't bother trying to send a position update
|
|
|
|
if( !player.hasInRangeActor() )
|
|
|
|
return;
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
//auto movePacket = std::make_shared< MoveActorPacket >( player, headRotation, animationType, animationState, animationSpeed, unknownRotation );
|
|
|
|
auto movePacket = std::make_shared< MoveActorPacket >( player, headRotation, data.flag, data.flag2, animationSpeed, unknownRotation );
|
2019-02-06 18:51:51 +01:00
|
|
|
player.sendToInRangeSet( movePacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::configHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2017-10-05 20:24:58 +02:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcConfig >( inPacket );
|
2018-05-17 20:46:11 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
player.setEquipDisplayFlags( packet.data().flag );
|
|
|
|
Service< World::Manager::PlayerMgr >::ref().onEquipDisplayFlagsChanged( player );
|
2017-10-05 20:24:58 +02:00
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
void Sapphire::Network::GameConnection::zoneJumpHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcZoneJump >( inPacket );
|
|
|
|
auto& data = packet.data();
|
|
|
|
const auto exitBoxId = data.ExitBox;
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
auto& teriMgr = Common::Service< TerritoryMgr >::ref();
|
|
|
|
auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref();
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& server = Common::Service< World::WorldServer >::ref();
|
2022-01-10 23:50:44 +01:00
|
|
|
|
|
|
|
auto pTeri = teriMgr.getTerritoryByGuId( player.getTerritoryId() );
|
|
|
|
auto tInfo = pTeri->getTerritoryTypeInfo();
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto pExitRange = instanceObjectCache.getExitRange( player.getTerritoryTypeId(), exitBoxId );
|
2018-08-29 21:40:59 +02:00
|
|
|
|
|
|
|
Common::FFXIVARR_POSITION3 targetPos{};
|
2021-11-27 00:53:57 +01:00
|
|
|
Common::FFXIVARR_POSITION3 targetRot{};
|
2022-01-12 22:28:39 +01:00
|
|
|
uint32_t targetZone{128};
|
2019-10-27 08:26:48 +01:00
|
|
|
float rotation = 0.0f;
|
|
|
|
|
2019-10-21 23:24:26 +02:00
|
|
|
if( pExitRange )
|
|
|
|
{
|
2020-03-01 01:00:57 +11:00
|
|
|
auto pPopRange = instanceObjectCache.getPopRange( pExitRange->data.destTerritoryType,
|
2022-01-07 21:22:55 +01:00
|
|
|
pExitRange->data.destInstanceObjectId );
|
2019-10-21 23:24:26 +02:00
|
|
|
if( pPopRange )
|
|
|
|
{
|
2019-10-22 22:34:34 +02:00
|
|
|
targetZone = pExitRange->data.destTerritoryType;
|
2021-11-27 00:53:57 +01:00
|
|
|
|
|
|
|
|
2019-10-21 23:24:26 +02:00
|
|
|
targetPos = Common::FFXIVARR_POSITION3 { pPopRange->header.transform.translation.x,
|
|
|
|
pPopRange->header.transform.translation.y,
|
|
|
|
pPopRange->header.transform.translation.z };
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
targetRot = Common::FFXIVARR_POSITION3 { pPopRange->header.transform.rotation.x,
|
|
|
|
pPopRange->header.transform.rotation.y,
|
|
|
|
pPopRange->header.transform.rotation.z };
|
|
|
|
|
|
|
|
rotation = Util::eulerToDirection( targetRot );
|
|
|
|
|
|
|
|
|
|
|
|
PlayerMgr::sendDebug( player, "ZoneLine #{0} found. Rotation: {1} {2} {3} - {4}", exitBoxId,
|
|
|
|
pPopRange->header.transform.rotation.x,
|
|
|
|
pPopRange->header.transform.rotation.y,
|
|
|
|
pPopRange->header.transform.rotation.z,
|
|
|
|
rotation );
|
2019-10-21 23:24:26 +02:00
|
|
|
|
2022-01-15 22:48:27 +01:00
|
|
|
server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), WarpStart,
|
|
|
|
Common::WarpType::WARP_TYPE_EXIT_RANGE, player.getId(), 0x01, targetZone ) );
|
2022-01-07 21:22:55 +01:00
|
|
|
|
|
|
|
auto moveTerritoryPacket = makeZonePacket< FFXIVIpcMoveTerritory >( player.getId() );
|
|
|
|
moveTerritoryPacket->data().index = -1;
|
|
|
|
moveTerritoryPacket->data().territoryType = targetZone;
|
2022-01-11 00:18:00 +01:00
|
|
|
moveTerritoryPacket->data().zoneId = player.getTerritoryTypeId();
|
2022-01-07 21:22:55 +01:00
|
|
|
moveTerritoryPacket->data().worldId = server.getWorldId();
|
|
|
|
moveTerritoryPacket->data().worldId1 = server.getWorldId();
|
|
|
|
moveTerritoryPacket->data().landId = -1;
|
|
|
|
moveTerritoryPacket->data().landSetId = -1;
|
|
|
|
moveTerritoryPacket->data().landTerritoryId = -1;
|
|
|
|
strcpy( moveTerritoryPacket->data().worldName, "Sapphire" );
|
|
|
|
server.queueForPlayer( player.getCharacterId(), moveTerritoryPacket );
|
2019-10-21 23:24:26 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendDebug( player, "Walking ZoneLine#{0}", exitBoxId );
|
2019-10-21 23:24:26 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
player.performZoning( targetZone, targetPos, rotation );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::newDiscoveryHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& server = Common::Service< World::WorldServer >::ref();
|
2022-01-10 23:50:44 +01:00
|
|
|
auto& teriMgr = Common::Service< TerritoryMgr >::ref();
|
2020-03-01 01:00:57 +11:00
|
|
|
auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref();
|
2022-01-10 23:50:44 +01:00
|
|
|
auto pTeri = teriMgr.getTerritoryByGuId( player.getTerritoryId() );
|
|
|
|
auto tInfo = pTeri->getTerritoryTypeInfo();
|
2021-11-27 00:53:57 +01:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcNewDiscovery >( inPacket );
|
|
|
|
const auto layoutId = packet.data().LayoutId;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto pRefInfo = instanceObjectCache.getMapRange( player.getTerritoryTypeId(), layoutId );
|
2018-03-09 10:19:38 +01:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
PlayerMgr::sendDebug( player, "Discovery ref pos id#{0}", layoutId );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2019-10-21 23:24:26 +02:00
|
|
|
if( pRefInfo )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto discoveryPacket = makeZonePacket< FFXIVIpcDiscoveryReply >( player.getId() );
|
|
|
|
discoveryPacket->data().mapId = tInfo->data().Map;
|
2019-10-22 22:34:34 +02:00
|
|
|
discoveryPacket->data().mapPartId = pRefInfo->data.discoveryIndex;
|
2021-11-27 00:53:57 +01:00
|
|
|
server.queueForPlayer( player.getCharacterId(), discoveryPacket );
|
|
|
|
player.discover( tInfo->data().Map, pRefInfo->data.discoveryIndex );
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-12-01 01:03:36 +01:00
|
|
|
void Sapphire::Network::GameConnection::loginHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref();
|
2018-08-29 21:40:59 +02:00
|
|
|
// init handler means this is a login procedure
|
|
|
|
player.setIsLogin( true );
|
2022-01-12 11:11:47 +01:00
|
|
|
player.setConnected( true );
|
2021-12-01 00:05:34 +01:00
|
|
|
teriMgr.joinWorld( player );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::syncHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& server = Common::Service< World::WorldServer >::ref();
|
2019-07-29 22:22:45 +10:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcPingHandler >( inPacket );
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& data = packet.data();
|
2018-06-18 23:03:39 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
queueOutPacket( std::make_shared< WorldPackets::Server::PingPacket >( player, data.clientTimeValue ) );
|
|
|
|
|
|
|
|
auto pSession = server.getSession( player.getCharacterId() );
|
|
|
|
if( !pSession )
|
|
|
|
return;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
pSession->setLastPing( Common::Util::getTimeSeconds() );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::setLanguageHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2021-12-20 00:06:52 +01:00
|
|
|
if( player.isLogin() )
|
|
|
|
{
|
|
|
|
auto &questMgr = Common::Service< World::Manager::QuestMgr >::ref();
|
|
|
|
questMgr.sendQuestsInfo( player );
|
|
|
|
}
|
2021-11-27 00:53:57 +01:00
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
auto& teriMgr = Common::Service< TerritoryMgr >::ref();
|
|
|
|
auto pCurrentZone = teriMgr.getTerritoryByGuId( player.getTerritoryId() );
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref();
|
|
|
|
|
|
|
|
/* // TODO: load and save this data instead of hardcoding
|
|
|
|
auto gcPacket = makeZonePacket< FFXIVGCAffiliation >( player.getId() );
|
|
|
|
gcPacket->data().gcId = player.getGc();
|
|
|
|
gcPacket->data().gcRank[ 0 ] = player.getGcRankArray()[ 0 ];
|
|
|
|
gcPacket->data().gcRank[ 1 ] = player.getGcRankArray()[ 1 ];
|
|
|
|
gcPacket->data().gcRank[ 2 ] = player.getGcRankArray()[ 2 ];
|
|
|
|
player.queuePacket( gcPacket );*/
|
2018-11-10 19:00:13 +01:00
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
pCurrentZone->onFinishLoading( player );
|
2018-02-07 00:00:48 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// player is done zoning
|
|
|
|
player.setLoadingComplete( true );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// if this is a login event
|
|
|
|
if( player.isLogin() )
|
|
|
|
{
|
|
|
|
// fire the onLogin Event
|
2021-11-27 00:53:57 +01:00
|
|
|
playerMgr.onLogin( player );
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// spawn the player for himself
|
|
|
|
player.spawn( player.getAsPlayer() );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// notify the zone of a change in position to force an "inRangeActor" update
|
2022-01-10 23:50:44 +01:00
|
|
|
pCurrentZone->updateActorPosition( player );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::pcSearchHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcPcSearch >( inPacket );
|
|
|
|
auto& data = packet.data();
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
// TODO: implement player search
|
|
|
|
auto& server = Common::Service< World::WorldServer >::ref();
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
bool isLastName = data.CharacterName[ 0 ] == ' ';
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
std::string queryName = data.CharacterName;
|
|
|
|
if( !isLastName )
|
|
|
|
queryName += " ";
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
// on lastName, client automatically adds a space to first character - no need to manually add space
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto queryPlayers = server.searchSessionByName( queryName );
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
// store result in player - we don't map out query keys to data yet
|
|
|
|
std::vector< uint32_t > entityIdVec;
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
for( const auto& pSession : queryPlayers )
|
2021-11-27 00:53:57 +01:00
|
|
|
{
|
|
|
|
if( !pSession )
|
|
|
|
continue;
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
entityIdVec.emplace_back( pSession->getPlayer()->getId() );
|
|
|
|
}
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
player.setLastPcSearchResult( entityIdVec );
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
// send amount of results found - client requires this to "enable" displaying new queries
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto pcSearchResultPacket = makeZonePacket< FFXIVIpcPcSearchResult >( player.getId() );
|
|
|
|
pcSearchResultPacket->data().ResultCount = static_cast< int16_t >( entityIdVec.size() );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
queueOutPacket( pcSearchResultPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
void Sapphire::Network::GameConnection::chatHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2020-03-01 01:00:57 +11:00
|
|
|
auto& debugCommandMgr = Common::Service< DebugCommandMgr >::ref();
|
2022-01-10 23:50:44 +01:00
|
|
|
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref();
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2019-07-29 22:22:45 +10:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcChatHandler >( inPacket );
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& data = packet.data();
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
auto pCurrentZone = teriMgr.getTerritoryByGuId( player.getTerritoryId() );
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
if( data.message[ 0 ] == '!' )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
|
|
|
// execute game console command
|
2021-11-27 00:53:57 +01:00
|
|
|
debugCommandMgr.execCommand( const_cast< char* >( data.message ) + 1, player );
|
2018-08-29 21:40:59 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto chatType = packet.data().chatType;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
//ToDo, need to implement sending GM chat types.
|
2021-11-27 00:53:57 +01:00
|
|
|
auto chatPacket = std::make_shared< WorldPackets::Server::ChatPacket >( player, chatType, data.message );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
switch( chatType )
|
|
|
|
{
|
|
|
|
case ChatType::Say:
|
|
|
|
{
|
|
|
|
if( player.isActingAsGm() )
|
2021-11-27 00:53:57 +01:00
|
|
|
chatPacket->data().type = static_cast< uint16_t >( ChatType::GMSay );
|
2018-04-18 21:00:20 +10:00
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
pCurrentZone->queuePacketForRange( player, 50.f, chatPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case ChatType::Yell:
|
|
|
|
{
|
2018-07-01 21:33:37 +10:00
|
|
|
if( player.isActingAsGm() )
|
2021-11-27 00:53:57 +01:00
|
|
|
chatPacket->data().type = static_cast< uint16_t >( ChatType::GMYell );
|
2018-04-18 21:00:20 +10:00
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
pCurrentZone->queuePacketForRange( player, 6000.f, chatPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
case ChatType::Shout:
|
|
|
|
{
|
2018-07-01 21:33:37 +10:00
|
|
|
if( player.isActingAsGm() )
|
2021-11-27 00:53:57 +01:00
|
|
|
chatPacket->data().type = static_cast< uint16_t >( ChatType::GMShout );
|
2018-04-18 21:00:20 +10:00
|
|
|
|
2022-01-10 23:50:44 +01:00
|
|
|
pCurrentZone->queuePacketForRange( player, 6000.f, chatPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
2022-01-10 23:50:44 +01:00
|
|
|
pCurrentZone->queuePacketForRange( player, 50.f, chatPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: this handler needs to be improved for timed logout, also the session should be instantly removed
|
|
|
|
// currently we wait for the session to just time out after logout, this can be a problem is the user tries to
|
|
|
|
// log right back in.
|
|
|
|
// Also the packet needs to be converted to an ipc structure
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::logoutHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto logoutPacket = makeZonePacket< FFXIVIpcEnableLogout >( player.getId() );
|
|
|
|
logoutPacket->data().content = 0x02;
|
|
|
|
// logoutPacket->data().flags2 = 0x2000;
|
2018-08-29 21:40:59 +02:00
|
|
|
queueOutPacket( logoutPacket );
|
2017-11-14 23:55:38 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
player.setMarkedForRemoval();
|
2017-08-22 21:36:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::tellHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2017-08-22 21:36:20 +02:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcChatTo >( inPacket );
|
|
|
|
auto& data = packet.data();
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& server = Common::Service< World::WorldServer >::ref();
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto pSession = server.getSession( data.toName );
|
2018-08-29 21:40:59 +02:00
|
|
|
|
|
|
|
if( !pSession )
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto tellErrPacket = makeZonePacket< Packets::Server::FFXIVIpcTellNotFound >( player.getId() );
|
|
|
|
strcpy( tellErrPacket->data().toName, data.toName );
|
2018-08-29 21:40:59 +02:00
|
|
|
sendSinglePacket( tellErrPacket );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto pTargetPlayer = pSession->getPlayer();
|
|
|
|
|
|
|
|
if( pTargetPlayer->hasStateFlag( PlayerStateFlag::BetweenAreas ) )
|
|
|
|
{
|
|
|
|
// send error for player between areas
|
|
|
|
// TODO: implement me
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto pSessionSource = server.getSession( player.getCharacterId() );
|
|
|
|
|
|
|
|
if( !pSession )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
Logger::error( std::string( __FUNCTION__ ) + ": Session not found for player#{}", player.getCharacterId() );
|
2018-08-29 21:40:59 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
if( pTargetPlayer->hasStateFlag( PlayerStateFlag::BoundByDuty ) && !player.isActingAsGm() )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto boundPacket = makeChatPacket< Packets::Server::FFXIVRecvFinderStatus >( player.getId() );
|
|
|
|
strcpy( boundPacket->data().toName, data.toName );
|
|
|
|
pSessionSource->getChatConnection()->queueOutPacket( boundPacket );
|
2018-08-29 21:40:59 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
if( pTargetPlayer->getOnlineStatus() == OnlineStatus::Busy && !player.isActingAsGm() )
|
2019-01-06 02:03:33 +01:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
auto busyPacket = makeChatPacket< Packets::Server::FFXIVRecvBusyStatus >( player.getId() );
|
|
|
|
strcpy( busyPacket->data().toName, data.toName );
|
|
|
|
pSessionSource->getChatConnection()->queueOutPacket( busyPacket );
|
2018-11-28 21:59:28 +11:00
|
|
|
return;
|
2021-11-27 00:53:57 +01:00
|
|
|
}
|
2018-11-28 21:59:28 +11:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto tellPacket = makeChatPacket< Packets::Server::FFXIVChatFrom >( player.getId() );
|
|
|
|
strcpy( tellPacket->data().message, data.message );
|
|
|
|
strcpy( tellPacket->data().fromName, player.getName().c_str() );
|
|
|
|
tellPacket->data().fromCharacterID = player.getCharacterId();
|
2018-12-26 18:11:18 +11:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
if( player.isActingAsGm() )
|
2018-12-30 21:26:32 +11:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
tellPacket->data().type |= ChatFromType::GmTellMsg; //TODO: Is there an enum for this? or is it only GM?
|
2018-12-30 21:26:32 +11:00
|
|
|
}
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
pSession->getChatConnection()->queueOutPacket( tellPacket );
|
2018-12-27 15:52:48 +11:00
|
|
|
}
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::chatToChannelHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2018-12-27 15:52:48 +11:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
const auto packet = ChatChannelPacket< Client::FFXIVIpcChatToChannel >( inPacket );
|
|
|
|
auto& data = packet.data();
|
2018-12-27 15:52:48 +11:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
auto& chatChannelMgr = Common::Service< ChatChannelMgr >::ref();
|
2018-12-27 15:52:48 +11:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
std::string message = std::string( data.message );
|
2018-12-31 23:20:36 +11:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
chatChannelMgr.sendMessageToChannel( data.channelID, player, message );
|
2021-02-06 05:18:26 +09:00
|
|
|
}
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::catalogSearch( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2018-12-31 23:20:36 +11:00
|
|
|
{
|
2020-03-01 01:00:57 +11:00
|
|
|
auto& marketMgr = Common::Service< MarketMgr >::ref();
|
2018-12-31 23:20:36 +11:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcCatalogSearch >( inPacket );
|
2018-12-31 23:20:36 +11:00
|
|
|
const auto& data = packet.data();
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
marketMgr.searchMarketboard(
|
|
|
|
player,
|
|
|
|
data.SearchCategory,
|
|
|
|
data.MaxLevel,
|
|
|
|
data.ClassJob,
|
|
|
|
data.ItemName,
|
|
|
|
data.RequestKey,
|
|
|
|
data.NextIndex
|
|
|
|
);
|
2019-01-01 11:51:48 +11:00
|
|
|
}
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::marketBoardRequestItemInfo( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2019-01-01 11:51:48 +11:00
|
|
|
{
|
2019-07-29 22:22:45 +10:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcMarketBoardRequestItemListingInfo >( inPacket );
|
2019-01-01 11:51:48 +11:00
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
auto& marketMgr = Common::Service< MarketMgr >::ref();
|
2019-01-01 17:29:06 +11:00
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
marketMgr.requestItemListingInfo( player, packet.data().catalogId, packet.data().requestId );
|
2019-01-01 17:29:06 +11:00
|
|
|
}
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::marketBoardRequestItemListings( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2019-01-01 17:29:06 +11:00
|
|
|
{
|
2019-07-29 22:22:45 +10:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcMarketBoardRequestItemListings >( inPacket );
|
2019-01-01 17:29:06 +11:00
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
auto& marketMgr = Common::Service< MarketMgr >::ref();
|
2019-01-01 17:29:06 +11:00
|
|
|
|
2020-03-01 01:00:57 +11:00
|
|
|
marketMgr.requestItemListings( player, packet.data().itemCatalogId );
|
2019-03-08 15:34:38 +01:00
|
|
|
}
|
2020-06-15 08:34:10 +09:00
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::getFcStatus( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2020-06-15 08:34:10 +09:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::getFcProfile( const Sapphire::Network::Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2021-11-27 00:53:57 +01:00
|
|
|
{
|
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcGetFcProfile >( inPacket );
|
|
|
|
|
|
|
|
auto& server = Common::Service< World::WorldServer >::ref();
|
|
|
|
|
|
|
|
auto resultPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcGetFcProfileResult >( player.getId() );
|
|
|
|
resultPacket->data().TargetCharacterID = packet.data().TargetCharacterID;
|
|
|
|
resultPacket->data().TargetEntityID = packet.data().TargetEntityID;
|
|
|
|
|
|
|
|
// haha test code
|
|
|
|
resultPacket->data().FreeCompanyID = 1;
|
|
|
|
resultPacket->data().CrestID = 0x0001000100010001;
|
|
|
|
resultPacket->data().LandID = Common::INVALID_GAME_OBJECT_ID64;
|
|
|
|
resultPacket->data().OnlineMemberCount = 69;
|
|
|
|
resultPacket->data().TotalMemberCount = 420;
|
|
|
|
resultPacket->data().JoinRequestCount = 69;
|
|
|
|
resultPacket->data().FcRank = 1;
|
|
|
|
resultPacket->data().FcStatus = 1;
|
|
|
|
resultPacket->data().FcRole = 1;
|
|
|
|
resultPacket->data().FcActivity = 1;
|
|
|
|
resultPacket->data().GrandCompanyID = 1;
|
|
|
|
resultPacket->data().CreateDate = 1587305592;
|
|
|
|
resultPacket->data().Reputation = 500;
|
|
|
|
resultPacket->data().FcActiveTimeFlag = 0xFF;
|
|
|
|
resultPacket->data().FcJoinRequestFlag = 0xFF;
|
|
|
|
strcpy( resultPacket->data().MasterCharacterName, "Biggus Dickus" );
|
|
|
|
strcpy( resultPacket->data().FcTag, "Wang" );
|
|
|
|
strcpy( resultPacket->data().FreeCompanyName, "Test FC" );
|
|
|
|
strcpy( resultPacket->data().CompanyMotto, "nobody here but us chickens" );
|
|
|
|
|
|
|
|
|
|
|
|
server.queueForPlayer( player.getCharacterId(), resultPacket );
|
|
|
|
|
2020-11-14 06:15:10 +09:00
|
|
|
}
|
|
|
|
|
2022-01-12 22:28:39 +01:00
|
|
|
void Sapphire::Network::GameConnection::getRequestItemListHandler( const Sapphire::Network::Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
2020-11-14 06:15:10 +09:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
|
|
|
|
}
|