1
0

Fix potential destruction crashes (#5095)

* Fix potential destruction crashes

* Fix destructors accessing destroyted objects
* Fix cPlayer not destroying windows (Destroyed never called)
* Tentatively fixes #4608, fixes #3236, fixes #3262
- Remove cEntity::Destroyed() and replace with cEntity::OnRemoveFromWorld()

* Add missing call to OnRemoveFromWorld
This commit is contained in:
Tiger Wang
2021-01-02 13:50:34 +00:00
committed by GitHub
parent 4656f7486d
commit 16aeb84cd3
33 changed files with 409 additions and 464 deletions

View File

@@ -80,32 +80,6 @@ cEntity::cEntity(eEntityType a_EntityType, Vector3d a_Pos, double a_Width, doubl
cEntity::~cEntity()
{
/*
// DEBUG:
FLOGD("Deleting entity {0} at pos {1:.2f} ~ [{2}, {3}]; ptr {4}",
m_UniqueID,
m_Pos,
GetChunkX(), GetChunkZ(),
static_cast<void *>(this)
);
*/
if (m_AttachedTo != nullptr)
{
Detach();
}
if (m_Attachee != nullptr)
{
m_Attachee->Detach();
}
}
const char * cEntity::GetClass(void) const
{
return "cEntity";
@@ -174,7 +148,22 @@ void cEntity::OnAddToWorld(cWorld & a_World)
void cEntity::OnRemoveFromWorld(cWorld & a_World)
{
RemoveAllLeashedMobs();
// Remove all mobs from the leashed list of mobs:
while (!m_LeashedMobs.empty())
{
m_LeashedMobs.front()->Unleash(false, true);
}
if (m_AttachedTo != nullptr)
{
Detach();
}
if (m_Attachee != nullptr)
{
m_Attachee->Detach();
}
a_World.BroadcastDestroyEntity(*this);
}
@@ -244,7 +233,6 @@ void cEntity::Destroy()
// Also, not storing the returned pointer means automatic destruction
VERIFY(a_World.RemoveEntity(*this));
});
Destroyed();
}
@@ -813,10 +801,17 @@ void cEntity::KilledBy(TakeDamageInfo & a_TDI)
cRoot::Get()->GetPluginManager()->CallHookKilled(*this, a_TDI, emptystring);
}
// Drop loot:
cItems Drops;
GetDrops(Drops, a_TDI.Attacker);
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ());
// Drop loot, unless the attacker was a creative mode player:
if (
(a_TDI.Attacker == nullptr) ||
!a_TDI.Attacker->IsPlayer() ||
!static_cast<cPlayer *>(a_TDI.Attacker)->IsGameModeCreative()
)
{
cItems Drops;
GetDrops(Drops, a_TDI.Attacker);
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ());
}
m_World->BroadcastEntityStatus(*this, esGenericDead);
}
@@ -2328,18 +2323,6 @@ void cEntity::RemoveLeashedMob(cMonster * a_Monster)
void cEntity::RemoveAllLeashedMobs()
{
while (!m_LeashedMobs.empty())
{
m_LeashedMobs.front()->Unleash(false, true);
}
}
void cEntity::BroadcastLeashedMobs()
{
// If has any mob leashed broadcast every leashed entity to this