summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Chunk.h3
-rw-r--r--src/ChunkMap.cpp4
-rw-r--r--src/Entities/Entity.cpp51
3 files changed, 33 insertions, 25 deletions
diff --git a/src/Chunk.h b/src/Chunk.h
index de46b5f8f..ecb594191 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -519,9 +519,8 @@ private:
std::vector<Vector3i> m_ToTickBlocks;
sSetBlockVector m_PendingSendBlocks; ///< Blocks that have changed and need to be sent to all clients
- // A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers
- std::vector<cClientHandle *> m_LoadedByClient;
cEntityList m_Entities;
+ std::vector<std::weak_ptr<cClientHandle>> m_LoadedByClient;
cBlockEntityList m_BlockEntities;
/** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index 7f53865d0..2e6153f0e 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -1582,10 +1582,7 @@ void cChunkMap::RemoveChunkClient(int a_ChunkX, int a_ChunkZ, const std::shared_
-
-void cChunkMap::RemoveClientFromChunks(cClientHandle * a_Client)
{
- cCSLock Lock(m_CSChunks);
for (const auto & Chunk : m_Chunks)
{
Chunk.second->RemoveClient(a_Client);
@@ -1613,6 +1610,7 @@ void cChunkMap::AddEntity(cEntity * a_Entity)
+ ASSERT(GetWorld()->IsInTickThread());
void cChunkMap::AddEntityIfNotPresent(cEntity * a_Entity)
{
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 8d74ee99a..489b55cf8 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -132,7 +132,9 @@ const char * cEntity::GetParentClass(void) const
bool cEntity::Initialize(cWorld & a_World)
{
- if (cPluginManager::Get()->CallHookSpawningEntity(a_World, *this))
+ ASSERT(a_EntityWorld.IsInTickThread());
+
+ if (cPluginManager::Get()->CallHookSpawningEntity(a_EntityWorld, *this) && !IsPlayer())
{
return false;
}
@@ -144,15 +146,22 @@ bool cEntity::Initialize(cWorld & a_World)
);
*/
- ASSERT(m_World == nullptr);
ASSERT(GetParentChunk() == nullptr);
- a_World.AddEntity(this);
- ASSERT(m_World != nullptr);
+ cpp14::move_on_copy_wrapper<decltype(a_Entity)> Entity(std::move(a_Entity));
+
+ // So that entities do not appear in the middle of ticks
+ a_EntityWorld.QueueTask(
+ [Entity, &a_EntityWorld](cWorld & a_World)
+ {
+ auto & EntityPtr = *Entity.value;
- cPluginManager::Get()->CallHookSpawnedEntity(a_World, *this);
+ EntityPtr.SetWorld(&a_EntityWorld);
+ a_EntityWorld.AddEntity(std::move(Entity.value));
- // Spawn the entity on the clients:
- a_World.BroadcastSpawnEntity(*this);
+ a_EntityWorld.BroadcastSpawnEntity(EntityPtr);
+ cPluginManager::Get()->CallHookSpawnedEntity(a_EntityWorld, EntityPtr);
+ }
+ );
return true;
}
@@ -209,8 +218,7 @@ cChunk * cEntity::GetParentChunk() const
void cEntity::Destroy(bool a_ShouldBroadcast)
{
- ASSERT(IsTicking());
- ASSERT(GetParentChunk() != nullptr);
+ ASSERT(GetWorld()->IsInTickThread());
SetIsTicking(false);
if (a_ShouldBroadcast)
@@ -218,17 +226,20 @@ void cEntity::Destroy(bool a_ShouldBroadcast)
m_World->BroadcastDestroyEntity(*this);
}
- cChunk * ParentChunk = GetParentChunk();
- m_World->QueueTask([this, ParentChunk](cWorld & a_World)
- {
- LOGD("Destroying entity #%i (%s) from chunk (%d, %d)",
- this->GetUniqueID(), this->GetClass(),
- ParentChunk->GetPosX(), ParentChunk->GetPosZ()
- );
- ParentChunk->RemoveEntity(this);
- delete this;
- });
- Destroyed();
+ // So that entities do not disappear unexpectedly during ticks
+ m_World->QueueTask(
+ [this](cWorld & a_World)
+ {
+ auto ParentChunk = GetParentChunk();
+ LOGD("Destroying entity #%i (%s) from chunk (%d, %d)",
+ GetUniqueID(), GetClass(),
+ ParentChunk->GetPosX(), ParentChunk->GetPosZ()
+ );
+
+ Destroyed(); // TODO: rename to OnPreDestroy()
+ ParentChunk->RemoveEntity(*this);
+ }
+ );
}