summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@hotmail.co.uk>2014-07-04 17:49:24 +0200
committerTiger Wang <ziwei.tiger@hotmail.co.uk>2014-07-04 17:49:24 +0200
commitf4e3c01a710a2cc5118807a65f8d27519a19ef37 (patch)
treeb01db2464263a6425ed39195f574523e7707fa5b
parentEps comparison (diff)
downloadcuberite-f4e3c01a710a2cc5118807a65f8d27519a19ef37.tar
cuberite-f4e3c01a710a2cc5118807a65f8d27519a19ef37.tar.gz
cuberite-f4e3c01a710a2cc5118807a65f8d27519a19ef37.tar.bz2
cuberite-f4e3c01a710a2cc5118807a65f8d27519a19ef37.tar.lz
cuberite-f4e3c01a710a2cc5118807a65f8d27519a19ef37.tar.xz
cuberite-f4e3c01a710a2cc5118807a65f8d27519a19ef37.tar.zst
cuberite-f4e3c01a710a2cc5118807a65f8d27519a19ef37.zip
-rw-r--r--src/Entities/ProjectileEntity.cpp75
-rw-r--r--src/Entities/ProjectileEntity.h34
-rw-r--r--src/Entities/ThrownEnderPearlEntity.cpp8
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp11
4 files changed, 111 insertions, 17 deletions
diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp
index 76daca186..ddcc0f7fd 100644
--- a/src/Entities/ProjectileEntity.cpp
+++ b/src/Entities/ProjectileEntity.cpp
@@ -21,6 +21,7 @@
#include "FireChargeEntity.h"
#include "FireworkEntity.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) :
super(etProjectile, a_X, a_Y, a_Z, a_Width, a_Height),
m_ProjectileKind(a_Kind),
- m_Creator(a_Creator),
+ m_CreatorData(a_Creator->GetUniqueID(), a_Creator->IsPlayer() ? ((cPlayer *)a_Creator)->GetName() : ""),
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) :
super(etProjectile, a_Pos.x, a_Pos.y, a_Pos.z, a_Width, a_Height),
m_ProjectileKind(a_Kind),
- m_Creator(a_Creator),
+ m_CreatorData(a_Creator->GetUniqueID(), a_Creator->IsPlayer() ? ((cPlayer *)a_Creator)->GetName() : ""),
m_IsInGround(false)
{
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
{
switch (m_ProjectileKind)
@@ -304,7 +373,7 @@ AString cProjectileEntity::GetMCAClassName(void) const
case pkEgg: return "Egg";
case pkGhastFireball: return "Fireball";
case pkFireCharge: return "SmallFireball";
- case pkEnderPearl: return "ThrownEnderPearl";
+ case pkEnderPearl: return "ThrownEnderpearl";
case pkExpBottle: return "ThrownExpBottle";
case pkSplashPotion: return "ThrownPotion";
case pkWitherSkull: return "WitherSkull";
diff --git a/src/Entities/ProjectileEntity.h b/src/Entities/ProjectileEntity.h
index ae06b072f..e2ebe9f27 100644
--- a/src/Entities/ProjectileEntity.h
+++ b/src/Entities/ProjectileEntity.h
@@ -66,8 +66,15 @@ public:
/// Returns the kind of the projectile (fast class identification)
eKind GetProjectileKind(void) const { return m_ProjectileKind; }
- /// Returns the entity who created this projectile; may be NULL
- cEntity * GetCreator(void) { return m_Creator; }
+ /** Returns the entity who created this projectile through running its Unique ID through cWorld::DoWithEntityByID()
+ 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
AString GetMCAClassName(void) const;
@@ -81,10 +88,29 @@ public:
void SetIsInGround(bool a_IsInGround) { m_IsInGround = a_IsInGround; }
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;
- /// The entity who has created this projectile; may be NULL (e. g. for dispensers)
- cEntity * m_Creator;
+ /** The structure for containing the entity ID and name who has created this projectile
+ 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
bool m_IsInGround;
diff --git a/src/Entities/ThrownEnderPearlEntity.cpp b/src/Entities/ThrownEnderPearlEntity.cpp
index a3ee23389..96dd41ee6 100644
--- a/src/Entities/ThrownEnderPearlEntity.cpp
+++ b/src/Entities/ThrownEnderPearlEntity.cpp
@@ -46,10 +46,12 @@ void cThrownEnderPearlEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d
void cThrownEnderPearlEntity::TeleportCreator(const Vector3d & a_HitPos)
{
+ cEntity * Creator = GetCreator();
+
// 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);
- m_Creator->TakeDamage(dtEnderPearl, this, 5, 0);
+ Creator->TeleportToCoords(a_HitPos.x, a_HitPos.y + 0.2, a_HitPos.z);
+ Creator->TakeDamage(dtEnderPearl, this, 5, 0);
}
}
diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp
index e49042ff7..2dcae51ce 100644
--- a/src/WorldStorage/NBTChunkSerializer.cpp
+++ b/src/WorldStorage/NBTChunkSerializer.cpp
@@ -619,14 +619,11 @@ void cNBTChunkSerializer::AddProjectileEntity(cProjectileEntity * a_Projectile)
{
ASSERT(!"Unsaved projectile entity!");
}
- } // switch (ProjectileKind)
- cEntity * Creator = a_Projectile->GetCreator();
- if (Creator != NULL)
+ } // switch (ProjectileKind)
+
+ if (!a_Projectile->GetCreatorName().empty())
{
- if (Creator->GetEntityType() == cEntity::etPlayer)
- {
- m_Writer.AddString("ownerName", ((cPlayer *)Creator)->GetName());
- }
+ m_Writer.AddString("ownerName", a_Projectile->GetCreatorName());
}
m_Writer.EndCompound();
}