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:
@@ -1203,7 +1203,6 @@ bool cMinecart::DoTakeDamage(TakeDamageInfo & TDI)
|
||||
{
|
||||
if ((TDI.Attacker != nullptr) && TDI.Attacker->IsPlayer() && static_cast<cPlayer *>(TDI.Attacker)->IsGameModeCreative())
|
||||
{
|
||||
Destroy();
|
||||
TDI.FinalDamage = GetMaxHealth(); // Instant hit for creative
|
||||
SetInvulnerableTicks(0);
|
||||
return Super::DoTakeDamage(TDI); // No drops for creative
|
||||
@@ -1217,42 +1216,6 @@ bool cMinecart::DoTakeDamage(TakeDamageInfo & TDI)
|
||||
|
||||
m_World->BroadcastEntityMetadata(*this);
|
||||
|
||||
if (GetHealth() <= 0)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
cItems Drops;
|
||||
switch (m_Payload)
|
||||
{
|
||||
case mpNone:
|
||||
{
|
||||
Drops.push_back(cItem(E_ITEM_MINECART, 1, 0));
|
||||
break;
|
||||
}
|
||||
case mpChest:
|
||||
{
|
||||
Drops.push_back(cItem(E_ITEM_CHEST_MINECART, 1, 0));
|
||||
break;
|
||||
}
|
||||
case mpFurnace:
|
||||
{
|
||||
Drops.push_back(cItem(E_ITEM_FURNACE_MINECART, 1, 0));
|
||||
break;
|
||||
}
|
||||
case mpTNT:
|
||||
{
|
||||
Drops.push_back(cItem(E_ITEM_MINECART_WITH_TNT, 1, 0));
|
||||
break;
|
||||
}
|
||||
case mpHopper:
|
||||
{
|
||||
Drops.push_back(cItem(E_ITEM_MINECART_WITH_HOPPER, 1, 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1260,6 +1223,31 @@ bool cMinecart::DoTakeDamage(TakeDamageInfo & TDI)
|
||||
|
||||
|
||||
|
||||
void cMinecart::KilledBy(TakeDamageInfo & a_TDI)
|
||||
{
|
||||
Super::KilledBy(a_TDI);
|
||||
|
||||
Destroy();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cMinecart::OnRemoveFromWorld(cWorld & a_World)
|
||||
{
|
||||
if (m_bIsOnDetectorRail)
|
||||
{
|
||||
m_World->SetBlock(m_DetectorRailPosition.x, m_DetectorRailPosition.y, m_DetectorRailPosition.z, E_BLOCK_DETECTOR_RAIL, m_World->GetBlockMeta(m_DetectorRailPosition) & 0x07);
|
||||
}
|
||||
|
||||
Super::OnRemoveFromWorld(a_World);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cMinecart::ApplyAcceleration(Vector3d a_ForwardDirection, double a_Acceleration)
|
||||
{
|
||||
double CurSpeed = GetSpeed().Dot(a_ForwardDirection);
|
||||
@@ -1314,18 +1302,6 @@ void cMinecart::DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
|
||||
|
||||
|
||||
|
||||
void cMinecart::Destroyed()
|
||||
{
|
||||
if (m_bIsOnDetectorRail)
|
||||
{
|
||||
m_World->SetBlock(m_DetectorRailPosition.x, m_DetectorRailPosition.y, m_DetectorRailPosition.z, E_BLOCK_DETECTOR_RAIL, m_World->GetBlockMeta(m_DetectorRailPosition) & 0x07);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cRideableMinecart:
|
||||
|
||||
@@ -1340,6 +1316,15 @@ cRideableMinecart::cRideableMinecart(Vector3d a_Pos, const cItem & a_Content, in
|
||||
|
||||
|
||||
|
||||
void cRideableMinecart::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
||||
{
|
||||
a_Drops.emplace_back(E_ITEM_MINECART);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cRideableMinecart::OnRightClicked(cPlayer & a_Player)
|
||||
{
|
||||
Super::OnRightClicked(a_Player);
|
||||
@@ -1386,6 +1371,31 @@ cMinecartWithChest::cMinecartWithChest(Vector3d a_Pos):
|
||||
|
||||
|
||||
|
||||
void cMinecartWithChest::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
||||
{
|
||||
m_Contents.CopyToItems(a_Drops);
|
||||
a_Drops.emplace_back(E_ITEM_CHEST_MINECART);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cMinecartWithChest::OnRemoveFromWorld(cWorld & a_World)
|
||||
{
|
||||
const auto Window = GetWindow();
|
||||
if (Window != nullptr)
|
||||
{
|
||||
Window->OwnerDestroyed();
|
||||
}
|
||||
|
||||
Super::OnRemoveFromWorld(a_World);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cMinecartWithChest::OnRightClicked(cPlayer & a_Player)
|
||||
{
|
||||
// If the window is not created, open it anew:
|
||||
@@ -1419,32 +1429,6 @@ void cMinecartWithChest::OpenNewWindow()
|
||||
|
||||
|
||||
|
||||
void cMinecartWithChest::Destroyed()
|
||||
{
|
||||
if (GetWindow() != nullptr)
|
||||
{
|
||||
GetWindow()->OwnerDestroyed();
|
||||
}
|
||||
cItems Pickups;
|
||||
m_Contents.CopyToItems(Pickups);
|
||||
|
||||
|
||||
// Schedule the pickups creation for the next world tick
|
||||
// This avoids a deadlock when terminating the world
|
||||
// Note that the scheduled task may be run when this object is no longer valid, we need to store everything in the task's captured variables
|
||||
auto posX = GetPosX();
|
||||
auto posY = GetPosY() + 1;
|
||||
auto posZ = GetPosZ();
|
||||
GetWorld()->ScheduleTask(1, [Pickups, posX, posY, posZ](cWorld & World)
|
||||
{
|
||||
World.SpawnItemPickups(Pickups, posX, posY, posZ, 4);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cMinecartWithFurnace:
|
||||
|
||||
@@ -1459,6 +1443,15 @@ cMinecartWithFurnace::cMinecartWithFurnace(Vector3d a_Pos):
|
||||
|
||||
|
||||
|
||||
void cMinecartWithFurnace::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
||||
{
|
||||
a_Drops.emplace_back(E_ITEM_FURNACE_MINECART);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cMinecartWithFurnace::OnRightClicked(cPlayer & a_Player)
|
||||
{
|
||||
if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_COAL)
|
||||
@@ -1526,6 +1519,15 @@ cMinecartWithTNT::cMinecartWithTNT(Vector3d a_Pos):
|
||||
|
||||
|
||||
|
||||
void cMinecartWithTNT::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
||||
{
|
||||
a_Drops.emplace_back(E_ITEM_MINECART_WITH_TNT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cMinecartWithHopper:
|
||||
|
||||
@@ -1536,3 +1538,12 @@ cMinecartWithHopper::cMinecartWithHopper(Vector3d a_Pos):
|
||||
|
||||
// TODO: Make it suck up blocks and travel further than any other cart and physics and put and take blocks
|
||||
// AND AVARYTHING!!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cMinecartWithHopper::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
||||
{
|
||||
a_Drops.emplace_back(E_ITEM_MINECART_WITH_HOPPER);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user