diff --git a/bin/scripts/chai/CmnDefCutSceneReplay.chai_outdated b/bin/scripts/chai/CmnDefCutSceneReplay.chai_outdated deleted file mode 100644 index 4bddaa63..00000000 --- a/bin/scripts/chai/CmnDefCutSceneReplay.chai_outdated +++ /dev/null @@ -1,61 +0,0 @@ -// This is an automatically generated chai script template -// Content needs to be added by hand to make it function -// In order for this script to be loaded, change its extension to .chai - - -// Quest Script: SubFst004_00027 -// Quest Name: Preserving the Past -// Quest ID: 65563 -// Start NPC: 1000194 -// End NPC: 1000789 - -class CmnDefCutSceneReplayDef -{ - // Basic quest information - var quest_name - var quest_id - - // These are the quest vars / flags used in this quest - // GetQuestUI8AL - // GetQuestUI8BH - - // Available Scenes in this quest, not necessarly all are used - attr onScene00000; - - // Quest rewards - var RewardExpFactor; - var RewardItem; - var RewardItemCount; - - // Entities found in the script data of the quest - // some of these may be useful - var ACTOR0; - var ACTOR1; - var ACTOR2; - var ITEM0; - - def CmnDefCutSceneReplayDef() - { - - } - - def Scene00000( player, eventId, flags, unk, unk1 ) - { - player.eventPlay(eventId, 0, 0x2000, unk, 1, - fun( player, eventId, subEvent, param1, param2, param3 ) - { - player.eventFinish(eventId, 1); - } ); - } - -}; - - -def CmnDefCutSceneReplay_START(player, actorId, eventId) -{ - var quest = CmnDefCutSceneReplay(); - var actor = mapActor( actorId ); - - player.eventStart( actorId, eventId, 1, 0, 0 ); - CmnDefCutSceneReplay.Scene00000( player, eventId, 0, 0, 0 ); -} diff --git a/src/servers/Server_Common/Network/CommonNetwork.h b/src/servers/Server_Common/Network/CommonNetwork.h index 4c06c02f..fd737255 100644 --- a/src/servers/Server_Common/Network/CommonNetwork.h +++ b/src/servers/Server_Common/Network/CommonNetwork.h @@ -5,8 +5,8 @@ #define _CORE_NETWORK_PACKETS_COMMON_H #include - #include +#include "PacketDef/Ipcs.h" using namespace std; @@ -14,343 +14,160 @@ namespace Core { namespace Network { namespace Packets { +/** +* Anticipated usage: +* ================== +* Set up a stream buffer to collect the bytes to be transmitted as a packet. +* Now, you can do the following (given you have the structs filled out already). +* +* FFXIVARR_PACKET_HEADER pkt_hdr = { . . . }; +* FFXIVARR_PACKET_SEGMENT_HEADER pkt_seg_hdr[n] = { . . . }; +* +* std::stringstream buf; +* buf << pkt_hdr; +* for (int i = 0; i < n; i++) +* { +* buf << pkt_seg_hdr[i]; +* buf << {pkt_seg_data[i]}; +* } +* +* The reverse can be done parsing a packet. Remember to validate the packet +* type before parsing the headers. +* +* Compression and Encryption: +* =========================== +* By using std::iostream's, you can support stream filters. Simply create a +* stream that performs the compression or encryption, and use that stream to +* read and write. +*/ + +/** +* Structure representing the common header for all FFXIVARR packets. +* +* 0 4 8 12 14 16 +* +-------------------------------+---------------+-------+-------+ +* | timestamp | size | cType | count | +* +---+---+-------+---------------+---------------+-------+-------+ +* | ? |CMP| ? | ? | +* +---+---+-------+---------------+ +* (followed by /count/ FFXIVARR_PACKET_SEGMENTs) +*/ +struct FFXIVARR_PACKET_HEADER +{ + + uint64_t unknown_0; + uint64_t unknown_8; /** - * Anticipated usage: - * ================== - * Set up a stream buffer to collect the bytes to be transmitted as a packet. - * Now, you can do the following (given you have the structs filled out already). - * - * FFXIVARR_PACKET_HEADER pkt_hdr = { . . . }; - * FFXIVARR_PACKET_SEGMENT_HEADER pkt_seg_hdr[n] = { . . . }; - * - * std::stringstream buf; - * buf << pkt_hdr; - * for (int i = 0; i < n; i++) - * { - * buf << pkt_seg_hdr[i]; - * buf << {pkt_seg_data[i]}; - * } - * - * The reverse can be done parsing a packet. Remember to validate the packet - * type before parsing the headers. - * - * Compression and Encryption: - * =========================== - * By using std::iostream's, you can support stream filters. Simply create a - * stream that performs the compression or encryption, and use that stream to - * read and write. + * Represents the number of milliseconds since epoch that the packet was + * sent. */ + uint64_t timestamp; + /** The size of the packet header and its payload */ + uint32_t size; + /** The type of this connection - 1 zone, 2 chat*/ + uint16_t connectionType; + /** The number of packet segments that follow. */ + uint16_t count; + uint8_t unknown_20; + /** Indicates if the data segments of this packet are compressed. */ + uint8_t isCompressed; + uint32_t unknown_24; +}; - /** - * Structure representing the common header for all FFXIVARR packets. - * - * 0 4 8 12 14 16 - * +-------------------------------+---------------+-------+-------+ - * | timestamp | size | cType | count | - * +---+---+-------+---------------+---------------+-------+-------+ - * | ? |CMP| ? | ? | - * +---+---+-------+---------------+ - * (followed by /count/ FFXIVARR_PACKET_SEGMENTs) - */ - struct FFXIVARR_PACKET_HEADER - { +inline ostream& operator<<(ostream& os, const FFXIVARR_PACKET_HEADER& hdr) +{ + return os.write(reinterpret_cast(&hdr), sizeof hdr); +} - uint64_t unknown_0; - uint64_t unknown_8; - /** - * Represents the number of milliseconds since epoch that the packet was - * sent. - */ - uint64_t timestamp; - /** The size of the packet header and its payload */ - uint32_t size; - /** The type of this connection - 1 zone, 2 chat*/ - uint16_t connectionType; - /** The number of packet segments that follow. */ - uint16_t count; - uint8_t unknown_20; - /** Indicates if the data segments of this packet are compressed. */ - uint8_t isCompressed; - uint32_t unknown_24; - }; +inline istream& operator>>(istream& is, FFXIVARR_PACKET_HEADER& hdr) +{ + return is.read(reinterpret_cast(&hdr), sizeof hdr); +} - inline ostream& operator<<(ostream& os, const FFXIVARR_PACKET_HEADER& hdr) - { - return os.write(reinterpret_cast(&hdr), sizeof hdr); - } +/** +* Structure representing the header portion of a packet segment. +* +* NOTE: If the main packet header indicated the packet is compressed, this +* header will be compressed as well! The header will NOT ever be encrypted. +* +* 0 4 8 12 16 +* +---------------+---------------+---------------+-------+-------+ +* | size | source_actor | target_actor | type | ? | +* +---------------+---------------+---------------+-------+-------+ +* | | +* : type-specific data of length, size, follows : +* | (NOTE: Some segments MAY be encrypted) | +* +---------------------------------------------------------------+ +*/ +struct FFXIVARR_PACKET_SEGMENT_HEADER +{ + /** The size of the segment header and its data. */ + uint32_t size; + /** The session ID this segment describes. */ + uint32_t source_actor; + /** The session ID this packet is being delivered to. */ + uint32_t target_actor; + /** The segment type. (1, 2, 3, 7, 8, 9, 10) */ + uint16_t type; + uint16_t _reserved_E; +}; - inline istream& operator>>(istream& is, FFXIVARR_PACKET_HEADER& hdr) - { - return is.read(reinterpret_cast(&hdr), sizeof hdr); - } +inline ostream& operator<<(ostream& os, const FFXIVARR_PACKET_SEGMENT_HEADER& hdr) +{ + return os.write(reinterpret_cast(&hdr), sizeof hdr); +} - /** - * Structure representing the header portion of a packet segment. - * - * NOTE: If the main packet header indicated the packet is compressed, this - * header will be compressed as well! The header will NOT ever be encrypted. - * - * 0 4 8 12 16 - * +---------------+---------------+---------------+-------+-------+ - * | size | source_actor | target_actor | type | ? | - * +---------------+---------------+---------------+-------+-------+ - * | | - * : type-specific data of length, size, follows : - * | (NOTE: Some segments MAY be encrypted) | - * +---------------------------------------------------------------+ - */ - struct FFXIVARR_PACKET_SEGMENT_HEADER - { - /** The size of the segment header and its data. */ - uint32_t size; - /** The session ID this segment describes. */ - uint32_t source_actor; - /** The session ID this packet is being delivered to. */ - uint32_t target_actor; - /** The segment type. (1, 2, 3, 7, 8, 9, 10) */ - uint16_t type; - uint16_t _reserved_E; - }; +inline istream& operator>>(istream& is, FFXIVARR_PACKET_SEGMENT_HEADER& hdr) +{ + return is.read(reinterpret_cast(&hdr), sizeof hdr); +} - inline ostream& operator<<(ostream& os, const FFXIVARR_PACKET_SEGMENT_HEADER& hdr) - { - return os.write(reinterpret_cast(&hdr), sizeof hdr); - } +// TODO: Include structures for the individual packet segment types - inline istream& operator>>(istream& is, FFXIVARR_PACKET_SEGMENT_HEADER& hdr) - { - return is.read(reinterpret_cast(&hdr), sizeof hdr); - } +template struct FFXIVIpcBasePacket +{ + /** Creates a constant representing the IPC type */ + enum { _ServerIpcType = T }; +}; - // TODO: Include structures for the individual packet segment types +struct FFXIVARR_PACKET_RAW +{ + FFXIVARR_PACKET_SEGMENT_HEADER segHdr; + std::vector data; +}; - template struct FFXIVIpcBasePacket - { - /** Creates a constant representing the IPC type */ - enum { _ServerIpcType = T }; - }; +/** +* Structural representation of the common header for IPC packet segments. +* NOTE: This is packet segment type 3. +* +* 0 4 6 8 12 16 +* +-------+-------+------+----------+---------------+---------------+ +* | 14 00 | type | ?? | serverId | timestamp | ??? | +* +-------+-------+------+----------+---------------+---------------+ +* | | +* : data : +* | | +* +-----------------------------------------------------------------+ +*/ +struct FFXIVARR_IPC_HEADER +{ + uint16_t reserved; + uint16_t type; + uint16_t unknown_2; + uint16_t serverId; + uint32_t timestamp; + uint32_t unknown_C; +}; - /** - * Server IPC Lobby Type Codes. - */ - enum ServerLobbyIpcType : uint16_t - { - LobbyError = 0x0002, - LobbyServiceAccountList = 0x000C, - LobbyCharList = 0x000D, - LobbyCharCreate = 0x000E, - LobbyEnterWorld = 0x000F, - LobbyServerList = 0x0015, - LobbyRetainerList = 0x0017, +inline ostream& operator<<(ostream& os, const FFXIVARR_IPC_HEADER& hdr) +{ + return os.write(reinterpret_cast(&hdr), sizeof hdr); +} - }; - - /** - * Client IPC Lobby Type Codes. - */ - enum ClientLobbyIpcType : uint16_t - { - ReqCharList = 0x0003, - ReqEnterWorld = 0x0004, - ReqServiceAccountList = 0x0005, - - ReqCharDelete = 0x000A, - ReqCharCreate = 0x000B, - }; - /** - * Server IPC Zone Type Codes. - */ - enum ServerZoneIpcType : uint16_t - { - Ping = 0x0065, // updated for sb - Init = 0x0066, // updated for sb - Chat = 0x0067, // updated for sb - Logout = 0x0077, // updated for sb - Playtime = 0x00AF, // updated for sb - SocialRequestError = 0x00AD, - SocialRequestResponse = 0x11AF, - SocialList = 0x00B4, // updated for sb - UpdateSearchInfo = 0x00B6, // updated for sb - InitSearchInfo = 0x00B7, // updated for sb - ServerNotice = 0x00BC, // updated for sb - SetOnlineStatus = 0x00BD, // updated for sb - BlackList = 0x00CA, // updated for sb - LinkshellList = 0x00D1, // updated for sb - StatusEffectList = 0x00F0, // updated for sb - Effect = 0x00F1, // updated for sb - GCAffiliation = 0x00FC, - - ActorSetPos = 0x0114, // updated for sb - ActorCast = 0x0116, // updated for sb - PlayerSpawn = 0x0110, // updated for sb - NpcSpawn = 0x0111, // updated for sb - ActorMove = 0x0112, // updated for sb - HateList = 0x011A, // updated for sb borked - UpdateClassInfo = 0x011D, // updated for sb - InitUI = 0x011E, // updated for sb - PlayerStats = 0x011F, // updated for sb - ActorOwner = 0x0120, // updated for sb - PlayerStateFlags = 0x0121, // updated for sb - PlayerClassInfo = 0x0123, // updated for sb - ModelEquip = 0x0124, // updated for sb - ItemInfo = 0x0139, // updated for sb - ContainerInfo = 0x013A, // updated for sb - InventoryTransactionFinish = 0x013B, - InventoryTransaction = 0x012A, - CurrencyCrystalInfo = 0x013D, - InventoryActionAck = 0x0139, - UpdateInventorySlot = 0x0140, // updated for sb - AddStatusEffect = 0x0141, - ActorControl142 = 0x0142, // unchanged for sb - ActorControl143 = 0x0143, // unchanged for sb - ActorControl144 = 0x0144, // unchanged for sb - UpdateHpMpTp = 0x0145, // unchanged for sb - - CFNotify = 0x0078, - CFMemberStatus = 0x0079, - CFDutyInfo = 0x007A, - CFPlayerInNeed = 0x007F, - CFRegistered = 0x00B0, - CFAvailableContents = 0x01CF, - - EventPlay = 0x0154, // updated for sb - EventStart = 0x015D, // updated for sb - EventFinish = 0x015E, // updated for sb - QuestActiveList = 0x0171, // updated for sb - QuestUpdate = 0x0172, // updated for sb - QuestCompleteList = 0x0173, // updated for sb - QuestFinish = 0x0174, // updated for sb - QuestMessage = 0x0179, - QuestTracker = 0x0181, // updated for sb - ActorSpawn = 0x0190, // todo: split into playerspawn/actorspawn and use opcode 0x110/0x111 - ActorFreeSpawn = 0x0191, // unchanged for sb - InitZone = 0x019A, // unchanged for sb - WeatherChange = 0x01AF, // updated for sb - Discovery = 0x01B2, // updated for sb - - PrepareZoning = 0x0239, // updated for sb - - // Unknown IPC types that still need to be sent - // TODO: figure all these out properly - IPCTYPE_UNK_320 = 0x1FB, - IPCTYPE_UNK_322 = 0x1FD, - - }; - - // TODO: Include structures for the individual packet segment types - - /** - * Client IPC Zone Type Codes. - */ - enum ClientZoneIpcType : uint16_t - { - - TellChatHandler = 0x0064,// updated for sb - - PingHandler = 0x0065,// updated for sb - InitHandler = 0x0066,// updated for sb - ChatHandler = 0x0067,// updated for sb - - FinishLoadingHandler = 0x0069,// updated for sb - - CFCommenceHandler = 0x006F, - CFRegisterDuty = 0x0071, - CFRegisterRoulette = 0x0072, - - PlayTimeHandler = 0x0073,// updated for sb - LogoutHandler = 0x0074,// updated for sb - - CFDutyInfoHandler = 0x0078, - - SocialReqSendHandler = 0x00A5, - SocialListHandler = 0x00AA,// updated for sb - SetSearchInfoHandler = 0x00AC,// updated for sb - - ReqSearchInfoHandler = 0x00AD, - - BlackListHandler = 0x00B7,// updated for sb - - LinkshellListHandler = 0x00BF,// updated for sb - - FcInfoReqHandler = 0x0100,// updated for sb - - ZoneLineHandler = 0x0107, // updated for sb - ActionHandler = 0x0108,// updated for sb - - DiscoveryHandler = 0x0109,// updated for sb - - SkillHandler = 0x010B, // updated for sb - GMCommand1 = 0x010C,// updated for sb - GMCommand2 = 0x010D,// updated for sb - UpdatePositionHandler = 0x010F, // updated for sb - - InventoryModifyHandler = 0x0116, // updated for sb - - TalkEventHandler = 0x011F, // updated for sb - EmoteEventHandler = 0x0120, // updated for sb - WithinRangeEventHandler = 0x0121, // updated for sb - OutOfRangeEventHandler = 0x0122, // updated for sb - EnterTeriEventHandler = 0x0123, // updated for sb - - ReturnEventHandler = 0x0128, - TradeReturnEventHandler = 0x0129, - }; - - - /** - * Server IPC Chat Type Codes. - */ - enum ServerChatIpcType : uint16_t - { - Tell = 0x0064, // updated for sb - }; - - /** - * Client IPC Chat Type Codes. - */ - enum ClientChatIpcType : uint16_t - { - TellReq = 0x0064, - }; - - struct FFXIVARR_PACKET_RAW - { - FFXIVARR_PACKET_SEGMENT_HEADER segHdr; - std::vector data; - }; - - /** - * Structural representation of the common header for IPC packet segments. - * NOTE: This is packet segment type 3. - * - * 0 4 6 8 12 16 - * +-------+-------+------+----------+---------------+---------------+ - * | 14 00 | type | ?? | serverId | timestamp | ??? | - * +-------+-------+------+----------+---------------+---------------+ - * | | - * : data : - * | | - * +-----------------------------------------------------------------+ - */ - struct FFXIVARR_IPC_HEADER - { - uint16_t reserved; - uint16_t type; - uint16_t unknown_2; - uint16_t serverId; - uint32_t timestamp; - uint32_t unknown_C; - }; - - inline ostream& operator<<(ostream& os, const FFXIVARR_IPC_HEADER& hdr) - { - return os.write(reinterpret_cast(&hdr), sizeof hdr); - } - - inline istream& operator>>(istream& is, FFXIVARR_IPC_HEADER& hdr) - { - return is.read(reinterpret_cast(&hdr), sizeof hdr); - } +inline istream& operator>>(istream& is, FFXIVARR_IPC_HEADER& hdr) +{ + return is.read(reinterpret_cast(&hdr), sizeof hdr); +} } /* Packets */ } /* Network */ diff --git a/src/servers/Server_Common/Network/GamePacket.cpp b/src/servers/Server_Common/Network/GamePacket.cpp index 9618eaa8..f468e90d 100644 --- a/src/servers/Server_Common/Network/GamePacket.cpp +++ b/src/servers/Server_Common/Network/GamePacket.cpp @@ -46,10 +46,11 @@ Core::Network::Packets::GamePacket::GamePacket( char * pData, uint16_t size, boo if( bWriteStamp && size > 0x18 ) { m_timeStamp = static_cast< uint32_t >( time( nullptr ) ); + *reinterpret_cast< uint16_t* >( &m_dataBuf[0] + 0x10 ) = 0x14; *reinterpret_cast< uint32_t* >( &m_dataBuf[0] + 0x18 ) = m_timeStamp; } - m_segHdr._reserved_E = 0; + //m_segHdr._reserved_E = 0; m_segHdr.size = *reinterpret_cast< uint32_t* >( &m_dataBuf[0] ); m_segHdr.type = *reinterpret_cast< uint16_t* >( &m_dataBuf[0] + 0x0C ); m_subType = *reinterpret_cast< uint16_t* >( &m_dataBuf[0] + 0x12 ); diff --git a/src/servers/Server_Common/Network/PacketContainer.cpp b/src/servers/Server_Common/Network/PacketContainer.cpp index 17ebc817..906d3de4 100644 --- a/src/servers/Server_Common/Network/PacketContainer.cpp +++ b/src/servers/Server_Common/Network/PacketContainer.cpp @@ -35,6 +35,8 @@ void Core::Network::Packets::PacketContainer::fillSendBuffer( std::vector< uint8 using namespace std::chrono; auto ms = duration_cast< milliseconds >( system_clock::now().time_since_epoch() ); uint64_t tick = ms.count(); + m_ipcHdr.unknown_0 = 0xE2465DFF41a05252; + m_ipcHdr.unknown_8 = 0x75C4997B4D642A7F; m_ipcHdr.timestamp = tick; m_ipcHdr.unknown_20 = 1; diff --git a/src/servers/Server_Common/Network/PacketDef/Chat/ServerChatDef.h b/src/servers/Server_Common/Network/PacketDef/Chat/ServerChatDef.h new file mode 100644 index 00000000..7eed0dd7 --- /dev/null +++ b/src/servers/Server_Common/Network/PacketDef/Chat/ServerChatDef.h @@ -0,0 +1,42 @@ +#ifndef _CORE_NETWORK_PACKETS_CHAT_SERVER_IPC_H +#define _CORE_NETWORK_PACKETS_CHAT_SERVER_IPC_H + +#include "src/servers/Server_Common/Common.h" +#include "src/servers/Server_Common/Network/CommonNetwork.h" + +namespace Core { +namespace Network { +namespace Packets { +namespace Server { + +/** +* Structural representation of the packet sent by the server as response +* to a tell request +*/ +struct FFXIVIpcTell : FFXIVIpcBasePacket +{ + uint32_t u1; + uint16_t u2a; + uint16_t u2b; + uint8_t preName; + char receipientName[32]; + char msg[1031]; +}; + + /** +* Structural representation of the packet sent by the server as response +* to a failed tell because of unavailable target player +*/ +struct FFXIVIpcTellErrNotFound : FFXIVIpcBasePacket +{ + char receipientName[32]; +}; + +} /* Server */ +} /* Packets */ +} /* Network */ +} /* Core */ + + + +#endif /*_CORE_NETWORK_PACKETS_CHAT_SERVER_IPC_H*/ diff --git a/src/servers/Server_Common/Network/PacketDef/Ipcs.h b/src/servers/Server_Common/Network/PacketDef/Ipcs.h new file mode 100644 index 00000000..b5e9b9b6 --- /dev/null +++ b/src/servers/Server_Common/Network/PacketDef/Ipcs.h @@ -0,0 +1,203 @@ +#ifndef _CORE_NETWORK_PACKETS_IPCS_H +#define _CORE_NETWORK_PACKETS_IPCS_H + +#include + +namespace Core { +namespace Network { +namespace Packets { + + //////////////////////////////////////////////////////////////////////////////// + /// Lobby Connection IPC Codes + /** + * Server IPC Lobby Type Codes. + */ + enum ServerLobbyIpcType : uint16_t + { + LobbyError = 0x0002, + LobbyServiceAccountList = 0x000C, + LobbyCharList = 0x000D, + LobbyCharCreate = 0x000E, + LobbyEnterWorld = 0x000F, + LobbyServerList = 0x0015, + LobbyRetainerList = 0x0017, + + }; + + /** + * Client IPC Lobby Type Codes. + */ + enum ClientLobbyIpcType : uint16_t + { + ReqCharList = 0x0003, + ReqEnterWorld = 0x0004, + ReqServiceAccountList = 0x0005, + + ReqCharDelete = 0x000A, + ReqCharCreate = 0x000B, + }; + + //////////////////////////////////////////////////////////////////////////////// + /// Zone Connection IPC Codes + /** + * Server IPC Zone Type Codes. + */ + enum ServerZoneIpcType : uint16_t + { + Ping = 0x0065, // updated for sb + Init = 0x0066, // updated for sb + Chat = 0x0067, // updated for sb + Logout = 0x0077, // updated for sb + Playtime = 0x00AF, // updated for sb + SocialRequestError = 0x00AD, + SocialRequestResponse = 0x11AF, + SocialList = 0x00B4, // updated for sb + UpdateSearchInfo = 0x00B6, // updated for sb + InitSearchInfo = 0x00B7, // updated for sb + ServerNotice = 0x00BC, // updated for sb + SetOnlineStatus = 0x00BD, // updated for sb + BlackList = 0x00CA, // updated for sb + LinkshellList = 0x00D1, // updated for sb + StatusEffectList = 0x00F0, // updated for sb + Effect = 0x00F1, // updated for sb + GCAffiliation = 0x00FC, + + ActorSetPos = 0x0114, // updated for sb + ActorCast = 0x0116, // updated for sb + PlayerSpawn = 0x0110, // updated for sb + NpcSpawn = 0x0111, // updated for sb + ActorMove = 0x0112, // updated for sb + HateList = 0x011A, // updated for sb borked + UpdateClassInfo = 0x011D, // updated for sb + InitUI = 0x011E, // updated for sb + PlayerStats = 0x011F, // updated for sb + ActorOwner = 0x0120, // updated for sb + PlayerStateFlags = 0x0121, // updated for sb + PlayerClassInfo = 0x0123, // updated for sb + ModelEquip = 0x0124, // updated for sb + ItemInfo = 0x0139, // updated for sb + ContainerInfo = 0x013A, // updated for sb + InventoryTransactionFinish = 0x013B, + InventoryTransaction = 0x012A, + CurrencyCrystalInfo = 0x013D, + InventoryActionAck = 0x0139, + UpdateInventorySlot = 0x0140, // updated for sb + AddStatusEffect = 0x0141, + ActorControl142 = 0x0142, // unchanged for sb + ActorControl143 = 0x0143, // unchanged for sb + ActorControl144 = 0x0144, // unchanged for sb + UpdateHpMpTp = 0x0145, // unchanged for sb + + CFNotify = 0x0078, + CFMemberStatus = 0x0079, + CFDutyInfo = 0x007A, + CFPlayerInNeed = 0x007F, + CFRegistered = 0x00B0, + CFAvailableContents = 0x01CF, + + EventPlay = 0x0154, // updated for sb + EventStart = 0x015D, // updated for sb + EventFinish = 0x015E, // updated for sb + QuestActiveList = 0x0171, // updated for sb + QuestUpdate = 0x0172, // updated for sb + QuestCompleteList = 0x0173, // updated for sb + QuestFinish = 0x0174, // updated for sb + QuestMessage = 0x0179, + QuestTracker = 0x0181, // updated for sb + ActorSpawn = 0x0190, // todo: split into playerspawn/actorspawn and use opcode 0x110/0x111 + ActorFreeSpawn = 0x0191, // unchanged for sb + InitZone = 0x019A, // unchanged for sb + WeatherChange = 0x01AF, // updated for sb + Discovery = 0x01B2, // updated for sb + + PrepareZoning = 0x0239, // updated for sb + + // Unknown IPC types that still need to be sent + // TODO: figure all these out properly + IPCTYPE_UNK_320 = 0x1FB, + IPCTYPE_UNK_322 = 0x1FD, + + }; + + // TODO: Include structures for the individual packet segment types + + /** + * Client IPC Zone Type Codes. + */ + enum ClientZoneIpcType : uint16_t + { + + PingHandler = 0x0065, // updated for sb + InitHandler = 0x0066, // updated for sb + ChatHandler = 0x0067, // updated for sb + + FinishLoadingHandler = 0x0069, // updated for sb + + CFCommenceHandler = 0x006F, + CFRegisterDuty = 0x0071, + CFRegisterRoulette = 0x0072, + PlayTimeHandler = 0x0073, // updated for sb + LogoutHandler = 0x0074, // updated for sb + + CFDutyInfoHandler = 0x0078, + + SocialReqSendHandler = 0x00A5, + SocialListHandler = 0x00AA, // updated for sb + SetSearchInfoHandler = 0x00AC, // updated for sb + + ReqSearchInfoHandler = 0x00AD, + + BlackListHandler = 0x00B7, // updated for sb + + LinkshellListHandler = 0x00BF, // updated for sb + + FcInfoReqHandler = 0x0100, // updated for sb + + ZoneLineHandler = 0x0107, // updated for sb + ActionHandler = 0x0108, // updated for sb + DiscoveryHandler = 0x0109, // updated for sb + + SkillHandler = 0x010B, // updated for sb + GMCommand1 = 0x010C, // updated for sb + GMCommand2 = 0x010D, // updated for sb + UpdatePositionHandler = 0x010F, // updated for sb + + InventoryModifyHandler = 0x0116, // updated for sb + + TalkEventHandler = 0x011F, // updated for sb + EmoteEventHandler = 0x0120, // updated for sb + WithinRangeEventHandler = 0x0121, // updated for sb + OutOfRangeEventHandler = 0x0122, // updated for sb + EnterTeriEventHandler = 0x0123, // updated for sb + + ReturnEventHandler = 0x0128, + TradeReturnEventHandler = 0x0129, + + LinkshellEventHandler = 0x013C, + }; + + //////////////////////////////////////////////////////////////////////////////// + /// Chat Connection IPC Codes + /** + * Server IPC Chat Type Codes. + */ + enum ServerChatIpcType : uint16_t + { + Tell = 0x0064, // updated for sb + TellErrNotFound = 0x0066, + }; + + /** + * Client IPC Chat Type Codes. + */ + enum ClientChatIpcType : uint16_t + { + TellReq = 0x0064, + }; + + +} /* Packets */ +} /* Network */ +} /* Core */ + +#endif /*_CORE_NETWORK_PACKETS_IPCS_H*/ diff --git a/src/servers/Server_Common/Network/PacketDef/Lobby/ServerLobbyDef.h b/src/servers/Server_Common/Network/PacketDef/Lobby/ServerLobbyDef.h index 2f356d33..2d0fe4d0 100644 --- a/src/servers/Server_Common/Network/PacketDef/Lobby/ServerLobbyDef.h +++ b/src/servers/Server_Common/Network/PacketDef/Lobby/ServerLobbyDef.h @@ -9,132 +9,132 @@ namespace Network { namespace Packets { namespace Server { - struct FFXIVIpcRetainerList : FFXIVIpcBasePacket - { - uint8_t padding[0x210]; - }; +struct FFXIVIpcRetainerList : FFXIVIpcBasePacket +{ + uint8_t padding[0x210]; +}; /** */ - struct FFXIVIpcServiceIdInfo : FFXIVIpcBasePacket +struct FFXIVIpcServiceIdInfo : FFXIVIpcBasePacket +{ + uint64_t seq; + uint8_t padding; + uint8_t numServiceAccounts; + uint8_t u1; + uint8_t u2; + uint32_t padding1; + + struct { - uint64_t seq; - uint8_t padding; - uint8_t numServiceAccounts; - uint8_t u1; - uint8_t u2; + uint32_t id; + uint32_t unknown; + uint32_t index; + char name[0x44]; + } serviceAccount[8]; +}; + + +struct FFXIVIpcServerList : FFXIVIpcBasePacket +{ + uint64_t seq; + uint16_t final; + uint16_t offset; + uint32_t numServers; + uint32_t padding; + uint32_t padding1; + + struct + { + uint16_t id; + uint16_t index; + uint32_t flags; // 0x02 = World not accepting new characters uint32_t padding1; - - struct - { - uint32_t id; - uint32_t unknown; - uint32_t index; - char name[0x44]; - } serviceAccount[8]; - }; - - - struct FFXIVIpcServerList : FFXIVIpcBasePacket - { - uint64_t seq; - uint16_t final; - uint16_t offset; - uint32_t numServers; - uint32_t padding; - uint32_t padding1; - - struct - { - uint16_t id; - uint16_t index; - uint32_t flags; // 0x02 = World not accepting new characters - uint32_t padding1; - uint32_t icon; // 2 = bonus XP star - uint32_t padding2; - char name[0x40]; - } server[6]; - }; - - struct FFXIVIpcCharList : FFXIVIpcBasePacket - { - uint64_t seq; - uint8_t counter; // current packet count * 4, count * 4 +1 on last packet. - uint8_t numInPacket; // always 2?? - uint16_t padding; - uint8_t unknown1; - uint8_t unknown2; - uint8_t unknown3; - uint8_t unknown4; // 0x80 in case of last packet - uint32_t unknown5[7]; - uint8_t unknown6; // 0x80 in case of last packet - uint8_t veteranRank; - uint8_t unknown7; - uint8_t padding1; - uint32_t daysSubscribed; - uint32_t remainingDays; - uint32_t daysToNextRank; - uint16_t maxCharOnWorld; - uint16_t unknown8; - uint32_t entitledExpansion; + uint32_t icon; // 2 = bonus XP star uint32_t padding2; + char name[0x40]; + } server[6]; +}; - struct CharaDetails - { - uint32_t uniqueId; - uint32_t padding; - uint64_t contentId; - uint32_t index; - uint32_t padding2; - uint16_t serverId; - char nameChara[32]; - char nameServer[32]; - char charDetailJson[1030]; - } charaDetails[2]; +struct FFXIVIpcCharList : FFXIVIpcBasePacket +{ + uint64_t seq; + uint8_t counter; // current packet count * 4, count * 4 +1 on last packet. + uint8_t numInPacket; // always 2?? + uint16_t padding; + uint8_t unknown1; + uint8_t unknown2; + uint8_t unknown3; + uint8_t unknown4; // 0x80 in case of last packet + uint32_t unknown5[7]; + uint8_t unknown6; // 0x80 in case of last packet + uint8_t veteranRank; + uint8_t unknown7; + uint8_t padding1; + uint32_t daysSubscribed; + uint32_t remainingDays; + uint32_t daysToNextRank; + uint16_t maxCharOnWorld; + uint16_t unknown8; + uint32_t entitledExpansion; + uint32_t padding2; - }; - - struct FFXIVIpcEnterWorld : FFXIVIpcBasePacket + struct CharaDetails { - uint64_t seq; - uint32_t charId; + uint32_t uniqueId; uint32_t padding; uint64_t contentId; + uint32_t index; uint32_t padding2; - char sid[66]; - uint16_t port; - char host[48]; - uint64_t padding3; - uint64_t padding4; - }; + uint16_t serverId; + char nameChara[32]; + char nameServer[32]; + char charDetailJson[1030]; + } charaDetails[2]; - struct FFXIVIpcCharCreate : FFXIVIpcBasePacket - { - uint64_t seq; - uint8_t unknown; - uint8_t unknown_2; - uint8_t type; - uint8_t padding; - uint32_t unknown_3; - uint32_t unknown_4; - uint32_t unknown_5; - uint64_t content_id; - uint16_t unknown_7; - uint16_t unknown_8; - uint32_t unknown_9; - uint16_t unknown_10; - char name[32]; - char world[32]; - }; +}; - struct FFXIVIpcLobbyError : FFXIVIpcBasePacket - { - uint64_t seq; - uint32_t error_id; - uint32_t param; - uint16_t message_id; - char message[516]; - }; +struct FFXIVIpcEnterWorld : FFXIVIpcBasePacket +{ + uint64_t seq; + uint32_t charId; + uint32_t padding; + uint64_t contentId; + uint32_t padding2; + char sid[66]; + uint16_t port; + char host[48]; + uint64_t padding3; + uint64_t padding4; +}; + +struct FFXIVIpcCharCreate : FFXIVIpcBasePacket +{ + uint64_t seq; + uint8_t unknown; + uint8_t unknown_2; + uint8_t type; + uint8_t padding; + uint32_t unknown_3; + uint32_t unknown_4; + uint32_t unknown_5; + uint64_t content_id; + uint16_t unknown_7; + uint16_t unknown_8; + uint32_t unknown_9; + uint16_t unknown_10; + char name[32]; + char world[32]; +}; + +struct FFXIVIpcLobbyError : FFXIVIpcBasePacket +{ + uint64_t seq; + uint32_t error_id; + uint32_t param; + uint16_t message_id; + char message[516]; +}; } } diff --git a/src/servers/Server_Lobby/GameConnection.h b/src/servers/Server_Lobby/GameConnection.h index f62fef2e..3d97e0f0 100644 --- a/src/servers/Server_Lobby/GameConnection.h +++ b/src/servers/Server_Lobby/GameConnection.h @@ -66,7 +66,7 @@ public: void handleGamePacket( Packets::FFXIVARR_PACKET_RAW &pPacket ); - void handleGamePacket( Packets::GamePacketPtr pPacket ); + void handlePacket( Packets::GamePacketPtr pPacket ); void sendPackets( Packets::PacketContainer * pPacket ); diff --git a/src/servers/Server_REST/PlayerMinimal.cpp b/src/servers/Server_REST/PlayerMinimal.cpp index 3ae784a5..591b05ca 100644 --- a/src/servers/Server_REST/PlayerMinimal.cpp +++ b/src/servers/Server_REST/PlayerMinimal.cpp @@ -247,7 +247,7 @@ namespace Core { " UPDATE_DATE ) " " VALUES (100, 100, " + std::to_string( m_iD ) + ", " + std::to_string( m_contentId ) + ", " + " UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)customize, size ) ) + "'), " + - "'" + std::string( m_name ) + "', " + std::to_string( m_voice ) + ", 1, 1, " + + "'" + g_database.escapeString( std::string( m_name ) ) + "', " + std::to_string( m_voice ) + ", 1, 1, " + std::to_string( startZone ) + ", " + std::to_string( x ) + ", " + std::to_string( y ) + ", " + std::to_string( z ) + ", " + std::to_string( o ) + ", " + std::to_string( m_accountId ) + ", UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)equipModel, 40 ) ) + "'), 1, NOW());" ); diff --git a/src/servers/Server_REST/SapphireAPI.cpp b/src/servers/Server_REST/SapphireAPI.cpp index f45900d2..a1072585 100644 --- a/src/servers/Server_REST/SapphireAPI.cpp +++ b/src/servers/Server_REST/SapphireAPI.cpp @@ -235,7 +235,7 @@ std::vector Core::Network::SapphireAPI::getCharList( uint32 bool Core::Network::SapphireAPI::checkNameTaken( std::string name ) { - std::string query = "SELECT * FROM charabase WHERE Name = '" + name + "';"; + std::string query = "SELECT * FROM charabase WHERE Name = '" + g_database.escapeString( name ) + "';"; auto pQR = g_database.query( query ); diff --git a/src/servers/Server_Zone/Actor/CalcBattle.cpp b/src/servers/Server_Zone/Actor/CalcBattle.cpp index 2ac8f563..772e59f1 100644 --- a/src/servers/Server_Zone/Actor/CalcBattle.cpp +++ b/src/servers/Server_Zone/Actor/CalcBattle.cpp @@ -20,7 +20,7 @@ extern Core::Data::ExdData g_exdData; TODO: Base HP val modifier. I can only find values for levels 50~70. - Attack power (and healing power). Need more researchg on this. + Attack power (and healing power). Needs more research on this. Damage outgoing calculations. This includes auto-attacks, etc. */ @@ -34,9 +34,9 @@ uint32_t CalcBattle::calculateBaseStat( PlayerPtr pPlayer ) uint8_t level = pPlayer->getLevel(); if (level < 51) - base = static_cast( 0.053f * ( level * level ) + (1.022f * level) - 0.907f + 20 ); + base = 0.053f * ( level * level ) + ( 1.022f * level ) - 0.907f + 20; else - base = static_cast( 1.627f * level + 120.773f ); + base = 1.627f * level + 120.773f; return base; } @@ -46,26 +46,35 @@ uint32_t CalcBattle::calculateBaseStat( PlayerPtr pPlayer ) uint32_t CalcBattle::calculateMaxHp( PlayerPtr pPlayer ) { - // TODO: Replace ApproxBaseHP with something that can get us a BaseHP reliably. + // TODO: Replace ApproxBaseHP with something that can get us an accurate BaseHP. // Is there any way to pull BaseHP without having to manually use a pet for every level, and using the values from a table? - + // More info here: https://docs.google.com/spreadsheets/d/1de06KGT0cNRUvyiXNmjNgcNvzBCCQku7jte5QxEQRbs/edit?usp=sharing + auto classInfoIt = g_exdData.m_classJobInfoMap.find( pPlayer->getClass() ); auto paramGrowthInfoIt = g_exdData.m_paramGrowthInfoMap.find( pPlayer->getLevel() ); + if ( classInfoIt == g_exdData.m_classJobInfoMap.end() || + paramGrowthInfoIt == g_exdData.m_paramGrowthInfoMap.end() ) + return 0; + + uint8_t level = pPlayer->getLevel(); + float baseStat = calculateBaseStat( pPlayer ); - uint16_t vit = pPlayer->getStats().vit; - uint16_t hp_mod = paramGrowthInfoIt->second.hp_mod; + uint16_t vitStat = pPlayer->getStats().vit; + uint16_t hpMod = paramGrowthInfoIt->second.hp_mod; uint16_t jobModHp = classInfoIt->second.mod_hp; - uint16_t approxBaseHp = 0; // Read above + float approxBaseHp = 0.0f; // Read above // These values are not precise. - if ( pPlayer->getLevel() > 50 ) - approxBaseHp = 0.1452f * paramGrowthInfoIt->second.mp_const + 1356.6f; + + if ( level >= 60 ) + approxBaseHp = 2600 + ( level - 60 ) * 100; + else if ( level >= 50 ) + approxBaseHp = 1700 + ( ( level - 50 ) * ( 1700 * 1.04325f ) ); else - approxBaseHp = paramGrowthInfoIt->second.mp_const * 0.525f; - - uint16_t result = floor( jobModHp * ( approxBaseHp / 100.0f ) ) + floor( hp_mod / 100.0f * ( vit - baseStat ) ); + approxBaseHp = paramGrowthInfoIt->second.mp_const * 0.7596f; + uint16_t result = floor( jobModHp * ( approxBaseHp / 100.0f ) ) + floor( hpMod / 100.0f * ( vitStat - baseStat ) ); return result; } @@ -78,13 +87,17 @@ uint32_t CalcBattle::calculateMaxMp( PlayerPtr pPlayer ) auto classInfoIt = g_exdData.m_classJobInfoMap.find( pPlayer->getClass() ); auto paramGrowthInfoIt = g_exdData.m_paramGrowthInfoMap.find( pPlayer->getLevel() ); + if ( classInfoIt == g_exdData.m_classJobInfoMap.end() || + paramGrowthInfoIt == g_exdData.m_paramGrowthInfoMap.end() ) + return 0; + float baseStat = calculateBaseStat( pPlayer ); uint16_t piety = pPlayer->getStats().pie; - uint16_t piety_scalar = paramGrowthInfoIt->second.mp_mod; + uint16_t pietyScalar = paramGrowthInfoIt->second.mp_mod; uint16_t jobModMp = classInfoIt->second.mod_mpcpgp; uint16_t baseMp = paramGrowthInfoIt->second.mp_const; - uint16_t result = floor( floor( piety - baseStat ) * ( piety_scalar / 100 ) + baseMp ) * jobModMp / 100; + uint16_t result = floor( floor( piety - baseStat ) * ( pietyScalar / 100 ) + baseMp ) * jobModMp / 100; return result; } @@ -99,7 +112,6 @@ uint32_t CalcBattle::calculateHealValue( PlayerPtr pPlayer, uint32_t potency ) paramGrowthInfoIt == g_exdData.m_paramGrowthInfoMap.end()) return 0; - auto jobModVal = classInfoIt->second; // consider 3% variation diff --git a/src/servers/Server_Zone/Actor/Player.cpp b/src/servers/Server_Zone/Actor/Player.cpp index 8b3803a9..f4899997 100644 --- a/src/servers/Server_Zone/Actor/Player.cpp +++ b/src/servers/Server_Zone/Actor/Player.cpp @@ -413,7 +413,8 @@ void Core::Entity::Player::setZone( uint32_t zoneId ) GamePacketNew< FFXIVIpcInitZone, ServerZoneIpcType > initZonePacket( getId() ); initZonePacket.data().zoneId = getCurrentZone()->getLayoutId(); initZonePacket.data().weatherId = static_cast< uint8_t >( getCurrentZone()->getCurrentWeather() ); - initZonePacket.data().bitmask = 0x2A; + initZonePacket.data().bitmask = 0x1; + initZonePacket.data().unknown5 = 0x2A; initZonePacket.data().pos.x = getPos().x; initZonePacket.data().pos.y = getPos().y; initZonePacket.data().pos.z = getPos().z; @@ -1255,6 +1256,19 @@ void Core::Entity::Player::queuePacket( Core::Network::Packets::GamePacketPtr pP } } +void Core::Entity::Player::queueChatPacket( Core::Network::Packets::GamePacketPtr pPacket ) +{ + auto pSession = g_serverZone.getSession( m_id ); + + if( pSession ) + { + auto pChatCon = pSession->getChatConnection(); + + if( pChatCon ) + pChatCon->queueOutPacket( pPacket ); + } +} + bool Core::Entity::Player::isLoadingComplete() const { return m_bLoadingComplete; diff --git a/src/servers/Server_Zone/Actor/Player.h b/src/servers/Server_Zone/Actor/Player.h index 3bcb2c57..1d788213 100644 --- a/src/servers/Server_Zone/Actor/Player.h +++ b/src/servers/Server_Zone/Actor/Player.h @@ -433,6 +433,8 @@ public: void sendQuestMessage( uint32_t questId, int8_t msgId, uint8_t type, uint32_t var1, uint32_t var2 ); /*! queue a packet for the player */ void queuePacket( Network::Packets::GamePacketPtr pPacket ); + /*! queue a char connection packet for the player */ + void queueChatPacket( Network::Packets::GamePacketPtr pPacket ); /*! returns true if loading is complete ( 0x69 has been received ) */ bool isLoadingComplete() const; /*! set the loading complete bool */ diff --git a/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp b/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp index e2bfcaa8..88136b4f 100644 --- a/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp +++ b/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp @@ -46,6 +46,7 @@ Core::DebugCommandHandler::DebugCommandHandler() registerCommand( "add", &DebugCommandHandler::add, "Loads and injects a premade Packet.", Common::UserLevel::all ); //registerCommand( "debug", &DebugCommandHandler::debug, "Loads and injects a premade Packet.", Common::UserLevel::all ); registerCommand( "inject", &DebugCommandHandler::injectPacket, "Loads and injects a premade Packet.", Common::UserLevel::all ); + registerCommand( "injectc", &DebugCommandHandler::injectChatPacket, "Loads and injects a premade Packet.", Common::UserLevel::all ); registerCommand( "script_reload", &DebugCommandHandler::scriptReload, "Loads and injects a premade Packet.", Common::UserLevel::all ); registerCommand( "nudge", &DebugCommandHandler::nudge, "Nudges you forward/up/down", Common::UserLevel::all ); @@ -473,6 +474,13 @@ void Core::DebugCommandHandler::injectPacket( char * data, Core::Entity::PlayerP pSession->getZoneConnection()->injectPacket( data + 7, pPlayer ); } +void Core::DebugCommandHandler::injectChatPacket( char * data, Core::Entity::PlayerPtr pPlayer, boost::shared_ptr< Core::DebugCommand > command ) +{ + auto pSession = g_serverZone.getSession( pPlayer->getId() ); + if( pSession ) + pSession->getChatConnection()->injectPacket( data + 8, pPlayer ); +} + void Core::DebugCommandHandler::nudge( char * data, Entity::PlayerPtr pPlayer, boost::shared_ptr command ) { std::string subCommand; diff --git a/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.h b/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.h index 4ea8647a..69ef7c4a 100644 --- a/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.h +++ b/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.h @@ -35,6 +35,7 @@ public: void scriptReload( char * data, Entity::PlayerPtr pPlayer, boost::shared_ptr command ); void injectPacket( char * data, Entity::PlayerPtr pPlayer, boost::shared_ptr command ); + void injectChatPacket( char * data, Entity::PlayerPtr pPlayer, boost::shared_ptr command ); void nudge( char* data, Entity::PlayerPtr pPlayer, boost::shared_ptr command ); }; diff --git a/src/servers/Server_Zone/Network/GameConnection.cpp b/src/servers/Server_Zone/Network/GameConnection.cpp index b70e5c07..fe6a57aa 100644 --- a/src/servers/Server_Zone/Network/GameConnection.cpp +++ b/src/servers/Server_Zone/Network/GameConnection.cpp @@ -34,7 +34,13 @@ Core::Network::GameConnection::GameConnection( Core::Network::HivePtr pHive, auto setZoneHandler = [=]( uint16_t opcode, std::string handlerName, GameConnection::Handler pHandler ) { m_zoneHandlerMap[opcode] = pHandler; - m_packetHandlerStrMap[opcode] = handlerName; + m_zoneHandlerStrMap[opcode] = handlerName; + }; + + auto setChatHandler = [=]( uint16_t opcode, std::string handlerName, GameConnection::Handler pHandler ) + { + m_chatHandlerMap[opcode] = pHandler; + m_chatHandlerStrMap[opcode] = handlerName; }; setZoneHandler( ClientZoneIpcType::PingHandler, "PingHandler", &GameConnection::pingHandler ); @@ -79,11 +85,16 @@ Core::Network::GameConnection::GameConnection( Core::Network::HivePtr pHive, setZoneHandler( ClientZoneIpcType::ReturnEventHandler, "EventHandlerReturn", &GameConnection::eventHandler ); setZoneHandler( ClientZoneIpcType::TradeReturnEventHandler, "EventHandlerReturn", &GameConnection::eventHandler ); + setZoneHandler( ClientZoneIpcType::LinkshellEventHandler, "LinkshellEventHandler", &GameConnection::eventHandler ); + setZoneHandler( ClientZoneIpcType::CFDutyInfoHandler, "CFDutyInfoRequest", &GameConnection::cfDutyInfoRequest ); setZoneHandler( ClientZoneIpcType::CFRegisterDuty, "CFRegisterDuty", &GameConnection::cfRegisterDuty ); setZoneHandler( ClientZoneIpcType::CFRegisterRoulette, "CFRegisterRoulette", &GameConnection::cfRegisterRoulette ); setZoneHandler( ClientZoneIpcType::CFCommenceHandler, "CFDutyAccepted", &GameConnection::cfDutyAccepted); + + setChatHandler( ClientChatIpcType::TellReq, "TellReq", &GameConnection::tellHandler); + } Core::Network::GameConnection::~GameConnection() @@ -168,40 +179,78 @@ void Core::Network::GameConnection::queueOutPacket( Core::Network::Packets::Game m_outQueue.push( outPacket ); } -void Core::Network::GameConnection::handleGamePacket( Core::Network::Packets::GamePacketPtr pPacket ) +void Core::Network::GameConnection::handleZonePacket( const Packets::GamePacket& pPacket ) +{ + auto it = m_zoneHandlerMap.find( pPacket.getSubType() ); + + std::string sessionStr = "[" + std::to_string( m_pSession->getId() ) + "]"; + + if( it != m_zoneHandlerMap.end() ) + { + auto itStr = m_zoneHandlerStrMap.find( pPacket.getSubType() ); + std::string name = itStr != m_zoneHandlerStrMap.end() ? itStr->second : "unknown"; + // dont display packet notification if it is a ping or pos update, don't want the spam + if( pPacket.getSubType() != PingHandler && + pPacket.getSubType() != UpdatePositionHandler ) + + g_log.debug( sessionStr + " Handling Zone IPC : " + name + "( " + + boost::str( boost::format( "%|04X|" ) % + static_cast< uint32_t >( pPacket.getSubType() & 0xFFFF ) ) + " )" ); + + ( this->*( it->second ) )( pPacket, m_pSession->getPlayer() ); + } + else + { + g_log.debug( sessionStr + " Undefined Zone IPC : Unknown ( " + + boost::str( boost::format( "%|04X|" ) % + static_cast< uint32_t >( pPacket.getSubType() & 0xFFFF ) ) + " )" ); + g_log.debug( pPacket.toString() ); + } +} + + +void Core::Network::GameConnection::handleChatPacket( const Packets::GamePacket& pPacket ) +{ + auto it = m_chatHandlerMap.find( pPacket.getSubType() ); + + std::string sessionStr = "[" + std::to_string( m_pSession->getId() ) + "]"; + + if( it != m_chatHandlerMap.end() ) + { + auto itStr = m_chatHandlerStrMap.find( pPacket.getSubType() ); + std::string name = itStr != m_chatHandlerStrMap.end() ? itStr->second : "unknown"; + // dont display packet notification if it is a ping or pos update, don't want the spam + + g_log.debug( sessionStr + " Handling Chat IPC : " + name + "( " + + boost::str( boost::format( "%|04X|" ) % + static_cast< uint32_t >( pPacket.getSubType() & 0xFFFF ) ) + " )" ); + + ( this->*( it->second ) )( pPacket, m_pSession->getPlayer() ); + } + else + { + g_log.debug( sessionStr + " Undefined Chat IPC : Unknown ( " + + boost::str( boost::format( "%|04X|" ) % + static_cast< uint32_t >( pPacket.getSubType() & 0xFFFF ) ) + " )" ); + g_log.debug( pPacket.toString() ); + } +} + +void Core::Network::GameConnection::handlePacket( Core::Network::Packets::GamePacketPtr pPacket ) { if( !m_pSession ) return; - /*if( m_conType == Network::ConnectionType::Zone ) + switch( m_conType ) { - g_log.debug( "Zone Packet" ); + case Network::ConnectionType::Zone: + handleZonePacket( *pPacket ); + break; + + case Network::ConnectionType::Chat: + handleChatPacket( *pPacket ); + break; } - else if( m_conType == Network::ConnectionType::Chat ) - { - g_log.debug( "Chat Packet" ); - }*/ - - auto it = m_zoneHandlerMap.find( pPacket->getSubType() ); - - if( it != m_zoneHandlerMap.end() ) - { - auto name = m_packetHandlerStrMap[pPacket->getSubType()]; - // dont display packet notification if it is a ping or pos update, don't want the spam - if( pPacket->getSubType() != ClientZoneIpcType::PingHandler && - pPacket->getSubType() != ClientZoneIpcType::UpdatePositionHandler ) - g_log.debug( "[" + std::to_string( m_pSession->getId() ) + "] Handling packet : " + name + "( " + - boost::str( boost::format( "%|04X|" ) % static_cast< uint32_t >( pPacket->getSubType() & 0xFFFF ) ) + " )" ); - - ( this->*( it->second ) )( *pPacket, m_pSession->getPlayer() ); - } - else - { - g_log.debug( "[" + std::to_string( m_pSession->getId() ) + "] Undefined packet : Unknown ( " + - boost::str( boost::format( "%|04X|" ) % static_cast< uint32_t >( pPacket->getSubType() & 0xFFFF ) ) + " )" ); - g_log.debug( pPacket->toString() ); - } - } @@ -219,7 +268,7 @@ void Core::Network::GameConnection::processInQueue() // handle the incoming game packets while( auto pPacket = m_inQueue.pop() ) { - handleGamePacket( pPacket ); + handlePacket(pPacket); } } @@ -338,27 +387,37 @@ void Core::Network::GameConnection::handlePackets( const Core::Network::Packets: if( !m_pSession && session ) m_pSession = session; + GamePacket pPe( 0x00, 0x18, 0, 0, 0x07 ); + //pPe.setValAt< uint32_t >( 0x10, 0xE0000005 ); + pPe.setValAt< uint32_t >( 0x10, 0xE0037603 ); + pPe.setValAt< uint32_t >( 0x14, static_cast< uint32_t >( time( nullptr ) ) ); + sendSinglePacket( &pPe ); + + + // main connection, assinging it to the session if( ipcHeader.connectionType == ConnectionType::Zone ) { + pPe = GamePacket( 0x00, 0x38, 0, 0, 0x02 ); + pPe.setValAt< uint32_t >( 0x10, playerId ); + sendSinglePacket( &pPe ); g_log.info( "[" + std::string( id ) + "] Setting session for zone connection" ); session->setZoneConnection( pCon ); } // chat connection, assinging it to the session else if( ipcHeader.connectionType == ConnectionType::Chat ) { + pPe = GamePacket( 0x00, 0x38, 0, 0, 0x02 ); + pPe.setValAt< uint32_t >( 0x10, playerId ); + sendSinglePacket( &pPe ); + g_log.info( "[" + std::string( id ) + "] Setting session for chat connection" ); session->setChatConnection( pCon ); + pPe = GamePacket( 0x02, 0x28, playerId, playerId, 0x03 ); + sendSinglePacket( &pPe ); } - GamePacket pPe( 0x00, 0x18, 0, 0, 0x07 ); - pPe.setValAt< uint32_t >( 0x10, 0xE0000005 ); - pPe.setValAt< uint32_t >( 0x14, static_cast< uint32_t >( time( nullptr ) ) ); - sendSinglePacket( &pPe ); - pPe = GamePacket( 0x00, 0x38, 0, 0, 0x02 ); - pPe.setValAt< uint32_t >( 0x10, playerId ); - sendSinglePacket( &pPe ); break; diff --git a/src/servers/Server_Zone/Network/GameConnection.h b/src/servers/Server_Zone/Network/GameConnection.h index a3a49f6f..d9156583 100644 --- a/src/servers/Server_Zone/Network/GameConnection.h +++ b/src/servers/Server_Zone/Network/GameConnection.h @@ -36,9 +36,13 @@ private: AcceptorPtr m_pAcceptor; - // handler for game packets (main type 0x03) + // handler for game packets (main type 0x03, connection type 1) HandlerMap m_zoneHandlerMap; - HandlerStrMap m_packetHandlerStrMap; + HandlerStrMap m_zoneHandlerStrMap; + + // handler for game packets (main type 0x03, connection type 2) + HandlerMap m_chatHandlerMap; + HandlerStrMap m_chatHandlerStrMap; SessionPtr m_pSession; @@ -70,7 +74,11 @@ public: void processInQueue(); void processOutQueue(); - void handleGamePacket( Packets::GamePacketPtr pPacket ); + void handlePacket( Packets::GamePacketPtr pPacket ); + + void handleZonePacket( const Packets::GamePacket& pPacket ); + + void handleChatPacket( const Packets::GamePacket& pPacket ); void sendPackets( Packets::PacketContainer * pPacket ); @@ -108,6 +116,8 @@ public: DECLARE_HANDLER( gm1Handler ); DECLARE_HANDLER( gm2Handler ); + DECLARE_HANDLER( tellHandler ); + }; diff --git a/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp b/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp index 3c800eb4..21efdb93 100644 --- a/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp +++ b/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp @@ -108,7 +108,8 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in } case 0x69: // Cancel cast { - pPlayer->getCurrentAction()->setInterrupted(); + if( pPlayer->checkAction() ) + pPlayer->getCurrentAction()->setInterrupted(); break; } case 0x133: // Update howtos seen diff --git a/src/servers/Server_Zone/Network/Handlers/EventHandlers.cpp b/src/servers/Server_Zone/Network/Handlers/EventHandlers.cpp index c75bd7b0..a3591b37 100644 --- a/src/servers/Server_Zone/Network/Handlers/EventHandlers.cpp +++ b/src/servers/Server_Zone/Network/Handlers/EventHandlers.cpp @@ -129,6 +129,16 @@ void Core::Network::GameConnection::eventHandler( const Packets::GamePacket& inP break; } + case ClientZoneIpcType::LinkshellEventHandler: + { + uint32_t eventId = inPacket.getValAt< uint32_t >( 0x20 ); + uint16_t subEvent = inPacket.getValAt< uint16_t >( 0x24 ); + std::string lsName = inPacket.getStringAt( 0x27 ); + + abortEventFunc( pPlayer, 0, eventId ); + break; + } + } } diff --git a/src/servers/Server_Zone/Network/Handlers/PacketHandlers.cpp b/src/servers/Server_Zone/Network/Handlers/PacketHandlers.cpp index 67cc8f58..85c81581 100644 --- a/src/servers/Server_Zone/Network/Handlers/PacketHandlers.cpp +++ b/src/servers/Server_Zone/Network/Handlers/PacketHandlers.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -541,4 +542,59 @@ void Core::Network::GameConnection::logoutHandler( const Packets::GamePacket& in logoutPacket.data().flags1 = 0x02; logoutPacket.data().flags2 = 0x2000; queueOutPacket( logoutPacket ); +} + + +void Core::Network::GameConnection::tellHandler( const Packets::GamePacket& inPacket, + Entity::PlayerPtr pPlayer ) +{ + std::string targetPcName = inPacket.getStringAt( 0x21 ); + std::string msg = inPacket.getStringAt( 0x41 ); + + auto pSession = g_serverZone.getSession( targetPcName ); + + if( !pSession ) + { + GamePacketNew< FFXIVIpcTellErrNotFound, ServerChatIpcType > tellErrPacket( pPlayer->getId() ); + strcpy( tellErrPacket.data().receipientName, targetPcName.c_str() ); + sendSinglePacket( tellErrPacket ); + + g_log.debug( "TargetPc not found" ); + return; + } + + auto pTargetPlayer = pSession->getPlayer(); + + if( pTargetPlayer->hasStateFlag( PlayerStateFlag::BetweenAreas ) || + pTargetPlayer->hasStateFlag( PlayerStateFlag::BetweenAreas1 ) ) + { + // send error for player between areas + // TODO: implement me + return; + } + + if( pTargetPlayer->hasStateFlag( PlayerStateFlag::BoundByDuty ) || + pTargetPlayer->hasStateFlag( PlayerStateFlag::BoundByDuty1 ) ) + { + // 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; + } + + GamePacketNew< FFXIVIpcTell, ServerChatIpcType > tellPacket( pPlayer->getId() ); + strcpy( tellPacket.data().msg, msg.c_str() ); + strcpy( tellPacket.data().receipientName, pPlayer->getName().c_str() ); + // TODO: do these have a meaning? + //tellPacket.data().u1 = 0x92CD7337; + //tellPacket.data().u2a = 0x2E; + //tellPacket.data().u2b = 0x40; + pTargetPlayer->queueChatPacket( tellPacket ); + } \ No newline at end of file