1047 lines
26 KiB
C++
1047 lines
26 KiB
C++
// Copyright (C) 2007 EQ2EMulator Development Team - GNU GPL v3
|
|
|
|
#pragma once
|
|
|
|
#define EQEMU_PROTOCOL_VERSION "0.5.0"
|
|
|
|
#include <vector>
|
|
#include <string>
|
|
#include <memory>
|
|
#include <cstring>
|
|
#include <iostream>
|
|
|
|
#include "types.hpp"
|
|
#include "packet/packet_functions.hpp"
|
|
|
|
// Server timing constants
|
|
#define SERVER_TIMEOUT 45000
|
|
#define INTERSERVER_TIMER 10000
|
|
#define LoginServer_StatusUpdateInterval 15000
|
|
#define LoginServer_AuthStale 60000
|
|
#define AUTHCHANGE_TIMEOUT 900
|
|
|
|
// Server operation codes
|
|
#define ServerOP_KeepAlive 0x0001
|
|
#define ServerOP_ChannelMessage 0x0002
|
|
#define ServerOP_SetZone 0x0003
|
|
#define ServerOP_ShutdownAll 0x0004
|
|
#define ServerOP_ZoneShutdown 0x0005
|
|
#define ServerOP_ZoneBootup 0x0006
|
|
#define ServerOP_ZoneStatus 0x0007
|
|
#define ServerOP_SetConnectInfo 0x0008
|
|
#define ServerOP_EmoteMessage 0x0009
|
|
#define ServerOP_ClientList 0x000A
|
|
#define ServerOP_Who 0x000B
|
|
#define ServerOP_ZonePlayer 0x000C
|
|
#define ServerOP_KickPlayer 0x000D
|
|
#define ServerOP_RefreshGuild 0x000E
|
|
#define ServerOP_GuildKickAll 0x000F
|
|
#define ServerOP_GuildInvite 0x0010
|
|
#define ServerOP_GuildRemove 0x0011
|
|
#define ServerOP_GuildPromote 0x0012
|
|
#define ServerOP_GuildDemote 0x0013
|
|
#define ServerOP_GuildLeader 0x0014
|
|
#define ServerOP_GuildGMSet 0x0015
|
|
#define ServerOP_GuildGMSetRank 0x0016
|
|
#define ServerOP_FlagUpdate 0x0018
|
|
#define ServerOP_GMGoto 0x0019
|
|
#define ServerOP_MultiLineMsg 0x001A
|
|
#define ServerOP_Lock 0x001B
|
|
#define ServerOP_Motd 0x001C
|
|
#define ServerOP_Uptime 0x001D
|
|
#define ServerOP_Petition 0x001E
|
|
#define ServerOP_KillPlayer 0x001F
|
|
#define ServerOP_UpdateGM 0x0020
|
|
#define ServerOP_RezzPlayer 0x0021
|
|
#define ServerOP_ZoneReboot 0x0022
|
|
#define ServerOP_ZoneToZoneRequest 0x0023
|
|
#define ServerOP_AcceptWorldEntrance 0x0024
|
|
#define ServerOP_ZAAuth 0x0025
|
|
#define ServerOP_ZAAuthFailed 0x0026
|
|
#define ServerOP_ZoneIncClient 0x0027
|
|
#define ServerOP_ClientListKA 0x0028
|
|
#define ServerOP_ChangeWID 0x0029
|
|
#define ServerOP_IPLookup 0x002A
|
|
#define ServerOP_LockZone 0x002B
|
|
#define ServerOP_ItemStatus 0x002C
|
|
#define ServerOP_OOCMute 0x002D
|
|
#define ServerOP_Revoke 0x002E
|
|
#define ServerOP_GuildJoin 0x002F
|
|
#define ServerOP_GroupIDReq 0x0030
|
|
#define ServerOP_GroupIDReply 0x0031
|
|
#define ServerOP_GroupLeave 0x0032
|
|
#define ServerOP_RezzPlayerAccept 0x0033
|
|
#define ServerOP_SpawnCondition 0x0034
|
|
#define ServerOP_SpawnEvent 0x0035
|
|
|
|
// Update server operation codes
|
|
#define UpdateServerOP_Verified 0x5090
|
|
#define UpdateServerOP_DisplayMsg 0x5091
|
|
#define UpdateServerOP_Completed 0x5092
|
|
|
|
// Login server operation codes
|
|
#define ServerOP_LSInfo 0x1000
|
|
#define ServerOP_LSStatus 0x1001
|
|
#define ServerOP_LSClientAuth 0x1002
|
|
#define ServerOP_LSFatalError 0x1003
|
|
#define ServerOP_SystemwideMessage 0x1005
|
|
#define ServerOP_ListWorlds 0x1006
|
|
#define ServerOP_PeerConnect 0x1007
|
|
|
|
// Login server zone operation codes
|
|
#define ServerOP_LSZoneInfo 0x3001
|
|
#define ServerOP_LSZoneStart 0x3002
|
|
#define ServerOP_LSZoneBoot 0x3003
|
|
#define ServerOP_LSZoneShutdown 0x3004
|
|
#define ServerOP_LSZoneSleep 0x3005
|
|
#define ServerOP_LSPlayerLeftWorld 0x3006
|
|
#define ServerOP_LSPlayerJoinWorld 0x3007
|
|
#define ServerOP_LSPlayerZoneChange 0x3008
|
|
|
|
// User to world operation codes
|
|
#define ServerOP_UsertoWorldReq 0xAB00
|
|
#define ServerOP_UsertoWorldResp 0xAB01
|
|
|
|
// Packet operation codes
|
|
#define ServerOP_EncapPacket 0x2007
|
|
#define ServerOP_WorldListUpdate 0x2008
|
|
#define ServerOP_WorldListRemove 0x2009
|
|
#define ServerOP_TriggerWorldListRefresh 0x200A
|
|
#define ServerOP_WhoAll 0x0210
|
|
|
|
// Time operation codes
|
|
#define ServerOP_SetWorldTime 0x200B
|
|
#define ServerOP_GetWorldTime 0x200C
|
|
#define ServerOP_SyncWorldTime 0x200E
|
|
|
|
// EQ2 specific operation codes
|
|
#define ServerOP_CharTimeStamp 0x200F
|
|
#define ServerOP_NameFilterCheck 0x2011
|
|
#define ServerOP_BasicCharUpdate 0x2012
|
|
#define ServerOP_CharacterCreate 0x2013
|
|
#define ServerOP_NameCharUpdate 0x2014
|
|
#define ServerOP_GetLatestTables 0x2015
|
|
#define ServerOP_GetTableQuery 0x2016
|
|
#define ServerOP_GetTableData 0x2017
|
|
#define ServerOP_RaceUpdate 0x2018
|
|
#define ServerOP_ZoneUpdate 0x2019
|
|
#define ServerOP_BugReport 0x201A
|
|
#define ServerOP_ResetDatabase 0x201B
|
|
#define ServerOP_ZoneUpdates 0x201C
|
|
#define ServerOP_LoginEquipment 0x201D
|
|
#define ServerOP_CharacterPicture 0x201E
|
|
|
|
// Character update flags
|
|
#define LEVEL_UPDATE_FLAG 1
|
|
#define RACE_UPDATE_FLAG 2
|
|
#define CLASS_UPDATE_FLAG 4
|
|
#define GENDER_UPDATE_FLAG 8
|
|
#define ZONE_UPDATE_FLAG 16
|
|
#define ARMOR_UPDATE_FLAG 32
|
|
#define NAME_UPDATE_FLAG 64
|
|
#define DELETE_UPDATE_FLAG 128
|
|
|
|
// Structure size limits
|
|
#define CHARNAMEUPDATESTRUCT_MAXSIZE 74
|
|
#define CHARZONESTRUCT_MAXSIZE 78
|
|
#define CHARPICSTRUCT_MINSIZE 10
|
|
|
|
/**
|
|
* Core server packet class for inter-server communication
|
|
* Handles packet creation, compression, and memory management
|
|
*/
|
|
class ServerPacket
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor - Creates a new server packet with specified opcode and size
|
|
* @param in_opcode - The operation code for this packet
|
|
* @param in_size - The size of the packet data buffer
|
|
*/
|
|
ServerPacket(int16 in_opcode = 0, int32 in_size = 0)
|
|
{
|
|
compressed = false;
|
|
size = in_size;
|
|
opcode = in_opcode;
|
|
if (size == 0) {
|
|
pBuffer = nullptr;
|
|
} else {
|
|
pBuffer = new uchar[size];
|
|
std::memset(pBuffer, 0, size);
|
|
}
|
|
destination = 0;
|
|
InflatedSize = 0;
|
|
}
|
|
|
|
/**
|
|
* Destructor - Cleans up packet buffer memory
|
|
*/
|
|
~ServerPacket()
|
|
{
|
|
delete[] pBuffer;
|
|
}
|
|
|
|
/**
|
|
* Creates a deep copy of this packet
|
|
* @return New ServerPacket instance with copied data, or nullptr if this packet is null
|
|
*/
|
|
ServerPacket* Copy()
|
|
{
|
|
if (this == nullptr) {
|
|
return nullptr;
|
|
}
|
|
ServerPacket* ret = new ServerPacket(this->opcode, this->size);
|
|
if (this->size) {
|
|
std::memcpy(ret->pBuffer, this->pBuffer, this->size);
|
|
}
|
|
ret->compressed = this->compressed;
|
|
ret->InflatedSize = this->InflatedSize;
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Compresses the packet data using deflate algorithm
|
|
* @return true if compression successful, false if already compressed or invalid data
|
|
*/
|
|
bool Deflate()
|
|
{
|
|
if (compressed) {
|
|
return false;
|
|
}
|
|
if (!pBuffer || !size) {
|
|
return false;
|
|
}
|
|
|
|
uchar* tmp = new uchar[size + 128];
|
|
int32 tmpsize = DeflatePacket(pBuffer, size, tmp, size + 128);
|
|
if (!tmpsize) {
|
|
delete[] tmp;
|
|
return false;
|
|
}
|
|
|
|
compressed = true;
|
|
InflatedSize = size;
|
|
size = tmpsize;
|
|
uchar* new_buffer = new uchar[size];
|
|
std::memcpy(new_buffer, tmp, size);
|
|
delete[] tmp;
|
|
delete[] pBuffer;
|
|
pBuffer = new_buffer;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Decompresses the packet data using inflate algorithm
|
|
* @return true if decompression successful, false if not compressed or invalid data
|
|
*/
|
|
bool Inflate()
|
|
{
|
|
if (!compressed) {
|
|
return false;
|
|
}
|
|
if (!pBuffer || !size) {
|
|
return false;
|
|
}
|
|
|
|
uchar* tmp = new uchar[InflatedSize];
|
|
int32 tmpsize = InflatePacket(pBuffer, size, tmp, InflatedSize);
|
|
if (!tmpsize) {
|
|
delete[] tmp;
|
|
return false;
|
|
}
|
|
|
|
compressed = false;
|
|
size = tmpsize;
|
|
delete[] pBuffer;
|
|
pBuffer = tmp;
|
|
return true;
|
|
}
|
|
|
|
int32 size; // Current size of packet buffer
|
|
int16 opcode; // Operation code identifying packet type
|
|
uchar* pBuffer; // Raw packet data buffer
|
|
bool compressed; // Flag indicating if packet is compressed
|
|
int32 InflatedSize; // Original size before compression
|
|
int32 destination; // Target server ID for routing
|
|
};
|
|
|
|
#pragma pack(1)
|
|
|
|
/**
|
|
* Structure for requesting latest table versions
|
|
*/
|
|
struct GetLatestTables_Struct
|
|
{
|
|
float table_version; // Current table version
|
|
float data_version; // Current data version
|
|
};
|
|
|
|
/**
|
|
* Login server information structure
|
|
*/
|
|
struct ServerLSInfo_Struct
|
|
{
|
|
char name[201]; // Server name identifier
|
|
char address[250]; // DNS address of the server
|
|
char account[31]; // Account name for authentication
|
|
char password[256]; // Password for authentication
|
|
char protocolversion[25]; // Protocol version string
|
|
char serverversion[64]; // Server software version
|
|
int8 servertype; // Server type: 0=world, 1=chat, 2=login, 3=MeshLogin, 4=World Debug
|
|
int32 dbversion; // Database version for compatibility
|
|
};
|
|
|
|
/**
|
|
* Login server status information
|
|
*/
|
|
struct ServerLSStatus_Struct
|
|
{
|
|
sint32 status; // Current server status
|
|
sint32 num_players; // Number of connected players
|
|
sint32 num_zones; // Number of active zones
|
|
int8 world_max_level; // Maximum character level allowed
|
|
};
|
|
|
|
/**
|
|
* System-wide message structure
|
|
*/
|
|
struct ServerSystemwideMessage
|
|
{
|
|
int32 lsaccount_id; // Login server account ID
|
|
char key[30]; // Session ID key for verification
|
|
int32 type; // Message type identifier
|
|
char message[0]; // Variable length message data
|
|
};
|
|
|
|
/**
|
|
* World list synchronization structure
|
|
*/
|
|
struct ServerSyncWorldList_Struct
|
|
{
|
|
int32 RemoteID; // Remote server identifier
|
|
int32 ip; // Server IP address
|
|
sint32 status; // Server status code
|
|
char name[201]; // Server name
|
|
char address[250]; // Server address
|
|
char account[31]; // Account name
|
|
int32 accountid; // Account ID
|
|
int8 authlevel; // Authorization level
|
|
int8 servertype; // Server type classification
|
|
int32 adminid; // Administrator ID
|
|
int8 showdown; // Shutdown flag
|
|
sint32 num_players; // Current player count
|
|
sint32 num_zones; // Current zone count
|
|
bool placeholder; // Placeholder server flag
|
|
};
|
|
|
|
/**
|
|
* User to world request structure
|
|
*/
|
|
struct UsertoWorldRequest_Struct
|
|
{
|
|
int32 lsaccountid; // Login server account ID
|
|
int32 char_id; // Character ID
|
|
int32 worldid; // Target world ID
|
|
int32 FromID; // Source server ID
|
|
int32 ToID; // Destination server ID
|
|
char ip_address[21]; // Client IP address
|
|
};
|
|
|
|
/**
|
|
* User to world response structure
|
|
*/
|
|
struct UsertoWorldResponse_Struct
|
|
{
|
|
int32 lsaccountid; // Login server account ID
|
|
int32 char_id; // Character ID
|
|
int32 worldid; // World ID
|
|
int32 access_key; // Access key for authentication
|
|
int8 response; // Response code
|
|
char ip_address[80]; // Server IP address
|
|
int32 port; // Server port
|
|
int32 FromID; // Source server ID
|
|
int32 ToID; // Destination server ID
|
|
};
|
|
|
|
/**
|
|
* Encapsulated packet structure for packet forwarding
|
|
*/
|
|
struct ServerEncapPacket_Struct
|
|
{
|
|
int32 ToID; // Target server ID
|
|
int16 opcode; // Encapsulated packet opcode
|
|
int16 size; // Encapsulated packet size
|
|
uchar data[0]; // Variable length packet data
|
|
};
|
|
|
|
/**
|
|
* Emote message structure
|
|
*/
|
|
struct ServerEmoteMessage_Struct
|
|
{
|
|
char to[64]; // Target recipient
|
|
int32 guilddbid; // Guild database ID
|
|
sint16 minstatus; // Minimum status required
|
|
int32 type; // Emote type
|
|
char message[0]; // Variable length message
|
|
};
|
|
|
|
/**
|
|
* Table version information structure
|
|
*/
|
|
typedef struct
|
|
{
|
|
char name[256]; // Table name
|
|
unsigned int name_len; // Length of table name
|
|
unsigned int version; // Table version number
|
|
unsigned int data_version; // Data version number
|
|
} TableVersion;
|
|
|
|
/**
|
|
* Helper template function to append data to string buffer
|
|
*/
|
|
template<class Type>
|
|
void AddPtrData(std::string* buffer, Type& data)
|
|
{
|
|
buffer->append(reinterpret_cast<char*>(&data), sizeof(Type));
|
|
}
|
|
|
|
/**
|
|
* Helper template function to append array data to string buffer
|
|
*/
|
|
template<class Type>
|
|
void AddPtrData(std::string* buffer, Type* data, int16 size)
|
|
{
|
|
buffer->append(reinterpret_cast<char*>(data), size);
|
|
}
|
|
|
|
/**
|
|
* Class for managing latest table versions across servers
|
|
* Handles serialization and deserialization of table version data
|
|
*/
|
|
class LatestTableVersions
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor - Initializes empty table version list
|
|
*/
|
|
LatestTableVersions()
|
|
{
|
|
tables = nullptr;
|
|
current_index = 0;
|
|
total_tables = 0;
|
|
data_version = 0;
|
|
}
|
|
|
|
/**
|
|
* Destructor - Cleans up allocated table array
|
|
*/
|
|
~LatestTableVersions()
|
|
{
|
|
delete[] tables;
|
|
}
|
|
|
|
/**
|
|
* Allocates memory for specified number of tables
|
|
* @param size - Number of tables to allocate space for
|
|
*/
|
|
void SetTableSize(int16 size)
|
|
{
|
|
total_tables = size;
|
|
tables = new TableVersion[total_tables];
|
|
}
|
|
|
|
/**
|
|
* Adds a table version entry to the collection
|
|
* @param name - Table name
|
|
* @param version - Table version number
|
|
* @param data_version - Data version number
|
|
*/
|
|
void AddTable(char* name, int32 version, int32 data_version)
|
|
{
|
|
std::strcpy(tables[current_index].name, name);
|
|
tables[current_index].version = version;
|
|
tables[current_index].data_version = data_version;
|
|
current_index++;
|
|
}
|
|
|
|
/**
|
|
* Calculates total serialized size of all table data
|
|
* @return Total size in bytes
|
|
*/
|
|
int16 GetTotalSize()
|
|
{
|
|
return total_tables * sizeof(TableVersion) + sizeof(int16);
|
|
}
|
|
|
|
/**
|
|
* Gets total number of tables in collection
|
|
* @return Number of tables
|
|
*/
|
|
int16 GetTotalTables()
|
|
{
|
|
return total_tables;
|
|
}
|
|
|
|
/**
|
|
* Gets pointer to table array
|
|
* @return Pointer to TableVersion array
|
|
*/
|
|
TableVersion* GetTables()
|
|
{
|
|
return tables;
|
|
}
|
|
|
|
/**
|
|
* Gets specific table by index
|
|
* @param index - Index of table to retrieve
|
|
* @return TableVersion structure
|
|
*/
|
|
TableVersion GetTable(int16 index)
|
|
{
|
|
return tables[index];
|
|
}
|
|
|
|
/**
|
|
* Serializes all table data into string buffer
|
|
* @return Serialized data string
|
|
*/
|
|
std::string Serialize()
|
|
{
|
|
AddPtrData(&buffer, total_tables);
|
|
for (int16 i = 0; i < total_tables; i++) {
|
|
AddPtrData(&buffer, tables[i].name, sizeof(tables[i].name));
|
|
AddPtrData(&buffer, tables[i].version);
|
|
AddPtrData(&buffer, tables[i].data_version);
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
/**
|
|
* Deserializes table data from byte array
|
|
* @param data - Raw byte data to deserialize
|
|
*/
|
|
void DeSerialize(uchar* data)
|
|
{
|
|
uchar* ptr = data;
|
|
std::memcpy(&total_tables, ptr, sizeof(total_tables));
|
|
ptr += sizeof(total_tables);
|
|
tables = new TableVersion[total_tables];
|
|
for (int16 i = 0; i < total_tables; i++) {
|
|
std::memcpy(&tables[i].name, ptr, sizeof(tables[i].name));
|
|
ptr += sizeof(tables[i].name);
|
|
std::memcpy(&tables[i].version, ptr, sizeof(tables[i].version));
|
|
ptr += sizeof(tables[i].version);
|
|
std::memcpy(&tables[i].data_version, ptr, sizeof(tables[i].data_version));
|
|
ptr += sizeof(tables[i].data_version);
|
|
}
|
|
}
|
|
|
|
int32 data_version; // Global data version
|
|
|
|
private:
|
|
int16 current_index; // Current insertion index
|
|
int16 total_tables; // Total number of tables allocated
|
|
TableVersion* tables; // Array of table versions
|
|
std::string buffer; // Serialization buffer
|
|
};
|
|
|
|
/**
|
|
* Structure for table data queries
|
|
*/
|
|
struct TableData
|
|
{
|
|
int16 size; // Size of query string
|
|
char* query; // SQL query string
|
|
};
|
|
|
|
/**
|
|
* Class for managing table query operations
|
|
* Handles multiple SQL queries with version tracking
|
|
*/
|
|
class TableQuery
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor - Initializes empty query collection
|
|
*/
|
|
TableQuery()
|
|
{
|
|
try_delete = true;
|
|
num_queries = 0;
|
|
data_version = 0;
|
|
current_index = 0;
|
|
latest_version = 0;
|
|
your_version = 0;
|
|
total_size = sizeof(num_queries) + sizeof(latest_version) + sizeof(your_version) + sizeof(tablename);
|
|
}
|
|
|
|
/**
|
|
* Destructor - Cleans up query strings if owned
|
|
*/
|
|
~TableQuery()
|
|
{
|
|
if (try_delete) {
|
|
for (size_t i = 0; i < tmp_queries.size(); i++) {
|
|
delete[] tmp_queries[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Concatenates all queries into single string
|
|
* @return Combined query string with newline separators
|
|
*/
|
|
std::string GetQueriesString()
|
|
{
|
|
std::string query_string;
|
|
for (size_t i = 0; i < tmp_queries.size(); i++) {
|
|
query_string.append(tmp_queries[i]).append("\n");
|
|
}
|
|
return query_string;
|
|
}
|
|
|
|
/**
|
|
* Adds a query string to the collection
|
|
* @param query - SQL query string to add
|
|
*/
|
|
void AddQuery(char* query)
|
|
{
|
|
num_queries++;
|
|
total_size += std::strlen(query) + 1;
|
|
tmp_queries.push_back(query);
|
|
}
|
|
|
|
/**
|
|
* Gets total serialized size of query collection
|
|
* @return Total size in bytes
|
|
*/
|
|
int16 GetTotalSize()
|
|
{
|
|
return total_size;
|
|
}
|
|
|
|
/**
|
|
* Gets number of queries in collection
|
|
* @return Query count
|
|
*/
|
|
int16 GetTotalQueries()
|
|
{
|
|
return num_queries;
|
|
}
|
|
|
|
/**
|
|
* Gets specific query by index
|
|
* @param index - Index of query to retrieve
|
|
* @return Query string pointer
|
|
*/
|
|
char* GetQuery(int16 index)
|
|
{
|
|
return tmp_queries[index];
|
|
}
|
|
|
|
/**
|
|
* Serializes query collection to string buffer
|
|
* @return Serialized data string
|
|
*/
|
|
std::string Serialize()
|
|
{
|
|
num_queries = tmp_queries.size();
|
|
AddPtrData(&buffer, num_queries);
|
|
AddPtrData(&buffer, latest_version);
|
|
AddPtrData(&buffer, your_version);
|
|
AddPtrData(&buffer, data_version);
|
|
AddPtrData(&buffer, tablename, sizeof(tablename));
|
|
for (int16 i = 0; i < GetTotalQueries(); i++) {
|
|
AddPtrData(&buffer, tmp_queries[i], std::strlen(tmp_queries[i]) + 1);
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
/**
|
|
* Deserializes query data from byte array
|
|
* @param data - Raw byte data to deserialize
|
|
*/
|
|
void DeSerialize(uchar* data)
|
|
{
|
|
try_delete = false;
|
|
uchar* ptr = data;
|
|
std::memcpy(&num_queries, ptr, sizeof(num_queries));
|
|
ptr += sizeof(num_queries);
|
|
std::memcpy(&latest_version, ptr, sizeof(latest_version));
|
|
ptr += sizeof(latest_version);
|
|
std::memcpy(&your_version, ptr, sizeof(your_version));
|
|
ptr += sizeof(your_version);
|
|
std::memcpy(&data_version, ptr, sizeof(data_version));
|
|
ptr += sizeof(data_version);
|
|
std::memcpy(&tablename, ptr, sizeof(tablename));
|
|
ptr += sizeof(tablename);
|
|
for (int16 i = 0; i < GetTotalQueries(); i++) {
|
|
tmp_queries.push_back(reinterpret_cast<char*>(ptr));
|
|
ptr += std::strlen(reinterpret_cast<char*>(ptr)) + 1;
|
|
}
|
|
}
|
|
|
|
int16 current_index; // Current processing index
|
|
int16 num_queries; // Number of queries in collection
|
|
int32 latest_version; // Latest available version
|
|
int32 your_version; // Client's current version
|
|
int32 data_version; // Data version number
|
|
bool try_delete; // Flag to control memory cleanup
|
|
char tablename[64]; // Associated table name
|
|
int32 total_size; // Total serialized size
|
|
std::string buffer; // Serialization buffer
|
|
|
|
private:
|
|
std::vector<char*> tmp_queries; // Collection of query strings
|
|
};
|
|
|
|
/**
|
|
* Class for managing table data queries with column information
|
|
* Handles database query results with metadata
|
|
*/
|
|
class TableDataQuery
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor - Initializes with table name
|
|
* @param table_name - Name of the associated table
|
|
*/
|
|
TableDataQuery(char* table_name)
|
|
{
|
|
if (std::strlen(table_name) >= sizeof(tablename)) {
|
|
return;
|
|
}
|
|
std::strcpy(tablename, table_name);
|
|
num_queries = 0;
|
|
columns_size = 0;
|
|
columns = nullptr;
|
|
version = 0;
|
|
table_size = 0;
|
|
}
|
|
|
|
/**
|
|
* Default constructor
|
|
*/
|
|
TableDataQuery()
|
|
{
|
|
num_queries = 0;
|
|
columns_size = 0;
|
|
columns = nullptr;
|
|
version = 0;
|
|
table_size = 0;
|
|
}
|
|
|
|
/**
|
|
* Destructor - Cleans up column data and queries
|
|
*/
|
|
~TableDataQuery()
|
|
{
|
|
delete[] columns;
|
|
for (int32 i = 0; i < num_queries; i++) {
|
|
delete[] queries[i]->query;
|
|
delete queries[i];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets total number of queries
|
|
* @return Query count
|
|
*/
|
|
int32 GetTotalQueries()
|
|
{
|
|
return num_queries;
|
|
}
|
|
|
|
/**
|
|
* Serializes query data to string buffer with query limit
|
|
* @return Pointer to serialized data string, or nullptr if no queries
|
|
*/
|
|
std::string* Serialize()
|
|
{
|
|
buffer = "";
|
|
num_queries = queries.size();
|
|
if (GetTotalQueries() == 0) {
|
|
return nullptr;
|
|
}
|
|
table_size = std::strlen(tablename);
|
|
AddPtrData(&buffer, table_size);
|
|
AddPtrData(&buffer, tablename, table_size + 1);
|
|
AddPtrData(&buffer, version);
|
|
if (num_queries > 200) {
|
|
int32 max_queries = 200;
|
|
AddPtrData(&buffer, max_queries);
|
|
} else {
|
|
AddPtrData(&buffer, num_queries);
|
|
}
|
|
AddPtrData(&buffer, columns_size);
|
|
AddPtrData(&buffer, columns, columns_size);
|
|
|
|
// Process queries in reverse order with limit of 200
|
|
int16 count = 0;
|
|
for (int i = GetTotalQueries() - 1; i >= 0 && count < 200; i--) {
|
|
AddPtrData(&buffer, queries[i]->size);
|
|
AddPtrData(&buffer, queries[i]->query, queries[i]->size);
|
|
delete[] queries[i]->query;
|
|
delete queries[i];
|
|
queries.pop_back();
|
|
count++;
|
|
}
|
|
return &buffer;
|
|
}
|
|
|
|
/**
|
|
* Deserializes query data from byte array
|
|
* @param data - Raw byte data to deserialize
|
|
*/
|
|
void DeSerialize(uchar* data)
|
|
{
|
|
uchar* ptr = data;
|
|
|
|
std::memcpy(&table_size, ptr, sizeof(table_size));
|
|
ptr += sizeof(table_size);
|
|
std::memcpy(&tablename, ptr, table_size + 1);
|
|
ptr += table_size + 1;
|
|
|
|
std::memcpy(&version, ptr, sizeof(version));
|
|
ptr += sizeof(version);
|
|
|
|
std::memcpy(&num_queries, ptr, sizeof(num_queries));
|
|
ptr += sizeof(num_queries);
|
|
|
|
std::memcpy(&columns_size, ptr, sizeof(columns_size));
|
|
ptr += sizeof(columns_size);
|
|
columns = new char[columns_size + 1];
|
|
std::memcpy(columns, ptr, columns_size + 1);
|
|
ptr += columns_size;
|
|
|
|
for (int32 i = 0; i < GetTotalQueries(); i++) {
|
|
TableData* new_query = new TableData;
|
|
try {
|
|
std::memcpy(&new_query->size, ptr, sizeof(new_query->size));
|
|
ptr += sizeof(new_query->size);
|
|
new_query->query = new char[new_query->size + 1];
|
|
std::memcpy(new_query->query, ptr, new_query->size);
|
|
ptr += new_query->size;
|
|
queries.push_back(new_query);
|
|
} catch (const std::bad_alloc& ba) {
|
|
std::cout << ba.what() << std::endl;
|
|
delete new_query;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string buffer; // Serialization buffer
|
|
int32 num_queries; // Number of queries in collection
|
|
int32 version; // Table version number
|
|
int16 table_size; // Size of table name string
|
|
char tablename[64]; // Associated table name
|
|
int16 columns_size; // Size of column definition string
|
|
char* columns; // Column definitions
|
|
std::vector<TableData*> queries; // Collection of table data queries
|
|
};
|
|
|
|
/**
|
|
* Equipment update request structure
|
|
*/
|
|
struct EquipmentUpdateRequest_Struct
|
|
{
|
|
int16 max_per_batch; // Maximum updates per batch
|
|
};
|
|
|
|
/**
|
|
* Login server equipment update structure
|
|
*/
|
|
struct LoginEquipmentUpdate
|
|
{
|
|
int32 world_char_id; // Character ID
|
|
int16 equip_type; // Equipment type identifier
|
|
int8 red; // Red color component
|
|
int8 green; // Green color component
|
|
int8 blue; // Blue color component
|
|
int8 highlight_red; // Highlight red component
|
|
int8 highlight_green; // Highlight green component
|
|
int8 highlight_blue; // Highlight blue component
|
|
int32 slot; // Equipment slot identifier
|
|
};
|
|
|
|
/**
|
|
* World server equipment update structure
|
|
*/
|
|
struct EquipmentUpdate_Struct
|
|
{
|
|
int32 id; // Unique record identifier
|
|
int32 world_char_id; // Character ID
|
|
int16 equip_type; // Equipment type identifier
|
|
int8 red; // Red color component
|
|
int8 green; // Green color component
|
|
int8 blue; // Blue color component
|
|
int8 highlight_red; // Highlight red component
|
|
int8 highlight_green; // Highlight green component
|
|
int8 highlight_blue; // Highlight blue component
|
|
int32 slot; // Equipment slot identifier
|
|
};
|
|
|
|
/**
|
|
* Equipment update list structure
|
|
*/
|
|
struct EquipmentUpdateList_Struct
|
|
{
|
|
sint16 total_updates; // Total number of updates available
|
|
};
|
|
|
|
/**
|
|
* Zone update request structure
|
|
*/
|
|
struct ZoneUpdateRequest_Struct
|
|
{
|
|
int16 max_per_batch; // Maximum updates per batch
|
|
};
|
|
|
|
/**
|
|
* Login server zone update structure
|
|
*/
|
|
struct LoginZoneUpdate
|
|
{
|
|
std::string name; // Zone name
|
|
std::string description; // Zone description
|
|
};
|
|
|
|
/**
|
|
* Zone update structure with variable data
|
|
*/
|
|
struct ZoneUpdate_Struct
|
|
{
|
|
int32 zone_id; // Zone identifier
|
|
int8 zone_name_length; // Length of zone name
|
|
int8 zone_desc_length; // Length of zone description
|
|
char data[0]; // Variable length name and description data
|
|
};
|
|
|
|
/**
|
|
* Zone update list structure
|
|
*/
|
|
struct ZoneUpdateList_Struct
|
|
{
|
|
uint16 total_updates; // Total number of zone updates
|
|
char data[0]; // Variable length update data
|
|
};
|
|
|
|
/**
|
|
* Character timestamp structure for EQ2
|
|
*/
|
|
struct CharacterTimeStamp_Struct
|
|
{
|
|
int32 char_id; // Character identifier
|
|
int32 account_id; // Account identifier
|
|
int32 unix_timestamp; // Unix timestamp of last update
|
|
};
|
|
|
|
/**
|
|
* Character data update structure for basic changes
|
|
*/
|
|
struct CharDataUpdate_Struct
|
|
{
|
|
int32 account_id; // Account identifier
|
|
int32 char_id; // Character identifier
|
|
int8 update_field; // Bitfield of updated fields
|
|
int32 update_data; // Updated data value
|
|
};
|
|
|
|
/**
|
|
* Bug report structure
|
|
*/
|
|
struct BugReport
|
|
{
|
|
char category[64]; // Bug category
|
|
char subcategory[64]; // Bug subcategory
|
|
char causes_crash[64]; // Crash information
|
|
char reproducible[64]; // Reproducibility info
|
|
char summary[128]; // Bug summary
|
|
char description[2000]; // Detailed description
|
|
char version[32]; // Game version
|
|
char player[64]; // Player name
|
|
int32 account_id; // Account identifier
|
|
char spawn_name[64]; // Associated spawn name
|
|
int32 spawn_id; // Spawn identifier
|
|
int32 zone_id; // Zone identifier
|
|
};
|
|
|
|
/**
|
|
* Race update structure
|
|
*/
|
|
struct RaceUpdate_Struct
|
|
{
|
|
int32 account_id; // Account identifier
|
|
int32 char_id; // Character identifier
|
|
int16 model_type; // Character model type
|
|
int8 race; // Race identifier
|
|
};
|
|
|
|
/**
|
|
* Character name update structure
|
|
*/
|
|
struct CharNameUpdate_Struct
|
|
{
|
|
int32 account_id; // Account identifier
|
|
int32 char_id; // Character identifier
|
|
int8 name_length; // Length of new name
|
|
char new_name[0]; // Variable length new name
|
|
};
|
|
|
|
/**
|
|
* Character zone update structure
|
|
*/
|
|
struct CharZoneUpdate_Struct
|
|
{
|
|
int32 account_id; // Account identifier
|
|
int32 char_id; // Character identifier
|
|
int32 zone_id; // Zone identifier
|
|
int8 zone_length; // Length of zone name
|
|
char new_zone[0]; // Variable length zone name
|
|
};
|
|
|
|
/**
|
|
* World character creation structure
|
|
*/
|
|
struct WorldCharCreate_Struct
|
|
{
|
|
int32 account_id; // Account identifier
|
|
int32 char_id; // Character identifier
|
|
int16 model_type; // Character model type
|
|
int16 char_size; // Size of character data
|
|
uchar character[0]; // Variable length character data
|
|
};
|
|
|
|
/**
|
|
* Character name filter request structure
|
|
*/
|
|
struct WorldCharNameFilter_Struct
|
|
{
|
|
int32 account_id; // Account identifier
|
|
int16 name_length; // Length of name to filter
|
|
uchar name[0]; // Variable length name data
|
|
};
|
|
|
|
/**
|
|
* Character name filter response structure
|
|
*/
|
|
struct WorldCharNameFilterResponse_Struct
|
|
{
|
|
int32 account_id; // Account identifier
|
|
int32 char_id; // Character identifier
|
|
int8 response; // Filter result code
|
|
};
|
|
|
|
/**
|
|
* Character picture update structure
|
|
*/
|
|
struct CharPictureUpdate_Struct
|
|
{
|
|
int32 account_id; // Account identifier
|
|
int32 char_id; // Character identifier
|
|
int16 pic_size; // Size of picture data
|
|
char pic[0]; // Variable length picture data
|
|
};
|
|
|
|
#pragma pack() |