summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLogicParrot <LogicParrot@users.noreply.github.com>2017-08-29 23:13:25 +0200
committerLogicParrot <LogicParrot@users.noreply.github.com>2017-08-29 23:13:25 +0200
commit00febf68ad8bc36546c02b0c0b926189fb3955a1 (patch)
treec10896365ce99cd0e22f9398908b094ea5114e9e
parentAgressives wander and don't crash (diff)
downloadcuberite-00febf68ad8bc36546c02b0c0b926189fb3955a1.tar
cuberite-00febf68ad8bc36546c02b0c0b926189fb3955a1.tar.gz
cuberite-00febf68ad8bc36546c02b0c0b926189fb3955a1.tar.bz2
cuberite-00febf68ad8bc36546c02b0c0b926189fb3955a1.tar.lz
cuberite-00febf68ad8bc36546c02b0c0b926189fb3955a1.tar.xz
cuberite-00febf68ad8bc36546c02b0c0b926189fb3955a1.tar.zst
cuberite-00febf68ad8bc36546c02b0c0b926189fb3955a1.zip
-rw-r--r--src/Entities/Entity.cpp4
-rw-r--r--src/Mobs/CMakeLists.txt2
-rw-r--r--src/Mobs/MobPointer.cpp75
-rw-r--r--src/Mobs/MobPointer.h34
-rw-r--r--src/Mobs/Monster.cpp52
-rw-r--r--src/Mobs/Monster.h16
-rw-r--r--src/Mobs/Zombie.h4
7 files changed, 138 insertions, 49 deletions
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 347c0ec91..ccba28d53 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -239,7 +239,9 @@ void cEntity::Destroy(bool a_ShouldBroadcast)
}
cChunk * ParentChunk = GetParentChunk();
- m_World->QueueTask([this, ParentChunk](cWorld & a_World)
+ // Destroy the entity after two seconds, to give time for all raw pointers such as m_Target
+ // to de-target this entity. This is a temporary solution.
+ m_World->ScheduleTask(40, [this, ParentChunk](cWorld & a_World)
{
LOGD("Destroying entity #%i (%s) from chunk (%d, %d)",
this->GetUniqueID(), this->GetClass(),
diff --git a/src/Mobs/CMakeLists.txt b/src/Mobs/CMakeLists.txt
index bccf98735..5f43219e2 100644
--- a/src/Mobs/CMakeLists.txt
+++ b/src/Mobs/CMakeLists.txt
@@ -26,6 +26,7 @@ SET (SRCS
PathFinder.cpp
Pig.cpp
Rabbit.cpp
+ MobPointer.cpp
Sheep.cpp
Skeleton.cpp
Slime.cpp
@@ -65,6 +66,7 @@ SET (HDRS
PathFinder.h
Pig.h
Rabbit.h
+ MobPointer.h
Sheep.h
Silverfish.h
Skeleton.h
diff --git a/src/Mobs/MobPointer.cpp b/src/Mobs/MobPointer.cpp
new file mode 100644
index 000000000..b755e3cdf
--- /dev/null
+++ b/src/Mobs/MobPointer.cpp
@@ -0,0 +1,75 @@
+#include "../Entities/Pawn.h"
+#include "MobPointer.h"
+
+cMobPointer::cMobPointer(cPawn * a_Pointer) : m_Pointer(a_Pointer)
+{
+ // Constructor
+}
+
+
+
+
+
+cMobPointer::cMobPointer(const cMobPointer & a_MobPointer) : m_Pointer(a_MobPointer.m_Pointer)
+{
+ // Copy constructor
+}
+
+
+
+
+
+cMobPointer::cMobPointer(cMobPointer && a_MobPointer)
+{
+ // move Constructor
+ m_Pointer = a_MobPointer.m_Pointer;
+ a_MobPointer.m_Pointer = nullptr;
+}
+
+
+
+
+
+cMobPointer& cMobPointer::operator=(const cMobPointer& a_MobPointer)
+{
+ // Copy assignment operator
+ m_Pointer = a_MobPointer.m_Pointer;
+ return *this;
+}
+
+
+
+
+
+cMobPointer& cMobPointer::operator=(cMobPointer&& a_MobPointer)
+{
+ // Move assignment operator
+ m_Pointer = a_MobPointer.m_Pointer;
+ a_MobPointer.m_Pointer = nullptr;
+ return *this;
+}
+
+
+
+
+
+void cMobPointer::operator=(cPawn * a_Pointer)
+{
+ m_Pointer = a_Pointer;
+}
+
+
+
+
+
+cPawn * cMobPointer::GetPointer()
+{
+ if (m_Pointer != nullptr)
+ {
+ if (!m_Pointer->IsTicking())
+ {
+ m_Pointer = nullptr;
+ }
+ }
+ return m_Pointer;
+}
diff --git a/src/Mobs/MobPointer.h b/src/Mobs/MobPointer.h
new file mode 100644
index 000000000..109b0511e
--- /dev/null
+++ b/src/Mobs/MobPointer.h
@@ -0,0 +1,34 @@
+#pragma once
+
+/** This class allows mobs to hold pointers to other mobs/players in a safe manner.
+When calling GetPointer(), it first checks if the Monster/Player being pointed to is still valid.
+If not, it returns a nullptr. The returned raw pointer must be used locally and then discarded.
+it MUST NOT be preserved across ticks.
+*/
+
+class cPawn;
+class cMobPointer
+{
+public:
+ cMobPointer(cPawn * a_Pointer); // Constructor
+ cMobPointer(const cMobPointer & a_MobPointer); // Copy constructor
+ cMobPointer(cMobPointer && a_MobPointer); // Move constructor
+ cMobPointer& operator=(const cMobPointer& a_MobPointer); // Copy assignment operator
+ cMobPointer& operator=(cMobPointer&& a_MobPointer); // Move assignment operator
+
+ void operator=(cPawn * a_Pointer); // set Pointer
+
+ /** Returns the raw pointer. The returned raw pointer must
+ be used locally and then discarded. it MUST NOT be preserved across ticks.
+ Returns null if raw pointer is null. Returns null if mob is destroyed or moved worlds.
+ Must be called at least once per tick, even if the raw pointer is not going to be used that tick. */
+ cPawn * GetPointer();
+
+
+private:
+ cPawn * m_Pointer;
+} ;
+
+
+
+
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index be240d55c..6bee21775 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -112,7 +112,7 @@ cMonster::cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const A
, m_LeashToPos(nullptr)
, m_IsLeashActionJustDone(false)
, m_CanBeLeashed(GetMobFamily() == eFamily::mfPassive)
- , m_Target(nullptr)
+ , m_LookingAt(nullptr)
, m_CurrentTickControllingBehavior(nullptr)
, m_NewTickControllingBehavior(nullptr)
, m_TickControllingBehaviorState(Normal)
@@ -129,7 +129,7 @@ cMonster::cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const A
cMonster::~cMonster()
{
- ASSERT(GetTarget() == nullptr);
+
}
@@ -167,7 +167,6 @@ void cMonster::Destroyed()
Behavior->Destroyed();
}
- SetTarget(nullptr); // Tell them we're no longer targeting them.
super::Destroyed();
}
@@ -519,9 +518,10 @@ void cMonster::CalcLeashActions()
void cMonster::SetPitchAndYawFromDestination(bool a_IsFollowingPath)
{
Vector3d BodyDistance;
- if (!a_IsFollowingPath && (GetTarget() != nullptr))
+ cPawn * LookingAt = m_LookingAt.GetPointer();
+ if (!a_IsFollowingPath && (LookingAt != nullptr))
{
- BodyDistance = GetTarget()->GetPosition() - GetPosition();
+ BodyDistance = LookingAt->GetPosition() - GetPosition();
}
else
{
@@ -533,15 +533,15 @@ void cMonster::SetPitchAndYawFromDestination(bool a_IsFollowingPath)
SetYaw(BodyRotation);
Vector3d HeadDistance;
- if (GetTarget() != nullptr)
+ if (LookingAt != nullptr)
{
- if (GetTarget()->IsPlayer()) // Look at a player
+ if (LookingAt->IsPlayer()) // Look at a player
{
- HeadDistance = GetTarget()->GetPosition() - GetPosition();
+ HeadDistance = LookingAt->GetPosition() - GetPosition();
}
else // Look at some other entity
{
- HeadDistance = GetTarget()->GetPosition() - GetPosition();
+ HeadDistance = LookingAt->GetPosition() - GetPosition();
// HeadDistance.y = GetTarget()->GetPosY() + GetHeight();
}
}
@@ -975,16 +975,19 @@ int cMonster::GetSpawnDelay(cMonster::eFamily a_MobFamily)
-/** Sets the target. */
-void cMonster::SetTarget (cPawn * a_NewTarget)
+
+void cMonster::SetLookingAt(cPawn * a_NewTarget)
{
+ m_LookingAt = a_NewTarget;
+
+ /*
ASSERT((a_NewTarget == nullptr) || (IsTicking()));
- if (m_Target == a_NewTarget)
+ if (m_LookingAt == a_NewTarget)
{
return;
}
- cPawn * OldTarget = m_Target;
- m_Target = a_NewTarget;
+ cPawn * OldTarget = m_LookingAt;
+ m_LookingAt = a_NewTarget;
if (OldTarget != nullptr)
{
@@ -998,32 +1001,13 @@ void cMonster::SetTarget (cPawn * a_NewTarget)
// Notify the new target that we are now targeting it.
m_Target->TargetingMe(this);
m_WasLastTargetAPlayer = m_Target->IsPlayer();
- }
+ }*/
}
-
-void cMonster::UnsafeUnsetTarget()
-{
- m_Target = nullptr;
-}
-
-
-
-
-
-cPawn * cMonster::GetTarget()
-{
- return m_Target;
-}
-
-
-
-
-
bool cMonster::IsPathFinderActivated() const
{
return m_PathfinderActivated;
diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h
index d864f9971..47688ae91 100644
--- a/src/Mobs/Monster.h
+++ b/src/Mobs/Monster.h
@@ -5,6 +5,7 @@
#include "MonsterTypes.h"
#include "PathFinder.h"
#include "Behaviors/BehaviorWanderer.h"
+#include "MobPointer.h"
#include <vector>
class cItem;
@@ -185,14 +186,7 @@ public:
static AString MobTypeToVanillaNBT(eMonsterType a_MobType);
/** Sets the target that this mob will chase. Pass a nullptr to unset. */
- void SetTarget (cPawn * a_NewTarget);
-
- /** Unset the target without notifying the target entity. Do not use this, use SetTarget(nullptr) instead.
- This is only used by cPawn internally. */
- void UnsafeUnsetTarget();
-
- /** Returns the current target. */
- cPawn * GetTarget();
+ void SetLookingAt(cPawn * a_NewTarget);
/** Creates a new object of the specified mob.
a_MobType is the type of the mob to be created
@@ -326,10 +320,8 @@ public:
void AddRandomWeaponDropItem(cItems & a_Drops, unsigned int a_LootingLevel);
private:
- /** A pointer to the entity this mobile is aiming to reach.
- The validity of this pointer SHALL be guaranteed by the pointee;
- it MUST be reset when the pointee changes worlds or is destroyed. */
- cPawn * m_Target;
+ /** A pointer to the entity this mobile is lookingAt */
+ cMobPointer m_LookingAt;
/** Leash calculations inside Tick function */
void CalcLeashActions();
diff --git a/src/Mobs/Zombie.h b/src/Mobs/Zombie.h
index 47a9f1904..66b6b6362 100644
--- a/src/Mobs/Zombie.h
+++ b/src/Mobs/Zombie.h
@@ -7,9 +7,9 @@
class cZombie :
- public cAggressiveMonster
+ public cMonster
{
- typedef cAggressiveMonster super;
+ typedef cMonster super;
public:
cZombie(bool a_IsVillagerZombie);