summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@hotmail.co.uk>2016-12-18 21:41:37 +0100
committerTiger Wang <ziwei.tiger@hotmail.co.uk>2016-12-18 21:41:37 +0100
commitb5b119ca750a1790848b514bb00831b050f25fac (patch)
treee7a145a856676d248da5050b57da1cee4d005815
parenttest (diff)
downloadcuberite-b5b119ca750a1790848b514bb00831b050f25fac.tar
cuberite-b5b119ca750a1790848b514bb00831b050f25fac.tar.gz
cuberite-b5b119ca750a1790848b514bb00831b050f25fac.tar.bz2
cuberite-b5b119ca750a1790848b514bb00831b050f25fac.tar.lz
cuberite-b5b119ca750a1790848b514bb00831b050f25fac.tar.xz
cuberite-b5b119ca750a1790848b514bb00831b050f25fac.tar.zst
cuberite-b5b119ca750a1790848b514bb00831b050f25fac.zip
-rw-r--r--src/BlockEntities/MobSpawnerEntity.cpp4
-rw-r--r--src/Chunk.cpp125
-rw-r--r--src/Chunk.h34
-rw-r--r--src/ChunkDef.h2
-rw-r--r--src/ChunkMap.cpp40
-rw-r--r--src/ChunkMap.h9
-rw-r--r--src/Entities/Entity.cpp2
-rw-r--r--src/Entities/Entity.h2
-rw-r--r--src/Entities/Pawn.cpp61
-rw-r--r--src/Entities/Pawn.h20
-rw-r--r--src/Entities/ProjectileEntity.cpp22
-rw-r--r--src/Entities/ProjectileEntity.h2
-rw-r--r--src/Entities/ThrownEnderPearlEntity.cpp2
-rw-r--r--src/Generating/FinishGen.cpp4
-rw-r--r--src/Items/ItemBoat.h3
-rw-r--r--src/Items/ItemBow.h11
-rw-r--r--src/Items/ItemFishingRod.h4
-rw-r--r--src/Items/ItemItemFrame.h6
-rw-r--r--src/Items/ItemMinecart.h17
-rw-r--r--src/Items/ItemPainting.h4
-rw-r--r--src/MobSpawner.cpp14
-rw-r--r--src/MobSpawner.h6
-rw-r--r--src/Mobs/Blaze.cpp10
-rw-r--r--src/Mobs/Ghast.cpp10
-rw-r--r--src/Mobs/Monster.cpp113
-rw-r--r--src/Mobs/Monster.h20
-rw-r--r--src/Mobs/Skeleton.cpp10
-rw-r--r--src/Mobs/Slime.cpp4
-rw-r--r--src/Mobs/Wither.cpp13
-rw-r--r--src/Mobs/Wither.h1
-rw-r--r--src/Simulator/SandSimulator.cpp4
-rw-r--r--src/World.cpp108
-rw-r--r--src/World.h4
-rwxr-xr-xsrc/WorldStorage/WSSAnvil.cpp102
34 files changed, 348 insertions, 445 deletions
diff --git a/src/BlockEntities/MobSpawnerEntity.cpp b/src/BlockEntities/MobSpawnerEntity.cpp
index 7f1b88c9b..cbf94de57 100644
--- a/src/BlockEntities/MobSpawnerEntity.cpp
+++ b/src/BlockEntities/MobSpawnerEntity.cpp
@@ -163,7 +163,7 @@ void cMobSpawnerEntity::SpawnEntity(void)
double PosX = Chunk->GetPosX() * cChunkDef::Width + RelX;
double PosZ = Chunk->GetPosZ() * cChunkDef::Width + RelZ;
- cMonster * Monster = cMonster::NewMonsterFromType(m_MobType);
+ auto Monster = cMonster::NewMonsterFromType(m_MobType);
if (Monster == nullptr)
{
continue;
@@ -171,7 +171,7 @@ void cMobSpawnerEntity::SpawnEntity(void)
Monster->SetPosition(PosX, RelY, PosZ);
Monster->SetYaw(Random.NextFloat() * 360.0f);
- if (Chunk->GetWorld()->SpawnMobFinalize(Monster) != cEntity::INVALID_ID)
+ if (Chunk->GetWorld()->SpawnMobFinalize(std::move(Monster)) != cEntity::INVALID_ID)
{
EntitiesSpawned = true;
Chunk->BroadcastSoundParticleEffect(
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index b5c2339b7..8068b2119 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -131,17 +131,18 @@ cChunk::~cChunk()
}
m_BlockEntities.clear();
- // Remove and destroy all entities that are not players:
- cEntityList Entities;
- std::swap(Entities, m_Entities); // Need another list because cEntity destructors check if they've been removed from chunk
- for (cEntityList::const_iterator itr = Entities.begin(); itr != Entities.end(); ++itr)
+ // Remove and destroy all entities:
+ for (auto & Entity : m_Entities)
{
- if (!(*itr)->IsPlayer())
+ if (Entity->IsDestroyed())
{
- // Scheduling a normal destruction is neither possible (Since this chunk will be gone till the schedule occurs) nor necessary.
- (*itr)->DestroyNoScheduling(false); // No point in broadcasting in an unloading chunk. Chunks unload when no one is nearby.
- delete *itr;
+ // Workaround to mitigate crashing in cPlayer::SaveToDisk which may try to access destroyed member variables on server stop
+ // All entities will have been destroyed in cWorld::Stop in this circumstance
+ continue;
}
+
+ // Scheduling a normal destruction is neither possible (Since this chunk will be gone till the schedule occurs) nor necessary.
+ Entity->DestroyNoScheduling(false); // No point in broadcasting in an unloading chunk. Chunks unload when no one is nearby.
}
if (m_NeighborXM != nullptr)
@@ -284,9 +285,9 @@ void cChunk::GetAllData(cChunkDataCallback & a_Callback)
a_Callback.ChunkData(m_ChunkData);
- for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
+ for (const auto & Entity : m_Entities)
{
- a_Callback.Entity(*itr);
+ a_Callback.Entity(Entity.get());
}
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
@@ -483,7 +484,7 @@ void cChunk::CollectMobCensus(cMobCensus & toFill)
}
Vector3d currentPosition;
- for (auto entity : m_Entities)
+ for (auto & entity : m_Entities)
{
// LOGD("Counting entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass());
if (entity->IsMob())
@@ -581,7 +582,7 @@ void cChunk::SpawnMobs(cMobSpawner & a_MobSpawner)
continue;
}
- cEntity * newMob = a_MobSpawner.TryToSpawnHere(this, TryX, TryY, TryZ, Biome, MaxNbOfSuccess);
+ auto newMob = a_MobSpawner.TryToSpawnHere(this, TryX, TryY, TryZ, Biome, MaxNbOfSuccess);
if (newMob == nullptr)
{
continue;
@@ -605,7 +606,7 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt)
// If we are not valid, tick players and bailout
if (!IsValid())
{
- for (auto Entity : m_Entities)
+ for (const auto & Entity : m_Entities)
{
if (Entity->IsPlayer())
{
@@ -630,7 +631,7 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt)
m_IsDirty = (*itr)->Tick(a_Dt, *this) | m_IsDirty;
}
- for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
+ for (auto itr = m_Entities.begin(); itr != m_Entities.end();)
{
// Do not tick mobs that are detached from the world. They're either scheduled for teleportation or for removal.
if (!(*itr)->IsTicking())
@@ -655,20 +656,22 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt)
continue;
}
- if ((((*itr)->GetChunkX() != m_PosX) ||
- ((*itr)->GetChunkZ() != m_PosZ))
+ if (
+ ((*itr)->GetChunkX() != m_PosX) ||
+ ((*itr)->GetChunkZ() != m_PosZ)
)
{
- // This block is very similar to RemoveEntity, except it uses an iterator to avoid scanning the whole m_Entities
- // The entity moved out of the chunk, move it to the neighbor
-
(*itr)->SetParentChunk(nullptr);
- MoveEntityToNewChunk(*itr);
+
// Mark as dirty if it was a server-generated entity:
if (!(*itr)->IsPlayer())
{
MarkDirty();
}
+
+ // The entity moved out of the chunk, move it to the neighbor
+ MoveEntityToNewChunk(std::move(*itr));
+
itr = m_Entities.erase(itr);
}
else
@@ -697,7 +700,7 @@ void cChunk::TickBlock(int a_RelX, int a_RelY, int a_RelZ)
-void cChunk::MoveEntityToNewChunk(cEntity * a_Entity)
+void cChunk::MoveEntityToNewChunk(std::unique_ptr<cEntity> a_Entity)
{
cChunk * Neighbor = GetNeighborChunk(a_Entity->GetChunkX() * cChunkDef::Width, a_Entity->GetChunkZ() * cChunkDef::Width);
if (Neighbor == nullptr)
@@ -711,28 +714,29 @@ void cChunk::MoveEntityToNewChunk(cEntity * a_Entity)
}
ASSERT(Neighbor != this); // Moving into the same chunk? wtf?
- Neighbor->AddEntity(a_Entity);
+ auto & EntityPtr = *a_Entity;
+ Neighbor->AddEntity(std::move(a_Entity));
class cMover :
public cClientDiffCallback
{
virtual void Removed(cClientHandle * a_Client) override
{
- a_Client->SendDestroyEntity(*m_Entity);
+ a_Client->SendDestroyEntity(m_Entity);
}
virtual void Added(cClientHandle * a_Client) override
{
- m_Entity->SpawnOn(*a_Client);
+ m_Entity.SpawnOn(*a_Client);
}
- cEntity * m_Entity;
+ cEntity & m_Entity;
public:
- cMover(cEntity * a_CallbackEntity) :
+ cMover(cEntity & a_CallbackEntity) :
m_Entity(a_CallbackEntity)
{}
- } Mover(a_Entity);
+ } Mover(EntityPtr);
m_ChunkMap->CompareChunkClients(this, Neighbor, Mover);
}
@@ -1810,15 +1814,15 @@ void cChunk::CollectPickupsByPlayer(cPlayer & a_Player)
double PosY = a_Player.GetPosY();
double PosZ = a_Player.GetPosZ();
- for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
+ for (auto & Entity : m_Entities)
{
- if ((!(*itr)->IsPickup()) && (!(*itr)->IsProjectile()))
+ if ((!Entity->IsPickup()) && (!Entity->IsProjectile()))
{
continue; // Only pickups and projectiles can be picked up
}
- float DiffX = static_cast<float>((*itr)->GetPosX() - PosX);
- float DiffY = static_cast<float>((*itr)->GetPosY() - PosY);
- float DiffZ = static_cast<float>((*itr)->GetPosZ() - PosZ);
+ float DiffX = static_cast<float>(Entity->GetPosX() - PosX);
+ float DiffY = static_cast<float>(Entity->GetPosY() - PosY);
+ float DiffZ = static_cast<float>(Entity->GetPosZ() - PosZ);
float SqrDist = DiffX * DiffX + DiffY * DiffY + DiffZ * DiffZ;
if (SqrDist < 1.5f * 1.5f) // 1.5 block
{
@@ -1828,13 +1832,13 @@ void cChunk::CollectPickupsByPlayer(cPlayer & a_Player)
);
*/
MarkDirty();
- if ((*itr)->IsPickup())
+ if (Entity->IsPickup())
{
- (reinterpret_cast<cPickup *>(*itr))->CollectedBy(a_Player);
+ reinterpret_cast<cPickup *>(Entity.get())->CollectedBy(a_Player);
}
else
{
- (reinterpret_cast<cProjectileEntity *>(*itr))->CollectedBy(a_Player);
+ reinterpret_cast<cProjectileEntity *>(Entity.get())->CollectedBy(a_Player);
}
}
else if (SqrDist < 5 * 5)
@@ -1970,34 +1974,49 @@ bool cChunk::HasAnyClients(void) const
-void cChunk::AddEntity(cEntity * a_Entity)
+void cChunk::AddEntity(std::unique_ptr<cEntity> a_Entity)
{
if (!a_Entity->IsPlayer())
{
MarkDirty();
}
+ auto EntityPtr = a_Entity.get();
+
ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end()); // Not there already
+ m_Entities.emplace_back(std::move(a_Entity));
- m_Entities.push_back(a_Entity);
- ASSERT(a_Entity->GetParentChunk() == nullptr);
- a_Entity->SetParentChunk(this);
+ ASSERT(EntityPtr->GetParentChunk() == nullptr);
+ EntityPtr->SetParentChunk(this);
+ EntityPtr->SetIsTicking(true);
}
-void cChunk::RemoveEntity(cEntity * a_Entity)
+void cChunk::RemoveEntity(cEntity & a_Entity)
{
- ASSERT(a_Entity->GetParentChunk() == this);
- a_Entity->SetParentChunk(nullptr);
- m_Entities.remove(a_Entity);
- // Mark as dirty if it was a server-generated entity:
- if (!a_Entity->IsPlayer())
+ ASSERT(a_Entity.GetParentChunk() == this);
+ ASSERT(!a_Entity.IsTicking());
+ a_Entity.SetParentChunk(nullptr);
+
+ if (!a_Entity.IsPlayer())
{
MarkDirty();
}
+
+ m_Entities.erase(
+ std::remove_if(
+ m_Entities.begin(),
+ m_Entities.end(),
+ [&a_Entity](const decltype(m_Entities)::value_type & a_Value)
+ {
+ return (a_Value.get() == &a_Entity);
+ }
+ ),
+ m_Entities.end()
+ );
}
@@ -2006,13 +2025,13 @@ void cChunk::RemoveEntity(cEntity * a_Entity)
bool cChunk::HasEntity(UInt32 a_EntityID)
{
- for (cEntityList::const_iterator itr = m_Entities.begin(), end = m_Entities.end(); itr != end; ++itr)
+ for (const auto & Entity : m_Entities)
{
- if ((*itr)->GetUniqueID() == a_EntityID)
+ if (Entity->GetUniqueID() == a_EntityID)
{
return true;
}
- } // for itr - m_Entities[]
+ }
return false;
}
@@ -2023,14 +2042,14 @@ bool cChunk::HasEntity(UInt32 a_EntityID)
bool cChunk::ForEachEntity(cEntityCallback & a_Callback)
{
// The entity list is locked by the parent chunkmap's CS
- for (cEntityList::iterator itr = m_Entities.begin(), itr2 = itr; itr != m_Entities.end(); itr = itr2)
+ for (auto itr = m_Entities.begin(), itr2 = itr; itr != m_Entities.end(); itr = itr2)
{
++itr2;
if (!(*itr)->IsTicking())
{
continue;
}
- if (a_Callback.Item(*itr))
+ if (a_Callback.Item((*itr).get()))
{
return false;
}
@@ -2045,7 +2064,7 @@ bool cChunk::ForEachEntity(cEntityCallback & a_Callback)
bool cChunk::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback)
{
// The entity list is locked by the parent chunkmap's CS
- for (cEntityList::iterator itr = m_Entities.begin(), itr2 = itr; itr != m_Entities.end(); itr = itr2)
+ for (auto itr = m_Entities.begin(), itr2 = itr; itr != m_Entities.end(); itr = itr2)
{
++itr2;
if (!(*itr)->IsTicking())
@@ -2058,7 +2077,7 @@ bool cChunk::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_
// The entity is not in the specified box
continue;
}
- if (a_Callback.Item(*itr))
+ if (a_Callback.Item((*itr).get()))
{
return false;
}
@@ -2093,7 +2112,7 @@ bool cChunk::ForEachBlockEntity(cBlockEntityCallback & a_Callback)
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
{
++itr2;
- if (a_Callback.Item((*itr).get()))
+ if (a_Callback.Item(*itr))
{
return false;
}
diff --git a/src/Chunk.h b/src/Chunk.h
index ecb594191..a75054d30 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -485,6 +485,36 @@ public:
return m_LoadedByClient;
}
+ std::unique_ptr<cEntity> AcquireAssociatedEntityPtr(const cEntity & a_Entity)
+ {
+ auto Iterator = std::find_if(
+ m_Entities.begin(),
+ m_Entities.end(),
+ [&a_Entity](const decltype(m_Entities)::value_type & a_Value)
+ {
+ return (a_Value.get() == &a_Entity);
+ }
+ );
+
+ if (Iterator == m_Entities.cend())
+ {
+ return nullptr;
+ }
+ else
+ {
+ auto Entity = std::move(*Iterator);
+ Entity->SetParentChunk(nullptr);
+
+ if (!Entity->IsPlayer())
+ {
+ MarkDirty();
+ }
+
+ m_Entities.erase(Iterator);
+ return Entity;
+ }
+ }
+
private:
friend class cChunkMap;
@@ -519,8 +549,8 @@ private:
std::vector<Vector3i> m_ToTickBlocks;
sSetBlockVector m_PendingSendBlocks; ///< Blocks that have changed and need to be sent to all clients
- cEntityList m_Entities;
std::vector<std::weak_ptr<cClientHandle>> m_LoadedByClient;
+ std::vector<std::unique_ptr<cEntity>> m_Entities;
cBlockEntityList m_BlockEntities;
/** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */
@@ -594,7 +624,7 @@ private:
bool GrowMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, MTRand & a_Random);
/** Called by Tick() when an entity moves out of this chunk into a neighbor; moves the entity and sends spawn / despawn packet to clients */
- void MoveEntityToNewChunk(cEntity * a_Entity);
+ void MoveEntityToNewChunk(std::unique_ptr<cEntity> a_Entity);
};
typedef cChunk * cChunkPtr;
diff --git a/src/ChunkDef.h b/src/ChunkDef.h
index d146fe9ac..f99cc761b 100644
--- a/src/ChunkDef.h
+++ b/src/ChunkDef.h
@@ -31,7 +31,7 @@ class cEntity;
class cClientHandle;
class cBlockEntity;
-typedef std::list<cEntity *> cEntityList;
+typedef std::vector<std::unique_ptr<cEntity>> cEntityList;
typedef std::list<cBlockEntity *> cBlockEntityList;
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index 2e6153f0e..abd4eb8bf 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -1582,51 +1582,19 @@ void cChunkMap::RemoveChunkClient(int a_ChunkX, int a_ChunkZ, const std::shared_
+void cChunkMap::AddEntity(std::unique_ptr<cEntity> a_Entity)
{
- for (const auto & Chunk : m_Chunks)
- {
- Chunk.second->RemoveClient(a_Client);
- }
-}
-
-
-
-
-
-void cChunkMap::AddEntity(cEntity * a_Entity)
-{
- cCSLock Lock(m_CSChunks);
- cChunkPtr Chunk = GetChunk(a_Entity->GetChunkX(), a_Entity->GetChunkZ());
- if (Chunk == nullptr) // This will assert inside GetChunk in Debug builds
- {
- LOGWARNING("Entity at %p (%s, ID %d) spawning in a non-existent chunk, the entity is lost.",
- static_cast<void *>(a_Entity), a_Entity->GetClass(), a_Entity->GetUniqueID()
- );
- return;
- }
- Chunk->AddEntity(a_Entity);
-}
-
-
-
-
ASSERT(GetWorld()->IsInTickThread());
-void cChunkMap::AddEntityIfNotPresent(cEntity * a_Entity)
-{
- cCSLock Lock(m_CSChunks);
cChunkPtr Chunk = GetChunk(a_Entity->GetChunkX(), a_Entity->GetChunkZ());
if (Chunk == nullptr) // This will assert inside GetChunk in Debug builds
{
LOGWARNING("Entity at %p (%s, ID %d) spawning in a non-existent chunk, the entity is lost.",
- static_cast<void *>(a_Entity), a_Entity->GetClass(), a_Entity->GetUniqueID()
+ static_cast<void *>(a_Entity.get()), a_Entity->GetClass(), a_Entity->GetUniqueID()
);
return;
}
- if (!Chunk->HasEntity(a_Entity->GetUniqueID()))
- {
- Chunk->AddEntity(a_Entity);
- }
+ Chunk->AddEntity(std::move(a_Entity));
}
@@ -2574,10 +2542,10 @@ void cChunkMap::GetChunkStats(int & a_NumChunksValid, int & a_NumChunksDirty)
bool cChunkMap::GrowMelonPumpkin(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, MTRand & a_Rand)
{
+ ASSERT(GetWorld()->IsInTickThread());
int ChunkX, ChunkZ;
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
- ASSERT(GetWorld()->IsInTickThread());
cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
if (Chunk != nullptr)
{
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index 7ca62a41d..cad1cddc2 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -211,18 +211,11 @@ public:
void RemoveChunkClient(int a_ChunkX, int a_ChunkZ, const std::shared_ptr<cClientHandle> & a_Client);
/** Adds the entity to its appropriate chunk, takes ownership of the entity pointer */
- void AddEntity(cEntity * a_Entity);
-
- /** Adds the entity to its appropriate chunk, if the entity is not already added.
- Takes ownership of the entity pointer */
- void AddEntityIfNotPresent(cEntity * a_Entity);
+ void AddEntity(std::unique_ptr<cEntity> a_Entity);
/** Returns true if the entity with specified ID is present in the chunks */
bool HasEntity(UInt32 a_EntityID);
- /** Removes the entity from its appropriate chunk */
- void RemoveEntity(cEntity * a_Entity);
-
/** Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true */
bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 489b55cf8..5693bc42b 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -130,7 +130,7 @@ const char * cEntity::GetParentClass(void) const
-bool cEntity::Initialize(cWorld & a_World)
+bool cEntity::Initialize(std::unique_ptr<cEntity> a_Entity, cWorld & a_EntityWorld)
{
ASSERT(a_EntityWorld.IsInTickThread());
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index 25f6e76bf..a8074406c 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -153,7 +153,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(std::unique_ptr<cEntity>a_Entity, cWorld & a_EntityWorld);
// tolua_begin
diff --git a/src/Entities/Pawn.cpp b/src/Entities/Pawn.cpp
index c83e7f3cb..809c51731 100644
--- a/src/Entities/Pawn.cpp
+++ b/src/Entities/Pawn.cpp
@@ -28,9 +28,8 @@ cPawn::cPawn(eEntityType a_EntityType, double a_Width, double a_Height) :
cPawn::~cPawn()
-bool cPawn::OnPreWorldTravel(cWorld & a_NewWorld)
{
- ASSERT(m_TargetingMe.size() == 0);
+ UnsetAllTargeters();
return super::OnPreWorldTravel(a_NewWorld);
}
@@ -40,7 +39,7 @@ bool cPawn::OnPreWorldTravel(cWorld & a_NewWorld)
void cPawn::Destroyed()
{
- StopEveryoneFromTargetingMe();
+ UnsetAllTargeters();
super::Destroyed();
}
@@ -221,32 +220,37 @@ void cPawn::ClearEntityEffects()
-void cPawn::NoLongerTargetingMe(cMonster * a_Monster)
+void cPawn::UnsetAllTargeters()
{
- ASSERT(IsTicking()); // Our destroy override is supposed to clear all targets before we're destroyed.
- for (auto i = m_TargetingMe.begin(); i != m_TargetingMe.end(); ++i)
+ class Callback : public cEntityCallback
{
- cMonster * Monster = *i;
- if (Monster == a_Monster)
+ public:
+ Callback(cPawn & a_Pawn) :
+ m_Pawn(a_Pawn)
{
- ASSERT(Monster->GetTarget() != this); // The monster is notifying us it is no longer targeting us, assert if that's a lie
- m_TargetingMe.erase(i);
- return;
}
- }
- ASSERT(false); // If this happens, something is wrong. Perhaps the monster never called TargetingMe() or called NoLongerTargetingMe() twice.
-}
+ virtual bool Item(cEntity * a_Entity) override
+ {
+ if (!a_Entity->IsMob())
+ {
+ return false;
+ }
+ auto Monster = static_cast<cMonster *>(a_Entity);
+ if (Monster->GetTarget() == &m_Pawn)
+ {
+ Monster->SetTarget(nullptr);
+ }
+ return false;
+ }
+ private:
+ cPawn & m_Pawn;
+ } Callback(*this);
-void cPawn::TargetingMe(cMonster * a_Monster)
-{
- ASSERT(IsTicking());
- ASSERT(m_TargetingMe.size() < 10000);
- ASSERT(a_Monster->GetTarget() == this);
- m_TargetingMe.push_back(a_Monster);
+ GetWorld()->ForEachEntity(Callback);
}
@@ -418,20 +422,3 @@ void cPawn::HandleFalling(void)
because of the client skipping an update about the lava block. This can only be resolved by
somehow integrating these above checks into the tracer in HandlePhysics. */
}
-
-
-
-
-
-void cPawn::StopEveryoneFromTargetingMe()
-{
- std::vector<cMonster*>::iterator i = m_TargetingMe.begin();
- while (i != m_TargetingMe.end())
- {
- cMonster * Monster = *i;
- ASSERT(Monster->GetTarget() == this);
- Monster->UnsafeUnsetTarget();
- i = m_TargetingMe.erase(i);
- }
- ASSERT(m_TargetingMe.size() == 0);
-}
diff --git a/src/Entities/Pawn.h b/src/Entities/Pawn.h
index 74bccc4a3..f613196e1 100644
--- a/src/Entities/Pawn.h
+++ b/src/Entities/Pawn.h
@@ -24,7 +24,6 @@ public:
cPawn(eEntityType a_EntityType, double a_Width, double a_Height);
~cPawn();
- virtual bool OnPreWorldTravel(cWorld & a_NewWorld) override;
virtual void Destroyed() override;
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
@@ -34,11 +33,6 @@ public:
virtual void HandleAir(void) override;
virtual void HandleFalling(void);
- /** Tells all pawns which are targeting us to stop targeting us. */
- void StopEveryoneFromTargetingMe();
-
-
-
// tolua_begin
/** Applies an entity effect.
@@ -59,23 +53,17 @@ public:
// tolua_end
- /** Remove the monster from the list of monsters targeting this pawn. */
- void NoLongerTargetingMe(cMonster * a_Monster);
-
- /** Add the monster to the list of monsters targeting this pawn. (Does not check if already in list!) */
- void TargetingMe(cMonster * a_Monster);
-
protected:
+ /** Resets the targeted entity of all who currently are targeting us in the current world.
+ Fulfils invariant set out in cMonster::m_Target. */
+ void UnsetAllTargeters();
+
typedef std::map<cEntityEffect::eType, cEntityEffect *> tEffectMap;
tEffectMap m_EntityEffects;
double m_LastGroundHeight;
bool m_bTouchGround;
-private:
-
- /** A list of all monsters that are targeting this pawn. */
- std::vector<cMonster*> m_TargetingMe;
} ; // tolua_export
diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp
index c4f705668..ebfaba366 100644
--- a/src/Entities/ProjectileEntity.cpp
+++ b/src/Entities/ProjectileEntity.cpp
@@ -252,7 +252,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> 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)
@@ -262,15 +262,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<cArrowEntity>(a_Creator, a_X, a_Y, a_Z, Speed);
+ case pkEgg: return cpp14::make_unique<cThrownEggEntity>(a_Creator, a_X, a_Y, a_Z, Speed);
+ case pkEnderPearl: return cpp14::make_unique<cThrownEnderPearlEntity>(a_Creator, a_X, a_Y, a_Z, Speed);
+ case pkSnowball: return cpp14::make_unique<cThrownSnowballEntity>(a_Creator, a_X, a_Y, a_Z, Speed);
+ case pkGhastFireball: return cpp14::make_unique<cGhastFireballEntity>(a_Creator, a_X, a_Y, a_Z, Speed);
+ case pkFireCharge: return cpp14::make_unique<cFireChargeEntity>(a_Creator, a_X, a_Y, a_Z, Speed);
+ case pkExpBottle: return cpp14::make_unique<cExpBottleEntity>(a_Creator, a_X, a_Y, a_Z, Speed);
+ case pkSplashPotion: return cpp14::make_unique<cSplashPotionEntity>(a_Creator, a_X, a_Y, a_Z, Speed, *a_Item);
+ case pkWitherSkull: return cpp14::make_unique<cWitherSkullEntity>(a_Creator, a_X, a_Y, a_Z, Speed);
case pkFirework:
{
ASSERT(a_Item != nullptr);
@@ -279,7 +279,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<cFireworkEntity>(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<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);
/** 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);
diff --git a/src/Entities/ThrownEnderPearlEntity.cpp b/src/Entities/ThrownEnderPearlEntity.cpp
index 4b2e2f9ff..68022d74e 100644
--- a/src/Entities/ThrownEnderPearlEntity.cpp
+++ b/src/Entities/ThrownEnderPearlEntity.cpp
@@ -86,7 +86,7 @@ void cThrownEnderPearlEntity::TeleportCreator(const Vector3d & a_HitPos)
virtual bool Item(cPlayer * a_Entity) override
{
// Teleport the creator here, make them take 5 damage:
- a_Entity->TeleportToCoords(m_HitPos.x, m_HitPos.y + 0.2, m_HitPos.z);
+ a_Entity->TeleportToCoords(m_HitPos + Vector3d(0, 0.2, 0));
a_Entity->TakeDamage(dtEnderPearl, m_Attacker, 5, 0);
return true;
}
diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp
index 3f6a1dc7a..f9e43d9fd 100644
--- a/src/Generating/FinishGen.cpp
+++ b/src/Generating/FinishGen.cpp
@@ -1483,11 +1483,11 @@ bool cFinishGenPassiveMobs::TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int a_RelX
double AnimalY = a_RelY;
double AnimalZ = static_cast<double>(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ + 0.5);
- cMonster * NewMob = cMonster::NewMonsterFromType(AnimalToSpawn);
+ auto NewMob = cMonster::NewMonsterFromType(AnimalToSpawn);
NewMob->SetHealth(NewMob->GetMaxHealth());
NewMob->SetPosition(AnimalX, AnimalY, AnimalZ);
- a_ChunkDesc.GetEntities().push_back(NewMob);
LOGD("Spawning %s #%i at {%.02f, %.02f, %.02f}", NewMob->GetClass(), NewMob->GetUniqueID(), AnimalX, AnimalY, AnimalZ);
+ a_ChunkDesc.GetEntities().emplace_back(std::move(NewMob));
return true;
}
diff --git a/src/Items/ItemBoat.h b/src/Items/ItemBoat.h
index de16c70dc..ad6934916 100644
--- a/src/Items/ItemBoat.h
+++ b/src/Items/ItemBoat.h
@@ -92,8 +92,7 @@ public:
}
// Spawn block at water level
- cBoat * Boat = new cBoat(x + 0.5, y + 0.5, z + 0.5);
- Boat->Initialize(*a_World);
+ a_World->SpawnBoat(x + 0.5, y + 0.5, z + 0.5);
return true;
}
diff --git a/src/Items/ItemBow.h b/src/Items/ItemBow.h
index fc0ee8434..0d4bdd46e 100644
--- a/src/Items/ItemBow.h
+++ b/src/Items/ItemBow.h
@@ -69,17 +69,12 @@ public:
}
// Create the arrow entity:
- cArrowEntity * Arrow = new cArrowEntity(*a_Player, Force * 2);
- if (Arrow == nullptr)
+ auto ArrowPtr = cpp14::make_unique<cArrowEntity>(*a_Player, Force * 2);
+ auto Arrow = ArrowPtr.get();
+ if (!Arrow->Initialize(std::move(ArrowPtr), *a_Player->GetWorld()))
{
return;
}
- if (!Arrow->Initialize(*a_Player->GetWorld()))
- {
- delete Arrow;
- Arrow = nullptr;
- return;
- }
a_Player->GetWorld()->BroadcastSoundEffect(
"random.bow",
a_Player->GetPosX(),
diff --git a/src/Items/ItemFishingRod.h b/src/Items/ItemFishingRod.h
index 3a2ef0275..e44eb09bb 100644
--- a/src/Items/ItemFishingRod.h
+++ b/src/Items/ItemFishingRod.h
@@ -244,9 +244,9 @@ public:
}
else
{
- cFloater * Floater = new cFloater(a_Player->GetPosX(), a_Player->GetStance(), a_Player->GetPosZ(), a_Player->GetLookVector() * 15, a_Player->GetUniqueID(), static_cast<int>(100 + static_cast<unsigned int>(a_World->GetTickRandomNumber(800)) - (a_Player->GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchLure) * 100)));
- Floater->Initialize(*a_World);
+ auto Floater = cpp14::make_unique<cFloater>(a_Player->GetPosX(), a_Player->GetStance(), a_Player->GetPosZ(), a_Player->GetLookVector() * 15, a_Player->GetUniqueID(), static_cast<int>(100 + static_cast<unsigned int>(a_World->GetTickRandomNumber(800)) - (a_Player->GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchLure) * 100)));
a_Player->SetIsFishing(true, Floater->GetUniqueID());
+ Floater->Initialize(std::move(Floater), *a_World);
}
return true;
}
diff --git a/src/Items/ItemItemFrame.h b/src/Items/ItemItemFrame.h
index 77a5bf47c..a670d6cac 100644
--- a/src/Items/ItemItemFrame.h
+++ b/src/Items/ItemItemFrame.h
@@ -38,11 +38,9 @@ public:
if (Block == E_BLOCK_AIR)
{
- cItemFrame * ItemFrame = new cItemFrame(a_BlockFace, a_BlockX, a_BlockY, a_BlockZ);
- if (!ItemFrame->Initialize(*a_World))
+ auto ItemFrame = cpp14::make_unique<cItemFrame>(a_BlockFace, a_BlockX, a_BlockY, a_BlockZ);
+ if (!ItemFrame->Initialize(std::move(ItemFrame), *a_World))
{
- delete ItemFrame;
- ItemFrame = nullptr;
return false;
}
diff --git a/src/Items/ItemMinecart.h b/src/Items/ItemMinecart.h
index 6344c0178..d7ea18719 100644
--- a/src/Items/ItemMinecart.h
+++ b/src/Items/ItemMinecart.h
@@ -59,21 +59,8 @@ public:
double x = static_cast<double>(a_BlockX) + 0.5;
double y = static_cast<double>(a_BlockY) + 0.5;
double z = static_cast<double>(a_BlockZ) + 0.5;
- cMinecart * Minecart = nullptr;
- switch (m_ItemType)
- {
- case E_ITEM_MINECART: Minecart = new cRideableMinecart (x, y, z, cItem(), 1); break;
- case E_ITEM_CHEST_MINECART: Minecart = new cMinecartWithChest (x, y, z); break;
- case E_ITEM_FURNACE_MINECART: Minecart = new cMinecartWithFurnace (x, y, z); break;
- case E_ITEM_MINECART_WITH_TNT: Minecart = new cMinecartWithTNT (x, y, z); break;
- case E_ITEM_MINECART_WITH_HOPPER: Minecart = new cMinecartWithHopper (x, y, z); break;
- default:
- {
- ASSERT(!"Unhandled minecart item");
- return false;
- }
- } // switch (m_ItemType)
- Minecart->Initialize(*a_World);
+
+ a_World->SpawnMinecart(x, y, z, m_ItemType);
if (!a_Player->IsGameModeCreative())
{
diff --git a/src/Items/ItemPainting.h b/src/Items/ItemPainting.h
index dd35931dd..60a231d2b 100644
--- a/src/Items/ItemPainting.h
+++ b/src/Items/ItemPainting.h
@@ -70,8 +70,8 @@ public:
{ "BurningSkull" }
};
- cPainting * Painting = new cPainting(gPaintingTitlesList[a_World->GetTickRandomNumber(ARRAYCOUNT(gPaintingTitlesList) - 1)].Title, a_BlockFace, a_BlockX, a_BlockY, a_BlockZ);
- Painting->Initialize(*a_World);
+ auto Painting = cpp14::make_unique<cPainting>(gPaintingTitlesList[a_World->GetTickRandomNumber(ARRAYCOUNT(gPaintingTitlesList) - 1)].Title, a_BlockFace, a_BlockX, a_BlockY, a_BlockZ);
+ Painting->Initialize(std::move(Painting), *a_World);
if (!a_Player->IsGameModeCreative())
{
diff --git a/src/MobSpawner.cpp b/src/MobSpawner.cpp
index 60f7cfb43..b6ad261b5 100644
--- a/src/MobSpawner.cpp
+++ b/src/MobSpawner.cpp
@@ -347,15 +347,14 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R
-cMonster * cMobSpawner::TryToSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int & a_MaxPackSize)
+std::unique_ptr<cMonster> cMobSpawner::TryToSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int & a_MaxPackSize)
{
- cMonster * toReturn = nullptr;
if (m_NewPack)
{
m_MobType = ChooseMobType(a_Biome);
if (m_MobType == mtInvalidType)
{
- return toReturn;
+ return nullptr;
}
if (m_MobType == mtWolf)
{
@@ -373,14 +372,15 @@ cMonster * cMobSpawner::TryToSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY,
if ((m_AllowedTypes.find(m_MobType) != m_AllowedTypes.end()) && CanSpawnHere(a_Chunk, a_RelX, a_RelY, a_RelZ, m_MobType, a_Biome))
{
- cMonster * newMob = cMonster::NewMonsterFromType(m_MobType);
+ auto newMob = cMonster::NewMonsterFromType(m_MobType);
if (newMob)
{
- m_Spawned.insert(newMob);
+ m_Spawned.insert(std::move(newMob));
}
- toReturn = newMob;
+ return newMob;
}
- return toReturn;
+
+ return nullptr;
}
diff --git a/src/MobSpawner.h b/src/MobSpawner.h
index 3a2776df4..935ded519 100644
--- a/src/MobSpawner.h
+++ b/src/MobSpawner.h
@@ -38,7 +38,7 @@ public :
If this is the first of a Pack, determine the type of monster
a_Biome, BlockType & BlockMeta are used to decide what kind of Mob can Spawn here
a_MaxPackSize is set to the maximal size for a pack this type of mob */
- cMonster * TryToSpawnHere(cChunk * a_Chunk, int A_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int & a_MaxPackSize);
+ std::unique_ptr<cMonster> TryToSpawnHere(cChunk * a_Chunk, int A_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int & a_MaxPackSize);
/** Mark the beginning of a new Pack.
All mobs of the same Pack are the same type */
@@ -47,7 +47,7 @@ public :
// return true if there is at least one allowed type
bool CanSpawnAnything(void);
- typedef const std::set<cMonster *> tSpawnedContainer;
+ typedef const std::set<std::unique_ptr<cMonster>> tSpawnedContainer;
tSpawnedContainer & getSpawned(void);
/** Returns true if specified type of mob can spawn on specified block */
@@ -65,7 +65,7 @@ protected :
std::set<eMonsterType> m_AllowedTypes;
bool m_NewPack;
eMonsterType m_MobType;
- std::set<cMonster*> m_Spawned;
+ std::set<std::unique_ptr<cMonster>> m_Spawned;
cFastRandom m_Random;
} ;
diff --git a/src/Mobs/Blaze.cpp b/src/Mobs/Blaze.cpp
index d002e14e7..1fcf086d5 100644
--- a/src/Mobs/Blaze.cpp
+++ b/src/Mobs/Blaze.cpp
@@ -39,17 +39,11 @@ bool cBlaze::Attack(std::chrono::milliseconds a_Dt)
// Setting this higher gives us more wiggle room for attackrate
Vector3d Speed = GetLookVector() * 20;
Speed.y = Speed.y + 1;
- cFireChargeEntity * FireCharge = new cFireChargeEntity(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed);
- if (FireCharge == nullptr)
+ auto FireCharge = cpp14::make_unique<cFireChargeEntity>(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed);
+ if (!FireCharge->Initialize(std::move(FireCharge), *m_World))
{
return false;
}
- if (!FireCharge->Initialize(*m_World))
- {
- delete FireCharge;
- FireCharge = nullptr;
- return false;
- }
ResetAttackCooldown();
// ToDo: Shoot 3 fireballs instead of 1.
return true;
diff --git a/src/Mobs/Ghast.cpp b/src/Mobs/Ghast.cpp
index 0544255df..d40545b1d 100644
--- a/src/Mobs/Ghast.cpp
+++ b/src/Mobs/Ghast.cpp
@@ -39,17 +39,11 @@ bool cGhast::Attack(std::chrono::milliseconds a_Dt)
// Setting this higher gives us more wiggle room for attackrate
Vector3d Speed = GetLookVector() * 20;
Speed.y = Speed.y + 1;
- cGhastFireballEntity * GhastBall = new cGhastFireballEntity(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed);
- if (GhastBall == nullptr)
+ auto GhastBall = cpp14::make_unique<cGhastFireballEntity>(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed);
+ if (!GhastBall->Initialize(std::move(GhastBall), *m_World))
{
return false;
}
- if (!GhastBall->Initialize(*m_World))
- {
- delete GhastBall;
- GhastBall = nullptr;
- return false;
- }
ResetAttackCooldown();
return true;
}
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index 3b0fdd36c..738e5b983 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -123,7 +123,7 @@ cMonster::~cMonster()
void cMonster::Destroyed()
{
- SetTarget(nullptr); // Tell them we're no longer targeting them.
+ SetTarget(nullptr);
super::Destroyed();
}
@@ -912,47 +912,26 @@ int cMonster::GetSpawnDelay(cMonster::eFamily a_MobFamily)
-
-/** Sets the target. */
-void cMonster::SetTarget (cPawn * a_NewTarget)
+void cMonster::SetTarget(cPawn * a_NewTarget)
{
- ASSERT((a_NewTarget == nullptr) || (IsTicking()));
- if (m_Target == a_NewTarget)
- {
- return;
- }
- cPawn * OldTarget = m_Target;
- m_Target = a_NewTarget;
+ ASSERT((a_NewTarget == nullptr) || IsTicking());
- if (OldTarget != nullptr)
+ if (a_NewTarget == nullptr)
{
- // Notify the old target that we are no longer targeting it.
- OldTarget->NoLongerTargetingMe(this);
- }
-
- if (a_NewTarget != nullptr)
- {
- ASSERT(a_NewTarget->IsTicking());
- // Notify the new target that we are now targeting it.
- m_Target->TargetingMe(this);
+ m_Target = nullptr;
+ return;
}
+ ASSERT(a_NewTarget->IsTicking());
+ m_Target = a_NewTarget;
+ ASSERT(GetTarget() != nullptr);
}
-void cMonster::UnsafeUnsetTarget()
-{
- m_Target = nullptr;
-}
-
-
-
-
-
-cPawn * cMonster::GetTarget ()
+cPawn * cMonster::GetTarget()
{
return m_Target;
}
@@ -961,29 +940,25 @@ cPawn * cMonster::GetTarget ()
-cMonster * cMonster::NewMonsterFromType(eMonsterType a_MobType)
+std::unique_ptr<cMonster> cMonster::NewMonsterFromType(eMonsterType a_MobType)
{
cFastRandom Random;
- cMonster * toReturn = nullptr;
// Create the mob entity
switch (a_MobType)
{
case mtMagmaCube:
{
- toReturn = new cMagmaCube(1 << Random.NextInt(3)); // Size 1, 2 or 4
- break;
+ return cpp14::make_unique<cMagmaCube>(1 << Random.NextInt(3)); // Size 1, 2 or 4
}
case mtSlime:
{
- toReturn = new cSlime(1 << Random.NextInt(3)); // Size 1, 2 or 4
- break;
+ return cpp14::make_unique<cSlime>(1 << Random.NextInt(3)); // Size 1, 2 or 4
}
case mtSkeleton:
{
// TODO: Actual detection of spawning in Nether
- toReturn = new cSkeleton((Random.NextInt(1) == 0) ? false : true);
- break;
+ return cpp14::make_unique<cSkeleton>((Random.NextInt(1) == 0) ? false : true);
}
case mtVillager:
{
@@ -994,8 +969,7 @@ cMonster * cMonster::NewMonsterFromType(eMonsterType a_MobType)
VillagerType = 0;
}
- toReturn = new cVillager(static_cast<cVillager::eVillagerType>(VillagerType));
- break;
+ return cpp14::make_unique<cVillager>(static_cast<cVillager::eVillagerType>(VillagerType));
}
case mtHorse:
{
@@ -1011,42 +985,41 @@ cMonster * cMonster::NewMonsterFromType(eMonsterType a_MobType)
HorseType = 0;
}
- toReturn = new cHorse(HorseType, HorseColor, HorseStyle, HorseTameTimes);
- break;
+ return cpp14::make_unique<cHorse>(HorseType, HorseColor, HorseStyle, HorseTameTimes);
}
- case mtBat: toReturn = new cBat(); break;
- case mtBlaze: toReturn = new cBlaze(); break;
- case mtCaveSpider: toReturn = new cCaveSpider(); break;
- case mtChicken: toReturn = new cChicken(); break;
- case mtCow: toReturn = new cCow(); break;
- case mtCreeper: toReturn = new cCreeper(); break;
- case mtEnderDragon: toReturn = new cEnderDragon(); break;
- case mtEnderman: toReturn = new cEnderman(); break;
- case mtGhast: toReturn = new cGhast(); break;
- case mtGiant: toReturn = new cGiant(); break;
- case mtGuardian: toReturn = new cGuardian(); break;
- case mtIronGolem: toReturn = new cIronGolem(); break;
- case mtMooshroom: toReturn = new cMooshroom(); break;
- case mtOcelot: toReturn = new cOcelot(); break;
- case mtPig: toReturn = new cPig(); break;
- case mtRabbit: toReturn = new cRabbit(); break;
- case mtSheep: toReturn = new cSheep(); break;
- case mtSilverfish: toReturn = new cSilverfish(); break;
- case mtSnowGolem: toReturn = new cSnowGolem(); break;
- case mtSpider: toReturn = new cSpider(); break;
- case mtSquid: toReturn = new cSquid(); break;
- case mtWitch: toReturn = new cWitch(); break;
- case mtWither: toReturn = new cWither(); break;
- case mtWolf: toReturn = new cWolf(); break;
- case mtZombie: toReturn = new cZombie(false); break; // TODO: Infected zombie parameter
- case mtZombiePigman: toReturn = new cZombiePigman(); break;
+ case mtBat: return cpp14::make_unique<cBat>();
+ case mtBlaze: return cpp14::make_unique<cBlaze>();
+ case mtCaveSpider: return cpp14::make_unique<cCaveSpider>();
+ case mtChicken: return cpp14::make_unique<cChicken>();
+ case mtCow: return cpp14::make_unique<cCow>();
+ case mtCreeper: return cpp14::make_unique < cCreeper>();
+ case mtEnderDragon: return cpp14::make_unique<cEnderDragon>();
+ case mtEnderman: return cpp14::make_unique<cEnderman>();
+ case mtGhast: return cpp14::make_unique<cGhast>();
+ case mtGiant: return cpp14::make_unique<cGiant>();
+ case mtGuardian: return cpp14::make_unique<cGuardian>();
+ case mtIronGolem: return cpp14::make_unique<cIronGolem>();
+ case mtMooshroom: return cpp14::make_unique<cMooshroom>();
+ case mtOcelot: return cpp14::make_unique<cOcelot>();
+ case mtPig: return cpp14::make_unique<cPig>();
+ case mtRabbit: return cpp14::make_unique<cRabbit>();
+ case mtSheep: return cpp14::make_unique<cSheep>();
+ case mtSilverfish: return cpp14::make_unique<cSilverfish>();
+ case mtSnowGolem: return cpp14::make_unique<cSnowGolem>();
+ case mtSpider: return cpp14::make_unique<cSpider>();
+ case mtSquid: return cpp14::make_unique<cSquid>();
+ case mtWitch: return cpp14::make_unique<cWitch>();
+ case mtWither: return cpp14::make_unique<cWither>();
+ case mtWolf: return cpp14::make_unique<cWolf>();
+ case mtZombie: return cpp14::make_unique<cZombie>(false); // TODO: Infected zombie parameter
+ case mtZombiePigman: return cpp14::make_unique<cZombiePigman>();
default:
{
ASSERT(!"Unhandled mob type whilst trying to spawn mob!");
+ return nullptr;
}
}
- return toReturn;
}
diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h
index 2155a4a7c..62c2a3564 100644
--- a/src/Mobs/Monster.h
+++ b/src/Mobs/Monster.h
@@ -161,20 +161,16 @@ public:
// tolua_end
/** 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();
+ void SetTarget(cPawn * a_NewTarget);
/** Returns the current target. */
- cPawn * GetTarget ();
+ cPawn * GetTarget();
/** Creates a new object of the specified mob.
a_MobType is the type of the mob to be created
Asserts and returns null if mob type is not specified
*/
- static cMonster * NewMonsterFromType(eMonsterType a_MobType);
+ static std::unique_ptr<cMonster> NewMonsterFromType(eMonsterType a_MobType);
protected:
@@ -200,7 +196,11 @@ protected:
bool ReachedFinalDestination(void) { return ((m_FinalDestination - GetPosition()).SqrLength() < WAYPOINT_RADIUS * WAYPOINT_RADIUS); }
/** Returns whether or not the target is close enough for attack. */
- bool TargetIsInRange(void) { ASSERT(m_Target != nullptr); return ((m_Target->GetPosition() - GetPosition()).SqrLength() < (m_AttackRange * m_AttackRange)); }
+ bool TargetIsInRange(void)
+ {
+ ASSERT(GetTarget() != nullptr);
+ return ((GetTarget()->GetPosition() - GetPosition()).SqrLength() < (m_AttackRange * m_AttackRange));
+ }
/** Returns if a monster can reach a given height by jumping. */
inline bool DoesPosYRequireJump(int a_PosY)
@@ -267,7 +267,9 @@ protected:
void AddRandomWeaponDropItem(cItems & a_Drops, unsigned int a_LootingLevel);
private:
- /** A pointer to the entity this mobile is aiming to reach */
+ /** 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;
} ; // tolua_export
diff --git a/src/Mobs/Skeleton.cpp b/src/Mobs/Skeleton.cpp
index 7697f1279..01a4c54fb 100644
--- a/src/Mobs/Skeleton.cpp
+++ b/src/Mobs/Skeleton.cpp
@@ -57,17 +57,11 @@ bool cSkeleton::Attack(std::chrono::milliseconds a_Dt)
Vector3d Inaccuracy = Vector3d(Random.NextFloat(0.5) - 0.25, Random.NextFloat(0.5) - 0.25, Random.NextFloat(0.5) - 0.25);
Vector3d Speed = (GetTarget()->GetPosition() + Inaccuracy - GetPosition()) * 5;
Speed.y = Speed.y - 1 + Random.NextInt(3);
- cArrowEntity * Arrow = new cArrowEntity(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed);
- if (Arrow == nullptr)
+ auto Arrow = cpp14::make_unique<cArrowEntity>(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed);
+ if (!Arrow->Initialize(std::move(Arrow), *m_World))
{
return false;
}
- if (!Arrow->Initialize(*m_World))
- {
- delete Arrow;
- Arrow = nullptr;
- return false;
- }
ResetAttackCooldown();
return true;
diff --git a/src/Mobs/Slime.cpp b/src/Mobs/Slime.cpp
index 316f68523..e4ef069ec 100644
--- a/src/Mobs/Slime.cpp
+++ b/src/Mobs/Slime.cpp
@@ -78,10 +78,10 @@ void cSlime::KilledBy(TakeDamageInfo & a_TDI)
double AddX = (i % 2 - 0.5) * m_Size / 4.0;
double AddZ = (i / 2 - 0.5) * m_Size / 4.0;
- cSlime * NewSlime = new cSlime(m_Size / 2);
+ auto NewSlime = cpp14::make_unique<cSlime>(m_Size / 2);
NewSlime->SetPosition(GetPosX() + AddX, GetPosY() + 0.5, GetPosZ() + AddZ);
NewSlime->SetYaw(Random.NextFloat(1.0f) * 360.0f);
- m_World->SpawnMobFinalize(NewSlime);
+ m_World->SpawnMobFinalize(std::move(NewSlime));
}
}
super::KilledBy(a_TDI);
diff --git a/src/Mobs/Wither.cpp b/src/Mobs/Wither.cpp
index 6ef81ce1b..fa9cb56f4 100644
--- a/src/Mobs/Wither.cpp
+++ b/src/Mobs/Wither.cpp
@@ -15,6 +15,7 @@ cWither::cWither(void) :
m_WitherInvulnerableTicks(220)
{
SetMaxHealth(300);
+ SetHealth(GetMaxHealth() / 3);
}
@@ -30,18 +31,6 @@ bool cWither::IsArmored(void) const
-bool cWither::Initialize(cWorld & a_World)
-{
- // Set health before BroadcastSpawnEntity()
- SetHealth(GetMaxHealth() / 3);
-
- return super::Initialize(a_World);
-}
-
-
-
-
-
bool cWither::DoTakeDamage(TakeDamageInfo & a_TDI)
{
if (a_TDI.DamageType == dtDrowning)
diff --git a/src/Mobs/Wither.h b/src/Mobs/Wither.h
index b430588c9..5f6ec607c 100644
--- a/src/Mobs/Wither.h
+++ b/src/Mobs/Wither.h
@@ -25,7 +25,6 @@ public:
bool IsArmored(void) const;
// cEntity overrides
- virtual bool Initialize(cWorld & a_World) override;
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
diff --git a/src/Simulator/SandSimulator.cpp b/src/Simulator/SandSimulator.cpp
index d3773ee41..e1d1f9c2b 100644
--- a/src/Simulator/SandSimulator.cpp
+++ b/src/Simulator/SandSimulator.cpp
@@ -61,8 +61,8 @@ void cSandSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX,
Pos.x, Pos.y, Pos.z, ItemTypeToString(BlockType).c_str(), ItemTypeToString(BlockBelow).c_str()
);
*/
- cFallingBlock * FallingBlock = new cFallingBlock(Pos, BlockType, a_Chunk->GetMeta(itr->x, itr->y, itr->z));
- FallingBlock->Initialize(m_World);
+ auto FallingBlock = cpp14::make_unique<cFallingBlock>(Pos, BlockType, a_Chunk->GetMeta(itr->x, itr->y, itr->z));
+ FallingBlock->Initialize(std::move(FallingBlock), m_World);
a_Chunk->SetBlock(itr->x, itr->y, itr->z, E_BLOCK_AIR, 0);
}
}
diff --git a/src/World.cpp b/src/World.cpp
index 399776320..a9d6b2b13 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -930,7 +930,7 @@ void cWorld::TickMobs(std::chrono::milliseconds a_Dt)
// do the spawn
for (cMobSpawner::tSpawnedContainer::const_iterator itr2 = Spawner.getSpawned().begin(); itr2 != Spawner.getSpawned().end(); ++itr2)
{
- SpawnMobFinalize(*itr2);
+ SpawnMobFinalize(std::move(const_cast<std::unique_ptr<cMonster> &>(*itr2)));
}
}
} // for i - AllFamilies[]
@@ -1307,7 +1307,7 @@ bool cWorld::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback
-bool cWorld::DoWithChunk(int a_ChunkX, int a_ChunkZ, std::function<bool(cChunk &)> a_Callback)
+bool cWorld::DoWithChunk(int a_ChunkX, int a_ChunkZ, std::function<bool(cChunk &)> a_Callback)
{
struct cCallBackWrapper : cChunkCallback
{
@@ -1904,11 +1904,11 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double
float SpeedY = static_cast<float>(a_FlyAwaySpeed * GetTickRandomNumber(50));
float SpeedZ = static_cast<float>(a_FlyAwaySpeed * (GetTickRandomNumber(10) - 5));
- cPickup * Pickup = new cPickup(
+ auto Pickup = cpp14::make_unique<cPickup>(
a_BlockX, a_BlockY, a_BlockZ,
*itr, IsPlayerCreated, SpeedX, SpeedY, SpeedZ
);
- Pickup->Initialize(*this);
+ Pickup->Initialize(std::move(Pickup), *this);
}
}
@@ -1925,11 +1925,11 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double
continue;
}
- cPickup * Pickup = new cPickup(
+ auto Pickup = cpp14::make_unique<cPickup>(
a_BlockX, a_BlockY, a_BlockZ,
*itr, IsPlayerCreated, static_cast<float>(a_SpeedX), static_cast<float>(a_SpeedY), static_cast<float>(a_SpeedZ)
);
- Pickup->Initialize(*this);
+ Pickup->Initialize(std::move(Pickup), *this);
}
}
@@ -1939,9 +1939,10 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double
UInt32 cWorld::SpawnFallingBlock(int a_X, int a_Y, int a_Z, BLOCKTYPE BlockType, NIBBLETYPE BlockMeta)
{
- cFallingBlock * FallingBlock = new cFallingBlock(Vector3i(a_X, a_Y, a_Z), BlockType, BlockMeta);
- FallingBlock->Initialize(*this);
- return FallingBlock->GetUniqueID();
+ auto FallingBlock = cpp14::make_unique<cFallingBlock>(Vector3i(a_X, a_Y, a_Z), BlockType, BlockMeta);
+ auto ID = FallingBlock->GetUniqueID();
+ FallingBlock->Initialize(std::move(FallingBlock), *this);
+ return ID;
}
@@ -1956,9 +1957,10 @@ UInt32 cWorld::SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Rewa
return cEntity::INVALID_ID;
}
- cExpOrb * ExpOrb = new cExpOrb(a_X, a_Y, a_Z, a_Reward);
- ExpOrb->Initialize(*this);
- return ExpOrb->GetUniqueID();
+ auto ExpOrb = cpp14::make_unique<cExpOrb>(a_X, a_Y, a_Z, a_Reward);
+ auto ID = ExpOrb->GetUniqueID();
+ ExpOrb->Initialize(std::move(ExpOrb), *this);
+ return ID;
}
@@ -1967,21 +1969,23 @@ UInt32 cWorld::SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Rewa
UInt32 cWorld::SpawnMinecart(double a_X, double a_Y, double a_Z, int a_MinecartType, const cItem & a_Content, int a_BlockHeight)
{
- cMinecart * Minecart;
+ std::unique_ptr<cMinecart> Minecart;
switch (a_MinecartType)
{
- case E_ITEM_MINECART: Minecart = new cRideableMinecart (a_X, a_Y, a_Z, a_Content, a_BlockHeight); break;
- case E_ITEM_CHEST_MINECART: Minecart = new cMinecartWithChest (a_X, a_Y, a_Z); break;
- case E_ITEM_FURNACE_MINECART: Minecart = new cMinecartWithFurnace (a_X, a_Y, a_Z); break;
- case E_ITEM_MINECART_WITH_TNT: Minecart = new cMinecartWithTNT (a_X, a_Y, a_Z); break;
- case E_ITEM_MINECART_WITH_HOPPER: Minecart = new cMinecartWithHopper (a_X, a_Y, a_Z); break;
+ case E_ITEM_MINECART: Minecart = cpp14::make_unique<cRideableMinecart>(a_X, a_Y, a_Z, a_Content, a_BlockHeight); break;
+ case E_ITEM_CHEST_MINECART: Minecart = cpp14::make_unique<cMinecartWithChest>(a_X, a_Y, a_Z); break;
+ case E_ITEM_FURNACE_MINECART: Minecart = cpp14::make_unique<cMinecartWithFurnace>(a_X, a_Y, a_Z); break;
+ case E_ITEM_MINECART_WITH_TNT: Minecart = cpp14::make_unique<cMinecartWithTNT>(a_X, a_Y, a_Z); break;
+ case E_ITEM_MINECART_WITH_HOPPER: Minecart = cpp14::make_unique<cMinecartWithHopper>(a_X, a_Y, a_Z); break;
default:
{
return cEntity::INVALID_ID;
}
} // switch (a_MinecartType)
- Minecart->Initialize(*this);
- return Minecart->GetUniqueID();
+
+ auto ID = Minecart->GetUniqueID();
+ Minecart->Initialize(std::move(Minecart), *this);
+ return ID;
}
@@ -1990,17 +1994,13 @@ UInt32 cWorld::SpawnMinecart(double a_X, double a_Y, double a_Z, int a_MinecartT
UInt32 cWorld::SpawnBoat(double a_X, double a_Y, double a_Z)
{
- cBoat * Boat = new cBoat(a_X, a_Y, a_Z);
- if (Boat == nullptr)
- {
- return cEntity::INVALID_ID;
- }
- if (!Boat->Initialize(*this))
+ auto Boat = cpp14::make_unique<cBoat>(a_X, a_Y, a_Z);
+ auto ID = Boat->GetUniqueID();
+ if (!Boat->Initialize(std::move(Boat), *this))
{
- delete Boat;
return cEntity::INVALID_ID;
}
- return Boat->GetUniqueID();
+ return ID;
}
@@ -2008,14 +2008,15 @@ UInt32 cWorld::SpawnBoat(double a_X, double a_Y, double a_Z)
UInt32 cWorld::SpawnPrimedTNT(double a_X, double a_Y, double a_Z, int a_FuseTicks, double a_InitialVelocityCoeff)
{
- cTNTEntity * TNT = new cTNTEntity(a_X, a_Y, a_Z, a_FuseTicks);
- TNT->Initialize(*this);
+ auto TNT = cpp14::make_unique<cTNTEntity>(a_X, a_Y, a_Z, a_FuseTicks);
+ auto ID = TNT->GetUniqueID();
TNT->SetSpeed(
- a_InitialVelocityCoeff * (GetTickRandomNumber(2) - 1), /** -1, 0, 1 */
+ a_InitialVelocityCoeff * (GetTickRandomNumber(2) - 1), /* -1, 0, 1 */
a_InitialVelocityCoeff * 2,
a_InitialVelocityCoeff * (GetTickRandomNumber(2) - 1)
);
- return TNT->GetUniqueID();
+ TNT->Initialize(std::move(TNT), *this);
+ return ID;
}
@@ -2591,10 +2592,9 @@ void cWorld::SetChunkData(cSetChunkData & a_SetChunkData)
// Initialise the entities:
cEntityList Entities;
- std::swap(a_SetChunkData.GetEntities(), Entities);
- for (cEntityList::iterator itr = Entities.begin(), end = Entities.end(); itr != end; ++itr)
+ for (auto & Entity : a_SetChunkData.GetEntities())
{
- (*itr)->Initialize(*this);
+ Entity->Initialize(std::move(Entity), *this);
}
// Save the chunk right after generating, so that we don't have to generate it again on next run
@@ -3159,8 +3159,9 @@ void cWorld::ScheduleTask(int a_DelayTicks, std::function<void (cWorld &)> a_Tas
-void cWorld::AddEntity(cEntity * a_Entity)
+void cWorld::AddEntity(std::unique_ptr<cEntity> a_Entity)
{
+ m_ChunkMap->AddEntity(std::move(a_Entity));
}
@@ -3274,9 +3275,7 @@ bool cWorld::IsBlockDirectlyWatered(int a_BlockX, int a_BlockY, int a_BlockZ)
UInt32 cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType, bool a_Baby)
{
- cMonster * Monster = nullptr;
-
- Monster = cMonster::NewMonsterFromType(a_MonsterType);
+ auto Monster = cMonster::NewMonsterFromType(a_MonsterType);
if (Monster == nullptr)
{
return cEntity::INVALID_ID;
@@ -3288,13 +3287,13 @@ UInt32 cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterTyp
Monster->SetAge(-1);
}
- return SpawnMobFinalize(Monster);
+ return SpawnMobFinalize(std::move(Monster));
}
-UInt32 cWorld::SpawnMobFinalize(cMonster * a_Monster)
+UInt32 cWorld::SpawnMobFinalize(std::unique_ptr<cMonster> a_Monster)
{
ASSERT(a_Monster != nullptr);
@@ -3304,22 +3303,20 @@ UInt32 cWorld::SpawnMobFinalize(cMonster * a_Monster)
// A plugin doesn't agree with the spawn. bail out.
if (cPluginManager::Get()->CallHookSpawningMonster(*this, *a_Monster))
{
- delete a_Monster;
- a_Monster = nullptr;
return cEntity::INVALID_ID;
}
+ auto & Monster = *a_Monster;
+
// Initialize the monster into the current world.
- if (!a_Monster->Initialize(*this))
+ if (!a_Monster->Initialize(std::move(a_Monster), *this))
{
- delete a_Monster;
- a_Monster = nullptr;
return cEntity::INVALID_ID;
}
- cPluginManager::Get()->CallHookSpawnedMonster(*this, *a_Monster);
+ cPluginManager::Get()->CallHookSpawnedMonster(*this, Monster);
- return a_Monster->GetUniqueID();
+ return Monster.GetUniqueID();
}
@@ -3328,18 +3325,15 @@ UInt32 cWorld::SpawnMobFinalize(cMonster * a_Monster)
UInt32 cWorld::CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem * a_Item, const Vector3d * a_Speed)
{
- cProjectileEntity * Projectile = cProjectileEntity::Create(a_Kind, a_Creator, a_PosX, a_PosY, a_PosZ, a_Item, a_Speed);
- if (Projectile == nullptr)
- {
- return cEntity::INVALID_ID;
- }
- if (!Projectile->Initialize(*this))
+ auto Projectile = cProjectileEntity::Create(a_Kind, a_Creator, a_PosX, a_PosY, a_PosZ, a_Item, a_Speed);
+ auto ID = Projectile->GetUniqueID();
+
+ if ((Projectile == nullptr) || !Projectile->Initialize(std::move(Projectile), *this))
{
- delete Projectile;
- Projectile = nullptr;
return cEntity::INVALID_ID;
}
- return Projectile->GetUniqueID();
+
+ return ID;
}
diff --git a/src/World.h b/src/World.h
index f6fbfae0f..de7fcac2e 100644
--- a/src/World.h
+++ b/src/World.h
@@ -276,7 +276,7 @@ public:
/** Adds the entity into its appropriate chunk; takes ownership of the entity ptr.
The entity is added lazily - this function only puts it in a queue that is then processed by the Tick thread. */
- void AddEntity(cEntity * a_Entity);
+ void AddEntity(std::unique_ptr<cEntity> a_Entity);
/** Returns true if an entity with the specified UniqueID exists in the world.
Note: Only loaded chunks are considered. */
@@ -770,7 +770,7 @@ public:
/** Spawns a mob of the specified type. Returns the mob's UniqueID if recognized and spawned, cEntity::INVALID_ID otherwise */
virtual UInt32 SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType, bool a_Baby = false) override; // tolua_export
- UInt32 SpawnMobFinalize(cMonster * a_Monster);
+ UInt32 SpawnMobFinalize(std::unique_ptr<cMonster> a_Monster);
/** Creates a projectile of the specified type. Returns the projectile's UniqueID if successful, cEntity::INVALID_ID otherwise
Item parameter is currently used for Fireworks to correctly set entity metadata based on item metadata. */
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index 1d81ac0b7..d89ef5e67 100755
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -1651,7 +1651,7 @@ void cWSSAnvil::LoadBoatFromNBT(cEntityList & a_Entities, const cParsedNBT & a_N
{
return;
}
- a_Entities.push_back(Boat.release());
+ a_Entities.emplace_back(std::move(Boat));
}
@@ -1665,7 +1665,7 @@ void cWSSAnvil::LoadEnderCrystalFromNBT(cEntityList & a_Entities, const cParsedN
{
return;
}
- a_Entities.push_back(EnderCrystal.release());
+ a_Entities.emplace_back(std::move(EnderCrystal));
}
@@ -1690,7 +1690,7 @@ void cWSSAnvil::LoadFallingBlockFromNBT(cEntityList & a_Entities, const cParsedN
{
return;
}
- a_Entities.push_back(FallingBlock.release());
+ a_Entities.emplace_back(std::move(FallingBlock));
}
@@ -1704,7 +1704,7 @@ void cWSSAnvil::LoadMinecartRFromNBT(cEntityList & a_Entities, const cParsedNBT
{
return;
}
- a_Entities.push_back(Minecart.release());
+ a_Entities.emplace_back(std::move(Minecart));
}
@@ -1736,7 +1736,7 @@ void cWSSAnvil::LoadMinecartCFromNBT(cEntityList & a_Entities, const cParsedNBT
Minecart->SetSlot(a_NBT.GetByte(Slot), Item);
}
} // for itr - ItemDefs[]
- a_Entities.push_back(Minecart.release());
+ a_Entities.emplace_back(std::move(Minecart));
}
@@ -1753,7 +1753,7 @@ void cWSSAnvil::LoadMinecartFFromNBT(cEntityList & a_Entities, const cParsedNBT
// TODO: Load the Push and Fuel tags
- a_Entities.push_back(Minecart.release());
+ a_Entities.emplace_back(std::move(Minecart));
}
@@ -1770,7 +1770,7 @@ void cWSSAnvil::LoadMinecartTFromNBT(cEntityList & a_Entities, const cParsedNBT
// TODO: Everything to do with TNT carts
- a_Entities.push_back(Minecart.release());
+ a_Entities.emplace_back(std::move(Minecart));
}
@@ -1787,7 +1787,7 @@ void cWSSAnvil::LoadMinecartHFromNBT(cEntityList & a_Entities, const cParsedNBT
// TODO: Everything to do with hopper carts
- a_Entities.push_back(Minecart.release());
+ a_Entities.emplace_back(std::move(Minecart));
}
@@ -1821,7 +1821,7 @@ void cWSSAnvil::LoadPickupFromNBT(cEntityList & a_Entities, const cParsedNBT & a
Pickup->SetAge(a_NBT.GetShort(Age));
}
- a_Entities.push_back(Pickup.release());
+ a_Entities.emplace_back(std::move(Pickup));
}
@@ -1843,7 +1843,7 @@ void cWSSAnvil::LoadTNTFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NB
TNT->SetFuseTicks(static_cast<int>(a_NBT.GetByte(FuseTicks)));
}
- a_Entities.push_back(TNT.release());
+ a_Entities.emplace_back(std::move(TNT));
}
@@ -1872,7 +1872,7 @@ void cWSSAnvil::LoadExpOrbFromNBT(cEntityList & a_Entities, const cParsedNBT & a
ExpOrb->SetReward(a_NBT.GetShort(Reward));
}
- a_Entities.push_back(ExpOrb.release());
+ a_Entities.emplace_back(std::move(ExpOrb));
}
@@ -1937,7 +1937,7 @@ void cWSSAnvil::LoadItemFrameFromNBT(cEntityList & a_Entities, const cParsedNBT
ItemFrame->SetItemRotation(static_cast<Byte>(a_NBT.GetByte(Rotation)));
}
- a_Entities.push_back(ItemFrame.release());
+ a_Entities.emplace_back(std::move(ItemFrame));
}
@@ -1960,7 +1960,7 @@ void cWSSAnvil::LoadPaintingFromNBT(cEntityList & a_Entities, const cParsedNBT &
}
LoadHangingFromNBT(*Painting.get(), a_NBT, a_TagIdx);
- a_Entities.push_back(Painting.release());
+ a_Entities.emplace_back(std::move(Painting));
}
@@ -2031,7 +2031,7 @@ void cWSSAnvil::LoadArrowFromNBT(cEntityList & a_Entities, const cParsedNBT & a_
}
// Store the new arrow in the entities list:
- a_Entities.push_back(Arrow.release());
+ a_Entities.emplace_back(std::move(Arrow));
}
@@ -2054,7 +2054,7 @@ void cWSSAnvil::LoadSplashPotionFromNBT(cEntityList & a_Entities, const cParsedN
SplashPotion->SetPotionColor(a_NBT.FindChildByName(a_TagIdx, "PotionName"));
// Store the new splash potion in the entities list:
- a_Entities.push_back(SplashPotion.release());
+ a_Entities.emplace_back(std::move(SplashPotion));
}
@@ -2070,7 +2070,7 @@ void cWSSAnvil::LoadSnowballFromNBT(cEntityList & a_Entities, const cParsedNBT &
}
// Store the new snowball in the entities list:
- a_Entities.push_back(Snowball.release());
+ a_Entities.emplace_back(std::move(Snowball));
}
@@ -2086,7 +2086,7 @@ void cWSSAnvil::LoadEggFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NB
}
// Store the new egg in the entities list:
- a_Entities.push_back(Egg.release());
+ a_Entities.emplace_back(std::move(Egg));
}
@@ -2102,7 +2102,7 @@ void cWSSAnvil::LoadFireballFromNBT(cEntityList & a_Entities, const cParsedNBT &
}
// Store the new fireball in the entities list:
- a_Entities.push_back(Fireball.release());
+ a_Entities.emplace_back(std::move(Fireball));
}
@@ -2118,7 +2118,7 @@ void cWSSAnvil::LoadFireChargeFromNBT(cEntityList & a_Entities, const cParsedNBT
}
// Store the new FireCharge in the entities list:
- a_Entities.push_back(FireCharge.release());
+ a_Entities.emplace_back(std::move(FireCharge));
}
@@ -2134,7 +2134,7 @@ void cWSSAnvil::LoadThrownEnderpearlFromNBT(cEntityList & a_Entities, const cPar
}
// Store the new enderpearl in the entities list:
- a_Entities.push_back(Enderpearl.release());
+ a_Entities.emplace_back(std::move(Enderpearl));
}
@@ -2154,7 +2154,7 @@ void cWSSAnvil::LoadBatFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NB
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2174,7 +2174,7 @@ void cWSSAnvil::LoadBlazeFromNBT(cEntityList & a_Entities, const cParsedNBT & a_
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2194,7 +2194,7 @@ void cWSSAnvil::LoadCaveSpiderFromNBT(cEntityList & a_Entities, const cParsedNBT
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2214,7 +2214,7 @@ void cWSSAnvil::LoadChickenFromNBT(cEntityList & a_Entities, const cParsedNBT &
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2234,7 +2234,7 @@ void cWSSAnvil::LoadCowFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NB
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2254,7 +2254,7 @@ void cWSSAnvil::LoadCreeperFromNBT(cEntityList & a_Entities, const cParsedNBT &
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2274,7 +2274,7 @@ void cWSSAnvil::LoadEnderDragonFromNBT(cEntityList & a_Entities, const cParsedNB
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2294,7 +2294,7 @@ void cWSSAnvil::LoadEndermanFromNBT(cEntityList & a_Entities, const cParsedNBT &
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2314,7 +2314,7 @@ void cWSSAnvil::LoadGhastFromNBT(cEntityList & a_Entities, const cParsedNBT & a_
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2334,7 +2334,7 @@ void cWSSAnvil::LoadGiantFromNBT(cEntityList & a_Entities, const cParsedNBT & a_
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2354,7 +2354,7 @@ void cWSSAnvil::LoadGuardianFromNBT(cEntityList & a_Entities, const cParsedNBT &
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2400,7 +2400,7 @@ void cWSSAnvil::LoadHorseFromNBT(cEntityList & a_Entities, const cParsedNBT & a_
Monster->SetAge(Age);
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2420,7 +2420,7 @@ void cWSSAnvil::LoadIronGolemFromNBT(cEntityList & a_Entities, const cParsedNBT
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2449,7 +2449,7 @@ void cWSSAnvil::LoadMagmaCubeFromNBT(cEntityList & a_Entities, const cParsedNBT
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2469,7 +2469,7 @@ void cWSSAnvil::LoadMooshroomFromNBT(cEntityList & a_Entities, const cParsedNBT
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2502,7 +2502,7 @@ void cWSSAnvil::LoadOcelotFromNBT(cEntityList & a_Entities, const cParsedNBT & a
Monster->SetAge(Age);
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2535,7 +2535,7 @@ void cWSSAnvil::LoadPigFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NB
Monster->SetAge(Age);
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2579,7 +2579,7 @@ void cWSSAnvil::LoadRabbitFromNBT(cEntityList & a_Entities, const cParsedNBT & a
Monster->SetAge(Age);
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2625,7 +2625,7 @@ void cWSSAnvil::LoadSheepFromNBT(cEntityList & a_Entities, const cParsedNBT & a_
Monster->SetAge(Age);
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2645,7 +2645,7 @@ void cWSSAnvil::LoadSilverfishFromNBT(cEntityList & a_Entities, const cParsedNBT
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2673,7 +2673,7 @@ void cWSSAnvil::LoadSkeletonFromNBT(cEntityList & a_Entities, const cParsedNBT &
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2702,7 +2702,7 @@ void cWSSAnvil::LoadSlimeFromNBT(cEntityList & a_Entities, const cParsedNBT & a_
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2722,7 +2722,7 @@ void cWSSAnvil::LoadSnowGolemFromNBT(cEntityList & a_Entities, const cParsedNBT
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2742,7 +2742,7 @@ void cWSSAnvil::LoadSpiderFromNBT(cEntityList & a_Entities, const cParsedNBT & a
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2762,7 +2762,7 @@ void cWSSAnvil::LoadSquidFromNBT(cEntityList & a_Entities, const cParsedNBT & a_
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2804,7 +2804,7 @@ void cWSSAnvil::LoadVillagerFromNBT(cEntityList & a_Entities, const cParsedNBT &
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2824,7 +2824,7 @@ void cWSSAnvil::LoadWitchFromNBT(cEntityList & a_Entities, const cParsedNBT & a_
return;
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2850,7 +2850,7 @@ void cWSSAnvil::LoadWitherFromNBT(cEntityList & a_Entities, const cParsedNBT & a
Monster->SetWitherInvulnerableTicks(static_cast<unsigned int>(a_NBT.GetInt(CurrLine)));
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2917,7 +2917,7 @@ void cWSSAnvil::LoadWolfFromNBT(cEntityList & a_Entities, const cParsedNBT & a_N
Monster->SetAge(Age);
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2958,7 +2958,7 @@ void cWSSAnvil::LoadZombieFromNBT(cEntityList & a_Entities, const cParsedNBT & a
Monster->SetAge(Age);
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}
@@ -2991,7 +2991,7 @@ void cWSSAnvil::LoadPigZombieFromNBT(cEntityList & a_Entities, const cParsedNBT
Monster->SetAge(Age);
}
- a_Entities.push_back(Monster.release());
+ a_Entities.emplace_back(std::move(Monster));
}