diff --git a/src/io/functions/iologindata_load_player.cpp b/src/io/functions/iologindata_load_player.cpp index 80881db361c..cb24c092ebb 100644 --- a/src/io/functions/iologindata_load_player.cpp +++ b/src/io/functions/iologindata_load_player.cpp @@ -734,6 +734,10 @@ void IOLoginDataLoad::loadPlayerPreyClass(std::shared_ptr player, DBResu query << "SELECT * FROM `player_prey` WHERE `player_id` = " << player->getGUID(); if ((result = db.storeQuery(query.str()))) { do { + auto selectedRaceId = result->getNumber("raceid"); + if (selectedRaceId == 0) { + continue; + } auto slot = std::make_unique(static_cast(result->getNumber("slot"))); auto state = static_cast(result->getNumber("state")); if (slot->id == PreySlot_Two && state == PreyDataState_Locked) { @@ -745,7 +749,7 @@ void IOLoginDataLoad::loadPlayerPreyClass(std::shared_ptr player, DBResu } else { slot->state = state; } - slot->selectedRaceId = result->getNumber("raceid"); + slot->selectedRaceId = selectedRaceId; slot->option = static_cast(result->getNumber("option")); slot->bonus = static_cast(result->getNumber("bonus_type")); slot->bonusRarity = static_cast(result->getNumber("bonus_rarity")); @@ -781,6 +785,10 @@ void IOLoginDataLoad::loadPlayerTaskHuntingClass(std::shared_ptr player, query << "SELECT * FROM `player_taskhunt` WHERE `player_id` = " << player->getGUID(); if ((result = db.storeQuery(query.str()))) { do { + auto selectedRaceId = result->getNumber("raceid"); + if (selectedRaceId == 0) { + continue; + } auto slot = std::make_unique(static_cast(result->getNumber("slot"))); auto state = static_cast(result->getNumber("state")); if (slot->id == PreySlot_Two && state == PreyTaskDataState_Locked) { @@ -792,7 +800,7 @@ void IOLoginDataLoad::loadPlayerTaskHuntingClass(std::shared_ptr player, } else { slot->state = state; } - slot->selectedRaceId = result->getNumber("raceid"); + slot->selectedRaceId = selectedRaceId; slot->upgrade = result->getNumber("upgrade"); slot->rarity = static_cast(result->getNumber("rarity")); slot->currentKills = result->getNumber("kills"); @@ -827,7 +835,7 @@ void IOLoginDataLoad::loadPlayerForgeHistory(std::shared_ptr player, DBR std::ostringstream query; query << "SELECT * FROM `forge_history` WHERE `player_id` = " << player->getGUID(); - if (result = Database::getInstance().storeQuery(query.str())) { + if ((result = Database::getInstance().storeQuery(query.str()))) { do { auto actionEnum = magic_enum::enum_value(result->getNumber("action_type")); ForgeHistory history; @@ -853,7 +861,7 @@ void IOLoginDataLoad::loadPlayerBosstiary(std::shared_ptr player, DBResu std::ostringstream query; query << "SELECT * FROM `player_bosstiary` WHERE `player_id` = " << player->getGUID(); - if (result = Database::getInstance().storeQuery(query.str())) { + if ((result = Database::getInstance().storeQuery(query.str()))) { do { player->setSlotBossId(1, result->getNumber("bossIdSlotOne")); player->setSlotBossId(2, result->getNumber("bossIdSlotTwo")); diff --git a/src/io/functions/iologindata_save_player.cpp b/src/io/functions/iologindata_save_player.cpp index a5caadd709c..f320a67ca22 100644 --- a/src/io/functions/iologindata_save_player.cpp +++ b/src/io/functions/iologindata_save_player.cpp @@ -82,7 +82,6 @@ bool IOLoginDataSave::saveItems(std::shared_ptr player, const ItemBlockL const ContainerBlock &cb = queue.front(); std::shared_ptr container = cb.first; int32_t parentId = cb.second; - queue.pop_front(); if (!container) { continue; // Check for null container @@ -137,6 +136,9 @@ bool IOLoginDataSave::saveItems(std::shared_ptr player, const ItemBlockL return false; } } + + // Removes the object after processing everything, avoiding memory usage after freeing + queue.pop_front(); } // Execute query diff --git a/src/io/iologindata.cpp b/src/io/iologindata.cpp index d834f9d0984..17816f969de 100644 --- a/src/io/iologindata.cpp +++ b/src/io/iologindata.cpp @@ -202,15 +202,21 @@ bool IOLoginData::loadPlayer(std::shared_ptr player, DBResult_ptr result } bool IOLoginData::savePlayer(std::shared_ptr player) { - bool success = DBTransaction::executeWithinTransaction([player]() { - return savePlayerGuard(player); - }); + try { + bool success = DBTransaction::executeWithinTransaction([player]() { + return savePlayerGuard(player); + }); + + if (!success) { + g_logger().error("[{}] Error occurred saving player", __FUNCTION__); + } - if (!success) { - g_logger().error("[{}] Error occurred saving player", __FUNCTION__); + return success; + } catch (const DatabaseException &e) { + g_logger().error("[{}] Exception occurred: {}", __FUNCTION__, e.what()); } - return success; + return false; } bool IOLoginData::savePlayerGuard(std::shared_ptr player) { diff --git a/src/security/argon.cpp b/src/security/argon.cpp index 1bed157e418..52fa4b0c94b 100644 --- a/src/security/argon.cpp +++ b/src/security/argon.cpp @@ -25,7 +25,7 @@ void Argon2::updateConstants() { } uint32_t Argon2::parseBitShift(const std::string &bitShiftStr) const { - static const std::regex pattern(R"(^\s*(\d+)\s*<<\s*(\d+)\s*$)"); + static const std::regex pattern(R"(^\s*(\d+)\s*<<\s*(\d+)\s*$)", std::regex_constants::ECMAScript | std::regex_constants::icase); std::smatch match; if (!std::regex_match(bitShiftStr, match, pattern)) { diff --git a/src/server/network/message/networkmessage.cpp b/src/server/network/message/networkmessage.cpp index edce96111cb..5b7c8a143b9 100644 --- a/src/server/network/message/networkmessage.cpp +++ b/src/server/network/message/networkmessage.cpp @@ -160,8 +160,7 @@ void NetworkMessage::addString(const std::string &value, const std::source_locat 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); + std::ranges::copy(value, buffer.begin() + info.position); info.position += stringLen; info.length += stringLen; } @@ -211,8 +210,7 @@ void NetworkMessage::addBytes(const char* bytes, size_t size) { return; } - 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); + std::ranges::copy(std::span(bytes, size), buffer.begin() + info.position); info.position += size; info.length += size; } @@ -293,13 +291,10 @@ void NetworkMessage::append(const NetworkMessage &other) { 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); + std::ranges::copy( + std::span(other.getBuffer() + otherStartPos, otherLength), + buffer.data() + info.position + ); // Update the buffer information info.length += otherLength; diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 7ba07d13e4d..e924b489c25 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -6091,16 +6091,17 @@ void ProtocolGame::sendTradeItemRequest(const std::string &traderName, std::shar std::list> listContainer { tradeContainer }; std::list> itemList { tradeContainer }; while (!listContainer.empty()) { - std::shared_ptr container = listContainer.front(); - listContainer.pop_front(); - - for (const std::shared_ptr &containerItem : container->getItemList()) { - std::shared_ptr tmpContainer = containerItem->getContainer(); + const auto &container = listContainer.front(); + for (const auto &containerItem : container->getItemList()) { + const auto &tmpContainer = containerItem->getContainer(); if (tmpContainer) { listContainer.push_back(tmpContainer); } itemList.push_back(containerItem); } + + // Removes the object after processing everything, avoiding memory usage after freeing + listContainer.pop_front(); } msg.addByte(itemList.size()); diff --git a/src/server/network/webhook/webhook.cpp b/src/server/network/webhook/webhook.cpp index bd0ab9a0c4c..6d28e263e54 100644 --- a/src/server/network/webhook/webhook.cpp +++ b/src/server/network/webhook/webhook.cpp @@ -147,7 +147,7 @@ void Webhook::sendWebhook() { return; } - auto task = webhooks.front(); + const auto &task = webhooks.front(); std::string response_body; auto response_code = sendRequest(task->url.c_str(), task->payload.c_str(), &response_body); @@ -162,8 +162,6 @@ void Webhook::sendWebhook() { return; } - webhooks.pop_front(); - if (response_code >= 300) { g_logger().error( "Failed to send webhook message, error code: {} response body: {} request body: {}", @@ -176,4 +174,7 @@ void Webhook::sendWebhook() { } g_logger().debug("Webhook successfully sent to {}", task->url); + + // Removes the object after processing everything, avoiding memory usage after freeing + webhooks.pop_front(); } diff --git a/src/utils/tools.cpp b/src/utils/tools.cpp index 8df1fde1065..df340a67f39 100644 --- a/src/utils/tools.cpp +++ b/src/utils/tools.cpp @@ -1952,3 +1952,18 @@ uint8_t convertWheelGemAffinityToDomain(uint8_t affinity) { return 0; } } + +bool caseInsensitiveCompare(std::string_view str1, std::string_view str2, size_t length /*= std::string_view::npos*/) { + if (length == std::string_view::npos) { + if (str1.size() != str2.size()) { + return false; + } + length = str1.size(); + } else { + length = std::min({ length, str1.size(), str2.size() }); + } + + return std::equal(str1.begin(), str1.begin() + length, str2.begin(), [](char c1, char c2) { + return std::tolower(static_cast(c1)) == std::tolower(static_cast(c2)); + }); +} diff --git a/src/utils/tools.hpp b/src/utils/tools.hpp index a4426a066a8..7e04132b36e 100644 --- a/src/utils/tools.hpp +++ b/src/utils/tools.hpp @@ -220,3 +220,5 @@ template (value); } + +bool caseInsensitiveCompare(std::string_view str1, std::string_view str2, size_t length = std::string_view::npos); diff --git a/vcproj/canary.vcxproj b/vcproj/canary.vcxproj index d2d8e1646c6..135389e491d 100644 --- a/vcproj/canary.vcxproj +++ b/vcproj/canary.vcxproj @@ -516,7 +516,7 @@ true true Default - /Zc:__cplusplus /fsanitize=address %(AdditionalOptions) + /Zc:__cplusplus /fsanitize=address /utf-8 %(AdditionalOptions) _DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION;%(PreprocessorDefinitions) Use @@ -552,7 +552,7 @@ true true true - /Zc:__cplusplus %(AdditionalOptions) + /Zc:__cplusplus /utf-8 %(AdditionalOptions) _DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION;NDEBUG;%(PreprocessorDefinitions) Use diff --git a/vcproj/settings.props b/vcproj/settings.props index 6f98969614d..8c6bc887fbc 100644 --- a/vcproj/settings.props +++ b/vcproj/settings.props @@ -8,59 +8,37 @@ _WIN32_WINNT=0x0501; BUILD_TYPE="RelWithDebInfo"; - + comctl32.lib; User32.lib; WS2_32.lib; pugixml.lib; - libprotobuf.lib; lua51.lib; mpir.lib; libmariadb.lib; + abseil_dll.lib; + argon2.lib; + + + $(CANARY_COMMON_LIBDEPS); + libprotobuf.lib; zlib.lib; libcurl.lib; fmt.lib; spdlog.lib; - abseil_dll.lib; - argon2.lib; - opentelemetry_common.lib; - opentelemetry_exporter_in_memory.lib; - opentelemetry_exporter_ostream_logs.lib; - opentelemetry_exporter_ostream_metrics.lib; - opentelemetry_exporter_ostream_span.lib; - opentelemetry_exporter_otlp_http.lib; - opentelemetry_exporter_otlp_http_client.lib; - opentelemetry_exporter_otlp_http_log.lib; - opentelemetry_exporter_otlp_http_metric.lib; - opentelemetry_exporter_prometheus.lib; - opentelemetry_http_client_curl.lib; - opentelemetry_logs.lib; - opentelemetry_metrics.lib; - opentelemetry_otlp_recordable.lib; - opentelemetry_proto.lib; - opentelemetry_resources.lib; - opentelemetry_trace.lib; - opentelemetry_version.lib; - prometheus-cpp-core.lib; - prometheus-cpp-pull.lib; - civetweb.lib; - civetweb-cpp.lib - comctl32.lib; - User32.lib; - WS2_32.lib; - pugixml.lib; + $(CANARY_COMMON_LIBDEPS); libprotobufd.lib; - lua51.lib; - mpir.lib; - libmariadb.lib; zlibd.lib; libcurl-d.lib; fmtd.lib; spdlogd.lib; - abseil_dll.lib; - argon2.lib; + + + + + opentelemetry_common.lib; opentelemetry_exporter_in_memory.lib; opentelemetry_exporter_ostream_logs.lib; @@ -79,13 +57,19 @@ opentelemetry_resources.lib; opentelemetry_trace.lib; opentelemetry_version.lib; + prometheus-cpp-core.lib; + prometheus-cpp-pull; civetweb.lib; - civetweb-cpp.lib - + civetweb-cpp.lib; + + $(CANARY_LIBDEPS);$(OPENTELEMETRY_LIBS) + $(CANARY_LIBDEPS_D);$(OPENTELEMETRY_LIBS) + true + Level3 @@ -101,6 +85,7 @@ mainCRTStartup + $(PREPROCESSOR_DEFS)