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

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
};