435 lines
10 KiB
C++
435 lines
10 KiB
C++
// Copyright (C) 2007 EQ2EMulator Development Team - GPL v3 License
|
|
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include <cstring>
|
|
#include <memory>
|
|
|
|
#include "types.hpp"
|
|
#include "eq_common_structs.hpp"
|
|
#include "packet/eq_packet.hpp"
|
|
|
|
#ifdef WORLD
|
|
#include "../WorldServer/SpawnLists.h"
|
|
#endif
|
|
|
|
using namespace std;
|
|
|
|
/**
|
|
* DataBuffer class for handling binary data serialization and deserialization
|
|
* Provides templated methods for reading/writing various data types to/from buffers
|
|
*/
|
|
class DataBuffer
|
|
{
|
|
public:
|
|
bool changed; // Flag indicating if buffer has been modified
|
|
|
|
/**
|
|
* Get raw pointer to buffer data
|
|
* @return Pointer to buffer contents as unsigned char array
|
|
*/
|
|
uchar* getData()
|
|
{
|
|
return (uchar*)buffer.c_str();
|
|
}
|
|
|
|
/**
|
|
* Get size of buffer data in bytes
|
|
* @return Size of buffer in bytes
|
|
*/
|
|
int32 getDataSize()
|
|
{
|
|
return buffer.length();
|
|
}
|
|
|
|
/**
|
|
* Get reference to internal buffer string
|
|
* @return Pointer to internal string buffer
|
|
*/
|
|
string* getDataString()
|
|
{
|
|
return &buffer;
|
|
}
|
|
|
|
/**
|
|
* Create EQ2 color from current load position (reference version)
|
|
* @param color Reference to EQ2_Color structure to populate
|
|
*/
|
|
void CreateEQ2Color(EQ2_Color& color)
|
|
{
|
|
CreateEQ2Color(&color);
|
|
}
|
|
|
|
/**
|
|
* Get current load buffer pointer
|
|
* @return Pointer to load buffer
|
|
*/
|
|
uchar* GetLoadBuffer()
|
|
{
|
|
return load_buffer;
|
|
}
|
|
|
|
/**
|
|
* Get current position in load buffer
|
|
* @return Current load position
|
|
*/
|
|
int32 GetLoadPos()
|
|
{
|
|
return load_pos;
|
|
}
|
|
|
|
/**
|
|
* Get total length of load buffer
|
|
* @return Load buffer length
|
|
*/
|
|
int32 GetLoadLen()
|
|
{
|
|
return load_len;
|
|
}
|
|
|
|
/**
|
|
* Set new position in load buffer
|
|
* @param new_pos New position to set
|
|
*/
|
|
void SetLoadPos(int32 new_pos)
|
|
{
|
|
load_pos = new_pos;
|
|
}
|
|
|
|
/**
|
|
* Create EQ2 color from current load position (pointer version)
|
|
* Reads 3 floats representing RGB values and converts to 0-255 range
|
|
* @param color Pointer to EQ2_Color structure to populate
|
|
*/
|
|
void CreateEQ2Color(EQ2_Color* color)
|
|
{
|
|
int8 rgb[3];
|
|
float* tmp = 0;
|
|
// Read 3 float values and convert to RGB bytes
|
|
for(int i = 0; i < 3; i++) {
|
|
tmp = (float*)(load_buffer + load_pos);
|
|
rgb[i] = (int8)((*tmp) * 255);
|
|
load_pos += sizeof(float);
|
|
}
|
|
color->red = rgb[0];
|
|
color->green = rgb[1];
|
|
color->blue = rgb[2];
|
|
}
|
|
|
|
/**
|
|
* Convert float to signed 8-bit integer scaled by 100 (reference version)
|
|
* @param output Reference to output variable
|
|
*/
|
|
template<class Type> void MakeEQ2_Int8(Type& output)
|
|
{
|
|
MakeEQ2_Int8(&output);
|
|
}
|
|
|
|
/**
|
|
* Convert float to signed 8-bit integer scaled by 100 (pointer version)
|
|
* Takes absolute value of float, multiplies by 100, and stores as sint8
|
|
* @param output Pointer to output variable
|
|
*/
|
|
template<class Type> void MakeEQ2_Int8(Type* output)
|
|
{
|
|
float* tmp = (float*)(load_buffer + load_pos);
|
|
if(*tmp < 0)
|
|
*tmp *= -1;
|
|
sint8 result = (sint8)((*tmp) * 100);
|
|
memcpy(output, &result, sizeof(sint8));
|
|
load_pos += sizeof(float);
|
|
}
|
|
|
|
/**
|
|
* Initialize buffer for data retrieval operations
|
|
* Sets up get_buffer pointer and related variables
|
|
*/
|
|
void InitializeGetData()
|
|
{
|
|
get_buffer = (uchar*)buffer.c_str();
|
|
get_len = buffer.length();
|
|
get_pos = 0;
|
|
}
|
|
|
|
/**
|
|
* Initialize buffer for data loading operations
|
|
* @param input Input data array
|
|
* @param size Size of input data
|
|
*/
|
|
void InitializeLoadData(uchar* input, int32 size)
|
|
{
|
|
buffer = string((char*)input, size);
|
|
load_buffer = (uchar*)buffer.c_str();
|
|
load_len = size;
|
|
load_pos = 0;
|
|
}
|
|
|
|
/**
|
|
* Load string data from buffer (reference version)
|
|
* @param output Reference to string structure to populate
|
|
*/
|
|
template<class String> void LoadDataString(String& output)
|
|
{
|
|
LoadDataString(&output);
|
|
}
|
|
|
|
/**
|
|
* Load string data from buffer (pointer version)
|
|
* Reads size field followed by string data
|
|
* @param output Pointer to string structure to populate
|
|
*/
|
|
template<class String> void LoadDataString(String* output)
|
|
{
|
|
// Read string size if enough bytes available
|
|
if((sizeof(output->size) + load_pos) <= load_len) {
|
|
memcpy(&output->size, load_buffer + load_pos, sizeof(output->size));
|
|
load_pos += sizeof(output->size);
|
|
}
|
|
// Read string data if enough bytes available
|
|
if((output->size + load_pos) <= load_len) {
|
|
output->data = string((char*)(load_buffer + load_pos), output->size);
|
|
load_pos += output->size;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load data from buffer (reference version)
|
|
* @param output Reference to variable to populate
|
|
*/
|
|
template<class Type> void LoadData(Type& output)
|
|
{
|
|
LoadData(&output);
|
|
}
|
|
|
|
/**
|
|
* Load array data from buffer
|
|
* @param output Pointer to array to populate
|
|
* @param array_size Number of elements to load
|
|
*/
|
|
template<class Type> void LoadData(Type* output, int32 array_size)
|
|
{
|
|
if(array_size <= 1) {
|
|
LoadData(output);
|
|
}
|
|
else {
|
|
// Load each array element sequentially
|
|
for(int32 i = 0; i < array_size; i++)
|
|
LoadData(&output[i]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load single data element from buffer
|
|
* @param output Pointer to variable to populate
|
|
*/
|
|
template<class Type> void LoadData(Type* output)
|
|
{
|
|
// Only load if enough bytes available in buffer
|
|
if((sizeof(Type) + load_pos) <= load_len) {
|
|
memcpy(output, load_buffer + load_pos, sizeof(Type));
|
|
load_pos += sizeof(Type);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load array data from buffer (reference version)
|
|
* @param output Reference to array to populate
|
|
* @param array_size Number of elements to load
|
|
*/
|
|
template<class Type> void LoadData(Type& output, int32 array_size)
|
|
{
|
|
LoadData(&output, array_size);
|
|
}
|
|
|
|
/**
|
|
* Skip bytes in load buffer
|
|
* @param bytes Number of bytes to skip
|
|
*/
|
|
void LoadSkip(int8 bytes)
|
|
{
|
|
load_pos += bytes;
|
|
}
|
|
|
|
/**
|
|
* Skip data type in load buffer (reference version)
|
|
* @param skip Reference to type (used for sizeof calculation)
|
|
*/
|
|
template<class Type> void LoadSkip(Type& skip)
|
|
{
|
|
LoadSkip(&skip);
|
|
}
|
|
|
|
/**
|
|
* Skip data type in load buffer (pointer version)
|
|
* @param skip Pointer to type (used for sizeof calculation)
|
|
*/
|
|
template<class Type> void LoadSkip(Type* skip)
|
|
{
|
|
load_pos += sizeof(Type);
|
|
}
|
|
|
|
/**
|
|
* Get data from get buffer
|
|
* @param output Pointer to store result
|
|
*/
|
|
template<class Type> void GetData(Type* output)
|
|
{
|
|
// Only get if enough bytes available
|
|
if((sizeof(Type) + get_pos) <= get_len) {
|
|
*output = (Type*)get_buffer;
|
|
get_pos += sizeof(output);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add zero bytes to buffer
|
|
* @param num Number of zero bytes to add
|
|
*/
|
|
void AddZeros(int16 num)
|
|
{
|
|
auto data = std::make_unique<int8[]>(num);
|
|
memset(data.get(), 0, num);
|
|
AddData(*data);
|
|
}
|
|
|
|
/**
|
|
* Add struct data with specific size
|
|
* @param input Input data to add
|
|
* @param size Size of data to add
|
|
* @param datastring Optional target string (uses internal buffer if null)
|
|
*/
|
|
template<class Type> void StructAddData(Type input, int16 size, string* datastring)
|
|
{
|
|
if(datastring)
|
|
datastring->append((char*)&input, size);
|
|
else
|
|
buffer.append((char*)&input, size);
|
|
}
|
|
|
|
/**
|
|
* Add array of struct data with specific size
|
|
* @param input Input array to add
|
|
* @param array_size Number of array elements
|
|
* @param size Size of each element
|
|
* @param datastring Optional target string
|
|
*/
|
|
template<class Type> void StructAddData(Type input, int32 array_size, int16 size, string* datastring)
|
|
{
|
|
if(array_size > 0) {
|
|
// Add each array element
|
|
for(int32 i = 0; i < array_size; i++)
|
|
StructAddData(input[i], size, datastring);
|
|
}
|
|
else
|
|
StructAddData(input, size, datastring);
|
|
}
|
|
|
|
/**
|
|
* Add data to buffer using sizeof for size
|
|
* @param input Data to add
|
|
* @param datastring Optional target string (uses internal buffer if null)
|
|
*/
|
|
template<class Type> void AddData(Type input, string* datastring = 0)
|
|
{
|
|
if(!datastring)
|
|
datastring = &buffer;
|
|
datastring->append((char*)&input, sizeof(input));
|
|
}
|
|
|
|
/**
|
|
* Add array data to buffer
|
|
* @param input Array data to add
|
|
* @param array_size Number of array elements
|
|
* @param datastring Optional target string
|
|
*/
|
|
template<class Type> void AddData(Type input, int32 array_size, string* datastring = 0)
|
|
{
|
|
if(array_size > 0) {
|
|
// Add each array element
|
|
for(int32 i = 0; i < array_size; i++)
|
|
AddData(input[i], datastring);
|
|
}
|
|
else
|
|
AddData(input, datastring);
|
|
}
|
|
|
|
/**
|
|
* Add string data with size prefix (pointer version)
|
|
* @param input Pointer to string structure
|
|
* @param datastring Optional target string
|
|
*/
|
|
template<class String> void AddDataString(String* input, string* datastring = 0)
|
|
{
|
|
AddDataString(*input, datastring);
|
|
}
|
|
|
|
/**
|
|
* Add string data with size prefix (reference version)
|
|
* Adds size field followed by string data
|
|
* @param input String structure to add
|
|
* @param datastring Optional target string
|
|
*/
|
|
template<class String> void AddDataString(String input, string* datastring = 0)
|
|
{
|
|
input.size = input.data.length();
|
|
if(!datastring)
|
|
datastring = &buffer;
|
|
datastring->append((char*)&input.size, sizeof(input.size));
|
|
datastring->append(input.data);
|
|
}
|
|
|
|
/**
|
|
* Add null-terminated character array
|
|
* @param array Character array to add
|
|
* @param datastring Optional target string
|
|
*/
|
|
void AddCharArray(char* array, string* datastring = 0)
|
|
{
|
|
if(!datastring)
|
|
datastring = &buffer;
|
|
datastring->append(array);
|
|
}
|
|
|
|
/**
|
|
* Add character array with specific size
|
|
* @param array Character array to add
|
|
* @param size Number of characters to add
|
|
* @param datastring Optional target string
|
|
*/
|
|
void AddCharArray(char* array, int16 size, string* datastring = 0)
|
|
{
|
|
if(!datastring)
|
|
datastring = &buffer;
|
|
datastring->append(array, size);
|
|
}
|
|
|
|
/**
|
|
* Add string data directly
|
|
* @param data String data to add
|
|
* @param datastring Optional target string
|
|
*/
|
|
void AddData(string data, string* datastring = 0)
|
|
{
|
|
if(!datastring)
|
|
datastring = &buffer;
|
|
datastring->append(data);
|
|
}
|
|
|
|
/**
|
|
* Clear all buffer contents
|
|
*/
|
|
void Clear()
|
|
{
|
|
buffer.clear();
|
|
}
|
|
|
|
private:
|
|
string buffer; // Main data buffer
|
|
uchar* get_buffer; // Pointer for get operations
|
|
uchar* load_buffer; // Pointer for load operations
|
|
int32 get_len; // Length for get operations
|
|
int32 get_pos; // Current position for get operations
|
|
int32 load_len; // Length for load operations
|
|
int32 load_pos; // Current position for load operations
|
|
}; |