From 511672c5cb23a1c90d0c181c68b4741bb7930775 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 16 Dec 2023 10:27:06 -0800 Subject: [PATCH 1/3] fix: general crashes (#1336) * Fix crashes fix crash with chat filter fix ldf_config being empty in database on windows debug * WorldServer: Fix further crashes on windows address multi threaded signal handling on worldservers Remove iterator invalidation code in zone manager --- dGame/User.cpp | 4 ++++ dGame/User.h | 4 ++-- dGame/dGameMessages/GameMessages.cpp | 2 +- dNet/ClientPackets.cpp | 10 ++++------ dWorldServer/WorldServer.cpp | 15 ++++++++++++--- dZoneManager/dZoneManager.cpp | 2 -- 6 files changed, 23 insertions(+), 14 deletions(-) diff --git a/dGame/User.cpp b/dGame/User.cpp index ce440bd7..0b2c3c3f 100644 --- a/dGame/User.cpp +++ b/dGame/User.cpp @@ -110,3 +110,7 @@ void User::UserOutOfSync() { Game::server->Disconnect(this->m_SystemAddress, eServerDisconnectIdentifiers::PLAY_SCHEDULE_TIME_DONE); } } + +void User::UpdateBestFriendValue(const std::string_view playerName, const bool newValue) { + m_IsBestFriendMap[playerName.data()] = newValue; +} diff --git a/dGame/User.h b/dGame/User.h index 3201538e..5d9ea8f1 100644 --- a/dGame/User.h +++ b/dGame/User.h @@ -43,8 +43,8 @@ public: bool GetLastChatMessageApproved() { return m_LastChatMessageApproved; } void SetLastChatMessageApproved(bool approved) { m_LastChatMessageApproved = approved; } - std::unordered_map GetIsBestFriendMap() { return m_IsBestFriendMap; } - void SetIsBestFriendMap(std::unordered_map mapToSet) { m_IsBestFriendMap = mapToSet; } + const std::unordered_map& GetIsBestFriendMap() { return m_IsBestFriendMap; } + void UpdateBestFriendValue(const std::string_view playerName, const bool newValue); bool GetIsMuted() const; diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index fd174a2b..51860d44 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -5578,7 +5578,7 @@ void GameMessages::HandleModularBuildFinish(RakNet::BitStream* inStream, Entity* std::unique_ptr stmt(Database::Get()->CreatePreppedStmt("INSERT INTO ugc_modular_build (ugc_id, ldf_config, character_id) VALUES (?,?,?)")); stmt->setUInt64(1, newIdBig); - stmt->setString(2, GeneralUtils::UTF16ToWTF8(modules)); + stmt->setString(2, GeneralUtils::UTF16ToWTF8(modules).c_str()); auto* pCharacter = character->GetCharacter(); pCharacter ? stmt->setUInt(3, pCharacter->GetID()) : stmt->setNull(3, sql::DataType::BIGINT); stmt->execute(); diff --git a/dNet/ClientPackets.cpp b/dNet/ClientPackets.cpp index cf405053..47513a66 100644 --- a/dNet/ClientPackets.cpp +++ b/dNet/ClientPackets.cpp @@ -359,8 +359,8 @@ void ClientPackets::HandleChatModerationRequest(const SystemAddress& sysAddr, Pa idOfReceiver = characterIdFetch->id; } } - - if (user->GetIsBestFriendMap().find(receiver) == user->GetIsBestFriendMap().end() && idOfReceiver != LWOOBJID_EMPTY) { + const auto& bffMap = user->GetIsBestFriendMap(); + if (bffMap.find(receiver) == bffMap.end() && idOfReceiver != LWOOBJID_EMPTY) { auto bffInfo = Database::Get()->GetBestFriendStatus(entity->GetObjectID(), idOfReceiver); if (bffInfo) { @@ -368,11 +368,9 @@ void ClientPackets::HandleChatModerationRequest(const SystemAddress& sysAddr, Pa } if (isBestFriend) { - auto tmpBestFriendMap = user->GetIsBestFriendMap(); - tmpBestFriendMap[receiver] = true; - user->SetIsBestFriendMap(tmpBestFriendMap); + user->UpdateBestFriendValue(receiver, true); } - } else if (user->GetIsBestFriendMap().find(receiver) != user->GetIsBestFriendMap().end()) { + } else if (bffMap.find(receiver) != bffMap.end()) { isBestFriend = true; } } diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index f916e40c..5fc0393a 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -18,6 +18,7 @@ #include "PerformanceManager.h" #include "Diagnostics.h" #include "BinaryPathFinder.h" +#include "dPlatforms.h" //RakNet includes: #include "RakNetDefines.h" @@ -1284,12 +1285,14 @@ void WorldShutdownProcess(uint32_t zoneId) { } void WorldShutdownSequence() { - if (Game::shouldShutdown || worldShutdownSequenceComplete) { + Game::shouldShutdown = true; +#ifndef DARKFLAME_PLATFORM_WIN32 + if (Game::shouldShutdown || worldShutdownSequenceComplete) +#endif + { return; } - Game::shouldShutdown = true; - LOG("Zone (%i) instance (%i) shutting down outside of main loop!", Game::server->GetZoneID(), instanceID); WorldShutdownProcess(Game::server->GetZoneID()); FinalizeShutdown(); @@ -1302,11 +1305,17 @@ void FinalizeShutdown() { Metrics::Clear(); Database::Destroy("WorldServer"); if (Game::chatFilter) delete Game::chatFilter; + Game::chatFilter = nullptr; if (Game::zoneManager) delete Game::zoneManager; + Game::zoneManager = nullptr; if (Game::server) delete Game::server; + Game::server = nullptr; if (Game::config) delete Game::config; + Game::config = nullptr; if (Game::entityManager) delete Game::entityManager; + Game::entityManager = nullptr; if (Game::logger) delete Game::logger; + Game::logger = nullptr; worldShutdownSequenceComplete = true; diff --git a/dZoneManager/dZoneManager.cpp b/dZoneManager/dZoneManager.cpp index 137a9cab..4aaa911d 100644 --- a/dZoneManager/dZoneManager.cpp +++ b/dZoneManager/dZoneManager.cpp @@ -79,8 +79,6 @@ dZoneManager::~dZoneManager() { delete p.second; p.second = nullptr; } - - m_Spawners.erase(p.first); } if (m_WorldConfig) delete m_WorldConfig; } From 24c236124864619c707ad6f967bbef7471ac38fd Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 16 Dec 2023 10:27:14 -0800 Subject: [PATCH 2/3] fix: achievements counting twice when accepted (#1337) Tested that new achievements progress exactly once Tested that already accepted achievements progress as expeected Tested that tiered achievements only count the progress to the current tier and not the next one as well Update MissionComponent.cpp --- dGame/dComponents/MissionComponent.cpp | 29 +++++++++++++------------- dGame/dComponents/MissionComponent.h | 2 +- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/dGame/dComponents/MissionComponent.cpp b/dGame/dComponents/MissionComponent.cpp index d7da29d9..277882bf 100644 --- a/dGame/dComponents/MissionComponent.cpp +++ b/dGame/dComponents/MissionComponent.cpp @@ -145,8 +145,13 @@ void MissionComponent::RemoveMission(uint32_t missionId) { } void MissionComponent::Progress(eMissionTaskType type, int32_t value, LWOOBJID associate, const std::string& targets, int32_t count, bool ignoreAchievements) { - for (const auto& pair : m_Missions) { - auto* mission = pair.second; + std::vector acceptedAchievements; + if (count > 0 && !ignoreAchievements) { + acceptedAchievements = LookForAchievements(type, value, true, associate, targets, count); + } + + for (const auto& [id, mission] : m_Missions) { + if (!mission || std::find(acceptedAchievements.begin(), acceptedAchievements.end(), mission->GetMissionId()) != acceptedAchievements.end()) continue; if (mission->IsAchievement() && ignoreAchievements) continue; @@ -154,10 +159,6 @@ void MissionComponent::Progress(eMissionTaskType type, int32_t value, LWOOBJID a mission->Progress(type, value, associate, targets, count); } - - if (count > 0 && !ignoreAchievements) { - LookForAchievements(type, value, true, associate, targets, count); - } } void MissionComponent::ForceProgress(const uint32_t missionId, const uint32_t taskId, const int32_t value, const bool acceptMission) { @@ -282,12 +283,12 @@ bool MissionComponent::GetMissionInfo(uint32_t missionId, CDMissions& result) { #define MISSION_NEW_METHOD -bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value, bool progress, LWOOBJID associate, const std::string& targets, int32_t count) { +const std::vector MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value, bool progress, LWOOBJID associate, const std::string& targets, int32_t count) { #ifdef MISSION_NEW_METHOD // Query for achievments, using the cache const auto& result = QueryAchievements(type, value, targets); - bool any = false; + std::vector acceptedAchievements; for (const uint32_t missionID : result) { // Check if we already have this achievement @@ -309,7 +310,7 @@ bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value, instance->Accept(); - any = true; + acceptedAchievements.push_back(missionID); if (progress) { // Progress mission to bring it up to speed @@ -317,7 +318,7 @@ bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value, } } - return any; + return acceptedAchievements; #else auto* missionTasksTable = CDClientManager::Instance().GetTable(); auto* missionsTable = CDClientManager::Instance().GetTable(); @@ -326,7 +327,7 @@ bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value, return entry.taskType == static_cast(type); }); - auto any = false; + std::vector acceptedAchievements; for (const auto& task : tasks) { if (GetMission(task.id) != nullptr) { @@ -380,14 +381,14 @@ bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value, instance->Accept(); - any = true; + acceptedAchievements.push_back(mission.id); if (progress) { instance->Progress(type, value, associate, targets, count); } } - return any; + return acceptedAchievements; #endif } @@ -499,7 +500,7 @@ bool MissionComponent::RequiresItem(const LOT lot) { const auto required = LookForAchievements(eMissionTaskType::GATHER, lot, false); - return required; + return !required.empty(); } diff --git a/dGame/dComponents/MissionComponent.h b/dGame/dComponents/MissionComponent.h index e82b5b67..37d5cd84 100644 --- a/dGame/dComponents/MissionComponent.h +++ b/dGame/dComponents/MissionComponent.h @@ -141,7 +141,7 @@ public: * @param count the number of values to progress by (differs by task type) * @return true if a achievement was accepted, false otherwise */ - bool LookForAchievements(eMissionTaskType type, int32_t value, bool progress = true, LWOOBJID associate = LWOOBJID_EMPTY, const std::string& targets = "", int32_t count = 1); + const std::vector LookForAchievements(eMissionTaskType type, int32_t value, bool progress = true, LWOOBJID associate = LWOOBJID_EMPTY, const std::string& targets = "", int32_t count = 1); /** * Checks if there's a mission active that requires the collection of the specified LOT From e2391665b94017cc0b58618a6d3e3bf414ab3ab2 Mon Sep 17 00:00:00 2001 From: jadebenn Date: Sat, 16 Dec 2023 19:35:16 -0600 Subject: [PATCH 3/3] imagination costs that equal your capacity no longer abort qbs (#1338) --- dGame/dComponents/RebuildComponent.cpp | 9 ++++----- dGame/dComponents/RebuildComponent.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/dGame/dComponents/RebuildComponent.cpp b/dGame/dComponents/RebuildComponent.cpp index 5359dee0..bcdf4f70 100644 --- a/dGame/dComponents/RebuildComponent.cpp +++ b/dGame/dComponents/RebuildComponent.cpp @@ -197,18 +197,17 @@ void RebuildComponent::Update(float deltaTime) { DestroyableComponent* destComp = builder->GetComponent(); if (!destComp) break; - int newImagination = destComp->GetImagination(); - ++m_DrainedImagination; - --newImagination; + const int32_t imaginationCostRemaining = m_TakeImagination - m_DrainedImagination; + + const int32_t newImagination = destComp->GetImagination() - 1; destComp->SetImagination(newImagination); Game::entityManager->SerializeEntity(builder); - if (newImagination <= 0) { + if (newImagination <= 0 && imaginationCostRemaining > 0) { CancelRebuild(builder, eQuickBuildFailReason::OUT_OF_IMAGINATION, true); break; } - } if (m_Timer >= m_CompleteTime && m_DrainedImagination >= m_TakeImagination) { diff --git a/dGame/dComponents/RebuildComponent.h b/dGame/dComponents/RebuildComponent.h index bb097edd..b67747aa 100644 --- a/dGame/dComponents/RebuildComponent.h +++ b/dGame/dComponents/RebuildComponent.h @@ -285,7 +285,7 @@ private: float m_CompleteTime = 0; /** - * The imagination that's deducted when compeleting the rebuild + * The imagination that's deducted when completing the rebuild */ int m_TakeImagination = 0;