From fc9c5876049292f1b2b364a5ae2070197bc2cd73 Mon Sep 17 00:00:00 2001 From: Shauren Date: Wed, 28 Oct 2015 21:43:44 +0100 Subject: [PATCH] Core/Corpses: Fixed leaking bones Ref #15765 (cherry picked from commit bd16520ecc91d827abae7f0447cc292fe9e843e9) Conflicts: src/server/game/Entities/Corpse/Corpse.cpp --- src/server/game/Entities/Corpse/Corpse.cpp | 23 +--------- src/server/game/Entities/Corpse/Corpse.h | 7 ++-- src/server/game/Entities/Player/Player.cpp | 5 ++- src/server/game/Handlers/CharacterHandler.cpp | 2 +- src/server/game/Maps/Map.cpp | 42 +++++++++++++++---- src/server/game/Maps/Map.h | 1 + 6 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp index dc49060909..3eb7164245 100644 --- a/src/server/game/Entities/Corpse/Corpse.cpp +++ b/src/server/game/Entities/Corpse/Corpse.cpp @@ -60,7 +60,6 @@ void Corpse::RemoveFromWorld() bool Corpse::Create(ObjectGuid::LowType guidlow, Map* map) { - SetMap(map); Object::_Create(guidlow, 0, HighGuid::Corpse); return true; } @@ -78,16 +77,12 @@ bool Corpse::Create(ObjectGuid::LowType guidlow, Player* owner) return false; } - //we need to assign owner's map for corpse - //in other way we will get a crash in Corpse::SaveToDB() - SetMap(owner->GetMap()); - WorldObject::_Create(guidlow, HighGuid::Corpse, owner->GetPhaseMask()); SetObjectScale(1.0f); SetGuidValue(CORPSE_FIELD_OWNER, owner->GetGUID()); - _gridCoord = Trinity::ComputeGridCoord(GetPositionX(), GetPositionY()); + _cellCoord = Trinity::ComputeCellCoord(GetPositionX(), GetPositionY()); CopyPhaseFrom(owner); @@ -131,20 +126,6 @@ void Corpse::SaveToDB() CharacterDatabase.CommitTransaction(trans); } -void Corpse::DeleteBonesFromWorld() -{ - ASSERT(GetType() == CORPSE_BONES); - Corpse* corpse = ObjectAccessor::GetCorpse(*this, GetGUID()); - - if (!corpse) - { - TC_LOG_ERROR("entities.player", "Bones %u not found in world.", GetGUID().GetCounter()); - return; - } - - AddObjectToRemoveList(); -} - void Corpse::DeleteFromDB(SQLTransaction& trans) { Corpse::DeleteFromDB(GetOwnerGUID(), trans); @@ -199,7 +180,7 @@ bool Corpse::LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields) return false; } - _gridCoord = Trinity::ComputeGridCoord(GetPositionX(), GetPositionY()); + _cellCoord = Trinity::ComputeCellCoord(GetPositionX(), GetPositionY()); return true; } diff --git a/src/server/game/Entities/Corpse/Corpse.h b/src/server/game/Entities/Corpse/Corpse.h index be2cb435ac..c135548bee 100644 --- a/src/server/game/Entities/Corpse/Corpse.h +++ b/src/server/game/Entities/Corpse/Corpse.h @@ -61,7 +61,6 @@ class Corpse : public WorldObject, public GridObject void SaveToDB(); bool LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields); - void DeleteBonesFromWorld(); void DeleteFromDB(SQLTransaction& trans); static void DeleteFromDB(ObjectGuid const& ownerGuid, SQLTransaction& trans); @@ -71,8 +70,8 @@ class Corpse : public WorldObject, public GridObject void ResetGhostTime() { m_time = time(NULL); } CorpseType GetType() const { return m_type; } - GridCoord const& GetGridCoord() const { return _gridCoord; } - void SetGridCoord(GridCoord const& gridCoord) { _gridCoord = gridCoord; } + CellCoord const& GetCellCoord() const { return _cellCoord; } + void SetCellCoord(CellCoord const& cellCoord) { _cellCoord = cellCoord; } Loot loot; // remove insignia ONLY at BG Player* lootRecipient; @@ -83,6 +82,6 @@ class Corpse : public WorldObject, public GridObject private: CorpseType m_type; time_t m_time; - GridCoord _gridCoord; // gride for corpse position for fast search + CellCoord _cellCoord; }; #endif diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 11de4ca800..b384615c26 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -5174,12 +5174,13 @@ Corpse* Player::CreateCorpse() } } + // register for player, but not show + GetMap()->AddCorpse(corpse); + // we do not need to save corpses for BG/arenas if (!GetMap()->IsBattlegroundOrArena()) corpse->SaveToDB(); - // register for player, but not show - GetMap()->AddCorpse(corpse); return corpse; } diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index d898104e38..c68dd81e2c 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -972,7 +972,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) if (!pCurrChar->GetMap()->AddPlayerToMap(pCurrChar) || !pCurrChar->CheckInstanceLoginValid()) { AreaTriggerStruct const* at = sObjectMgr->GetGoBackTrigger(pCurrChar->GetMapId()); - if (at)l + if (at) pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()); else pCurrChar->TeleportTo(pCurrChar->m_homebindMapId, pCurrChar->m_homebindX, pCurrChar->m_homebindY, pCurrChar->m_homebindZ, pCurrChar->GetOrientation()); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index f6cb6f5f50..405b0b7152 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -1578,6 +1578,13 @@ void Map::UnloadAll() RemoveFromMap(transport, true); } + + for (auto& cellCorpsePair : _corpsesByCell) + for (Corpse* corpse : cellCorpsePair.second) + delete corpse; + + _corpsesByCell.clear(); + _corpsesByPlayer.clear(); } // ***************************** @@ -3600,14 +3607,16 @@ void Map::AddCorpse(Corpse* corpse) { corpse->SetMap(this); - CellCoord cellCoord = Trinity::ComputeCellCoord(corpse->GetPositionX(), corpse->GetPositionY()); - _corpsesByCell[cellCoord.GetId()].insert(corpse); - _corpsesByPlayer[corpse->GetOwnerGUID()] = corpse; + _corpsesByCell[corpse->GetCellCoord().GetId()].insert(corpse); + if (corpse->GetType() != CORPSE_BONES) + _corpsesByPlayer[corpse->GetOwnerGUID()] = corpse; + else + _corpseBones.insert(corpse); } void Map::RemoveCorpse(Corpse* corpse) { - ASSERT(corpse && corpse->GetType() != CORPSE_BONES); + ASSERT(corpse); corpse->DestroyForNearbyPlayers(); if (corpse->IsInGrid()) @@ -3618,9 +3627,11 @@ void Map::RemoveCorpse(Corpse* corpse) corpse->ResetMap(); } - CellCoord cellCoord = Trinity::ComputeCellCoord(corpse->GetPositionX(), corpse->GetPositionY()); - _corpsesByCell[cellCoord.GetId()].erase(corpse); - _corpsesByPlayer.erase(corpse->GetOwnerGUID()); + _corpsesByCell[corpse->GetCellCoord().GetId()].erase(corpse); + if (corpse->GetType() != CORPSE_BONES) + _corpsesByPlayer.erase(corpse->GetOwnerGUID()); + else + _corpseBones.erase(corpse); } Corpse* Map::ConvertCorpseToBones(ObjectGuid const& ownerGuid, bool insignia /*= false*/) @@ -3651,12 +3662,12 @@ Corpse* Map::ConvertCorpseToBones(ObjectGuid const& ownerGuid, bool insignia /*= for (uint8 i = OBJECT_FIELD_GUID + 4; i < CORPSE_END; ++i) // don't overwrite guid bones->SetUInt32Value(i, corpse->GetUInt32Value(i)); - bones->SetGridCoord(corpse->GetGridCoord()); + bones->SetCellCoord(corpse->GetCellCoord()); bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation()); bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES); bones->SetGuidValue(CORPSE_FIELD_OWNER, ObjectGuid::Empty); - bones->SetGuidValue(OBJECT_FIELD_DATA, corpse->GetGuidValue(OBJECT_FIELD_DATA)); + bones->SetGuidValue(OBJECT_FIELD_DATA, ObjectGuid::Empty); for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i) if (corpse->GetUInt32Value(CORPSE_FIELD_ITEM + i)) @@ -3664,6 +3675,8 @@ Corpse* Map::ConvertCorpseToBones(ObjectGuid const& ownerGuid, bool insignia /*= bones->CopyPhaseFrom(corpse); + AddCorpse(bones); + // add bones in grid store if grid loaded where corpse placed AddToMap(bones); } @@ -3687,6 +3700,17 @@ void Map::RemoveOldCorpses() for (ObjectGuid const& ownerGuid : corpses) ConvertCorpseToBones(ownerGuid); + + std::vector expiredBones; + for (Corpse* bones : _corpseBones) + if (bones->IsExpired(now)) + expiredBones.push_back(bones); + + for (Corpse* bones : expiredBones) + { + RemoveCorpse(bones); + delete bones; + } } void Map::SendZoneDynamicInfo(Player* player) diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 88abd2eb4e..00b95ac54a 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -727,6 +727,7 @@ class Map : public GridRefManager GameObjectBySpawnIdContainer _gameObjectBySpawnIdStore; std::unordered_map> _corpsesByCell; std::unordered_map _corpsesByPlayer; + std::unordered_set _corpseBones; std::unordered_set _updateObjects; };