From 4ef47aed62364f9cf1474864e5cf94232b4477af Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 19 Dec 2016 20:12:23 +0000 Subject: Changed entity ownership model to use smart pointers --- src/Entities/Entity.cpp | 19 ++++++++++--------- src/Entities/Entity.h | 4 +--- src/Entities/Player.cpp | 14 +++++++++----- src/Entities/Player.h | 2 +- src/Entities/ProjectileEntity.cpp | 22 +++++++++++----------- src/Entities/ProjectileEntity.h | 2 +- 6 files changed, 33 insertions(+), 30 deletions(-) (limited to 'src/Entities') diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index b596bc93d..3167d2917 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -135,9 +135,9 @@ const char * cEntity::GetParentClass(void) const -bool cEntity::Initialize(cWorld & a_World) +bool cEntity::Initialize(OwnedEntity a_Self, cWorld & a_EntityWorld) { - if (cPluginManager::Get()->CallHookSpawningEntity(a_World, *this)) + if (cPluginManager::Get()->CallHookSpawningEntity(a_EntityWorld, *this)) { return false; } @@ -151,13 +151,13 @@ bool cEntity::Initialize(cWorld & a_World) ASSERT(m_World == nullptr); ASSERT(GetParentChunk() == nullptr); - a_World.AddEntity(this); + a_EntityWorld.AddEntity(std::move(a_Self)); ASSERT(m_World != nullptr); - cPluginManager::Get()->CallHookSpawnedEntity(a_World, *this); + cPluginManager::Get()->CallHookSpawnedEntity(a_EntityWorld, *this); // Spawn the entity on the clients: - a_World.BroadcastSpawnEntity(*this); + a_EntityWorld.BroadcastSpawnEntity(*this); return true; } @@ -230,8 +230,10 @@ void cEntity::Destroy(bool a_ShouldBroadcast) this->GetUniqueID(), this->GetClass(), ParentChunk->GetPosX(), ParentChunk->GetPosZ() ); - ParentChunk->RemoveEntity(this); - delete this; + + // Make sure that RemoveEntity returned a valid smart pointer + // Also, not storing the returned pointer means automatic destruction + VERIFY(ParentChunk->RemoveEntity(*this)); }); Destroyed(); } @@ -1585,8 +1587,7 @@ bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d a_OldWorld.GetName().c_str(), a_World->GetName().c_str(), ParentChunk->GetPosX(), ParentChunk->GetPosZ() ); - ParentChunk->RemoveEntity(this); - a_World->AddEntity(this); + a_World->AddEntity(ParentChunk->RemoveEntity(*this)); cRoot::Get()->GetPluginManager()->CallHookEntityChangedWorld(*this, a_OldWorld); }); return true; diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index 8991b9fad..8f433b816 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -157,7 +157,7 @@ public: /** Spawns the entity in the world; returns true if spawned, false if not (plugin disallowed). Adds the entity to the world. */ - virtual bool Initialize(cWorld & a_World); + virtual bool Initialize(OwnedEntity a_Self, cWorld & a_EntityWorld); // tolua_begin @@ -670,8 +670,6 @@ private: int m_InvulnerableTicks; } ; // tolua_export -typedef std::list cEntityList; - diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 3bbe334fb..aaf06fa34 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -149,12 +149,12 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) : -bool cPlayer::Initialize(cWorld & a_World) +bool cPlayer::Initialize(OwnedEntity a_Self, cWorld & a_World) { UNUSED(a_World); ASSERT(GetWorld() != nullptr); ASSERT(GetParentChunk() == nullptr); - GetWorld()->AddPlayer(this); + GetWorld()->AddPlayer(std::unique_ptr(static_cast(a_Self.release()))); cPluginManager::Get()->CallHookSpawnedEntity(*GetWorld(), *this); @@ -2003,7 +2003,9 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d GetWorld()->BroadcastDestroyEntity(*this); // Remove player from world - GetWorld()->RemovePlayer(this, false); + // Make sure that RemovePlayer didn't return a valid smart pointer, due to the second parameter being false + // We remain valid and not destructed after this call + VERIFY(!GetWorld()->RemovePlayer(*this, false)); // Set position to the new position SetPosition(a_NewPosition); @@ -2045,8 +2047,10 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d a_OldWorld.GetName().c_str(), a_World->GetName().c_str(), ParentChunk->GetPosX(), ParentChunk->GetPosZ() ); - ParentChunk->RemoveEntity(this); - a_World->AddPlayer(this, &a_OldWorld); // New world will take over and announce client at its next tick + + // New world will take over and announce client at its next tick + auto PlayerPtr = static_cast(ParentChunk->RemoveEntity(*this).release()); + a_World->AddPlayer(std::unique_ptr(PlayerPtr), &a_OldWorld); }); return true; diff --git a/src/Entities/Player.h b/src/Entities/Player.h index c00dbc7f1..8c21c25d6 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -41,7 +41,7 @@ public: cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName); - virtual bool Initialize(cWorld & a_World) override; + virtual bool Initialize(OwnedEntity a_Self, cWorld & a_World) override; virtual ~cPlayer() override; diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp index 64522acef..d1e101964 100644 --- a/src/Entities/ProjectileEntity.cpp +++ b/src/Entities/ProjectileEntity.cpp @@ -260,7 +260,7 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Ve -cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem * a_Item, const Vector3d * a_Speed) +std::unique_ptr cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem * a_Item, const Vector3d * a_Speed) { Vector3d Speed; if (a_Speed != nullptr) @@ -270,15 +270,15 @@ cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator, switch (a_Kind) { - case pkArrow: return new cArrowEntity (a_Creator, a_X, a_Y, a_Z, Speed); - case pkEgg: return new cThrownEggEntity (a_Creator, a_X, a_Y, a_Z, Speed); - case pkEnderPearl: return new cThrownEnderPearlEntity(a_Creator, a_X, a_Y, a_Z, Speed); - case pkSnowball: return new cThrownSnowballEntity (a_Creator, a_X, a_Y, a_Z, Speed); - case pkGhastFireball: return new cGhastFireballEntity (a_Creator, a_X, a_Y, a_Z, Speed); - case pkFireCharge: return new cFireChargeEntity (a_Creator, a_X, a_Y, a_Z, Speed); - case pkExpBottle: return new cExpBottleEntity (a_Creator, a_X, a_Y, a_Z, Speed); - case pkSplashPotion: return new cSplashPotionEntity (a_Creator, a_X, a_Y, a_Z, Speed, *a_Item); - case pkWitherSkull: return new cWitherSkullEntity (a_Creator, a_X, a_Y, a_Z, Speed); + case pkArrow: return cpp14::make_unique (a_Creator, a_X, a_Y, a_Z, Speed); + case pkEgg: return cpp14::make_unique (a_Creator, a_X, a_Y, a_Z, Speed); + case pkEnderPearl: return cpp14::make_unique(a_Creator, a_X, a_Y, a_Z, Speed); + case pkSnowball: return cpp14::make_unique (a_Creator, a_X, a_Y, a_Z, Speed); + case pkGhastFireball: return cpp14::make_unique (a_Creator, a_X, a_Y, a_Z, Speed); + case pkFireCharge: return cpp14::make_unique (a_Creator, a_X, a_Y, a_Z, Speed); + case pkExpBottle: return cpp14::make_unique (a_Creator, a_X, a_Y, a_Z, Speed); + case pkSplashPotion: return cpp14::make_unique (a_Creator, a_X, a_Y, a_Z, Speed, *a_Item); + case pkWitherSkull: return cpp14::make_unique (a_Creator, a_X, a_Y, a_Z, Speed); case pkFirework: { ASSERT(a_Item != nullptr); @@ -287,7 +287,7 @@ cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator, return nullptr; } - return new cFireworkEntity(a_Creator, a_X, a_Y, a_Z, *a_Item); + return cpp14::make_unique(a_Creator, a_X, a_Y, a_Z, *a_Item); } case pkFishingFloat: break; } diff --git a/src/Entities/ProjectileEntity.h b/src/Entities/ProjectileEntity.h index b354c7cfc..da8c650f5 100644 --- a/src/Entities/ProjectileEntity.h +++ b/src/Entities/ProjectileEntity.h @@ -46,7 +46,7 @@ public: cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height); cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height); - static cProjectileEntity * Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem * a_Item, const Vector3d * a_Speed = nullptr); + static std::unique_ptr Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem * a_Item, const Vector3d * a_Speed = nullptr); /** Called by the physics blocktracer when the entity hits a solid block, the hit position and the face hit (BLOCK_FACE_) is given */ virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace); -- cgit v1.2.3