// Copyright (C) 2007 EQ2EMulator Development Team - GPL v3 License #pragma once #include #include #include #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 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 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 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 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 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 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 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 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 void LoadSkip(Type& skip) { LoadSkip(&skip); } /** * Skip data type in load buffer (pointer version) * @param skip Pointer to type (used for sizeof calculation) */ template void LoadSkip(Type* skip) { load_pos += sizeof(Type); } /** * Get data from get buffer * @param output Pointer to store result */ template 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(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 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 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 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 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 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 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 };