From f2b4f2208e161c50defa48047c646ba4c620c84f Mon Sep 17 00:00:00 2001 From: Shauren Date: Sat, 29 Jan 2022 19:04:21 +0100 Subject: [PATCH] Core/Objects: ported master branch handling for properly destroying objects via out of range and destroy object opcode # Conflicts: # src/server/game/Entities/Creature/Creature.cpp --- src/server/game/Entities/Creature/Creature.cpp | 4 ++-- .../game/Entities/DynamicObject/DynamicObject.cpp | 3 --- src/server/game/Entities/GameObject/GameObject.cpp | 4 ++-- src/server/game/Entities/Object/Object.cpp | 13 ++++++++++++- src/server/game/Entities/Object/Object.h | 7 ++++++- src/server/game/Entities/Player/Player.cpp | 14 +++++++++++--- src/server/game/Entities/Unit/Unit.h | 3 ++- src/server/game/Grids/ObjectGridLoader.cpp | 3 +++ src/server/game/Maps/Map.cpp | 7 ++++--- src/server/game/Server/WorldSession.cpp | 1 + 10 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index e6e1737c61..67b5f32298 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1992,7 +1992,7 @@ void Creature::Respawn(bool force) if (m_respawnCompatibilityMode) { - DestroyForNearbyPlayers(); + UpdateObjectVisibilityOnDestroy(); RemoveCorpse(false); if (getDeathState() == DEAD) @@ -2055,7 +2055,7 @@ void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds forceRespawnTimer) uint32 respawnDelay = GetRespawnDelay(); // do it before killing creature - DestroyForNearbyPlayers(); + UpdateObjectVisibilityOnDestroy(); bool overrideRespawnTime = false; if (IsAlive()) diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp index 5abe35fbd0..cd5cf275c2 100644 --- a/src/server/game/Entities/DynamicObject/DynamicObject.cpp +++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp @@ -164,10 +164,7 @@ void DynamicObject::Update(uint32 p_time) void DynamicObject::Remove() { if (IsInWorld()) - { - RemoveFromWorld(); AddObjectToRemoveList(); - } } void DynamicObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 882790910a..1fef4bc707 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -789,7 +789,7 @@ void GameObject::Update(uint32 diff) m_respawnTime = 0; if (m_spawnId) - DestroyForNearbyPlayers(); + UpdateObjectVisibilityOnDestroy(); else Delete(); @@ -806,7 +806,7 @@ void GameObject::Update(uint32 diff) SaveRespawnTime(); if (m_respawnCompatibilityMode) - DestroyForNearbyPlayers(); + UpdateObjectVisibilityOnDestroy(); else AddObjectToRemoveList(); diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 42da86c8f3..ac24395ba9 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -276,6 +276,17 @@ void Object::DestroyForPlayer(Player* target, bool isDead /*= false*/) const target->SendDirectMessage(packet.Write()); } +void Object::SendOutOfRangeForPlayer(Player* target) const +{ + ASSERT(target); + + UpdateData updateData(target->GetMapId()); + BuildOutOfRangeUpdateBlock(&updateData); + WorldPacket packet; + updateData.BuildPacket(&packet); + target->SendDirectMessage(&packet); +} + int32 Object::GetInt32Value(uint16 index) const { ASSERT(index < m_valuesCount || PrintIndexError(index, false)); @@ -1265,7 +1276,7 @@ void WorldObject::RemoveFromWorld() if (!IsInWorld()) return; - DestroyForNearbyPlayers(); + UpdateObjectVisibilityOnDestroy(); Object::RemoveFromWorld(); } diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index d37e78b32d..e7e6aff6c8 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -90,6 +90,7 @@ class TC_GAME_API Object void BuildOutOfRangeUpdateBlock(UpdateData* data) const; virtual void DestroyForPlayer(Player* target, bool isDead = false) const; + void SendOutOfRangeForPlayer(Player* target) const; int32 GetInt32Value(uint16 index) const; uint32 GetUInt32Value(uint16 index) const; @@ -145,6 +146,8 @@ class TC_GAME_API Object virtual bool hasQuest(uint32 /* quest_id */) const { return false; } virtual bool hasInvolvedQuest(uint32 /* quest_id */) const { return false; } void SetIsNewObject(bool enable) { m_isNewObject = enable; } + bool IsDestroyedObject() const { return m_isDestroyedObject; } + void SetDestroyedObject(bool destroyed) { m_isDestroyedObject = destroyed; } virtual void BuildUpdate(UpdateDataMapType&) { } void BuildFieldsUpdate(Player*, UpdateDataMapType &) const; @@ -222,6 +225,7 @@ class TC_GAME_API Object private: bool m_inWorld; bool m_isNewObject; + bool m_isDestroyedObject; PackedGuid m_PackGUID; @@ -426,6 +430,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation void DestroyForNearbyPlayers(); virtual void UpdateObjectVisibility(bool forced = true); virtual void UpdateObjectVisibilityOnCreate() { UpdateObjectVisibility(true); } + virtual void UpdateObjectVisibilityOnDestroy() { DestroyForNearbyPlayers(); } void UpdatePositionData(); void BuildUpdate(UpdateDataMapType&) override; @@ -516,7 +521,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation void SetLocationMapId(uint32 _mapId) { m_mapId = _mapId; } void SetLocationInstanceId(uint32 _instanceId) { m_InstanceId = _instanceId; } - virtual bool IsNeverVisible() const { return !IsInWorld(); } + virtual bool IsNeverVisible() const { return !IsInWorld() || IsDestroyedObject(); } virtual bool IsAlwaysVisibleFor(WorldObject const* /*seer*/) const { return false; } virtual bool IsInvisibleDueToDespawn() const { return false; } //difference from IsAlwaysVisibleFor: 1. after distance check; 2. use owner or charmer as seer diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index d402eab1c3..56c31d993a 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -23121,7 +23121,11 @@ void Player::UpdateVisibilityOf(WorldObject* target) if (target->GetTypeId() == TYPEID_UNIT) BeforeVisibilityDestroy(target->ToCreature(), this); - target->DestroyForPlayer(this); + if (!target->IsDestroyedObject()) + target->SendOutOfRangeForPlayer(this); + else + target->DestroyForPlayer(this); + m_clientGUIDs.erase(target->GetGUID()); #ifdef TRINITY_DEBUG @@ -23209,7 +23213,11 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set& vi { BeforeVisibilityDestroy(target, this); - target->BuildOutOfRangeUpdateBlock(&data); + if (!target->IsDestroyedObject()) + target->BuildOutOfRangeUpdateBlock(&data); + else + target->DestroyForPlayer(this); + m_clientGUIDs.erase(target->GetGUID()); #ifdef TRINITY_DEBUG @@ -23217,7 +23225,7 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set& vi #endif } } - else //if (visibleNow.size() < 30 || target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->IsVehicle()) + else { if (CanSeeOrDetect(target, false, true)) { diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index ac2c290d95..44bf23d51b 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1850,11 +1850,12 @@ class TC_GAME_API Unit : public WorldObject void CancelPendingCastRequest(); bool CanRequestSpellCast(SpellInfo const* spell) const; + void DestroyForPlayer(Player* target, bool onDeath = false) const override; + protected: explicit Unit (bool isWorldObject); void BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, Player* target) const override; - void DestroyForPlayer(Player* target, bool onDeath = false) const override; void _UpdateSpells(uint32 time); void _DeleteRemovedAuras(); diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp index 8c12ff340f..d71c3c9ef7 100644 --- a/src/server/game/Grids/ObjectGridLoader.cpp +++ b/src/server/game/Grids/ObjectGridLoader.cpp @@ -255,7 +255,10 @@ template void ObjectGridCleaner::Visit(GridRefManager &m) { for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) + { + iter->GetSource()->SetDestroyedObject(true); iter->GetSource()->CleanupsBeforeDelete(); + } } template void ObjectGridUnloader::Visit(CreatureMapType &); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 61ba3df83b..7ae261a520 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -1091,7 +1091,7 @@ void Map::RemovePlayerFromMap(Player* player, bool remove) SendRemoveTransports(player); if (!inWorld) // if was in world, RemoveFromWorld() called DestroyForNearbyPlayers() - player->DestroyForNearbyPlayers(); // previous player->UpdateObjectVisibility(true) + player->UpdateObjectVisibilityOnDestroy(); if (player->IsInGrid()) player->RemoveFromGrid(); @@ -1112,7 +1112,7 @@ void Map::RemoveFromMap(T *obj, bool remove) RemoveFromActive(obj); if (!inWorld) // if was in world, RemoveFromWorld() called DestroyForNearbyPlayers() - obj->DestroyForNearbyPlayers(); // previous obj->UpdateObjectVisibility(true) + obj->UpdateObjectVisibilityOnDestroy(); obj->RemoveFromGrid(); @@ -3489,6 +3489,7 @@ void Map::AddObjectToRemoveList(WorldObject* obj) { ASSERT(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId()); + obj->SetDestroyedObject(true); obj->CleanupsBeforeDelete(false); // remove or simplify at least cross referenced links i_objectsToRemove.insert(obj); @@ -4541,7 +4542,7 @@ void Map::RemoveCorpse(Corpse* corpse) { ASSERT(corpse); - corpse->DestroyForNearbyPlayers(); + corpse->UpdateObjectVisibilityOnDestroy(); if (corpse->IsInGrid()) RemoveFromMap(corpse, false); else diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index c35a9326b7..ff26336d8d 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -645,6 +645,7 @@ void WorldSession::LogoutPlayer(bool save) // the player may not be in the world when logging out // e.g if he got disconnected during a transfer to another map // calls to GetMap in this case may cause crashes + _player->SetDestroyedObject(true); _player->CleanupsBeforeDelete(); TC_LOG_INFO("entities.player.character", "Account: %d (IP: %s) Logout Character:[%s] (GUID: %u) Level: %d", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName().c_str(), _player->GetGUID().GetCounter(), _player->getLevel());