2018-03-02 07:22:25 -03:00
|
|
|
#include <boost/format.hpp>
|
|
|
|
|
2018-03-06 22:22:19 +01:00
|
|
|
#include <Common.h>
|
|
|
|
#include <Network/CommonNetwork.h>
|
|
|
|
#include <Network/GamePacketNew.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
|
|
|
|
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>
|
|
|
|
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Network/GameConnection.h"
|
|
|
|
|
2018-01-27 23:52:49 +01:00
|
|
|
#include "Zone/TerritoryMgr.h"
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Zone/Zone.h"
|
|
|
|
#include "Zone/ZonePosition.h"
|
|
|
|
|
|
|
|
#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"
|
|
|
|
#include "Network/PacketWrappers/ActorControlPacket143.h"
|
|
|
|
#include "Network/PacketWrappers/ActorControlPacket144.h"
|
|
|
|
#include "Network/PacketWrappers/EventStartPacket.h"
|
|
|
|
#include "Network/PacketWrappers/EventFinishPacket.h"
|
|
|
|
#include "Network/PacketWrappers/PlayerStateFlagsPacket.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-08 13:53:47 +02:00
|
|
|
|
2018-03-02 07:22:25 -03:00
|
|
|
#include "Session.h"
|
|
|
|
#include "ServerZone.h"
|
|
|
|
#include "Forwards.h"
|
|
|
|
#include "Framework.h"
|
2017-10-27 00:10:13 +02:00
|
|
|
|
2018-03-09 10:19:38 +01:00
|
|
|
extern Core::Framework g_fw;
|
2017-08-08 13:53:47 +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-08 13:53:47 +02:00
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::fcInfoReqHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
// TODO: use new packet struct for this
|
|
|
|
//GamePacketPtr pPe( new GamePacket( 0xDD, 0x78, player.getId(), player.getId() ) );
|
|
|
|
//pPe->setValAt< uint8_t >( 0x48, 0x01 );
|
|
|
|
//queueOutPacket( pPe );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::setSearchInfoHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcSetSearchInfo >( inPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-10-14 23:31:52 +11:00
|
|
|
const auto inval = packet.data().status1;
|
|
|
|
const auto inval1 = packet.data().status2;
|
|
|
|
const auto status = packet.data().status;
|
|
|
|
const auto selectRegion = packet.data().language;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
player.setSearchInfo( selectRegion, 0, packet.data().searchComment );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
player.setOnlineStatusMask( status );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( player.isNewAdventurer() && !( inval & 0x01000000 ) )
|
|
|
|
// mark player as not new adventurer anymore
|
|
|
|
player.setNewAdventurer( false );
|
|
|
|
else if( inval & 0x01000000 )
|
|
|
|
// mark player as new adventurer
|
|
|
|
player.setNewAdventurer( true );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto statusPacket = makeZonePacket< FFXIVIpcSetOnlineStatus >( player.getId() );
|
|
|
|
statusPacket->data().onlineStatusFlags = status;
|
|
|
|
queueOutPacket( statusPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto searchInfoPacket = makeZonePacket< FFXIVIpcSetSearchInfo >( player.getId() );
|
|
|
|
searchInfoPacket->data().onlineStatusFlags = status;
|
|
|
|
searchInfoPacket->data().selectRegion = player.getSearchSelectRegion();
|
|
|
|
strcpy( searchInfoPacket->data().searchMessage, player.getSearchMessage() );
|
|
|
|
queueOutPacket( searchInfoPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
player.sendToInRangeSet( makeActorControl142( player.getId(), SetStatusIcon,
|
|
|
|
static_cast< uint8_t >( player.getOnlineStatus() ) ), true );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::reqSearchInfoHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto searchInfoPacket = makeZonePacket< FFXIVIpcInitSearchInfo >( player.getId() );
|
|
|
|
searchInfoPacket->data().onlineStatusFlags = player.getOnlineStatusMask();
|
|
|
|
searchInfoPacket->data().selectRegion = player.getSearchSelectRegion();
|
|
|
|
strcpy( searchInfoPacket->data().searchMessage, player.getSearchMessage() );
|
|
|
|
queueOutPacket( searchInfoPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-10 14:34:24 +01:00
|
|
|
void Core::Network::GameConnection::reqExamineSearchCommentHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
|
|
|
Entity::Player& player )
|
|
|
|
{
|
|
|
|
|
|
|
|
auto targetId = *reinterpret_cast< const uint32_t* >( &inPacket.data[ 0x10 ] );
|
|
|
|
auto pSession = g_fw.get< Core::ServerZone >()->getSession( targetId );
|
|
|
|
|
|
|
|
g_fw.get< Core::Logger >()->debug( std::to_string( targetId ) );
|
|
|
|
|
|
|
|
if( pSession )
|
|
|
|
{
|
|
|
|
auto pPlayer = pSession->getPlayer();
|
|
|
|
|
|
|
|
if( pPlayer )
|
|
|
|
{
|
2018-09-25 01:24:50 +10:00
|
|
|
if( pPlayer->isActingAsGm() || pPlayer->getZoneId() != player.getZoneId() )
|
|
|
|
return;
|
2018-09-25 01:11:14 +10:00
|
|
|
|
2018-09-10 14:34:24 +01:00
|
|
|
// 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() );
|
|
|
|
player.queuePacket( searchInfoPacket );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Core::Network::GameConnection::reqExamineFcInfo( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
|
|
|
Entity::Player& player )
|
|
|
|
{
|
|
|
|
|
|
|
|
auto targetId = *reinterpret_cast< const uint32_t* >( &inPacket.data[ 0x18 ] );
|
|
|
|
auto pSession = g_fw.get< Core::ServerZone >()->getSession( targetId );
|
|
|
|
|
|
|
|
g_fw.get< Core::Logger >()->debug( std::to_string( targetId ) );
|
|
|
|
|
|
|
|
if( pSession )
|
|
|
|
{
|
|
|
|
auto pPlayer = pSession->getPlayer();
|
|
|
|
|
|
|
|
if( pPlayer )
|
|
|
|
{
|
2018-09-25 01:24:50 +10:00
|
|
|
if( pPlayer->isActingAsGm() || pPlayer->getZoneId() != player.getZoneId() )
|
|
|
|
return;
|
2018-09-25 01:11:14 +10:00
|
|
|
|
2018-09-10 14:34:24 +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
|
|
|
|
|
|
|
|
player.queuePacket( examineFcInfoPacket );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::linkshellListHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto linkshellListPacket = makeZonePacket< FFXIVIpcLinkshellList >( player.getId() );
|
|
|
|
queueOutPacket( linkshellListPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::updatePositionHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
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;
|
|
|
|
|
|
|
|
Packets::FFXIVARR_PACKET_RAW copy = inPacket;
|
|
|
|
|
|
|
|
struct testMov
|
|
|
|
{
|
|
|
|
uint32_t specialMovement : 23; // 0x00490FDA
|
|
|
|
uint32_t strafe : 7;
|
|
|
|
uint32_t moveBackward : 1;
|
|
|
|
uint32_t strafeRight : 1; // if 0, strafe left.
|
|
|
|
} IPC_OP_019A;
|
|
|
|
|
|
|
|
struct testMov1
|
|
|
|
{
|
|
|
|
uint16_t bit1 : 1; // 0x00490FDA
|
|
|
|
uint16_t bit2 : 1;
|
|
|
|
uint16_t bit3 : 1;
|
|
|
|
uint16_t bit4 : 1;
|
|
|
|
uint16_t bit5 : 1;
|
|
|
|
uint16_t bit6 : 1;
|
|
|
|
uint16_t bit7 : 1;
|
|
|
|
uint16_t bit8 : 1;
|
|
|
|
uint16_t bit9 : 1; // 0x00490FDA
|
|
|
|
uint16_t bit10 : 1;
|
|
|
|
uint16_t bit11 : 1;
|
|
|
|
uint16_t bit12 : 1;
|
|
|
|
uint16_t bit13 : 1;
|
|
|
|
uint16_t bit14 : 1;
|
|
|
|
uint16_t bit15 : 1;
|
|
|
|
uint16_t bit16 : 1;
|
|
|
|
} IPC_OP_019AB;
|
|
|
|
|
|
|
|
auto flags = *reinterpret_cast< uint16_t* >( ©.data[ 0x18 ] );
|
|
|
|
memcpy( &IPC_OP_019AB, &flags, 2 );
|
|
|
|
|
|
|
|
auto flags1 = *reinterpret_cast< uint32_t* >( ©.data[ 0x18 ] );
|
|
|
|
memcpy( &IPC_OP_019A, &flags1, 4 );
|
|
|
|
|
|
|
|
|
|
|
|
auto pLog = g_fw.get< Logger >();
|
|
|
|
|
|
|
|
bool bPosChanged = false;
|
|
|
|
if( ( player.getPos().x != *reinterpret_cast< float* >( ©.data[ 0x1C ] ) ) ||
|
|
|
|
( player.getPos().y != *reinterpret_cast< float* >( ©.data[ 0x20 ] ) ) ||
|
|
|
|
( player.getPos().z != *reinterpret_cast< float* >( ©.data[ 0x24 ] ) ) )
|
|
|
|
bPosChanged = true;
|
|
|
|
if( !bPosChanged && player.getRot() == *reinterpret_cast< float* >( ©.data[ 0x10 ] ) )
|
|
|
|
return;
|
|
|
|
|
|
|
|
player.setRot( *reinterpret_cast< float* >( ©.data[ 0x10 ] ) );
|
|
|
|
player.setPos( *reinterpret_cast< float* >( ©.data[ 0x1C ] ),
|
|
|
|
*reinterpret_cast< float* >( ©.data[ 0x20 ] ),
|
|
|
|
*reinterpret_cast< float* >( ©.data[ 0x24 ] ) );
|
|
|
|
|
|
|
|
if( ( player.getCurrentAction() != nullptr ) && bPosChanged )
|
|
|
|
player.getCurrentAction()->setInterrupted();
|
|
|
|
|
|
|
|
// if no one is in range, don't bother trying to send a position update
|
|
|
|
if( !player.hasInRangeActor() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
auto moveState = *reinterpret_cast< uint8_t* >( ©.data[ 0x19 ] );
|
|
|
|
auto moveType = *reinterpret_cast< uint8_t* >( ©.data[ 0x18 ] );
|
|
|
|
|
|
|
|
uint8_t unk1 = 0;
|
|
|
|
uint8_t unk2 = 0;
|
|
|
|
uint8_t unk3 = moveState;
|
|
|
|
uint16_t unk4 = 0;
|
|
|
|
|
|
|
|
// HACK: This part is hackish, we need to find out what all theese things really do.
|
|
|
|
//pLog->debug( std::to_string( moveState ) + " -- moveState " );
|
|
|
|
//pLog->debug( std::to_string( moveType ) + " -- moveType " );
|
|
|
|
|
|
|
|
if( moveType & MoveType::Running )
|
|
|
|
{
|
|
|
|
unk1 = 0x7F;
|
|
|
|
unk2 = 0x00;
|
|
|
|
unk4 = 0x3C;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( moveType & MoveType::Strafing )
|
|
|
|
{
|
|
|
|
unk2 = 0x40;
|
|
|
|
unk1 = 0x7F;
|
|
|
|
//if( IPC_OP_019A.strafeRight == 1 )
|
|
|
|
// unk1 = 0xbf;
|
|
|
|
//else
|
|
|
|
// unk1 = 0x5f;
|
|
|
|
unk4 = 0x3C;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( moveType & MoveType::Walking )
|
|
|
|
{
|
|
|
|
unk1 = 0x7F;
|
|
|
|
unk2 = 0x02;
|
|
|
|
unk3 = 0x00;
|
|
|
|
unk4 = 0x18;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( moveType & MoveType::Walking && moveType & MoveType::Strafing )
|
|
|
|
{
|
|
|
|
unk2 = 0x06;
|
|
|
|
unk1 = 0xFF;
|
|
|
|
unk4 = 0x18;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( moveType & MoveType::Jumping )
|
|
|
|
{
|
|
|
|
|
|
|
|
unk1 = 0x3F;
|
|
|
|
unk2 = 0x32;
|
|
|
|
unk4 = 0x5f18;
|
|
|
|
if( moveState == MoveState::Land )
|
2018-07-07 00:10:16 +02:00
|
|
|
unk2 = 0x02;
|
|
|
|
|
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
|
|
|
if( ( currentTime - player.m_lastMoveTime ) < 100 && player.m_lastMoveflag == moveState )
|
|
|
|
return;
|
2018-07-07 00:10:16 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
player.m_lastMoveTime = currentTime;
|
|
|
|
player.m_lastMoveflag = moveState;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto movePacket = boost::make_shared< MoveActorPacket >( player, unk1, unk2, moveState, unk4 );
|
|
|
|
player.sendToInRangeSet( movePacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
void
|
|
|
|
Core::Network::GameConnection::reqEquipDisplayFlagsHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
|
|
|
Entity::Player& player )
|
2017-10-05 20:24:58 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
player.setEquipDisplayFlags( inPacket.data[ 0x10 ] );
|
2018-05-17 20:46:11 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
player.sendDebug( "EquipDisplayFlag CHANGE: " + std::to_string( player.getEquipDisplayFlags() ) );
|
2017-10-05 20:24:58 +02:00
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::zoneLineHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto pTeriMgr = g_fw.get< TerritoryMgr >();
|
|
|
|
|
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcZoneLineHandler >( inPacket );
|
2018-10-14 23:31:52 +11:00
|
|
|
const auto zoneLineId = packet.data().zoneLineId;
|
2018-08-29 21:40:59 +02:00
|
|
|
|
|
|
|
player.sendDebug( "Walking ZoneLine " + std::to_string( zoneLineId ) );
|
|
|
|
|
|
|
|
auto pZone = player.getCurrentZone();
|
|
|
|
|
|
|
|
auto pLine = pTeriMgr->getTerritoryPosition( zoneLineId );
|
|
|
|
|
|
|
|
Common::FFXIVARR_POSITION3 targetPos{};
|
|
|
|
uint32_t targetZone;
|
|
|
|
float rotation = 0.0f;
|
|
|
|
|
|
|
|
if( pLine != nullptr )
|
|
|
|
{
|
|
|
|
player.sendDebug( "ZoneLine " + std::to_string( zoneLineId ) + " found." );
|
|
|
|
targetPos = pLine->getTargetPosition();
|
|
|
|
targetZone = pLine->getTargetZoneId();
|
|
|
|
rotation = pLine->getTargetRotation();
|
|
|
|
|
|
|
|
auto preparePacket = makeZonePacket< FFXIVIpcPrepareZoning >( player.getId() );
|
|
|
|
preparePacket->data().targetZone = targetZone;
|
|
|
|
|
|
|
|
//ActorControlPacket143 controlPacket( pPlayer, ActorControlType::DespawnZoneScreenMsg,
|
|
|
|
// 0x03, player.getId(), 0x01, targetZone );
|
|
|
|
player.queuePacket( preparePacket );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// No zoneline found, revert to last zone
|
|
|
|
player.sendUrgent( "ZoneLine " + std::to_string( zoneLineId ) + " not found." );
|
|
|
|
targetPos.x = 0;
|
|
|
|
targetPos.y = 0;
|
|
|
|
targetPos.z = 0;
|
|
|
|
targetZone = pZone->getTerritoryId();
|
|
|
|
}
|
|
|
|
|
|
|
|
player.performZoning( targetZone, targetPos, rotation );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::discoveryHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcDiscoveryHandler >( inPacket );
|
2018-10-14 23:31:52 +11:00
|
|
|
const auto positionRef = packet.data().positionRef;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-09-09 23:56:22 +02:00
|
|
|
auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >();
|
2018-03-09 10:19:38 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto pQR = pDb->query( "SELECT id, map_id, discover_id "
|
|
|
|
"FROM discoveryinfo "
|
|
|
|
"WHERE id = " + std::to_string( positionRef ) + ";" );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( !pQR->next() )
|
|
|
|
{
|
2018-09-21 02:03:10 +10:00
|
|
|
player.sendDebug( "Discovery ref pos ID: " + std::to_string( positionRef ) + " not found. " );
|
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 discoveryPacket = makeZonePacket< FFXIVIpcDiscovery >( player.getId() );
|
|
|
|
discoveryPacket->data().map_id = pQR->getUInt( 2 );
|
|
|
|
discoveryPacket->data().map_part_id = pQR->getUInt( 3 );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
player.queuePacket( discoveryPacket );
|
2018-09-21 02:03:10 +10:00
|
|
|
player.sendDebug( "Discovery ref pos ID: " + std::to_string( positionRef ) );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
player.discover( pQR->getUInt16( 2 ), pQR->getUInt16( 3 ) );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::playTimeHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto playTimePacket = makeZonePacket< FFXIVIpcPlayTime >( player.getId() );
|
|
|
|
playTimePacket->data().playTimeInMinutes = player.getPlayTime() / 60;
|
|
|
|
player.queuePacket( playTimePacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::initHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
// init handler means this is a login procedure
|
|
|
|
player.setIsLogin( true );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
player.sendZonePackets();
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::blackListHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
uint8_t count = inPacket.data[ 0x11 ];
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto blackListPacket = makeZonePacket< FFXIVIpcBlackList >( player.getId() );
|
|
|
|
blackListPacket->data().sequence = count;
|
|
|
|
// TODO: Fill with actual blacklist data
|
|
|
|
//blackListPacket.data().entry[0].contentId = 1;
|
|
|
|
//sprintf( blackListPacket.data().entry[0].name, "Test Test" );
|
|
|
|
queueOutPacket( blackListPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::pingHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcPingHandler >( inPacket );
|
2018-06-18 23:03:39 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
queueOutPacket( boost::make_shared< Server::PingPacket >( player, packet.data().timestamp ) );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
player.setLastPing( static_cast< uint32_t >( time( nullptr ) ) );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::finishLoadingHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
player.getCurrentZone()->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
|
|
|
|
player.onLogin();
|
|
|
|
player.setIsLogin( false );
|
|
|
|
}
|
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
|
|
|
|
player.getCurrentZone()->updateActorPosition( player );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::socialListHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
uint8_t type = inPacket.data[ 0x1A ];
|
|
|
|
uint8_t count = inPacket.data[ 0x1B ];
|
|
|
|
|
|
|
|
if( type == 0x02 )
|
|
|
|
{ // party list
|
|
|
|
|
|
|
|
auto listPacket = makeZonePacket< FFXIVIpcSocialList >( player.getId() );
|
|
|
|
|
|
|
|
listPacket->data().type = 2;
|
|
|
|
listPacket->data().sequence = count;
|
|
|
|
|
|
|
|
int32_t entrysizes = sizeof( listPacket->data().entries );
|
|
|
|
memset( listPacket->data().entries, 0, sizeof( listPacket->data().entries ) );
|
|
|
|
|
|
|
|
listPacket->data().entries[ 0 ].bytes[ 2 ] = player.getCurrentZone()->getTerritoryId();
|
|
|
|
listPacket->data().entries[ 0 ].bytes[ 3 ] = 0x80;
|
|
|
|
listPacket->data().entries[ 0 ].bytes[ 4 ] = 0x02;
|
|
|
|
listPacket->data().entries[ 0 ].bytes[ 6 ] = 0x3B;
|
|
|
|
listPacket->data().entries[ 0 ].bytes[ 11 ] = 0x10;
|
|
|
|
listPacket->data().entries[ 0 ].classJob = static_cast< uint8_t >( player.getClass() );
|
|
|
|
listPacket->data().entries[ 0 ].contentId = player.getContentId();
|
|
|
|
listPacket->data().entries[ 0 ].level = player.getLevel();
|
|
|
|
listPacket->data().entries[ 0 ].zoneId = player.getCurrentZone()->getTerritoryId();
|
|
|
|
listPacket->data().entries[ 0 ].zoneId1 = 0x0100;
|
|
|
|
// TODO: no idea what this does
|
|
|
|
//listPacket.data().entries[0].one = 1;
|
|
|
|
|
|
|
|
memcpy( listPacket->data().entries[ 0 ].name, player.getName().c_str(), strlen( player.getName().c_str() ) );
|
|
|
|
|
|
|
|
// TODO: actually store and read language from somewhere
|
|
|
|
listPacket->data().entries[ 0 ].bytes1[ 0 ] = 0x01;//flags (lang)
|
|
|
|
// TODO: these flags need to be figured out
|
|
|
|
//listPacket.data().entries[0].bytes1[1] = 0x00;//flags
|
|
|
|
listPacket->data().entries[ 0 ].onlineStatusMask = player.getOnlineStatusMask();
|
|
|
|
|
|
|
|
queueOutPacket( listPacket );
|
|
|
|
|
|
|
|
}
|
|
|
|
else if( type == 0x0b )
|
|
|
|
{ // friend list
|
|
|
|
auto listPacket = makeZonePacket< FFXIVIpcSocialList >( player.getId() );
|
|
|
|
listPacket->data().type = 0x0B;
|
|
|
|
listPacket->data().sequence = count;
|
|
|
|
memset( listPacket->data().entries, 0, sizeof( listPacket->data().entries ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
else if( type == 0x0e )
|
|
|
|
{ // player search result
|
|
|
|
// TODO: implement player search
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::chatHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto pDebugCom = g_fw.get< DebugCommandHandler >();
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcChatHandler >( inPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( packet.data().message[ 0 ] == '!' )
|
|
|
|
{
|
|
|
|
// execute game console command
|
|
|
|
pDebugCom->execCommand( const_cast< char* >( packet.data().message ) + 1, player );
|
|
|
|
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.
|
|
|
|
auto chatPacket = boost::make_shared< Server::ChatPacket >( player, chatType, packet.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() )
|
|
|
|
chatPacket->data().chatType = ChatType::GMSay;
|
2018-04-18 21:00:20 +10:00
|
|
|
|
2017-12-08 11:46:47 +01:00
|
|
|
player.getCurrentZone()->queueOutPacketForRange( player, 50, 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() )
|
2018-08-29 21:40:59 +02:00
|
|
|
chatPacket->data().chatType = ChatType::GMYell;
|
2018-04-18 21:00:20 +10:00
|
|
|
|
2017-12-08 11:46:47 +01:00
|
|
|
player.getCurrentZone()->queueOutPacketForRange( player, 6000, 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() )
|
2018-08-29 21:40:59 +02:00
|
|
|
chatPacket->data().chatType = ChatType::GMShout;
|
2018-04-18 21:00:20 +10:00
|
|
|
|
2018-01-28 11:16:34 +01:00
|
|
|
player.getCurrentZone()->queueOutPacketForRange( player, 6000, chatPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
break;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
2017-12-08 11:46:47 +01:00
|
|
|
player.getCurrentZone()->queueOutPacketForRange( player, 50, 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
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::logoutHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto logoutPacket = makeZonePacket< FFXIVIpcLogout >( player.getId() );
|
|
|
|
logoutPacket->data().flags1 = 0x02;
|
|
|
|
logoutPacket->data().flags2 = 0x2000;
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::tellHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-08-22 21:36:20 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcTellHandler >( inPacket );
|
|
|
|
|
|
|
|
auto pZoneServer = g_fw.get< ServerZone >();
|
|
|
|
|
|
|
|
auto pSession = pZoneServer->getSession( packet.data().targetPCName );
|
|
|
|
|
|
|
|
if( !pSession )
|
|
|
|
{
|
|
|
|
auto tellErrPacket = makeZonePacket< FFXIVIpcTellErrNotFound >( player.getId() );
|
|
|
|
strcpy( tellErrPacket->data().receipientName, packet.data().targetPCName );
|
|
|
|
sendSinglePacket( tellErrPacket );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto pTargetPlayer = pSession->getPlayer();
|
|
|
|
|
|
|
|
if( pTargetPlayer->hasStateFlag( PlayerStateFlag::BetweenAreas ) )
|
|
|
|
{
|
|
|
|
// send error for player between areas
|
|
|
|
// TODO: implement me
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( pTargetPlayer->hasStateFlag( PlayerStateFlag::BoundByDuty ) )
|
|
|
|
{
|
|
|
|
// send error for player bound by duty
|
|
|
|
// TODO: implement me
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( pTargetPlayer->getOnlineStatus() == OnlineStatus::Busy )
|
|
|
|
{
|
|
|
|
// send error for player being busy
|
|
|
|
// TODO: implement me ( i've seen this done with packet type 67 i think )
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto tellPacket = makeChatPacket< FFXIVIpcTell >( player.getId() );
|
|
|
|
strcpy( tellPacket->data().msg, packet.data().message );
|
|
|
|
strcpy( tellPacket->data().receipientName, player.getName().c_str() );
|
|
|
|
// TODO: do these have a meaning?
|
|
|
|
//tellPacket.data().u1 = 0x92CD7337;
|
|
|
|
//tellPacket.data().u2a = 0x2E;
|
|
|
|
//tellPacket.data().u2b = 0x40;
|
|
|
|
pTargetPlayer->queueChatPacket( tellPacket );
|
2017-08-22 21:36:20 +02:00
|
|
|
|
2017-09-23 00:45:30 +09:00
|
|
|
}
|
2017-11-22 00:29:42 +09:00
|
|
|
|
2018-06-18 23:03:39 +02:00
|
|
|
void Core::Network::GameConnection::performNoteHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
|
2017-12-08 11:46:47 +01:00
|
|
|
Entity::Player& player )
|
2017-11-22 00:29:42 +09:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
auto performPacket = makeZonePacket< FFXIVIpcPerformNote >( player.getId() );
|
|
|
|
memcpy( &performPacket->data().data[ 0 ], &inPacket.data[ 0x10 ], 32 );
|
|
|
|
player.sendToInRangeSet( performPacket );
|
2017-11-22 00:29:42 +09:00
|
|
|
}
|