From 6a6573e339c665d50217e5c8aa1d9c35aab96534 Mon Sep 17 00:00:00 2001 From: Emagi Date: Thu, 31 Jul 2025 18:38:39 -0400 Subject: [PATCH] Addressing a number of coincidental lock conditions with removing a dead spawn (out of order), clearing hate (deadlock due to early dead spawn removal), saving a player to database (before player loaded) --- source/WorldServer/NPC_AI.h | 2 +- source/WorldServer/client.cpp | 2 +- source/WorldServer/zoneserver.cpp | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source/WorldServer/NPC_AI.h b/source/WorldServer/NPC_AI.h index 4532cdd..40567ea 100644 --- a/source/WorldServer/NPC_AI.h +++ b/source/WorldServer/NPC_AI.h @@ -60,7 +60,7 @@ public: /// The amount of hate to add virtual void AddHate(Entity* entity, sint32 hate); /// Completely clears the hate list for this npc - void ClearHate(bool lockSpawnList = true); + void ClearHate(bool lockSpawnList = false); /// Removes the given entity from this NPC's hate list /// Entity to remove from this NPC's hate list void ClearHate(Entity* entity); diff --git a/source/WorldServer/client.cpp b/source/WorldServer/client.cpp index 26372cf..c0fb38f 100644 --- a/source/WorldServer/client.cpp +++ b/source/WorldServer/client.cpp @@ -5307,7 +5307,7 @@ void Client::DetermineCharacterUpdates() { } void Client::Save() { - if (GetCharacterID() == 0 || IsSaveDisabled()) + if (GetCharacterID() == 0 || IsSaveDisabled() || !IsReadyForUpdates()) return; if (current_zone) { diff --git a/source/WorldServer/zoneserver.cpp b/source/WorldServer/zoneserver.cpp index 0ccb763..e9c2f29 100644 --- a/source/WorldServer/zoneserver.cpp +++ b/source/WorldServer/zoneserver.cpp @@ -1517,7 +1517,6 @@ void ZoneServer::DeleteSpawns(bool delete_all) { if(to_process.size() > 0) { to_keep.reserve(to_process.size()); int32 current_time = Timer::GetCurrentTime2(); - MSpawnList.writelock(__FUNCTION__, __LINE__); for (auto &entry : to_process) { Spawn* spawn = entry.first; int32 when = entry.second; @@ -1533,6 +1532,7 @@ void ZoneServer::DeleteSpawns(bool delete_all) { spellProcess->RemoveCaster(spawn, true); } + MSpawnList.writelock(__FUNCTION__, __LINE__); if(spawn->IsEntity() && movementMgr != nullptr) { movementMgr->RemoveMob((Entity*)spawn); } @@ -1563,9 +1563,9 @@ void ZoneServer::DeleteSpawns(bool delete_all) { } housing_spawn_map.erase(spawn->GetID()); } + MSpawnList.releasewritelock(__FUNCTION__, __LINE__); safe_delete(spawn); } - MSpawnList.releasewritelock(__FUNCTION__, __LINE__); } // Add all the kept entries @@ -5403,10 +5403,6 @@ void ZoneServer::KillSpawn(bool spawnListLocked, Spawn* dead, Spawn* killer, boo // the corpse has loot or not if the timer value (pop_timer) is 0xFFFFFFFF } } - - // If the dead spawns was not a player add it to the dead spawn list - if (!dead->IsPlayer() && !dead->IsBot()) - AddDeadSpawn(dead, pop_timer); // if dead was a player clear hostile spells from its spell queue if (dead->IsPlayer()) @@ -5439,6 +5435,10 @@ void ZoneServer::KillSpawn(bool spawnListLocked, Spawn* dead, Spawn* killer, boo } } } + + // If the dead spawns was not a player add it to the dead spawn list + if (!dead->IsPlayer() && !dead->IsBot()) + AddDeadSpawn(dead, pop_timer); } void ZoneServer::SendDamagePacket(Spawn* attacker, Spawn* victim, int8 type1, int8 type2, int8 damage_type, int16 damage, const char* spell_name) {