Various fixed
* Fixed potential invalid pointer dereferencing, fixes #1117 * Fixed ender pearls not being loaded properly
This commit is contained in:
parent
f635066241
commit
f4e3c01a71
@ -21,6 +21,7 @@
|
|||||||
#include "FireChargeEntity.h"
|
#include "FireChargeEntity.h"
|
||||||
#include "FireworkEntity.h"
|
#include "FireworkEntity.h"
|
||||||
#include "GhastFireballEntity.h"
|
#include "GhastFireballEntity.h"
|
||||||
|
#include "Player.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -215,7 +216,7 @@ protected:
|
|||||||
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height) :
|
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height) :
|
||||||
super(etProjectile, a_X, a_Y, a_Z, a_Width, a_Height),
|
super(etProjectile, a_X, a_Y, a_Z, a_Width, a_Height),
|
||||||
m_ProjectileKind(a_Kind),
|
m_ProjectileKind(a_Kind),
|
||||||
m_Creator(a_Creator),
|
m_CreatorData(a_Creator->GetUniqueID(), a_Creator->IsPlayer() ? ((cPlayer *)a_Creator)->GetName() : ""),
|
||||||
m_IsInGround(false)
|
m_IsInGround(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -227,7 +228,7 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a
|
|||||||
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height) :
|
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height) :
|
||||||
super(etProjectile, a_Pos.x, a_Pos.y, a_Pos.z, a_Width, a_Height),
|
super(etProjectile, a_Pos.x, a_Pos.y, a_Pos.z, a_Width, a_Height),
|
||||||
m_ProjectileKind(a_Kind),
|
m_ProjectileKind(a_Kind),
|
||||||
m_Creator(a_Creator),
|
m_CreatorData(a_Creator->GetUniqueID(), a_Creator->IsPlayer() ? ((cPlayer *)a_Creator)->GetName() : ""),
|
||||||
m_IsInGround(false)
|
m_IsInGround(false)
|
||||||
{
|
{
|
||||||
SetSpeed(a_Speed);
|
SetSpeed(a_Speed);
|
||||||
@ -295,6 +296,74 @@ void cProjectileEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cEntity * cProjectileEntity::GetCreator()
|
||||||
|
{
|
||||||
|
if (m_CreatorData.m_Name.empty())
|
||||||
|
{
|
||||||
|
class cProjectileCreatorCallback : public cEntityCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cProjectileCreatorCallback(void) :
|
||||||
|
m_Entity(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Item(cEntity * a_Entity) override
|
||||||
|
{
|
||||||
|
m_Entity = a_Entity;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
cEntity * GetEntity(void)
|
||||||
|
{
|
||||||
|
return m_Entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
cEntity * m_Entity;
|
||||||
|
};
|
||||||
|
|
||||||
|
cProjectileCreatorCallback PCC;
|
||||||
|
GetWorld()->DoWithEntityByID(m_CreatorData.m_UniqueID, PCC);
|
||||||
|
return PCC.GetEntity();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
class cProjectileCreatorCallbackForPlayers : public cPlayerListCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cProjectileCreatorCallbackForPlayers(void) :
|
||||||
|
m_Entity(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Item(cPlayer * a_Entity) override
|
||||||
|
{
|
||||||
|
m_Entity = a_Entity;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
cPlayer * GetEntity(void)
|
||||||
|
{
|
||||||
|
return m_Entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
cPlayer * m_Entity;
|
||||||
|
};
|
||||||
|
|
||||||
|
cProjectileCreatorCallbackForPlayers PCCFP;
|
||||||
|
GetWorld()->FindAndDoWithPlayer(m_CreatorData.m_Name, PCCFP);
|
||||||
|
return PCCFP.GetEntity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AString cProjectileEntity::GetMCAClassName(void) const
|
AString cProjectileEntity::GetMCAClassName(void) const
|
||||||
{
|
{
|
||||||
switch (m_ProjectileKind)
|
switch (m_ProjectileKind)
|
||||||
@ -304,7 +373,7 @@ AString cProjectileEntity::GetMCAClassName(void) const
|
|||||||
case pkEgg: return "Egg";
|
case pkEgg: return "Egg";
|
||||||
case pkGhastFireball: return "Fireball";
|
case pkGhastFireball: return "Fireball";
|
||||||
case pkFireCharge: return "SmallFireball";
|
case pkFireCharge: return "SmallFireball";
|
||||||
case pkEnderPearl: return "ThrownEnderPearl";
|
case pkEnderPearl: return "ThrownEnderpearl";
|
||||||
case pkExpBottle: return "ThrownExpBottle";
|
case pkExpBottle: return "ThrownExpBottle";
|
||||||
case pkSplashPotion: return "ThrownPotion";
|
case pkSplashPotion: return "ThrownPotion";
|
||||||
case pkWitherSkull: return "WitherSkull";
|
case pkWitherSkull: return "WitherSkull";
|
||||||
|
@ -66,8 +66,15 @@ public:
|
|||||||
/// Returns the kind of the projectile (fast class identification)
|
/// Returns the kind of the projectile (fast class identification)
|
||||||
eKind GetProjectileKind(void) const { return m_ProjectileKind; }
|
eKind GetProjectileKind(void) const { return m_ProjectileKind; }
|
||||||
|
|
||||||
/// Returns the entity who created this projectile; may be NULL
|
/** Returns the entity who created this projectile through running its Unique ID through cWorld::DoWithEntityByID()
|
||||||
cEntity * GetCreator(void) { return m_Creator; }
|
May return NULL; do not store the returned pointer outside the scope of the tick thread!
|
||||||
|
*/
|
||||||
|
cEntity * GetCreator(void);
|
||||||
|
|
||||||
|
/** Returns the name of the player that created the projectile
|
||||||
|
Will be empty for non-player creators
|
||||||
|
*/
|
||||||
|
AString GetCreatorName(void) const { return m_CreatorData.m_Name; }
|
||||||
|
|
||||||
/// Returns the string that is used as the entity type (class name) in MCA files
|
/// Returns the string that is used as the entity type (class name) in MCA files
|
||||||
AString GetMCAClassName(void) const;
|
AString GetMCAClassName(void) const;
|
||||||
@ -81,10 +88,29 @@ public:
|
|||||||
void SetIsInGround(bool a_IsInGround) { m_IsInGround = a_IsInGround; }
|
void SetIsInGround(bool a_IsInGround) { m_IsInGround = a_IsInGround; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
/** A structure that stores the Entity ID and Playername of the projectile's creator
|
||||||
|
Used to migitate invalid pointers caused by the creator being destroyed
|
||||||
|
*/
|
||||||
|
struct CreatorData
|
||||||
|
{
|
||||||
|
CreatorData(int a_UniqueID, AString & a_Name) :
|
||||||
|
m_UniqueID(a_UniqueID),
|
||||||
|
m_Name(a_Name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const int m_UniqueID;
|
||||||
|
AString m_Name;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** The type of projectile I am */
|
||||||
eKind m_ProjectileKind;
|
eKind m_ProjectileKind;
|
||||||
|
|
||||||
/// The entity who has created this projectile; may be NULL (e. g. for dispensers)
|
/** The structure for containing the entity ID and name who has created this projectile
|
||||||
cEntity * m_Creator;
|
The ID and/or name may be NULL (e.g. for dispensers/mobs)
|
||||||
|
*/
|
||||||
|
CreatorData m_CreatorData;
|
||||||
|
|
||||||
/// True if the projectile has hit the ground and is stuck there
|
/// True if the projectile has hit the ground and is stuck there
|
||||||
bool m_IsInGround;
|
bool m_IsInGround;
|
||||||
|
@ -46,10 +46,12 @@ void cThrownEnderPearlEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d
|
|||||||
|
|
||||||
void cThrownEnderPearlEntity::TeleportCreator(const Vector3d & a_HitPos)
|
void cThrownEnderPearlEntity::TeleportCreator(const Vector3d & a_HitPos)
|
||||||
{
|
{
|
||||||
|
cEntity * Creator = GetCreator();
|
||||||
|
|
||||||
// Teleport the creator here, make them take 5 damage:
|
// Teleport the creator here, make them take 5 damage:
|
||||||
if (m_Creator != NULL)
|
if (Creator != NULL)
|
||||||
{
|
{
|
||||||
m_Creator->TeleportToCoords(a_HitPos.x, a_HitPos.y + 0.2, a_HitPos.z);
|
Creator->TeleportToCoords(a_HitPos.x, a_HitPos.y + 0.2, a_HitPos.z);
|
||||||
m_Creator->TakeDamage(dtEnderPearl, this, 5, 0);
|
Creator->TakeDamage(dtEnderPearl, this, 5, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -619,14 +619,11 @@ void cNBTChunkSerializer::AddProjectileEntity(cProjectileEntity * a_Projectile)
|
|||||||
{
|
{
|
||||||
ASSERT(!"Unsaved projectile entity!");
|
ASSERT(!"Unsaved projectile entity!");
|
||||||
}
|
}
|
||||||
} // switch (ProjectileKind)
|
} // switch (ProjectileKind)
|
||||||
cEntity * Creator = a_Projectile->GetCreator();
|
|
||||||
if (Creator != NULL)
|
if (!a_Projectile->GetCreatorName().empty())
|
||||||
{
|
{
|
||||||
if (Creator->GetEntityType() == cEntity::etPlayer)
|
m_Writer.AddString("ownerName", a_Projectile->GetCreatorName());
|
||||||
{
|
|
||||||
m_Writer.AddString("ownerName", ((cPlayer *)Creator)->GetName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m_Writer.EndCompound();
|
m_Writer.EndCompound();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user