eq2go/old/common/packet/data_struct.hpp
2025-08-06 19:00:30 -05:00

453 lines
13 KiB
C++

// Copyright (C) 2007 EQ2EMulator Development Team, GPL v3+
#pragma once
#include <string>
#include <vector>
#include "../log.hpp"
#include "../types.hpp"
#include "../misc_functions.hpp"
#define DATA_STRUCT_NONE 0
#define DATA_STRUCT_INT8 1
#define DATA_STRUCT_INT16 2
#define DATA_STRUCT_INT32 3
#define DATA_STRUCT_INT64 4
#define DATA_STRUCT_FLOAT 5
#define DATA_STRUCT_DOUBLE 6
#define DATA_STRUCT_COLOR 7
#define DATA_STRUCT_SINT8 8
#define DATA_STRUCT_SINT16 9
#define DATA_STRUCT_SINT32 10
#define DATA_STRUCT_CHAR 11
#define DATA_STRUCT_EQ2_8BIT_STRING 12
#define DATA_STRUCT_EQ2_16BIT_STRING 13
#define DATA_STRUCT_EQ2_32BIT_STRING 14
#define DATA_STRUCT_EQUIPMENT 15
#define DATA_STRUCT_ARRAY 16
#define DATA_STRUCT_ITEM 17
#define DATA_STRUCT_SINT64 18
class DataStruct
{
public:
// Default constructor - initializes all member variables to default values
DataStruct()
{
item_size = 0;
type = 0;
type2 = 0;
length = 1;
if_flag_set = false;
if_flag_not_set = false;
if_set = false;
if_not_set = false;
if_not_equals = false;
if_equals = false;
is_set = false;
optional = false;
oversized = 0;
oversized_byte = 0;
add = false;
addType = 0;
maxArraySize = 0;
default_value = 0;
}
// Copy constructor - creates new DataStruct from existing one
DataStruct(DataStruct* data_struct)
{
type = data_struct->GetType();
type2 = data_struct->GetType2();
length = data_struct->GetLength();
name = data_struct->GetName();
array_size_variable = data_struct->array_size_variable;
default_value = data_struct->default_value;
add = true;
addType = type;
oversized = data_struct->GetOversized();
oversized_byte = data_struct->GetOversizedByte();
maxArraySize = data_struct->GetMaxArraySize();
if_flag_set = false;
if_flag_not_set = false;
if_set = false;
if_not_set = false;
if_not_equals = false;
if_equals = false;
optional = false;
if (data_struct->GetIfSet())
SetIfSetVariable(data_struct->GetIfSetVariable());
if (data_struct->GetIfNotSet())
SetIfNotSetVariable(data_struct->GetIfNotSetVariable());
if (data_struct->GetIfNotEquals())
SetIfNotEqualsVariable(data_struct->GetIfNotEqualsVariable());
if (data_struct->GetIfEquals())
SetIfEqualsVariable(data_struct->GetIfEqualsVariable());
if (data_struct->GetIfFlagSet())
SetIfFlagSetVariable(data_struct->GetIfFlagSetVariable());
if (data_struct->GetIfFlagNotSet())
SetIfFlagNotSetVariable(data_struct->GetIfFlagNotSetVariable());
item_size = 0;
is_set = false;
}
// Constructor with name and type strings
DataStruct(const char* new_name, const char* new_type, int32 new_length, const char* new_type2)
{
name = std::string(new_name);
type = 0;
type2 = 0;
SetType(new_type, &type);
if (new_type2)
SetType(new_type2, &type2);
length = new_length;
add = true;
addType = type;
if_set = false;
if_not_set = false;
is_set = false;
if_not_equals = false;
item_size = 0;
}
// Constructor with name and length only
DataStruct(const char* new_name, int32 new_length)
{
name = std::string(new_name);
length = new_length;
if_set = false;
if_not_set = false;
is_set = false;
item_size = 0;
}
// Constructor with name, type integers, and length
DataStruct(const char* new_name, int8 new_type, int32 new_length, int8 new_type2)
{
name = std::string(new_name);
type = new_type;
length = new_length;
type2 = new_type2;
addType = type;
if_set = false;
if_not_set = false;
is_set = false;
item_size = 0;
}
// Converts type string to numeric type constant
void SetType(const char* new_type, int8* output_type)
{
if (strlen(new_type) > 3 && strncasecmp("int", new_type, 3) == 0) {
if (strncasecmp("int8", new_type, 4) == 0)
*output_type = DATA_STRUCT_INT8;
else if (strncasecmp("int16", new_type, 5) == 0)
*output_type = DATA_STRUCT_INT16;
else if (strncasecmp("int32", new_type, 5) == 0)
*output_type = DATA_STRUCT_INT32;
else if (strncasecmp("int64", new_type, 5) == 0)
*output_type = DATA_STRUCT_INT64;
}
else if (strlen(new_type) > 4 && strncasecmp("sint", new_type, 4) == 0) {
if (strncasecmp("sint8", new_type, 5) == 0)
*output_type = DATA_STRUCT_SINT8;
else if (strncasecmp("sint16", new_type, 6) == 0)
*output_type = DATA_STRUCT_SINT16;
else if (strncasecmp("sint32", new_type, 6) == 0)
*output_type = DATA_STRUCT_SINT32;
else if (strncasecmp("sint64", new_type, 6) == 0)
*output_type = DATA_STRUCT_SINT64;
}
else if (strlen(new_type) == 4 && strncasecmp("char", new_type, 4) == 0)
*output_type = DATA_STRUCT_CHAR;
else if (strlen(new_type) == 5 && strncasecmp("float", new_type, 5) == 0)
*output_type = DATA_STRUCT_FLOAT;
else if (strlen(new_type) == 6 && strncasecmp("double", new_type, 6) == 0)
*output_type = DATA_STRUCT_DOUBLE;
else if (strlen(new_type) >= 5 && strncasecmp("EQ2_", new_type, 4) == 0) {
if (strncasecmp("EQ2_8", new_type, 5) == 0)
*output_type = DATA_STRUCT_EQ2_8BIT_STRING;
else if (strncasecmp("EQ2_16", new_type, 6) == 0)
*output_type = DATA_STRUCT_EQ2_16BIT_STRING;
else if (strncasecmp("EQ2_32", new_type, 6) == 0)
*output_type = DATA_STRUCT_EQ2_32BIT_STRING;
else if (strncasecmp("EQ2_E", new_type, 5) == 0)
*output_type = DATA_STRUCT_EQUIPMENT;
else if (strncasecmp("EQ2_C", new_type, 5) == 0)
*output_type = DATA_STRUCT_COLOR;
else if (strncasecmp("EQ2_I", new_type, 5) == 0)
*output_type = DATA_STRUCT_ITEM;
}
else if (strlen(new_type) >= 5) {
if (strncasecmp("Array", new_type, 5) == 0)
*output_type = DATA_STRUCT_ARRAY;
}
else
LogWrite(PACKET__ERROR, 0, "Packet", "Invalid Type: %s", new_type);
}
// Setter methods
void SetType(int8 new_type) { type = new_type; addType = type; }
void SetMaxArraySize(int8 size) { maxArraySize = size; }
void SetOversized(int8 val) { oversized = val; }
void SetDefaultValue(int8 new_val) { default_value = new_val; }
void SetName(const char* new_name) { name = std::string(new_name); }
void SetLength(int32 new_length) { length = new_length; }
void SetOversizedByte(int8 val) { oversized_byte = val; }
void SetAddToStruct(bool val) { add = val; }
void SetAddType(int8 new_type) { addType = new_type; }
void SetArraySizeVariable(const char* new_name) { array_size_variable = std::string(new_name); }
void SetIsSet(bool val) { is_set = val; }
void SetIsOptional(bool val) { optional = val; }
// Sets item size in bytes and marks as set if size > 0
void SetItemSize(int32 val)
{
item_size = val;
if (item_size)
is_set = true;
else
is_set = false;
}
// Conditional variable setters
void SetIfEqualsVariable(const char* variable)
{
if (variable) {
if_equals = true;
if_equals_variable = std::string(variable);
}
else
if_equals = false;
}
void SetIfNotEqualsVariable(const char* variable)
{
if (variable) {
if_not_equals = true;
if_not_equals_variable = std::string(variable);
}
else
if_not_equals = false;
}
void SetIfFlagNotSetVariable(const char* variable)
{
if (variable) {
if_flag_not_set = true;
if_flag_not_set_variable = std::string(variable);
}
else
if_flag_not_set = false;
}
void SetIfFlagSetVariable(const char* variable)
{
if (variable) {
if_flag_set = true;
if_flag_set_variable = std::string(variable);
}
else
if_flag_set = false;
}
void SetIfSetVariable(const char* variable)
{
if (variable) {
if_set = true;
if_set_variable = std::string(variable);
}
else
if_set = false;
}
void SetIfNotSetVariable(const char* variable)
{
if (variable) {
if_not_set = true;
if_not_set_variable = std::string(variable);
}
else
if_not_set = false;
}
// Getter methods
const char* GetArraySizeVariable() { return array_size_variable.c_str(); }
int32 GetItemSize() { return item_size; }
bool GetIfSet() { return if_set; }
bool GetIfNotSet() { return if_not_set; }
bool GetIfEquals() { return if_equals; }
bool GetIfNotEquals() { return if_not_equals; }
bool GetIfFlagSet() { return if_flag_set; }
bool GetIfFlagNotSet() { return if_flag_not_set; }
bool IsSet() { return is_set; }
bool IsOptional() { return optional; }
bool AddToStruct() { return add; }
int8 GetDefaultValue() { return default_value; }
int8 GetType() { return type; }
int8 GetType2() { return type2; }
int8 GetOversized() { return oversized; }
int8 GetOversizedByte() { return oversized_byte; }
int8 GetMaxArraySize() { return maxArraySize; }
int8 GetAddType() { return addType; }
int32 GetLength() { return length; }
const char* GetName() { return name.c_str(); }
std::string GetStringName() { return name; }
// Conditional variable getters
const char* GetIfSetVariable()
{
if (if_set_variable.length() > 0)
return if_set_variable.c_str();
return 0;
}
const char* GetIfNotSetVariable()
{
if (if_not_set_variable.length() > 0)
return if_not_set_variable.c_str();
return 0;
}
const char* GetIfEqualsVariable()
{
if (if_equals_variable.length() > 0)
return if_equals_variable.c_str();
return 0;
}
const char* GetIfNotEqualsVariable()
{
if (if_not_equals_variable.length() > 0)
return if_not_equals_variable.c_str();
return 0;
}
const char* GetIfFlagSetVariable()
{
if (if_flag_set_variable.length() > 0)
return if_flag_set_variable.c_str();
return 0;
}
const char* GetIfFlagNotSetVariable()
{
if (if_flag_not_set_variable.length() > 0)
return if_flag_not_set_variable.c_str();
return 0;
}
// Appends variable name to existing variable list, avoiding duplicates
std::string AppendVariable(std::string orig, const char* val)
{
if (!val)
return orig;
if (orig.length() == 0)
return std::string(val);
if (orig.find(",") < 0xFFFFFFFF) { // has more than one already
std::string valstr = std::string(val);
std::vector<std::string>* varnames = SplitString(orig, ',');
if (varnames) {
for (int32 i = 0; i < varnames->size(); i++) {
if (valstr.compare(varnames->at(i)) == 0) {
return orig; // already in the variable, no need to append
}
}
safe_delete(varnames);
}
}
return orig.append(",").append(val);
}
// Calculates total data size in bytes based on type and length
int32 GetDataSizeInBytes()
{
int32 ret = 0;
switch (type) {
case DATA_STRUCT_INT8:
ret = length * sizeof(int8);
break;
case DATA_STRUCT_INT16:
ret = length * sizeof(int16);
break;
case DATA_STRUCT_INT32:
ret = length * sizeof(int32);
break;
case DATA_STRUCT_INT64:
ret = length * sizeof(int64);
break;
case DATA_STRUCT_SINT8:
ret = length * sizeof(sint8);
break;
case DATA_STRUCT_SINT16:
ret = length * sizeof(sint16);
break;
case DATA_STRUCT_SINT32:
ret = length * sizeof(sint32);
break;
case DATA_STRUCT_SINT64:
ret = length * sizeof(sint64);
break;
case DATA_STRUCT_FLOAT:
ret = length * sizeof(float);
break;
case DATA_STRUCT_DOUBLE:
ret = length * sizeof(double);
break;
case DATA_STRUCT_ARRAY:
// Array elements won't have a size so get out now to avoid the warning.
break;
default:
LogWrite(PACKET__WARNING, 0, "DataStruct", "Tried retrieving a data size from an unsupported data struct type in GetDataSizeInBytes()");
break;
}
return ret;
}
// Adds variable to if-set condition list
void AddIfSetVariable(const char* val)
{
if (val) {
if_set_variable = AppendVariable(if_set_variable, val);
is_set = true;
}
}
// Adds variable to if-not-set condition list
void AddIfNotSetVariable(const char* val)
{
if (val) {
if_not_set_variable = AppendVariable(if_not_set_variable, val);
if_not_set = true;
}
}
private:
bool is_set; // Whether this data structure contains data
bool if_not_set; // Conditional inclusion based on variable not set
bool optional; // Whether this field is optional
bool if_set; // Conditional inclusion based on variable set
bool if_not_equals; // Conditional inclusion based on variable not equals
bool if_equals; // Conditional inclusion based on variable equals
bool if_flag_set; // Conditional inclusion based on flag set
bool if_flag_not_set; // Conditional inclusion based on flag not set
std::string if_flag_not_set_variable; // Variable name for flag not set condition
std::string if_flag_set_variable; // Variable name for flag set condition
std::string if_not_equals_variable; // Variable name for not equals condition
std::string if_equals_variable; // Variable name for equals condition
std::string if_not_set_variable; // Variable name for not set condition
std::string if_set_variable; // Variable name for set condition
int8 oversized; // Threshold for oversized data handling
int8 oversized_byte; // Byte marker for oversized data
bool add; // Whether to include in packet structure
int8 addType; // Type to use when adding to packet
int8 maxArraySize; // Maximum allowed array size
std::string array_size_variable; // Variable name containing array size
std::string name; // Name identifier of this data structure
int8 type; // Primary data type
int8 default_value; // Default value for initialization
int8 type2; // Secondary data type (for special cases)
int32 length; // Number of elements/length
int32 item_size; // Size in bytes for item data
};