From 00febf68ad8bc36546c02b0c0b926189fb3955a1 Mon Sep 17 00:00:00 2001 From: LogicParrot Date: Wed, 30 Aug 2017 00:13:25 +0300 Subject: Much safer raw pointers to entities --- src/Mobs/CMakeLists.txt | 2 ++ src/Mobs/MobPointer.cpp | 75 +++++++++++++++++++++++++++++++++++++++++++++++++ src/Mobs/MobPointer.h | 34 ++++++++++++++++++++++ src/Mobs/Monster.cpp | 52 ++++++++++++---------------------- src/Mobs/Monster.h | 16 +++-------- src/Mobs/Zombie.h | 4 +-- 6 files changed, 135 insertions(+), 48 deletions(-) create mode 100644 src/Mobs/MobPointer.cpp create mode 100644 src/Mobs/MobPointer.h (limited to 'src/Mobs') 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 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); -- cgit v1.2.3