diff --git a/src/creatures/monsters/spawns/spawn_monster.hpp b/src/creatures/monsters/spawns/spawn_monster.hpp index 81a08973cb7..caf454c41b5 100644 --- a/src/creatures/monsters/spawns/spawn_monster.hpp +++ b/src/creatures/monsters/spawns/spawn_monster.hpp @@ -38,9 +38,12 @@ class SpawnMonster { // moveable SpawnMonster(SpawnMonster &&rhs) noexcept : - spawnMonsterMap(std::move(rhs.spawnMonsterMap)), spawnedMonsterMap(std::move(rhs.spawnedMonsterMap)), - checkSpawnMonsterEvent(rhs.checkSpawnMonsterEvent), centerPos(rhs.centerPos), radius(rhs.radius), interval(rhs.interval) { } + spawnMonsterMap(std::move(rhs.spawnMonsterMap)), + centerPos(rhs.centerPos), + radius(rhs.radius), + interval(rhs.interval), + checkSpawnMonsterEvent(rhs.checkSpawnMonsterEvent) { } SpawnMonster &operator=(SpawnMonster &&rhs) noexcept { if (this != &rhs) { @@ -77,15 +80,12 @@ class SpawnMonster { void setMonsterVariant(const std::string &variant); private: - // map of the spawned creatures + // The map of the spawned creatures std::map> spawnedMonsterMap; - - // map of creatures in the spawn + // The map of creatures in the spawn std::map spawnMonsterMap; - Position centerPos; int32_t radius; - uint32_t interval = 30000; uint32_t checkSpawnMonsterEvent = 0; diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index b923dd952d2..e3790583eff 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -5575,7 +5575,7 @@ int32_t Player::getMagicShieldCapacityPercent(bool useCharges) const { double_t Player::getReflectPercent(CombatType_t combat, bool useCharges) const { double_t result = reflectPercent[combatTypeToIndex(combat)]; - for (const auto item : getEquippedItems()) { + for (const auto &item : getEquippedItems()) { const ItemType &itemType = Item::items[item->getID()]; if (!itemType.abilities) { continue; diff --git a/src/lua/functions/core/network/network_message_functions.cpp b/src/lua/functions/core/network/network_message_functions.cpp index a1b66264fac..e2f4013448d 100644 --- a/src/lua/functions/core/network/network_message_functions.cpp +++ b/src/lua/functions/core/network/network_message_functions.cpp @@ -196,7 +196,7 @@ int NetworkMessageFunctions::luaNetworkMessageAddString(lua_State* L) { const std::string &function = getString(L, 3); const auto &message = getUserdataShared(L, 1); if (message) { - message->addString(string, function); + message->addString(string, std::source_location::current(), function); pushBoolean(L, true); } else { lua_pushnil(L); diff --git a/src/map/utils/astarnodes.cpp b/src/map/utils/astarnodes.cpp index 21ebe5f982f..e7c5b7ce48e 100644 --- a/src/map/utils/astarnodes.cpp +++ b/src/map/utils/astarnodes.cpp @@ -14,7 +14,21 @@ #include "creatures/combat/combat.hpp" AStarNodes::AStarNodes(uint32_t x, uint32_t y, int_fast32_t extraCost) : - openNodes(), nodes() { +#if defined(__AVX2__) || defined(__SSE2__) + nodesTable(), // 1. nodesTable + calculatedNodes(), // 2. calculatedNodes + nodes(), // 3. nodes + closedNodes(0), // 4. closedNodes + curNode(0), // 5. curNode + openNodes() // 6. openNodes +#else + nodes(), // 1. nodes + nodesTable(), // 2. nodesTable + closedNodes(0), // 3. closedNodes + curNode(0), // 4. curNode + openNodes() // 5. openNodes +#endif +{ #if defined(__AVX2__) __m256i defaultCost = _mm256_set1_epi32(std::numeric_limits::max()); for (int32_t i = 0; i < MAX_NODES; i += 32) { @@ -47,7 +61,7 @@ AStarNodes::AStarNodes(uint32_t x, uint32_t y, int_fast32_t extraCost) : startNode.g = 0; startNode.c = extraCost; nodesTable[0] = (x << 16) | y; -#if defined(__SSE2__) +#if defined(__SSE2__) || defined(__AVX2__) calculatedNodes[0] = 0; #endif } @@ -265,9 +279,9 @@ int_fast32_t AStarNodes::getMapWalkCost(AStarNode* node, const Position &neighbo int_fast32_t AStarNodes::getTileWalkCost(const std::shared_ptr &creature, const std::shared_ptr &tile) { int_fast32_t cost = 0; - if (creature) { + if (creature && tile) { + // Destroy creature cost if (tile->getTopVisibleCreature(creature) != nullptr) { - // destroy creature cost cost += MAP_NORMALWALKCOST * 4; } if (const auto &field = tile->getFieldItem()) { diff --git a/src/pch.hpp b/src/pch.hpp index e69c27016a4..ea3c9cd2e73 100644 --- a/src/pch.hpp +++ b/src/pch.hpp @@ -46,6 +46,8 @@ #include #include #include +#include +#include // -------------------- // System Includes diff --git a/src/server/network/message/networkmessage.cpp b/src/server/network/message/networkmessage.cpp index 38acc0b484c..d8cb599a07c 100644 --- a/src/server/network/message/networkmessage.cpp +++ b/src/server/network/message/networkmessage.cpp @@ -13,23 +13,101 @@ #include "items/containers/container.hpp" int32_t NetworkMessage::decodeHeader() { - int32_t newSize = buffer[0] | buffer[1] << 8; - info.length = newSize; - return info.length; + // Ensure there are enough bytes to read the header (2 bytes) + if (!canRead(2)) { + g_logger().error("[{}] Not enough data to decode header. Current position: {}, Length: {}", __FUNCTION__, info.position, info.length); + return {}; + } + + // Log the current position and buffer content before decoding + g_logger().debug("[{}] Decoding header at position: {}", __FUNCTION__, info.position); + g_logger().debug("[{}] Buffer content: ", __FUNCTION__); + + // Log only up to 10 bytes of the buffer or until the end of the buffer + for (size_t i = 0; i < 10 && i < buffer.size(); ++i) { + g_logger().debug("[{}] Buffer[{}]: {}", __FUNCTION__, i, buffer[i]); + } + + // Check if there are enough bytes in the buffer for the header + if (info.position + 1 < buffer.size()) { + // Create a span view for safety + std::span bufferSpan(buffer.data(), buffer.size()); + auto decodedHeader = bufferSpan[info.position] | (bufferSpan[info.position + 1] << 8); + // Update position after reading the header + info.position += sizeof(decodedHeader); + return decodedHeader; + } else { + g_logger().warn("Index out of bounds when trying to access buffer with position: {}", info.position); + } + + // Handle buffer overflow error here + g_logger().error("[{}] attempted to read beyond buffer limits at position: {}", __FUNCTION__, info.position); + return {}; +} + +// Simply read functions for incoming message +uint8_t NetworkMessage::getByte() { + // Check if there is at least 1 byte to read + if (!canRead(1)) { + g_logger().error("[{}] Not enough data to read a byte. Current position: {}, Length: {}", __FUNCTION__, info.position, info.length); + return {}; + } + + // Ensure that position is within bounds before decrementing + if (info.position == 0) { + g_logger().error("[{}] Position is at the beginning of the buffer. Cannot decrement.", __FUNCTION__); + return {}; + } + + try { + // Decrement position safely and return the byte + return buffer.at(info.position++); + } catch (const std::out_of_range &e) { + g_logger().error("[{}] Out of range error: {}. Position: {}, Buffer size: {}", __FUNCTION__, e.what(), info.position, buffer.size()); + } + + return {}; +} + +uint8_t NetworkMessage::getPreviousByte() { + // Check if position is at the beginning of the buffer + if (info.position == 0) { + g_logger().error("[{}] Attempted to get previous byte at position 0", __FUNCTION__); + return {}; // Return default value (0) when at the start of the buffer + } + + try { + // Safely decrement position and access the previous byte using 'at()' + return buffer.at(--info.position); + } catch (const std::out_of_range &e) { + // Log the out-of-range exception if accessing outside buffer limits + g_logger().error("[{}] Out of range error: {}. Position: {}, Buffer size: {}", __FUNCTION__, e.what(), info.position, buffer.size()); + } + + return {}; } -std::string NetworkMessage::getString(uint16_t stringLen /* = 0*/) { +std::string NetworkMessage::getString(uint16_t stringLen /* = 0*/, const std::source_location &location) { if (stringLen == 0) { stringLen = get(); } if (!canRead(stringLen)) { - return std::string(); + g_logger().error("[{}] not enough data to read string of length: {}. Called line {}:{} in {}", __FUNCTION__, stringLen, location.line(), location.column(), location.function_name()); + return {}; } - char* v = reinterpret_cast(buffer) + info.position; // does not break strict aliasing + if (stringLen > NETWORKMESSAGE_MAXSIZE) { + g_logger().error("[{}] exceded NetworkMessage max size: {}, actually size: {}. Called line '{}:{}' in '{}'", __FUNCTION__, NETWORKMESSAGE_MAXSIZE, stringLen, location.line(), location.column(), location.function_name()); + return {}; + } + + g_logger().trace("[{}] called line '{}:{}' in '{}'", __FUNCTION__, location.line(), location.column(), location.function_name()); + + // Copy the string from the buffer + std::string result(buffer.begin() + info.position, buffer.begin() + info.position + stringLen); info.position += stringLen; - return std::string(v, stringLen); + return result; } Position NetworkMessage::getPosition() { @@ -40,29 +118,85 @@ Position NetworkMessage::getPosition() { return pos; } -void NetworkMessage::addString(const std::string &value, const std::string &function /* = ""*/) { +// Skips count unknown/unused bytes in an incoming message +void NetworkMessage::skipBytes(int16_t count) { + info.position += count; +} + +void NetworkMessage::addString(const std::string &value, const std::source_location &location /*= std::source_location::current()*/, const std::string &function /* = ""*/) { size_t stringLen = value.length(); - if (value.empty() && !function.empty()) { - g_logger().debug("[NetworkMessage::addString] - Value string is empty, function '{}'", function); + if (value.empty()) { + if (!function.empty()) { + g_logger().debug("[{}] attempted to add an empty string. Called line '{}'", __FUNCTION__, function); + } else { + g_logger().debug("[{}] attempted to add an empty string. Called line '{}:{}' in '{}'", __FUNCTION__, location.line(), location.column(), location.function_name()); + } + + // Add a 0 length string, the std::array will be filled with 0s + add(uint16_t()); + return; } if (!canAdd(stringLen + 2)) { - g_logger().error("[NetworkMessage::addString] - NetworkMessage size is wrong: {}, function '{}'", stringLen, function); + if (!function.empty()) { + g_logger().error("[{}] NetworkMessage size is wrong: {}. Called line '{}'", __FUNCTION__, stringLen, function); + } else { + g_logger().error("[{}] NetworkMessage size is wrong: {}. Called line '{}:{}' in '{}'", __FUNCTION__, stringLen, location.line(), location.column(), location.function_name()); + } return; } if (stringLen > NETWORKMESSAGE_MAXSIZE) { - g_logger().error("[NetworkMessage::addString] - Exceded NetworkMessage max size: {}, actually size: {}, function '{}'", NETWORKMESSAGE_MAXSIZE, stringLen, function); + if (!function.empty()) { + g_logger().error("[{}] exceeded NetworkMessage max size: {}, actual size: {}. Called line '{}'", __FUNCTION__, NETWORKMESSAGE_MAXSIZE, stringLen, function); + } else { + g_logger().error("[{}] exceeded NetworkMessage max size: {}, actual size: {}. Called line '{}:{}' in '{}'", __FUNCTION__, NETWORKMESSAGE_MAXSIZE, stringLen, location.line(), location.column(), location.function_name()); + } return; } - add(stringLen); - memcpy(buffer + info.position, value.c_str(), stringLen); + if (!function.empty()) { + g_logger().trace("[{}] called line '{}'", __FUNCTION__, function); + } else { + g_logger().trace("[{}] called line '{}:{}' in '{}'", __FUNCTION__, location.line(), location.column(), location.function_name()); + } + + auto len = static_cast(stringLen); + add(len); + // Using to copy the string into the buffer + auto it = std::ranges::copy(value, buffer.begin() + info.position); + g_logger().trace("First value copied from sourceSpan: {}, second value copied from sourceSpan: {}", *it.in, *it.out); info.position += stringLen; info.length += stringLen; } -void NetworkMessage::addDouble(double value, uint8_t precision /* = 2*/) { +void NetworkMessage::addDouble(double value, uint8_t precision /*= 2*/) { addByte(precision); - add((value * std::pow(static_cast(10), precision)) + std::numeric_limits::max()); + add((value * std::pow(static_cast(SCALING_BASE), precision)) + std::numeric_limits::max()); +} + +double NetworkMessage::getDouble() { + // Retrieve the precision byte from the buffer + uint8_t precision = getByte(); + // Retrieve the scaled uint32_t value from the buffer + auto scaledValue = get(); + // Convert the scaled value back to double using the precision factor + double adjustedValue = static_cast(scaledValue) - static_cast(std::numeric_limits::max()); + // Convert back to the original double value using the precision factor + return adjustedValue / std::pow(static_cast(SCALING_BASE), precision); +} + +void NetworkMessage::addByte(uint8_t value, std::source_location location /*= std::source_location::current()*/) { + if (!canAdd(1)) { + g_logger().error("[{}] cannot add byte, buffer overflow. Called line '{}:{}' in '{}'", __FUNCTION__, location.line(), location.column(), location.function_name()); + return; + } + + g_logger().trace("[{}] called line '{}:{}' in '{}'", __FUNCTION__, location.line(), location.column(), location.function_name()); + try { + buffer.at(info.position++) = value; + info.length++; + } catch (const std::out_of_range &e) { + g_logger().error("[{}] buffer access out of range: {}. Called line '{}:{}' in '{}'", __FUNCTION__, e.what(), location.line(), location.column(), location.function_name()); + } } void NetworkMessage::addBytes(const char* bytes, size_t size) { @@ -79,19 +213,20 @@ void NetworkMessage::addBytes(const char* bytes, size_t size) { return; } - memcpy(buffer + info.position, bytes, size); + auto it = std::ranges::copy(bytes, bytes + size, buffer.begin() + info.position); + g_logger().trace("First value copied from sourceSpan: {}, second value copied from sourceSpan: {}", *it.in, *it.out); info.position += size; info.length += size; } void NetworkMessage::addPaddingBytes(size_t n) { -#define canAdd(size) ((size + info.position) < NETWORKMESSAGE_MAXSIZE) if (!canAdd(n)) { + g_logger().error("[NetworkMessage::addPaddingBytes] - Cannot add padding bytes, buffer overflow"); return; } -#undef canAdd - memset(buffer + info.position, 0x33, n); + std::fill(buffer.begin() + info.position, buffer.begin() + info.position + n, 0x33); + info.position += n; info.length += n; } @@ -100,3 +235,77 @@ void NetworkMessage::addPosition(const Position &pos) { add(pos.y); addByte(pos.z); } + +NetworkMessage::MsgSize_t NetworkMessage::getLength() const { + return info.length; +} + +void NetworkMessage::setLength(NetworkMessage::MsgSize_t newLength) { + info.length = newLength; +} + +NetworkMessage::MsgSize_t NetworkMessage::getBufferPosition() const { + return info.position; +} + +void NetworkMessage::setBufferPosition(NetworkMessage::MsgSize_t newPosition) { + info.position = newPosition; +} + +uint16_t NetworkMessage::getLengthHeader() const { + return static_cast(buffer[0] | buffer[1] << 8); +} + +bool NetworkMessage::isOverrun() const { + return info.overrun; +} + +uint8_t* NetworkMessage::getBuffer() { + return buffer.data(); +} + +const uint8_t* NetworkMessage::getBuffer() const { + return buffer.data(); +} + +uint8_t* NetworkMessage::getBodyBuffer() { + info.position = 2; + // Return the pointer to the body of the buffer starting after the header + // Convert HEADER_LENGTH to uintptr_t to ensure safe pointer arithmetic with enum type + return buffer.data() + static_cast(HEADER_LENGTH); +} + +bool NetworkMessage::canAdd(size_t size) const { + return (size + info.position) < MAX_BODY_LENGTH; +} + +bool NetworkMessage::canRead(int32_t size) const { + return size <= (info.length - (info.position - INITIAL_BUFFER_POSITION)); +} + +void NetworkMessage::append(const NetworkMessage &other) { + size_t otherLength = other.getLength(); + size_t otherStartPos = NetworkMessage::INITIAL_BUFFER_POSITION; // Always start copying from the initial buffer position + + g_logger().debug("[{}] appending message, other Length = {}, current length = {}, current position = {}, other start position = {}", __FUNCTION__, otherLength, info.length, info.position, otherStartPos); + + // Ensure there is enough space in the buffer to append the new data + if (!canAdd(otherLength)) { + std::cerr << "Cannot append message: not enough space in buffer.\n"; + return; + } + + // Create a span for the source data (from the other message) + std::span sourceSpan(other.getBuffer() + otherStartPos, otherLength); + // Create a span for the destination in the current buffer + std::span destSpan(buffer.data() + info.position, otherLength); + // Copy the data from the source span to the destination span + auto it = std::ranges::copy(sourceSpan, destSpan.begin()); + g_logger().trace("First value copied from sourceSpan: {}, second value copied from sourceSpan: {}", *it.in, *it.out); + + // Update the buffer information + info.length += otherLength; + info.position += otherLength; + // Debugging output after appending + g_logger().debug("After append: New Length = {}, New Position = {}", info.length, info.position); +} diff --git a/src/server/network/message/networkmessage.hpp b/src/server/network/message/networkmessage.hpp index 02e19253146..1889b7725b6 100644 --- a/src/server/network/message/networkmessage.hpp +++ b/src/server/network/message/networkmessage.hpp @@ -27,62 +27,64 @@ class NetworkMessage { // 2 bytes for encrypted message size static constexpr MsgSize_t INITIAL_BUFFER_POSITION = 8; - NetworkMessage() = default; + int32_t decodeHeader(); void reset() { info = {}; } // simply read functions for incoming message - uint8_t getByte() { - if (!canRead(1)) { - return 0; - } - - return buffer[info.position++]; - } + uint8_t getByte(); - uint8_t getPreviousByte() { - return buffer[--info.position]; - } + uint8_t getPreviousByte(); template T get() { + static_assert(!std::is_same_v, "Error: get() is not allowed. Use getDouble() instead."); + static_assert(std::is_trivially_copyable_v, "Type T must be trivially copyable"); if (!canRead(sizeof(T))) { - return 0; + return T(); } - T v; - memcpy(&v, buffer + info.position, sizeof(T)); + // Create a temporary byte array to store the value read from the buffer. + std::array tempBuffer; + // Copy data from the buffer to the temporary array + std::span sourceSpan(buffer.data() + info.position, sizeof(T)); + auto it = std::ranges::copy(sourceSpan, tempBuffer.begin()); + g_logger().trace("First value copied from sourceSpan: {}, second value copied from sourceSpan: {}", *it.in, *it.out); + // Update the read position in the buffer info.position += sizeof(T); - return v; + // Convert the byte array to type T using std::bit_cast and return the result + return std::bit_cast(tempBuffer); } - std::string getString(uint16_t stringLen = 0); + std::string getString(uint16_t stringLen = 0, const std::source_location &location = std::source_location::current()); Position getPosition(); // skips count unknown/unused bytes in an incoming message - void skipBytes(int16_t count) { - info.position += count; - } + void skipBytes(int16_t count); // simply write functions for outgoing message - void addByte(uint8_t value) { - if (!canAdd(1)) { - return; - } - - buffer[info.position++] = value; - info.length++; - } + void addByte(uint8_t value, std::source_location location = std::source_location::current()); template - void add(T value) { + void add(T value, std::source_location location = std::source_location::current()) { if (!canAdd(sizeof(T))) { + g_logger().error("Cannot add value of size {}, buffer overflow", sizeof(T)); return; } - memcpy(buffer + info.position, &value, sizeof(T)); + g_logger().trace("[{}] called line '{}:{}' in '{}'", __FUNCTION__, location.line(), location.column(), location.function_name()); + + // Ensure that T is trivially copyable + static_assert(std::is_trivially_copyable_v, "Type T must be trivially copyable"); + // Convert the value to an array of unsigned char using std::bit_cast + auto byteArray = std::bit_cast>(value); + // Create a span from the byte array + std::span byteSpan(byteArray); + // Copy the bytes into the buffer + auto it = std::ranges::copy(byteSpan.begin(), byteSpan.end(), buffer.begin() + info.position); + g_logger().trace("First value copied from sourceSpan: {}, second value copied from sourceSpan: {}", *it.in, *it.out); info.position += sizeof(T); info.length += sizeof(T); } @@ -94,74 +96,66 @@ class NetworkMessage { * Adds a string to the network message buffer. * * @param value The string value to be added to the message buffer. - * @param function * @param function An optional parameter that specifies the function name from which `addString` is invoked. - * Including this enhances logging by adding the function name to the debug and error log messages. - * This helps in debugging by indicating the context when issues occur, such as attempting to add an - * empty string or when there are message size errors. * - * When the function parameter is used, it aids in identifying the context in log messages, - * making it easier to diagnose issues related to network message construction, - * especially in complex systems where the same method might be called from multiple places. + * @param location An optional parameter that captures the location from which `addString` is invoked. + * This enhances logging by including the file name, line number, and function name + * in debug and error log messages. It helps in debugging by indicating the context when issues occur, + * such as attempting to add an empty string or when there are message size errors. + * + * Using `std::source_location` automatically captures the caller context, making it easier + * to diagnose issues related to network message construction, especially in complex systems + * where the same method might be called from multiple places. + * + * @param function An optional string parameter provided from Lua that specifies the name of the Lua + * function or context from which `addString` is called. When this parameter is not empty, + * it overrides the information captured by `std::source_location` in log messages. + * This allows for more precise and meaningful logging in scenarios where `addString` is invoked + * directly from Lua scripts, enabling developers to trace the origin of network messages + * back to specific Lua functions or contexts. + * + * This dual-parameter approach ensures flexibility: + * - When called from C++ without specifying `function`, `std::source_location` provides the necessary + * context for logging. + * - When called from Lua with a `function` name, the provided string offers clearer insight into + * the Lua-side invocation, enhancing the ability to debug and maintain Lua-C++ integrations. + * + * @note It is recommended to use the `function` parameter when invoking `addString` from Lua to ensure + * that log messages accurately reflect the Lua context. When invoking from C++, omitting the `function` + * parameter allows `std::source_location` to automatically capture the C++ context. */ - void addString(const std::string &value, const std::string &function = ""); + void addString(const std::string &value, const std::source_location &location = std::source_location::current(), const std::string &function = ""); void addDouble(double value, uint8_t precision = 2); + double getDouble(); // write functions for complex types void addPosition(const Position &pos); - MsgSize_t getLength() const { - return info.length; - } + MsgSize_t getLength() const; - void setLength(MsgSize_t newLength) { - info.length = newLength; - } + void setLength(MsgSize_t newLength); - MsgSize_t getBufferPosition() const { - return info.position; - } + MsgSize_t getBufferPosition() const; - void setBufferPosition(MsgSize_t newPosition) { - info.position = newPosition; - } + void setBufferPosition(MsgSize_t newPosition); - uint16_t getLengthHeader() const { - return static_cast(buffer[0] | buffer[1] << 8); - } + uint16_t getLengthHeader() const; - int32_t decodeHeader(); + bool isOverrun() const; - bool isOverrun() const { - return info.overrun; - } + uint8_t* getBuffer(); - uint8_t* getBuffer() { - return buffer; - } + const uint8_t* getBuffer() const; - const uint8_t* getBuffer() const { - return buffer; - } + uint8_t* getBodyBuffer(); - uint8_t* getBodyBuffer() { - info.position = 2; - return buffer + HEADER_LENGTH; - } + bool canAdd(size_t size) const; -protected: - bool canAdd(size_t size) const { - return (size + info.position) < MAX_BODY_LENGTH; - } + bool canRead(int32_t size) const; - bool canRead(int32_t size) { - if ((info.position + size) > (info.length + 8) || size >= (NETWORKMESSAGE_MAXSIZE - info.position)) { - info.overrun = true; - return false; - } - return true; - } + void append(const NetworkMessage &other); +protected: struct NetworkMessageInfo { MsgSize_t length = 0; MsgSize_t position = INITIAL_BUFFER_POSITION; @@ -169,5 +163,5 @@ class NetworkMessage { }; NetworkMessageInfo info; - uint8_t buffer[NETWORKMESSAGE_MAXSIZE]; + std::array buffer = {}; }; diff --git a/src/server/network/message/outputmessage.hpp b/src/server/network/message/outputmessage.hpp index 1f590fbd214..459e243cea3 100644 --- a/src/server/network/message/outputmessage.hpp +++ b/src/server/network/message/outputmessage.hpp @@ -24,7 +24,7 @@ class OutputMessage : public NetworkMessage { OutputMessage &operator=(const OutputMessage &) = delete; uint8_t* getOutputBuffer() { - return buffer + outputBufferStart; + return buffer.data() + outputBufferStart; } void writeMessageLength() { @@ -41,14 +41,18 @@ class OutputMessage : public NetworkMessage { void append(const NetworkMessage &msg) { auto msgLen = msg.getLength(); - memcpy(buffer + info.position, msg.getBuffer() + INITIAL_BUFFER_POSITION, msgLen); + std::span sourceSpan(msg.getBuffer() + INITIAL_BUFFER_POSITION, msgLen); + std::span destSpan(buffer.data() + info.position, msgLen); + std::ranges::copy(sourceSpan, destSpan.begin()); info.length += msgLen; info.position += msgLen; } void append(const OutputMessage_ptr &msg) { auto msgLen = msg->getLength(); - memcpy(buffer + info.position, msg->getBuffer() + INITIAL_BUFFER_POSITION, msgLen); + std::span sourceSpan(msg->getBuffer() + INITIAL_BUFFER_POSITION, msgLen); + std::span destSpan(buffer.data() + info.position, msgLen); + std::ranges::copy(sourceSpan, destSpan.begin()); info.length += msgLen; info.position += msgLen; } @@ -61,10 +65,20 @@ class OutputMessage : public NetworkMessage { return; } + // Ensure at runtime that outputBufferStart >= sizeof(T) assert(outputBufferStart >= sizeof(T)); + // Move the buffer position back to make space for the header outputBufferStart -= sizeof(T); - memcpy(buffer + outputBufferStart, &addHeader, sizeof(T)); - // added header size to the message size + + static_assert(std::is_trivially_copyable_v, "Type T must be trivially copyable"); + + // Convert the header to an array of unsigned char using std::bit_cast + auto byteArray = std::bit_cast>(addHeader); + + std::span byteSpan(byteArray); + // Copy the bytes into the buffer + std::ranges::copy(byteSpan, buffer.begin() + outputBufferStart); + // Update the message size info.length += sizeof(T); } diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 7ae02e31b10..560ae1168c5 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -242,7 +242,7 @@ namespace { g_logger().debug("Sendding category number '{}', category name '{}'", static_cast(value), magic_enum::enum_name(value).data()); msg.addByte(static_cast(value)); - msg.addString(toStartCaseWithSpace(magic_enum::enum_name(value).data()), "void sendContainerCategory - toStartCaseWithSpace(magic_enum::enum_name(value).data())"); + msg.addString(toStartCaseWithSpace(magic_enum::enum_name(value).data())); } } } // namespace @@ -568,7 +568,7 @@ void ProtocolGame::login(const std::string &name, uint32_t accountId, OperatingS auto output = OutputMessagePool::getOutputMessage(); output->addByte(0x16); - output->addString(ss.str(), "ProtocolGame::login - ss.str()"); + output->addString(ss.str()); output->addByte(retryTime); send(output); disconnect(); @@ -851,7 +851,7 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage &msg) { auto output = OutputMessagePool::getOutputMessage(); output->addByte(0x14); - output->addString(ss.str(), "ProtocolGame::onRecvFirstMessage - ss.str()"); + output->addString(ss.str()); send(output); g_dispatcher().scheduleEvent( 1000, [self = getThis()] { self->disconnect(); }, "ProtocolGame::disconnect" @@ -893,7 +893,7 @@ void ProtocolGame::onConnect() { void ProtocolGame::disconnectClient(const std::string &message) const { auto output = OutputMessagePool::getOutputMessage(); output->addByte(0x14); - output->addString(message, "ProtocolGame::disconnectClient - message"); + output->addString(message); send(output); disconnect(); } @@ -1317,7 +1317,7 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt parseWheelGemAction(msg); break; case 0xE8: - parseDebugAssert(msg); + parseOfferDescription(msg); break; case 0xEB: parsePreyAction(msg); @@ -2104,10 +2104,10 @@ void ProtocolGame::sendItemInspection(uint16_t itemId, uint8_t itemCount, std::s const ItemType &it = Item::items[itemId]; if (item) { - msg.addString(item->getName(), "ProtocolGame::sendItemInspection - item->getName()"); + msg.addString(item->getName()); AddItem(msg, item); } else { - msg.addString(it.name, "ProtocolGame::sendItemInspection - it.name"); + msg.addString(it.name); AddItem(msg, it.id, itemCount, 0); } msg.addByte(0); @@ -2115,8 +2115,8 @@ void ProtocolGame::sendItemInspection(uint16_t itemId, uint8_t itemCount, std::s auto descriptions = Item::getDescriptions(it, item); msg.addByte(descriptions.size()); for (const auto &description : descriptions) { - msg.addString(description.first, "ProtocolGame::sendItemInspection - description.first"); - msg.addString(description.second, "ProtocolGame::sendItemInspection - description.second"); + msg.addString(description.first); + msg.addString(description.second); } writeToOutputBuffer(msg); } @@ -2207,8 +2207,8 @@ void ProtocolGame::sendHighscores(const std::vector &charact msg.addByte(1); // Worlds auto serverName = g_configManager().getString(SERVER_NAME, __FUNCTION__); - msg.addString(serverName, "ProtocolGame::sendHighscores - g_configManager().getString(SERVER_NAME)"); // First World - msg.addString(serverName, "ProtocolGame::sendHighscores - g_configManager().getString(SERVER_NAME)"); // Selected World + msg.addString(serverName); // First World + msg.addString(serverName); // Selected World msg.addByte(0); // Game World Category: 0xFF(-1) - Selected World msg.addByte(0); // BattlEye World Type @@ -2218,7 +2218,7 @@ void ProtocolGame::sendHighscores(const std::vector &charact msg.skipBytes(1); // Vocation Count msg.add(0xFFFFFFFF); // All Vocations - hardcoded - msg.addString("(all)", "ProtocolGame::sendHighscores - (all)"); // All Vocations - hardcoded + msg.addString("(all)"); // All Vocations - hardcoded uint32_t selectedVocation = 0xFFFFFFFF; const auto vocationsMap = g_vocations().getVocations(); @@ -2226,7 +2226,7 @@ void ProtocolGame::sendHighscores(const std::vector &charact const auto &vocation = it.second; if (vocation->getFromVocation() == static_cast(vocation->getId())) { msg.add(vocation->getFromVocation()); // Vocation Id - msg.addString(vocation->getVocName(), "ProtocolGame::sendHighscores - vocation.getVocName()"); // Vocation Name + msg.addString(vocation->getVocName()); // Vocation Name ++vocations; if (vocation->getFromVocation() == vocationId) { selectedVocation = vocationId; @@ -2242,7 +2242,7 @@ void ProtocolGame::sendHighscores(const std::vector &charact for (const HighscoreCategory &category : highscoreCategories) { g_logger().debug("[ProtocolGame::sendHighscores] - Category: {} - Name: {}", category.m_id, category.m_name); msg.addByte(category.m_id); // Category Id - msg.addString(category.m_name, "ProtocolGame::sendHighscores - category.name"); // Category Name + msg.addString(category.m_name); // Category Name if (category.m_id == categoryId) { selectedCategory = categoryId; } @@ -2255,10 +2255,10 @@ void ProtocolGame::sendHighscores(const std::vector &charact msg.addByte(characters.size()); // Character Count for (const HighscoreCharacter &character : characters) { msg.add(character.rank); // Rank - msg.addString(character.name, "ProtocolGame::sendHighscores - character.name"); // Character Name - msg.addString(character.loyaltyTitle, "ProtocolGame::sendHighscores - character.loyaltyTitle"); // Character Loyalty Title + msg.addString(character.name); // Character Name + msg.addString(character.loyaltyTitle); // Character Loyalty Title msg.addByte(character.vocation); // Vocation Id - msg.addString(serverName, "ProtocolGame::sendHighscores - g_configManager().getString(SERVER_NAME)"); // World + msg.addString(serverName); // World msg.add(character.level); // Level msg.addByte((player->getGUID() == character.id)); // Player Indicator Boolean msg.add(character.points); // Points @@ -2322,7 +2322,7 @@ void ProtocolGame::parseBestiarysendRaces() { BestClass = mtype->info.bestiaryClass; } } - msg.addString(BestClass, "ProtocolGame::parseBestiarysendRaces - BestClass"); + msg.addString(BestClass); msg.add(count); uint16_t unlockedCount = g_iobestiary().getBestiaryRaceUnlocked(player, static_cast(i)); msg.add(unlockedCount); @@ -2374,7 +2374,7 @@ void ProtocolGame::parseBestiarysendMonsterData(NetworkMessage &msg) { NetworkMessage newmsg; newmsg.addByte(0xd7); newmsg.add(raceId); - newmsg.addString(Class, "ProtocolGame::parseBestiarysendMonsterData - Class"); + newmsg.addString(Class); newmsg.addByte(currentLevel); @@ -2419,7 +2419,7 @@ void ProtocolGame::parseBestiarysendMonsterData(NetworkMessage &msg) { newmsg.addByte(difficult); newmsg.addByte(0); // 1 if special event - 0 if regular loot (?) if (g_configManager().getBoolean(SHOW_LOOTS_IN_BESTIARY, __FUNCTION__) || shouldAddItem == true) { - newmsg.addString(loot.name, "ProtocolGame::parseBestiarysendMonsterData - loot.name"); + newmsg.addString(loot.name); newmsg.addByte(loot.countmax > 0 ? 0x1 : 0x0); } } @@ -2452,7 +2452,7 @@ void ProtocolGame::parseBestiarysendMonsterData(NetworkMessage &msg) { } newmsg.add(1); - newmsg.addString(mtype->info.bestiaryLocations, "ProtocolGame::parseBestiarysendMonsterData - mtype->info.bestiaryLocations"); + newmsg.addString(mtype->info.bestiaryLocations); } if (currentLevel > 3) { @@ -2530,7 +2530,7 @@ void ProtocolGame::sendTeamFinderList() { uint8_t status = 0; uint16_t membersSize = 0; msg.add(leader->getGUID()); - msg.addString(leader->getName(), "ProtocolGame::sendTeamFinderList - leader->getName()"); + msg.addString(leader->getName()); msg.add(teamAssemble->minLevel); msg.add(teamAssemble->maxLevel); msg.addByte(teamAssemble->vocationIDs); @@ -2636,7 +2636,7 @@ void ProtocolGame::sendLeaderTeamFinder(bool reset) { } msg.add(leader->getGUID()); - msg.addString(leader->getName(), "ProtocolGame::sendLeaderTeamFinder - leader->getName()"); + msg.addString(leader->getName()); msg.add(leader->getLevel()); msg.addByte(leader->getVocation()->getClientId()); msg.addByte(3); @@ -2647,7 +2647,7 @@ void ProtocolGame::sendLeaderTeamFinder(bool reset) { continue; } msg.add(member->getGUID()); - msg.addString(member->getName(), "ProtocolGame::sendLeaderTeamFinder - member->getName()"); + msg.addString(member->getName()); msg.add(member->getLevel()); msg.addByte(member->getVocation()->getClientId()); msg.addByte(memberPair.second); @@ -2913,8 +2913,8 @@ void ProtocolGame::BestiarysendCharms() { msg.addByte(charmList.size()); for (const auto &c_type : charmList) { msg.addByte(c_type->id); - msg.addString(c_type->name, "ProtocolGame::BestiarysendCharms - c_type->name"); - msg.addString(c_type->description, "ProtocolGame::BestiarysendCharms - c_type->description"); + msg.addString(c_type->name); + msg.addString(c_type->description); msg.addByte(0); // Unknown msg.add(c_type->points); if (g_iobestiary().hasCharmUnlockedRuneBit(c_type, player->getUnlockedRunesBit())) { @@ -2986,7 +2986,7 @@ void ProtocolGame::parseBestiarysendCreatures(NetworkMessage &msg) { } NetworkMessage newmsg; newmsg.addByte(0xd6); - newmsg.addString(text, "ProtocolGame::parseBestiarysendCreatures - text"); + newmsg.addString(text); newmsg.add(race.size()); std::map creaturesKilled = g_iobestiary().getBestiaryKillCountByMonsterIDs(player, race); @@ -3039,18 +3039,9 @@ void ProtocolGame::parseGreet(NetworkMessage &msg) { g_game().playerNpcGreet(player->getID(), npcId); } -void ProtocolGame::parseDebugAssert(NetworkMessage &msg) { - if (debugAssertSent) { - return; - } - - debugAssertSent = true; - - std::string assertLine = msg.getString(); - std::string date = msg.getString(); - std::string description = msg.getString(); - std::string comment = msg.getString(); - g_game().playerDebugAssert(player->getID(), assertLine, date, description, comment); +void ProtocolGame::parseOfferDescription(NetworkMessage &msg) { + auto offerId = msg.get(); + g_logger().debug("[{}] offer id: {}", __FUNCTION__, offerId); } void ProtocolGame::parsePreyAction(NetworkMessage &msg) { @@ -3214,7 +3205,7 @@ void ProtocolGame::parseSeekInContainer(NetworkMessage &msg) { void ProtocolGame::sendOpenPrivateChannel(const std::string &receiver) { NetworkMessage msg; msg.addByte(0xAD); - msg.addString(receiver, "ProtocolGame::sendOpenPrivateChannel - receiver"); + msg.addString(receiver); writeToOutputBuffer(msg); } @@ -3234,7 +3225,7 @@ void ProtocolGame::sendChannelEvent(uint16_t channelId, const std::string &playe NetworkMessage msg; msg.addByte(0xF3); msg.add(channelId); - msg.addString(playerName, "ProtocolGame::sendChannelEvent - playerName"); + msg.addString(playerName); msg.addByte(channelEvent); writeToOutputBuffer(msg); } @@ -3435,7 +3426,7 @@ void ProtocolGame::sendAddMarker(const Position &pos, uint8_t markType, const st msg.addPosition(pos); msg.addByte(markType); - msg.addString(desc, "ProtocolGame::sendAddMarker - desc"); + msg.addString(desc); writeToOutputBuffer(msg); } @@ -3460,13 +3451,13 @@ void ProtocolGame::sendCyclopediaCharacterBaseInformation() { msg.addByte(0xDA); msg.addByte(CYCLOPEDIA_CHARACTERINFO_BASEINFORMATION); msg.addByte(0x00); - msg.addString(player->getName(), "ProtocolGame::sendCyclopediaCharacterBaseInformation - player->getName()"); - msg.addString(player->getVocation()->getVocName(), "ProtocolGame::sendCyclopediaCharacterBaseInformation - player->getVocation()->getVocName()"); + msg.addString(player->getName()); + msg.addString(player->getVocation()->getVocName()); msg.add(player->getLevel()); AddOutfit(msg, player->getDefaultOutfit(), false); msg.addByte(0x01); // Store summary & Character titles - msg.addString(player->title()->getCurrentTitleName(), "ProtocolGame::sendCyclopediaCharacterBaseInformation - player->title()->getCurrentTitleName()"); // character title + msg.addString(player->title()->getCurrentTitleName()); // character title writeToOutputBuffer(msg); } @@ -3711,7 +3702,7 @@ void ProtocolGame::sendCyclopediaCharacterRecentDeaths(uint16_t page, uint16_t p msg.add(entries.size()); for (const RecentDeathEntry &entry : entries) { msg.add(entry.timestamp); - msg.addString(entry.cause, "ProtocolGame::sendCyclopediaCharacterRecentDeaths - entry.cause"); + msg.addString(entry.cause); } writeToOutputBuffer(msg); @@ -3731,7 +3722,7 @@ void ProtocolGame::sendCyclopediaCharacterRecentPvPKills(uint16_t page, uint16_t msg.add(entries.size()); for (const RecentPvPKillEntry &entry : entries) { msg.add(entry.timestamp); - msg.addString(entry.description, "ProtocolGame::sendCyclopediaCharacterRecentPvPKills - entry.description"); + msg.addString(entry.description); msg.addByte(entry.status); } @@ -3750,15 +3741,13 @@ void ProtocolGame::sendCyclopediaCharacterAchievements(uint16_t secretsUnlocked, msg.add(player->achiev()->getPoints()); msg.add(secretsUnlocked); msg.add(static_cast(achievementsUnlocked.size())); - std::string messageAchievName = "ProtocolGame::sendCyclopediaCharacterAchievements - achievement.name"; - std::string messageAchievDesc = "ProtocolGame::sendCyclopediaCharacterAchievements - achievement.description"; for (const auto &[achievement, addedTimestamp] : achievementsUnlocked) { msg.add(achievement.id); msg.add(addedTimestamp); if (achievement.secret) { msg.addByte(0x01); - msg.addString(achievement.name, messageAchievName); - msg.addString(achievement.description, messageAchievDesc); + msg.addString(achievement.name); + msg.addString(achievement.description); msg.addByte(achievement.grade); } else { msg.addByte(0x00); @@ -3904,7 +3893,7 @@ void ProtocolGame::sendCyclopediaCharacterOutfitsMounts() { ++outfitSize; msg.add(outfit->lookType); - msg.addString(outfit->name, "ProtocolGame::sendCyclopediaCharacterOutfitsMounts - outfit->name"); + msg.addString(outfit->name); msg.addByte(addons); if (from == "store") { msg.addByte(CYCLOPEDIA_CHARACTERINFO_OUTFITTYPE_STORE); @@ -3935,7 +3924,7 @@ void ProtocolGame::sendCyclopediaCharacterOutfitsMounts() { ++mountSize; msg.add(mount->clientId); - msg.addString(mount->name, "ProtocolGame::sendCyclopediaCharacterOutfitsMounts - mount->name"); + msg.addString(mount->name); if (type == "store") { msg.addByte(CYCLOPEDIA_CHARACTERINFO_OUTFITTYPE_STORE); } else if (type == "quest") { @@ -3964,7 +3953,7 @@ void ProtocolGame::sendCyclopediaCharacterOutfitsMounts() { } ++familiarsSize; msg.add(familiar->lookType); - msg.addString(familiar->name, "ProtocolGame::sendCyclopediaCharacterOutfitsMounts - familiar.name"); + msg.addString(familiar->name); if (type == "quest") { msg.addByte(CYCLOPEDIA_CHARACTERINFO_OUTFITTYPE_QUEST); } else { @@ -4000,7 +3989,7 @@ void ProtocolGame::sendCyclopediaCharacterStoreSummary() { msg.addByte(static_cast(magic_enum::enum_count())); for (auto bless : magic_enum::enum_values()) { std::string name = toStartCaseWithSpace(magic_enum::enum_name(bless).data()); - msg.addString(name, "ProtocolGame::sendCyclopediaCharacterStoreSummary - blessing.name"); + msg.addString(name); auto blessValue = enumToValue(bless); if (player->hasBlessing(blessValue)) { msg.addByte(static_cast(player->blessings[blessValue - 1])); @@ -4057,7 +4046,7 @@ void ProtocolGame::sendCyclopediaCharacterStoreSummary() { for (const auto &hItem_it : houseItems) { const ItemType &it = Item::items[hItem_it.first]; msg.add(it.id); // Item ID - msg.addString(it.name, "ProtocolGame::sendCyclopediaCharacterStoreSummary - houseItem.name"); + msg.addString(it.name); msg.addByte(hItem_it.second); } @@ -4082,7 +4071,7 @@ void ProtocolGame::sendCyclopediaCharacterInspection() { ++inventoryItems; msg.addByte(slot); - msg.addString(inventoryItem->getName(), "ProtocolGame::sendCyclopediaCharacterInspection - inventoryItem->getName()"); + msg.addString(inventoryItem->getName()); AddItem(msg, inventoryItem); uint8_t itemImbuements = 0; @@ -4106,12 +4095,12 @@ void ProtocolGame::sendCyclopediaCharacterInspection() { auto descriptions = Item::getDescriptions(Item::items[inventoryItem->getID()], inventoryItem); msg.addByte(descriptions.size()); for (const auto &description : descriptions) { - msg.addString(description.first, "ProtocolGame::sendCyclopediaCharacterInspection - description.first"); - msg.addString(description.second, "ProtocolGame::sendCyclopediaCharacterInspection - description.second"); + msg.addString(description.first); + msg.addString(description.second); } } } - msg.addString(player->getName(), "ProtocolGame::sendCyclopediaCharacterInspection - player->getName()"); + msg.addString(player->getName()); AddOutfit(msg, player->getDefaultOutfit(), false); // Player overall summary @@ -4122,33 +4111,33 @@ void ProtocolGame::sendCyclopediaCharacterInspection() { // Player title if (player->title()->getCurrentTitle() != 0) { playerDescriptionSize++; - msg.addString("Character Title", "ProtocolGame::sendCyclopediaCharacterInspection - Title"); - msg.addString(player->title()->getCurrentTitleName(), "ProtocolGame::sendCyclopediaCharacterInspection - player->title()->getCurrentTitleName()"); + msg.addString("Character Title"); + msg.addString(player->title()->getCurrentTitleName()); } // Level description playerDescriptionSize++; - msg.addString("Level", "ProtocolGame::sendCyclopediaCharacterInspection - Level"); - msg.addString(std::to_string(player->getLevel()), "ProtocolGame::sendCyclopediaCharacterInspection - std::to_string(player->getLevel())"); + msg.addString("Level"); + msg.addString(std::to_string(player->getLevel())); // Vocation description playerDescriptionSize++; - msg.addString("Vocation", "ProtocolGame::sendCyclopediaCharacterInspection - Vocation"); - msg.addString(player->getVocation()->getVocName(), "ProtocolGame::sendCyclopediaCharacterInspection - player->getVocation()->getVocName()"); + msg.addString("Vocation"); + msg.addString(player->getVocation()->getVocName()); // Loyalty title if (!player->getLoyaltyTitle().empty()) { playerDescriptionSize++; - msg.addString("Loyalty Title", "ProtocolGame::sendCyclopediaCharacterInspection - Loyalty Title"); - msg.addString(player->getLoyaltyTitle(), "ProtocolGame::sendCyclopediaCharacterInspection - player->getLoyaltyTitle()"); + msg.addString("Loyalty Title"); + msg.addString(player->getLoyaltyTitle()); } // Marriage description if (const auto spouseId = player->getMarriageSpouse(); spouseId > 0) { if (const auto &spouse = g_game().getPlayerByID(spouseId, true); spouse) { playerDescriptionSize++; - msg.addString("Married to", "ProtocolGame::sendCyclopediaCharacterInspection - Married to"); - msg.addString(spouse->getName(), "ProtocolGame::sendCyclopediaCharacterInspection - spouse->getName()"); + msg.addString("Married to"); + msg.addString(spouse->getName()); } } @@ -4158,7 +4147,7 @@ void ProtocolGame::sendCyclopediaCharacterInspection() { slot && slot->isOccupied()) { playerDescriptionSize++; std::string activePrey = fmt::format("Active Prey {}", slotId + 1); - msg.addString(activePrey, "ProtocolGame::sendCyclopediaCharacterInspection - active prey"); + msg.addString(activePrey); std::string desc; if (auto mtype = g_monsters().getMonsterTypeByRaceId(slot->selectedRaceId)) { @@ -4180,17 +4169,17 @@ void ProtocolGame::sendCyclopediaCharacterInspection() { uint8_t hours = slot->bonusTimeLeft / 3600; uint8_t minutes = (slot->bonusTimeLeft - (hours * 3600)) / 60; desc.append(fmt::format("{}:{}{}h", hours, (minutes < 10 ? "0" : ""), minutes)); - msg.addString(desc, "ProtocolGame::sendCyclopediaCharacterInspection - prey description"); + msg.addString(desc); } } // Outfit description playerDescriptionSize++; - msg.addString("Outfit", "ProtocolGame::sendCyclopediaCharacterInspection - Outfit"); + msg.addString("Outfit"); if (const auto outfit = Outfits::getInstance().getOutfitByLookType(player, player->getDefaultOutfit().lookType)) { - msg.addString(outfit->name, "ProtocolGame::sendCyclopediaCharacterInspection - outfit->name"); + msg.addString(outfit->name); } else { - msg.addString("unknown", "ProtocolGame::sendCyclopediaCharacterInspection - unknown"); + msg.addString("unknown"); } msg.setBufferPosition(startInventory); @@ -4217,7 +4206,7 @@ void ProtocolGame::sendCyclopediaCharacterBadges() { msg.addByte(loggedPlayer ? 0x01 : 0x00); // IsOnline msg.addByte(player->isPremium() ? 0x01 : 0x00); // IsPremium (GOD has always 'Premium') // Character loyalty title - msg.addString(player->getLoyaltyTitle(), "ProtocolGame::sendCyclopediaCharacterBadges - player->getLoyaltyTitle()"); + msg.addString(player->getLoyaltyTitle()); uint8_t badgesSize = 0; auto badgesSizePosition = msg.getBufferPosition(); @@ -4225,7 +4214,7 @@ void ProtocolGame::sendCyclopediaCharacterBadges() { for (const auto &badge : g_game().getBadges()) { if (player->badge()->hasBadge(badge.m_id)) { msg.add(badge.m_id); - msg.addString(badge.m_name, "ProtocolGame::sendCyclopediaCharacterBadges - name"); + msg.addString(badge.m_name); badgesSize++; } } @@ -4249,14 +4238,11 @@ void ProtocolGame::sendCyclopediaCharacterTitles() { msg.addByte(0x00); // 0x00 Here means 'no error' msg.addByte(player->title()->getCurrentTitle()); msg.addByte(static_cast(titles.size())); - - std::string messageTitleName = "ProtocolGame::sendCyclopediaCharacterTitles - title.name"; - std::string messageTitleDesc = "ProtocolGame::sendCyclopediaCharacterTitles - title.description"; for (const auto &title : titles) { msg.addByte(title.m_id); auto titleName = player->title()->getNameBySex(player->getSex(), title.m_maleName, title.m_femaleName); - msg.addString(titleName, messageTitleName); - msg.addString(title.m_description, messageTitleDesc); + msg.addString(titleName); + msg.addString(title.m_description); msg.addByte(title.m_permanent ? 0x01 : 0x00); auto isUnlocked = player->title()->isTitleUnlocked(title.m_id); msg.addByte(isUnlocked ? 0x01 : 0x00); @@ -4503,7 +4489,7 @@ void ProtocolGame::sendTextMessage(const TextMessage &message) { default: break; } - msg.addString(message.text, "ProtocolGame::sendTextMessage - message.text"); + msg.addString(message.text); writeToOutputBuffer(msg); } @@ -4518,9 +4504,9 @@ void ProtocolGame::sendCreatePrivateChannel(uint16_t channelId, const std::strin NetworkMessage msg; msg.addByte(0xB2); msg.add(channelId); - msg.addString(channelName, "ProtocolGame::sendCreatePrivateChannel - channelName"); + msg.addString(channelName); msg.add(0x01); - msg.addString(player->getName(), "ProtocolGame::sendCreatePrivateChannel - player->getName()"); + msg.addString(player->getName()); msg.add(0x00); writeToOutputBuffer(msg); } @@ -4533,7 +4519,7 @@ void ProtocolGame::sendChannelsDialog() { msg.addByte(list.size()); for (const auto &channel : list) { msg.add(channel->getId()); - msg.addString(channel->getName(), "ProtocolGame::sendChannelsDialog - channel->getName()"); + msg.addString(channel->getName()); } writeToOutputBuffer(msg); @@ -4544,12 +4530,12 @@ void ProtocolGame::sendChannel(uint16_t channelId, const std::string &channelNam msg.addByte(0xAC); msg.add(channelId); - msg.addString(channelName, "ProtocolGame::sendChannel - channelName"); + msg.addString(channelName); if (channelUsers) { msg.add(channelUsers->size()); for (const auto &it : *channelUsers) { - msg.addString(it.second->getName(), "ProtocolGame::sendChannel - it.second->getName()"); + msg.addString(it.second->getName()); } } else { msg.add(0x00); @@ -4558,7 +4544,7 @@ void ProtocolGame::sendChannel(uint16_t channelId, const std::string &channelNam if (invitedUsers) { msg.add(invitedUsers->size()); for (const auto &it : *invitedUsers) { - msg.addString(it.second->getName(), "ProtocolGame::sendChannel - it.second->getName()"); + msg.addString(it.second->getName()); } } else { msg.add(0x00); @@ -4570,11 +4556,11 @@ void ProtocolGame::sendChannelMessage(const std::string &author, const std::stri NetworkMessage msg; msg.addByte(0xAA); msg.add(0x00); - msg.addString(author, "ProtocolGame::sendChannelMessage - author"); + msg.addString(author); msg.add(0x00); msg.addByte(type); msg.add(channel); - msg.addString(text, "ProtocolGame::sendChannelMessage - text"); + msg.addString(text); writeToOutputBuffer(msg); } @@ -4634,10 +4620,10 @@ void ProtocolGame::sendContainer(uint8_t cid, std::shared_ptr contain if (container->getID() == ITEM_BROWSEFIELD) { AddItem(msg, ITEM_BAG, 1, container->getTier()); - msg.addString("Browse Field", "ProtocolGame::sendContainer - Browse Field"); + msg.addString("Browse Field"); } else { AddItem(msg, container); - msg.addString(container->getName(), "ProtocolGame::sendContainer - container->getName()"); + msg.addString(container->getName()); } const auto itemsStoreInboxToSend = container->getStoreInboxFilteredItems(); @@ -4793,7 +4779,7 @@ void ProtocolGame::sendLootStats(std::shared_ptr item, uint8_t count) { NetworkMessage msg; msg.addByte(0xCF); AddItem(msg, lootedItem); - msg.addString(lootedItem->getName(), "ProtocolGame::sendLootStats - lootedItem->getName()"); + msg.addString(lootedItem->getName()); item->setIsLootTrackeable(false); writeToOutputBuffer(msg); @@ -4804,7 +4790,7 @@ void ProtocolGame::sendShop(std::shared_ptr npc) { Benchmark brenchmark; NetworkMessage msg; msg.addByte(0x7A); - msg.addString(npc->getName(), "ProtocolGame::sendShop - npc->getName()"); + msg.addString(npc->getName()); if (!oldProtocol) { msg.add(npc->getCurrency()); @@ -5085,7 +5071,7 @@ void ProtocolGame::sendMarketBrowseItem(uint16_t itemId, const MarketOfferList & } else { msg.add(static_cast(offer.price)); } - msg.addString(offer.playerName, "ProtocolGame::sendMarketBrowseItem - offer.playerName"); + msg.addString(offer.playerName); } msg.add(sellOffers.size()); @@ -5098,7 +5084,7 @@ void ProtocolGame::sendMarketBrowseItem(uint16_t itemId, const MarketOfferList & } else { msg.add(static_cast(offer.price)); } - msg.addString(offer.playerName, "ProtocolGame::sendMarketBrowseItem - offer.playerName"); + msg.addString(offer.playerName); } updateCoinBalance(); @@ -5127,7 +5113,7 @@ void ProtocolGame::sendMarketAcceptOffer(const MarketOfferEx &offer) { } else { msg.add(static_cast(offer.price)); } - msg.addString(offer.playerName, "ProtocolGame::sendMarketAcceptOffer - offer.playerName"); + msg.addString(offer.playerName); msg.add(0x00); } else { msg.add(0x00); @@ -5140,7 +5126,7 @@ void ProtocolGame::sendMarketAcceptOffer(const MarketOfferEx &offer) { } else { msg.add(static_cast(offer.price)); } - msg.addString(offer.playerName, "ProtocolGame::sendMarketAcceptOffer - offer.playerName"); + msg.addString(offer.playerName); } writeToOutputBuffer(msg); @@ -5701,7 +5687,7 @@ void ProtocolGame::sendForgeHistory(uint8_t page) { auto action = magic_enum::enum_integer(history.actionType); msg.add(static_cast(history.createdAt)); msg.addByte(action); - msg.addString(history.description, "ProtocolGame::sendForgeHistory - history.description"); + msg.addString(history.description); msg.addByte((history.bonus >= 1 && history.bonus < 8) ? 0x01 : 0x00); } } @@ -5731,7 +5717,7 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { } if (it.armor != 0) { - msg.addString(std::to_string(it.armor), "ProtocolGame::sendMarketDetail - std::to_string(it.armor)"); + msg.addString(std::to_string(it.armor)); } else { msg.add(0x00); } @@ -5759,21 +5745,21 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { } ss << static_cast(it.shootRange) << " fields"; } - msg.addString(ss.str(), "ProtocolGame::sendMarketDetail - ss.str()"); + msg.addString(ss.str()); } else if (!it.isRanged() && it.attack != 0) { if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0) { std::ostringstream ss; ss << it.attack << " physical +" << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType); - msg.addString(ss.str(), "ProtocolGame::sendMarketDetail - ss.str()"); + msg.addString(ss.str()); } else { - msg.addString(std::to_string(it.attack), "ProtocolGame::sendMarketDetail - std::to_string(it.attack)"); + msg.addString(std::to_string(it.attack)); } } else { msg.add(0x00); } if (it.isContainer()) { - msg.addString(std::to_string(it.maxItems), "ProtocolGame::sendMarketDetail - std::to_string(it.maxItems)"); + msg.addString(std::to_string(it.maxItems)); } else { msg.add(0x00); } @@ -5782,9 +5768,9 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { if (it.extraDefense != 0) { std::ostringstream ss; ss << it.defense << ' ' << std::showpos << it.extraDefense << std::noshowpos; - msg.addString(ss.str(), "ProtocolGame::sendMarketDetail - ss.str()"); + msg.addString(ss.str()); } else { - msg.addString(std::to_string(it.defense), "ProtocolGame::sendMarketDetail - std::to_string(it.defense)"); + msg.addString(std::to_string(it.defense)); } } else { msg.add(0x00); @@ -5793,9 +5779,9 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { if (!it.description.empty()) { const std::string &descr = it.description; if (descr.back() == '.') { - msg.addString(std::string(descr, 0, descr.length() - 1), "ProtocolGame::sendMarketDetail - std::string(descr, 0, descr.length() - 1)"); + msg.addString(std::string(descr, 0, descr.length() - 1)); } else { - msg.addString(descr, "ProtocolGame::sendMarketDetail - descr"); + msg.addString(descr); } } else { msg.add(0x00); @@ -5804,7 +5790,7 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { if (it.decayTime != 0) { std::ostringstream ss; ss << it.decayTime << " seconds"; - msg.addString(ss.str(), "ProtocolGame::sendMarketDetail - ss.str()"); + msg.addString(ss.str()); } else { msg.add(0x00); } @@ -5827,25 +5813,25 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { ss << fmt::format("{} {:+}%", getCombatName(indexToCombatType(i)), it.abilities->absorbPercent[i]); } - msg.addString(ss.str(), "ProtocolGame::sendMarketDetail - ss.str()"); + msg.addString(ss.str()); } else { msg.add(0x00); } if (it.minReqLevel != 0) { - msg.addString(std::to_string(it.minReqLevel), "ProtocolGame::sendMarketDetail - std::to_string(it.minReqLevel)"); + msg.addString(std::to_string(it.minReqLevel)); } else { msg.add(0x00); } if (it.minReqMagicLevel != 0) { - msg.addString(std::to_string(it.minReqMagicLevel), "ProtocolGame::sendMarketDetail - std::to_string(it.minReqMagicLevel)"); + msg.addString(std::to_string(it.minReqMagicLevel)); } else { msg.add(0x00); } - msg.addString(it.vocationString, "ProtocolGame::sendMarketDetail - it.vocationString"); - msg.addString(it.runeSpellName, "ProtocolGame::sendMarketDetail - it.runeSpellName"); + msg.addString(it.vocationString); + msg.addString(it.runeSpellName); if (it.abilities) { std::ostringstream ss; @@ -5911,13 +5897,13 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { ss << fmt::format("speed {:+}", (it.abilities->speed >> 1)); } - msg.addString(ss.str(), "ProtocolGame::sendMarketDetail - ss.str()"); + msg.addString(ss.str()); } else { msg.add(0x00); } if (it.charges != 0) { - msg.addString(std::to_string(it.charges), "ProtocolGame::sendMarketDetail - std::to_string(it.charges)"); + msg.addString(std::to_string(it.charges)); } else { msg.add(0x00); } @@ -5932,7 +5918,7 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { } } - msg.addString(weaponName, "ProtocolGame::sendMarketDetail - weaponName"); + msg.addString(weaponName); if (it.weight != 0) { std::ostringstream ss; @@ -5946,7 +5932,7 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { ss << weightString; } ss << " oz"; - msg.addString(ss.str(), "ProtocolGame::sendMarketDetail - ss.str()"); + msg.addString(ss.str()); } else { msg.add(0x00); } @@ -5954,14 +5940,14 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { if (!oldProtocol) { std::string augmentsDescription = it.parseAugmentDescription(true); if (!augmentsDescription.empty()) { - msg.addString(augmentsDescription, "ProtocolGame::sendMarketDetail - augmentsDescription"); + msg.addString(augmentsDescription); } else { msg.add(0x00); // no augments } } if (it.imbuementSlot > 0) { - msg.addString(std::to_string(it.imbuementSlot), "ProtocolGame::sendMarketDetail - std::to_string(it.imbuementSlot)"); + msg.addString(std::to_string(it.imbuementSlot)); } else { msg.add(0x00); } @@ -5973,7 +5959,7 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { if (it.abilities->magicShieldCapacityFlat > 0) { string.clear(); string << std::showpos << it.abilities->magicShieldCapacityFlat << std::noshowpos << " and " << it.abilities->magicShieldCapacityPercent << "%"; - msg.addString(string.str(), "ProtocolGame::sendMarketDetail - string.str()"); + msg.addString(string.str()); } else { msg.add(0x00); } @@ -5981,7 +5967,7 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { if (it.abilities->cleavePercent > 0) { string.clear(); string << it.abilities->cleavePercent << "%"; - msg.addString(string.str(), "ProtocolGame::sendMarketDetail - string.str()"); + msg.addString(string.str()); } else { msg.add(0x00); } @@ -5989,7 +5975,7 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { if (it.abilities->reflectFlat[COMBAT_PHYSICALDAMAGE] > 0) { string.clear(); string << it.abilities->reflectFlat[COMBAT_PHYSICALDAMAGE]; - msg.addString(string.str(), "ProtocolGame::sendMarketDetail - string.str()"); + msg.addString(string.str()); } else { msg.add(0x00); } @@ -5997,7 +5983,7 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { if (it.abilities->perfectShotDamage > 0) { string.clear(); string << std::showpos << it.abilities->perfectShotDamage << std::noshowpos << " at range " << unsigned(it.abilities->perfectShotRange); - msg.addString(string.str(), "ProtocolGame::sendMarketDetail - string.str()"); + msg.addString(string.str()); } else { msg.add(0x00); } @@ -6015,7 +6001,7 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { // Upgrade and tier detail modifier if (it.upgradeClassification > 0 && tier > 0) { - msg.addString(std::to_string(it.upgradeClassification), "ProtocolGame::sendMarketDetail - std::to_string(it.upgradeClassification)"); + msg.addString(std::to_string(it.upgradeClassification)); std::ostringstream ss; double chance; @@ -6029,10 +6015,10 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { chance = (0.0307576 * tier * tier) + (0.440697 * tier) + 0.026; ss << fmt::format("{} ({:.2f}% Ruse)", static_cast(tier), chance); } - msg.addString(ss.str(), "ProtocolGame::sendMarketDetail - ss.str()"); + msg.addString(ss.str()); } else if (it.upgradeClassification > 0 && tier == 0) { - msg.addString(std::to_string(it.upgradeClassification), "ProtocolGame::sendMarketDetail - std::to_string(it.upgradeClassification)"); - msg.addString(std::to_string(tier), "ProtocolGame::sendMarketDetail - std::to_string(tier)"); + msg.addString(std::to_string(it.upgradeClassification)); + msg.addString(std::to_string(tier)); } else { msg.add(0x00); msg.add(0x00); @@ -6101,7 +6087,7 @@ void ProtocolGame::sendTradeItemRequest(const std::string &traderName, std::shar msg.addByte(0x7E); } - msg.addString(traderName, "ProtocolGame::sendTradeItemRequest - traderName"); + msg.addString(traderName); if (std::shared_ptr tradeContainer = item->getContainer()) { std::list> listContainer { tradeContainer }; @@ -6166,7 +6152,7 @@ void ProtocolGame::sendCreatureSay(std::shared_ptr creature, SpeakClas static uint32_t statementId = 0; msg.add(++statementId); - msg.addString(creature->getName(), "ProtocolGame::sendCreatureSay - creature->getName()"); + msg.addString(creature->getName()); if (!oldProtocol) { msg.addByte(0x00); // Show (Traded) @@ -6191,7 +6177,7 @@ void ProtocolGame::sendCreatureSay(std::shared_ptr creature, SpeakClas msg.addPosition(creature->getPosition()); } - msg.addString(text, "ProtocolGame::sendCreatureSay - text"); + msg.addString(text); writeToOutputBuffer(msg); } @@ -6213,7 +6199,7 @@ void ProtocolGame::sendToChannel(std::shared_ptr creature, SpeakClasse } type = TALKTYPE_CHANNEL_R1; } else { - msg.addString(creature->getName(), "ProtocolGame::sendToChannel - creature->getName()"); + msg.addString(creature->getName()); if (!oldProtocol && statementId != 0) { msg.addByte(0x00); // Show (Traded) } @@ -6233,7 +6219,7 @@ void ProtocolGame::sendToChannel(std::shared_ptr creature, SpeakClasse } msg.add(channelId); - msg.addString(text, "ProtocolGame::sendToChannel - text"); + msg.addString(text); writeToOutputBuffer(msg); } @@ -6243,7 +6229,7 @@ void ProtocolGame::sendPrivateMessage(std::shared_ptr speaker, SpeakClas static uint32_t statementId = 0; msg.add(++statementId); if (speaker) { - msg.addString(speaker->getName(), "ProtocolGame::sendPrivateMessage - speaker->getName()"); + msg.addString(speaker->getName()); if (!oldProtocol && statementId != 0) { msg.addByte(0x00); // Show (Traded) } @@ -6261,7 +6247,7 @@ void ProtocolGame::sendPrivateMessage(std::shared_ptr speaker, SpeakClas msg.addByte(type); } - msg.addString(text, "ProtocolGame::sendPrivateMessage - text"); + msg.addString(text); writeToOutputBuffer(msg); } @@ -6349,7 +6335,7 @@ void ProtocolGame::sendRestingStatus(uint8_t protection) { msg.addByte(dailyStreak < 2 ? 0 : 1); if (dailyStreak < 2) { - msg.addString("Resting Area (no active bonus)", "ProtocolGame::sendRestingStatus - Resting Area (no active bonus)"); + msg.addString("Resting Area (no active bonus)"); } else { std::ostringstream ss; ss << "Active Resting Area Bonuses: "; @@ -6372,7 +6358,7 @@ void ProtocolGame::sendRestingStatus(uint8_t protection) { ss << ",\nSoul Points Regeneration"; } ss << "."; - msg.addString(ss.str(), "ProtocolGame::sendRestingStatus - ss.str()"); + msg.addString(ss.str()); } writeToOutputBuffer(msg); } @@ -6568,7 +6554,7 @@ void ProtocolGame::sendPlayerVocation(std::shared_ptr target) { void ProtocolGame::sendFYIBox(const std::string &message) { NetworkMessage msg; msg.addByte(0x15); - msg.addString(message, "ProtocolGame::sendFYIBox - message"); + msg.addString(message); writeToOutputBuffer(msg); } @@ -6748,7 +6734,7 @@ void ProtocolGame::sendAddCreature(std::shared_ptr creature, const Pos msg.addByte(0x00); // can change pvp framing option msg.addByte(0x00); // expert mode button enabled - msg.addString(g_configManager().getString(STORE_IMAGES_URL, __FUNCTION__), "ProtocolGame::sendAddCreature - g_configManager().getString(STORE_IMAGES_URL)"); + msg.addString(g_configManager().getString(STORE_IMAGES_URL, __FUNCTION__)); msg.add(static_cast(g_configManager().getNumber(STORE_COIN_PACKET, __FUNCTION__))); if (!oldProtocol) { @@ -6990,16 +6976,16 @@ void ProtocolGame::sendTextWindow(uint32_t windowTextId, std::shared_ptr i if (canWrite) { msg.add(maxlen); - msg.addString(item->getAttribute(ItemAttribute_t::TEXT), "ProtocolGame::sendTextWindow - item->getAttribute(ItemAttribute_t::TEXT)"); + msg.addString(item->getAttribute(ItemAttribute_t::TEXT)); } else { const std::string &text = item->getAttribute(ItemAttribute_t::TEXT); msg.add(text.size()); - msg.addString(text, "ProtocolGame::sendTextWindow - text"); + msg.addString(text); } const std::string &writer = item->getAttribute(ItemAttribute_t::WRITER); if (!writer.empty()) { - msg.addString(writer, "ProtocolGame::sendTextWindow - writer"); + msg.addString(writer); } else { msg.add(0x00); } @@ -7010,7 +6996,7 @@ void ProtocolGame::sendTextWindow(uint32_t windowTextId, std::shared_ptr i auto writtenDate = item->getAttribute(ItemAttribute_t::DATE); if (writtenDate != 0) { - msg.addString(formatDateShort(writtenDate), "ProtocolGame::sendTextWindow - formatDateShort(writtenDate)"); + msg.addString(formatDateShort(writtenDate)); } else { msg.add(0x00); } @@ -7024,7 +7010,7 @@ void ProtocolGame::sendTextWindow(uint32_t windowTextId, uint32_t itemId, const msg.add(windowTextId); AddItem(msg, itemId, 1, 0); msg.add(text.size()); - msg.addString(text, "ProtocolGame::sendTextWindow - text"); + msg.addString(text); msg.add(0x00); if (!oldProtocol) { @@ -7040,7 +7026,7 @@ void ProtocolGame::sendHouseWindow(uint32_t windowTextId, const std::string &tex msg.addByte(0x97); msg.addByte(0x00); msg.add(windowTextId); - msg.addString(text, "ProtocolGame::sendHouseWindow - text"); + msg.addString(text); writeToOutputBuffer(msg); } @@ -7084,7 +7070,7 @@ void ProtocolGame::sendOutfitWindow() { msg.addByte(protocolOutfits.size()); for (const ProtocolOutfit &outfit : protocolOutfits) { msg.add(outfit.lookType); - msg.addString(outfit.name, "ProtocolGame::sendOutfitWindow - outfit.name"); + msg.addString(outfit.name); msg.addByte(outfit.addons); } @@ -7098,7 +7084,7 @@ void ProtocolGame::sendOutfitWindow() { msg.addByte(mounts.size()); for (const auto &mount : mounts) { msg.add(mount->clientId); - msg.addString(mount->name, "ProtocolGame::sendOutfitWindow - mount->name"); + msg.addString(mount->name); } writeToOutputBuffer(msg); @@ -7119,19 +7105,19 @@ void ProtocolGame::sendOutfitWindow() { if (player->isAccessPlayer() && g_configManager().getBoolean(ENABLE_SUPPORT_OUTFIT, __FUNCTION__)) { msg.add(75); - msg.addString("Gamemaster", "ProtocolGame::sendOutfitWindow - Gamemaster"); + msg.addString("Gamemaster"); msg.addByte(0); msg.addByte(0x00); ++outfitSize; msg.add(266); - msg.addString("Customer Support", "ProtocolGame::sendOutfitWindow - Customer Support"); + msg.addString("Customer Support"); msg.addByte(0); msg.addByte(0x00); ++outfitSize; msg.add(302); - msg.addString("Community Manager", "ProtocolGame::sendOutfitWindow - Community Manager"); + msg.addString("Community Manager"); msg.addByte(0); msg.addByte(0x00); ++outfitSize; @@ -7143,14 +7129,14 @@ void ProtocolGame::sendOutfitWindow() { uint8_t addons; if (player->getOutfitAddons(outfit, addons)) { msg.add(outfit->lookType); - msg.addString(outfit->name, "ProtocolGame::sendOutfitWindow - outfit->name"); + msg.addString(outfit->name); msg.addByte(addons); msg.addByte(0x00); ++outfitSize; } else if (outfit->lookType == 1210 || outfit->lookType == 1211) { if (player->canWear(1210, 0) || player->canWear(1211, 0)) { msg.add(outfit->lookType); - msg.addString(outfit->name, "ProtocolGame::sendOutfitWindow - outfit->name"); + msg.addString(outfit->name); msg.addByte(3); msg.addByte(0x02); ++outfitSize; @@ -7158,14 +7144,14 @@ void ProtocolGame::sendOutfitWindow() { } else if (outfit->lookType == 1456 || outfit->lookType == 1457) { if (player->canWear(1456, 0) || player->canWear(1457, 0)) { msg.add(outfit->lookType); - msg.addString(outfit->name, "ProtocolGame::sendOutfitWindow - outfit->name"); + msg.addString(outfit->name); msg.addByte(3); msg.addByte(0x03); ++outfitSize; } } else if (outfit->from == "store") { msg.add(outfit->lookType); - msg.addString(outfit->name, "ProtocolGame::sendOutfitWindow - outfit->name"); + msg.addString(outfit->name); msg.addByte(outfit->lookType >= 962 && outfit->lookType <= 975 ? 0 : 3); msg.addByte(0x01); msg.add(0x00); @@ -7191,12 +7177,12 @@ void ProtocolGame::sendOutfitWindow() { for (const auto &mount : mounts) { if (player->hasMount(mount)) { msg.add(mount->clientId); - msg.addString(mount->name, "ProtocolGame::sendOutfitWindow - mount->name"); + msg.addString(mount->name); msg.addByte(0x00); ++mountSize; } else if (mount->type == "store") { msg.add(mount->clientId); - msg.addString(mount->name, "ProtocolGame::sendOutfitWindow - mount->name"); + msg.addString(mount->name); msg.addByte(0x01); msg.add(0x00); ++mountSize; @@ -7225,7 +7211,7 @@ void ProtocolGame::sendOutfitWindow() { } msg.add(familiar->lookType); - msg.addString(familiar->name, "ProtocolGame::sendOutfitWindow - familiar.name"); + msg.addString(familiar->name); msg.addByte(0x00); if (++familiarSize == limitFamiliars) { break; @@ -7289,7 +7275,7 @@ void ProtocolGame::sendPodiumWindow(std::shared_ptr podium, const Position } msg.add(outfit->lookType); - msg.addString(outfit->name, "ProtocolGame::sendPodiumWindow - outfit->name"); + msg.addString(outfit->name); msg.addByte(addons); msg.addByte(0x00); if (++outfitSize == limitOutfits) { @@ -7311,7 +7297,7 @@ void ProtocolGame::sendPodiumWindow(std::shared_ptr podium, const Position for (const auto &mount : mounts) { if (player->hasMount(mount)) { msg.add(mount->clientId); - msg.addString(mount->name, "ProtocolGame::sendPodiumWindow - mount->name"); + msg.addString(mount->name); msg.addByte(0x00); if (++mountSize == limitMounts) { break; @@ -7361,8 +7347,8 @@ void ProtocolGame::sendVIP(uint32_t guid, const std::string &name, const std::st NetworkMessage msg; msg.addByte(0xD2); msg.add(guid); - msg.addString(name, "ProtocolGame::sendVIP - name"); - msg.addString(description, "ProtocolGame::sendVIP - description"); + msg.addString(name); + msg.addString(description); msg.add(std::min(10, icon)); msg.addByte(notify ? 0x01 : 0x00); msg.addByte(enumToValue(status)); @@ -7391,7 +7377,7 @@ void ProtocolGame::sendVIPGroups() { msg.addByte(vipGroups.size()); // vipGroups.size() for (const auto &vipGroup : vipGroups) { msg.addByte(vipGroup->id); - msg.addString(vipGroup->name, "ProtocolGame::sendVIP - vipGroup.name"); + msg.addString(vipGroup->name); msg.addByte(vipGroup->customizable ? 0x01 : 0x00); // 0x00 = not Customizable, 0x01 = Customizable } msg.addByte(player->vip()->getMaxGroupEntries() - vipGroups.size()); // max vip groups @@ -7486,7 +7472,7 @@ void ProtocolGame::sendPreyData(const std::unique_ptr &slot) { // Empty } else if (slot->state == PreyDataState_Active) { if (const auto mtype = g_monsters().getMonsterTypeByRaceId(slot->selectedRaceId)) { - msg.addString(mtype->name, "ProtocolGame::sendPreyData - mtype->name"); + msg.addString(mtype->name); const Outfit_t outfit = mtype->info.outfit; msg.add(outfit.lookType); if (outfit.lookType == 0) { @@ -7512,7 +7498,7 @@ void ProtocolGame::sendPreyData(const std::unique_ptr &slot) { continue; } - msg.addString(mtype->name, "ProtocolGame::sendPreyData - mtype->name"); + msg.addString(mtype->name); const Outfit_t outfit = mtype->info.outfit; msg.add(outfit.lookType); if (outfit.lookType == 0) { @@ -7537,7 +7523,7 @@ void ProtocolGame::sendPreyData(const std::unique_ptr &slot) { continue; } - msg.addString(mtype->name, "ProtocolGame::sendPreyData - mtype->name"); + msg.addString(mtype->name); const Outfit_t outfit = mtype->info.outfit; msg.add(outfit.lookType); if (outfit.lookType == 0) { @@ -7605,18 +7591,18 @@ void ProtocolGame::sendModalWindow(const ModalWindow &modalWindow) { msg.addByte(0xFA); msg.add(modalWindow.id); - msg.addString(modalWindow.title, "ProtocolGame::sendModalWindow - modalWindow.title"); - msg.addString(modalWindow.message, "ProtocolGame::sendModalWindow - modalWindow.message"); + msg.addString(modalWindow.title); + msg.addString(modalWindow.message); msg.addByte(modalWindow.buttons.size()); for (const auto &it : modalWindow.buttons) { - msg.addString(it.first, "ProtocolGame::sendModalWindow - it.first"); + msg.addString(it.first); msg.addByte(it.second); } msg.addByte(modalWindow.choices.size()); for (const auto &it : modalWindow.choices) { - msg.addString(it.first, "ProtocolGame::sendModalWindow - it.first"); + msg.addString(it.first); msg.addByte(it.second); } @@ -7656,7 +7642,7 @@ void ProtocolGame::AddCreature(NetworkMessage &msg, std::shared_ptr cr if (!oldProtocol && creature->isHealthHidden()) { msg.addString(std::string()); } else { - msg.addString(creature->getName(), "ProtocolGame::AddCreature - creature->getName()"); + msg.addString(creature->getName()); } } @@ -7875,10 +7861,9 @@ void ProtocolGame::addImbuementInfo(NetworkMessage &msg, uint16_t imbuementId) c const CategoryImbuement* categoryImbuement = g_imbuements().getCategoryByID(imbuement->getCategory()); msg.add(imbuementId); - msg.addString(baseImbuement->name + " " + imbuement->getName(), "ProtocolGame::addImbuementInfo - baseImbuement->name + " - " + imbuement->getName()"); - msg.addString(imbuement->getDescription(), "ProtocolGame::addImbuementInfo - imbuement->getDescription()"); - msg.addString(categoryImbuement->name + imbuement->getSubGroup(), "ProtocolGame::addImbuementInfo - categoryImbuement->name + imbuement->getSubGroup()"); + msg.addString(baseImbuement->name + " " + imbuement->getName()); + msg.addString(imbuement->getDescription()); + msg.addString(categoryImbuement->name + imbuement->getSubGroup()); msg.add(imbuement->getIconID()); msg.add(baseImbuement->duration); @@ -7891,7 +7876,7 @@ void ProtocolGame::addImbuementInfo(NetworkMessage &msg, uint16_t imbuementId) c for (const auto &itm : items) { const ItemType &it = Item::items[itm.first]; msg.add(itm.first); - msg.addString(it.name, "ProtocolGame::addImbuementInfo - it.name"); + msg.addString(it.name); msg.add(itm.second); } @@ -7963,7 +7948,7 @@ void ProtocolGame::sendMessageDialog(const std::string &message) { NetworkMessage msg; msg.addByte(0xED); msg.addByte(0x14); // Unknown type - msg.addString(message, "ProtocolGame::sendMessageDialog - message"); + msg.addString(message); writeToOutputBuffer(msg); } @@ -7971,7 +7956,7 @@ void ProtocolGame::sendImbuementResult(const std::string message) { NetworkMessage msg; msg.addByte(0xED); msg.addByte(0x01); - msg.addString(message, "ProtocolGame::sendImbuementResult - message"); + msg.addString(message); writeToOutputBuffer(msg); } @@ -8032,7 +8017,7 @@ void ProtocolGame::updatePartyTrackerAnalyzer(const std::shared_ptr party msg.addByte(static_cast(party->membersData.size())); for (const std::shared_ptr &analyzer : party->membersData) { msg.add(analyzer->id); - msg.addString(analyzer->name, "ProtocolGame::updatePartyTrackerAnalyzer - analyzer->name"); + msg.addString(analyzer->name); } } @@ -8068,7 +8053,7 @@ void ProtocolGame::sendKillTrackerUpdate(std::shared_ptr corpse, cons NetworkMessage msg; msg.addByte(0xD1); - msg.addString(name, "ProtocolGame::sendKillTrackerUpdate - name"); + msg.addString(name); msg.add(creatureOutfit.lookType ? creatureOutfit.lookType : 21); msg.addByte(creatureOutfit.lookType ? creatureOutfit.lookHead : 0x00); msg.addByte(creatureOutfit.lookType ? creatureOutfit.lookBody : 0x00); @@ -8136,7 +8121,7 @@ void ProtocolGame::sendUpdateInputAnalyzer(CombatType_t type, int32_t amount, st msg.addByte(ANALYZER_DAMAGE_RECEIVED); msg.add(amount); msg.addByte(clientElement); - msg.addString(target, "ProtocolGame::sendUpdateInputAnalyzer - target"); + msg.addString(target); writeToOutputBuffer(msg); } @@ -8323,9 +8308,9 @@ void ProtocolGame::AddShopItem(NetworkMessage &msg, const ShopBlock &shopBlock) // If not send "itemName" variable from the npc shop, will registered the name that is in items.xml if (shopBlock.itemName.empty()) { - msg.addString(it.name, "ProtocolGame::AddShopItem - it.name"); + msg.addString(it.name); } else { - msg.addString(shopBlock.itemName, "ProtocolGame::AddShopItem - shopBlock.itemName"); + msg.addString(shopBlock.itemName); } msg.add(it.weight); msg.add(shopBlock.itemBuyPrice == 4294967295 ? 0 : shopBlock.itemBuyPrice); @@ -8407,8 +8392,7 @@ void ProtocolGame::sendInventoryImbuements(const std::mapgetBaseID()); msg.addByte(0x01); - msg.addString(baseImbuement->name + " " + imbuement->getName(), "ProtocolGame::sendInventoryImbuements - baseImbuement->name + " - " + imbuement->getName()"); + msg.addString(baseImbuement->name + " " + imbuement->getName()); msg.add(imbuement->getIconID()); msg.add(imbuementInfo.duration); @@ -9007,9 +8991,9 @@ void ProtocolGame::sendPodiumDetails(NetworkMessage &msg, const std::vectorname, "ProtocolGame::sendPodiumDetails - mType->name"); + msg.addString(mType->name); } msg.add(monsterOutfit.lookType); if (isLookType) { diff --git a/src/server/network/protocol/protocolgame.hpp b/src/server/network/protocol/protocolgame.hpp index 2a5fde6c6c4..769771c975a 100644 --- a/src/server/network/protocol/protocolgame.hpp +++ b/src/server/network/protocol/protocolgame.hpp @@ -143,7 +143,7 @@ class ProtocolGame final : public Protocol { void parseGreet(NetworkMessage &msg); void parseBugReport(NetworkMessage &msg); - void parseDebugAssert(NetworkMessage &msg); + void parseOfferDescription(NetworkMessage &msg); void parsePreyAction(NetworkMessage &msg); void parseSendResourceBalance(); void parseRuleViolationReport(NetworkMessage &msg); diff --git a/src/server/network/protocol/protocollogin.cpp b/src/server/network/protocol/protocollogin.cpp index f8c68634f64..9cf6cc1c370 100644 --- a/src/server/network/protocol/protocollogin.cpp +++ b/src/server/network/protocol/protocollogin.cpp @@ -23,7 +23,7 @@ void ProtocolLogin::disconnectClient(const std::string &message) { auto output = OutputMessagePool::getOutputMessage(); output->addByte(0x0B); - output->addString(message, "ProtocolLogin::disconnectClient - message"); + output->addString(message); send(output); disconnect(); @@ -57,12 +57,12 @@ void ProtocolLogin::getCharacterList(const std::string &accountDescriptor, const std::ostringstream ss; ss << g_game().getMotdNum() << "\n" << motd; - output->addString(ss.str(), "ProtocolLogin::getCharacterList - ss.str()"); + output->addString(ss.str()); } // Add session key output->addByte(0x28); - output->addString(accountDescriptor + "\n" + password, "ProtocolLogin::getCharacterList - accountDescriptor + password"); + output->addString(accountDescriptor + "\n" + password); // Add char list auto [players, result] = account.getAccountPlayers(); @@ -75,8 +75,8 @@ void ProtocolLogin::getCharacterList(const std::string &accountDescriptor, const output->addByte(1); // number of worlds output->addByte(0); // world id - output->addString(g_configManager().getString(SERVER_NAME, __FUNCTION__), "ProtocolLogin::getCharacterList - _configManager().getString(SERVER_NAME)"); - output->addString(g_configManager().getString(IP, __FUNCTION__), "ProtocolLogin::getCharacterList - g_configManager().getString(IP)"); + output->addString(g_configManager().getString(SERVER_NAME, __FUNCTION__)); + output->addString(g_configManager().getString(IP, __FUNCTION__)); output->add(g_configManager().getNumber(GAME_PORT, __FUNCTION__)); @@ -86,7 +86,7 @@ void ProtocolLogin::getCharacterList(const std::string &accountDescriptor, const output->addByte(size); for (const auto &[name, deletion] : players) { output->addByte(0); - output->addString(name, "ProtocolLogin::getCharacterList - name"); + output->addString(name); } // Get premium days, check is premium and get lastday diff --git a/src/server/network/protocol/protocolstatus.cpp b/src/server/network/protocol/protocolstatus.cpp index f9ec878eda9..1e7e68e1542 100644 --- a/src/server/network/protocol/protocolstatus.cpp +++ b/src/server/network/protocol/protocolstatus.cpp @@ -167,22 +167,22 @@ void ProtocolStatus::sendInfo(uint16_t requestedInfo, const std::string &charact if (requestedInfo & REQUEST_BASIC_SERVER_INFO) { output->addByte(0x10); - output->addString(g_configManager().getString(ConfigKey_t::SERVER_NAME, __FUNCTION__), "ProtocolStatus::sendInfo - g_configManager().getString(stringConfig_t::SERVER_NAME)"); - output->addString(g_configManager().getString(IP, __FUNCTION__), "ProtocolStatus::sendInfo - g_configManager().getString(IP)"); - output->addString(std::to_string(g_configManager().getNumber(LOGIN_PORT, __FUNCTION__)), "ProtocolStatus::sendInfo - std::to_string(g_configManager().getNumber(LOGIN_PORT))"); + output->addString(g_configManager().getString(ConfigKey_t::SERVER_NAME, __FUNCTION__)); + output->addString(g_configManager().getString(IP, __FUNCTION__)); + output->addString(std::to_string(g_configManager().getNumber(LOGIN_PORT, __FUNCTION__))); } if (requestedInfo & REQUEST_OWNER_SERVER_INFO) { output->addByte(0x11); - output->addString(g_configManager().getString(OWNER_NAME, __FUNCTION__), "ProtocolStatus::sendInfo - g_configManager().getString(OWNER_NAME)"); - output->addString(g_configManager().getString(OWNER_EMAIL, __FUNCTION__), "ProtocolStatus::sendInfo - g_configManager().getString(OWNER_EMAIL)"); + output->addString(g_configManager().getString(OWNER_NAME, __FUNCTION__)); + output->addString(g_configManager().getString(OWNER_EMAIL, __FUNCTION__)); } if (requestedInfo & REQUEST_MISC_SERVER_INFO) { output->addByte(0x12); - output->addString(g_configManager().getString(SERVER_MOTD, __FUNCTION__), "ProtocolStatus::sendInfo - g_configManager().getString(SERVER_MOTD)"); - output->addString(g_configManager().getString(LOCATION, __FUNCTION__), "ProtocolStatus::sendInfo - g_configManager().getString(LOCATION)"); - output->addString(g_configManager().getString(URL, __FUNCTION__), "ProtocolStatus::sendInfo - g_configManager().getString(URL)"); + output->addString(g_configManager().getString(SERVER_MOTD, __FUNCTION__)); + output->addString(g_configManager().getString(LOCATION, __FUNCTION__)); + output->addString(g_configManager().getString(URL, __FUNCTION__)); output->add((OTSYS_TIME() - ProtocolStatus::start) / 1000); } @@ -195,8 +195,8 @@ void ProtocolStatus::sendInfo(uint16_t requestedInfo, const std::string &charact if (requestedInfo & REQUEST_MAP_INFO) { output->addByte(0x30); - output->addString(g_configManager().getString(MAP_NAME, __FUNCTION__), "ProtocolStatus::sendInfo - g_configManager().getString(MAP_NAME)"); - output->addString(g_configManager().getString(MAP_AUTHOR, __FUNCTION__), "ProtocolStatus::sendInfo - g_configManager().getString(MAP_AUTHOR)"); + output->addString(g_configManager().getString(MAP_NAME, __FUNCTION__)); + output->addString(g_configManager().getString(MAP_AUTHOR, __FUNCTION__)); uint32_t mapWidth, mapHeight; g_game().getMapDimensions(mapWidth, mapHeight); output->add(mapWidth); @@ -209,7 +209,7 @@ void ProtocolStatus::sendInfo(uint16_t requestedInfo, const std::string &charact const auto players = g_game().getPlayers(); output->add(players.size()); for (const auto &it : players) { - output->addString(it.second->getName(), "ProtocolStatus::sendInfo - it.second->getName()"); + output->addString(it.second->getName()); output->add(it.second->getLevel()); } } @@ -225,9 +225,9 @@ void ProtocolStatus::sendInfo(uint16_t requestedInfo, const std::string &charact if (requestedInfo & REQUEST_SERVER_SOFTWARE_INFO) { output->addByte(0x23); // server software info - output->addString(ProtocolStatus::SERVER_NAME, "ProtocolStatus::sendInfo - ProtocolStatus::SERVER_NAME"); - output->addString(ProtocolStatus::SERVER_VERSION, "ProtocolStatus::sendInfo - ProtocolStatus::SERVER_VERSION)"); - output->addString(fmt::format("{}.{}", CLIENT_VERSION_UPPER, CLIENT_VERSION_LOWER), "ProtocolStatus::sendInfo - fmt::format(CLIENT_VERSION_UPPER, CLIENT_VERSION_LOWER)"); + output->addString(ProtocolStatus::SERVER_NAME); + output->addString(ProtocolStatus::SERVER_VERSION); + output->addString(fmt::format("{}.{}", CLIENT_VERSION_UPPER, CLIENT_VERSION_LOWER)); } send(output); disconnect(); diff --git a/src/utils/const.hpp b/src/utils/const.hpp index c3f82df7ff7..4cc296e4a7e 100644 --- a/src/utils/const.hpp +++ b/src/utils/const.hpp @@ -35,6 +35,8 @@ static constexpr int32_t STORAGEVALUE_HAZARDCOUNT = 112550; // Wheel of destiny static constexpr int32_t STORAGEVALUE_GIFT_OF_LIFE_COOLDOWN_WOD = 43200; +constexpr double SCALING_BASE = 10.0; + // Reserved player storage key ranges; // [10000000 - 20000000]; static constexpr int32_t PSTRG_RESERVED_RANGE_START = 10000000; diff --git a/tests/build_and_run.sh b/tests/build_and_run.sh index 3d5531ebf0b..ac4ccad512c 100755 --- a/tests/build_and_run.sh +++ b/tests/build_and_run.sh @@ -3,10 +3,12 @@ docker-compose down --rmi all -v --remove-orphans docker-compose up --build -d cd .. -mkdir build -cd build -cmake -DPACKAGE_TESTS=On .. ; make -j`nproc` -./tests/canary_unittest --reporter compact --success -d yes +if [ ! -d "build" ]; then + mkdir build +fi +cd build || exit +cmake -DCMAKE_BUILD_TYPE=Debug -DPACKAGE_TESTS=On .. ; make -j"$(nproc)" +./tests/unit/canary_ut --reporter compact --success cd .. -cd tests +cd tests || exit docker-compose down --rmi all -v --remove-orphans diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 8d234a676a2..5da4ec590ce 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -4,4 +4,5 @@ add_subdirectory(account) add_subdirectory(kv) add_subdirectory(lib) add_subdirectory(security) +add_subdirectory(server) add_subdirectory(utils) diff --git a/tests/unit/server/CMakeLists.txt b/tests/unit/server/CMakeLists.txt new file mode 100644 index 00000000000..ec98d50a3f9 --- /dev/null +++ b/tests/unit/server/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(canary_ut PRIVATE + network/message/networkmessage_test.cpp +) diff --git a/tests/unit/server/network/message/networkmessage_test.cpp b/tests/unit/server/network/message/networkmessage_test.cpp new file mode 100644 index 00000000000..f1ec904a3bf --- /dev/null +++ b/tests/unit/server/network/message/networkmessage_test.cpp @@ -0,0 +1,144 @@ +#include "pch.hpp" + +#include + +#include "lib/logging/in_memory_logger.hpp" + +#include "server/network/message/networkmessage.hpp" +#include "utils/tools.hpp" + +using namespace boost::ut; + +// Define a test suite for NetworkMessage +suite<"networkmessage"> networkMessageTest = [] { + di::extension::injector<> injector {}; + DI::setTestContainer(&InMemoryLogger::install(injector)); + auto& logger = dynamic_cast(injector.create()); + + test("NetworkMessage::addByte and getByte") = [&]() { + NetworkMessage msg; + uint8_t byteToAdd = 100; + msg.addByte(byteToAdd); + msg.setBufferPosition(NetworkMessage::INITIAL_BUFFER_POSITION); + auto byte = msg.getByte(); + expect(eq(byte, byteToAdd)) << "Expected: " << byteToAdd << ", Got: " << byte; + }; + + test("NetworkMessage::addString and getString") = [&]() { + NetworkMessage msg; + std::string testStr = "TestString"; + msg.addString(testStr); + msg.setBufferPosition(NetworkMessage::INITIAL_BUFFER_POSITION); + std::string retrievedStr = msg.getString(); + expect(eq(retrievedStr, testStr)) << "Expected: \"" << testStr << "\", Got: \"" << retrievedStr << "\""; + }; + + test("NetworkMessage::addString should handle empty string") = [&]() { + NetworkMessage msg; + msg.addString(""); + msg.setBufferPosition(NetworkMessage::INITIAL_BUFFER_POSITION); + expect(eq(msg.getString(), std::string {})) << "Expected to retrieve an empty string"; + }; + + test("NetworkMessage::addString should fail with oversized string") = [&]() { + NetworkMessage msg; + std::string oversizedString(NETWORKMESSAGE_MAXSIZE + 1, 'a'); + msg.addString(oversizedString); + msg.setBufferPosition(NetworkMessage::INITIAL_BUFFER_POSITION); + expect(eq(msg.getString(), std::string {})) << "Expected to retrieve an empty string due to oversized input"; + }; + + test("NetworkMessage::canAdd should return false when exceeding max size") = [&]() { + NetworkMessage msg; + expect(not msg.canAdd(NETWORKMESSAGE_MAXSIZE)) << "Should have enough space in buffer"; + expect(not msg.canAdd(NETWORKMESSAGE_MAXSIZE + 1)) << "Should not be able to add data exceeding the max buffer size"; + }; + + test("NetworkMessage::addDouble and getDouble") = [&]() { + NetworkMessage msg; + double testValue = 123.123; + uint8_t precision = 3; + msg.addDouble(testValue, precision); + msg.setBufferPosition(NetworkMessage::INITIAL_BUFFER_POSITION); + double retrievedValue = msg.getDouble(); + expect(abs(retrievedValue - testValue) < 1e-6) << "Expected: " << testValue << ", Got: " << retrievedValue; + }; + + test("NetworkMessage::addPosition and getPosition") = [&]() { + NetworkMessage msg; + Position pos { 100, 200, 7 }; + msg.addPosition(pos); + msg.setBufferPosition(NetworkMessage::INITIAL_BUFFER_POSITION); + Position retrievedPos = msg.getPosition(); + expect(eq(retrievedPos, pos)) << "Expected to retrieve the same position values"; + }; + + test("NetworkMessage::reset should clear buffer") = [&]() { + NetworkMessage msg; + msg.addByte(0x64); + msg.reset(); + expect(eq(msg.getLength(), 0)) << "Expected the message length to be zero after reset"; + }; + + test("NetworkMessage::append should merge messages correctly") = [&]() { + NetworkMessage msg1, msg2; + + // Adding initial byte and string to msg1 + msg1.addByte(1); // Byte value 1 + msg1.addString("Hello"); // String value "Hello" + // Adding initial byte and string to msg2 + msg2.addByte(2); // Byte value 2 + msg2.addString("World"); // String value "World" + // Append msg2 to msg1 + msg1.append(msg2); + msg1.setBufferPosition(NetworkMessage::INITIAL_BUFFER_POSITION); // Reset read position to start + // Verify the first byte (msg1) + uint8_t byte1 = msg1.getByte(); + expect(eq(byte1, 1)) << "Expected the first byte of the first message (1)"; + // Verify the first string (msg1) + std::string str1 = msg1.getString(); + expect(eq(str1, std::string("Hello"))) << "Expected the first string of the first message"; + // Verify the second byte (msg2) + uint8_t byte2 = msg1.getByte(); + expect(eq(byte2, 2)) << "Expected the first byte of the second message (2)"; + // Verify the second string (msg2) + std::string str2 = msg1.getString(); + expect(eq(str2, std::string("World"))) << "Expected the first string of the second message"; + }; + + test("NetworkMessage::getString should handle out-of-bounds access safely") = [&]() { + NetworkMessage msg; + std::string testStr = "Short"; + msg.addString(testStr); + + // Move the position to simulate incomplete data read + msg.setBufferPosition(msg.getBufferPosition() + 10); + expect(eq(msg.getString(), std::string {})) << "Expected empty string due to out-of-bounds access"; + }; + + test("NetworkMessage::decodeHeader should correctly decode the header") = [&]() { + NetworkMessage msg; + msg.addByte(0x12); + msg.addByte(0x34); + + msg.setBufferPosition(NetworkMessage::INITIAL_BUFFER_POSITION); + int32_t header = msg.decodeHeader(); + expect(eq(header, 0x3412)) << "Expected header to be decoded correctly"; + }; + + test("NetworkMessage::addBytes and validate content") = [&]() { + NetworkMessage msg; + std::string testData = "testBytes"; + + // Add bytes to the buffer + msg.addBytes(testData.data(), testData.size()); + // Set buffer position to the initial position for reading the added data + msg.setBufferPosition(NetworkMessage::INITIAL_BUFFER_POSITION); + // Verify the content of the buffer before extracting the data + auto buffer = msg.getBuffer(); + std::string extractedData(buffer + NetworkMessage::INITIAL_BUFFER_POSITION, + buffer + NetworkMessage::INITIAL_BUFFER_POSITION + testData.size()); + // Check if the extracted data matches the added data + expect(eq(extractedData, testData)) << "Expected the same bytes added"; + }; +};