summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Entities/Entity.cpp21
-rw-r--r--src/World.cpp30
-rw-r--r--src/World.h4
3 files changed, 44 insertions, 11 deletions
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index c31f05211..b78c4dd82 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -223,8 +223,6 @@ cChunk * cEntity::GetParentChunk()
void cEntity::Destroy(bool a_ShouldBroadcast)
{
- ASSERT(IsTicking());
- ASSERT(GetParentChunk() != nullptr);
SetIsTicking(false);
// Unleash leashed mobs
@@ -238,17 +236,17 @@ void cEntity::Destroy(bool a_ShouldBroadcast)
m_World->BroadcastDestroyEntity(*this);
}
- cChunk * ParentChunk = GetParentChunk();
- m_World->QueueTask([this, ParentChunk](cWorld & a_World)
+ auto ParentChunkCoords = cChunkDef::BlockToChunk(GetPosition());
+ m_World->QueueTask([this, ParentChunkCoords](cWorld & a_World)
{
LOGD("Destroying entity #%i (%s) from chunk (%d, %d)",
this->GetUniqueID(), this->GetClass(),
- ParentChunk->GetPosX(), ParentChunk->GetPosZ()
+ ParentChunkCoords.m_ChunkX, ParentChunkCoords.m_ChunkZ
);
// Make sure that RemoveEntity returned a valid smart pointer
// Also, not storing the returned pointer means automatic destruction
- VERIFY(ParentChunk->RemoveEntity(*this));
+ VERIFY(a_World.RemoveEntity(*this));
});
Destroyed();
}
@@ -1565,7 +1563,6 @@ bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d
{
UNUSED(a_ShouldSendRespawn);
ASSERT(a_World != nullptr);
- ASSERT(IsTicking());
if (GetWorld() == a_World)
{
@@ -1586,6 +1583,9 @@ bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d
// Tell others we are gone
GetWorld()->BroadcastDestroyEntity(*this);
+ // Take note of old chunk coords
+ auto OldChunkCoords = cChunkDef::BlockToChunk(GetPosition());
+
// Set position to the new position
SetPosition(a_NewPosition);
@@ -1600,16 +1600,15 @@ bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d
// Queue add to new world and removal from the old one
cWorld * OldWorld = GetWorld();
- cChunk * ParentChunk = GetParentChunk();
SetWorld(a_World); // Chunks may be streamed before cWorld::AddPlayer() sets the world to the new value
- OldWorld->QueueTask([this, ParentChunk, a_World](cWorld & a_OldWorld)
+ OldWorld->QueueTask([this, OldChunkCoords, a_World](cWorld & a_OldWorld)
{
LOGD("Warping entity #%i (%s) from world \"%s\" to \"%s\". Source chunk: (%d, %d) ",
this->GetUniqueID(), this->GetClass(),
a_OldWorld.GetName().c_str(), a_World->GetName().c_str(),
- ParentChunk->GetPosX(), ParentChunk->GetPosZ()
+ OldChunkCoords.m_ChunkX, OldChunkCoords.m_ChunkZ
);
- a_World->AddEntity(ParentChunk->RemoveEntity(*this));
+ a_World->AddEntity(a_OldWorld.RemoveEntity(*this));
cRoot::Get()->GetPluginManager()->CallHookEntityChangedWorld(*this, a_OldWorld);
});
return true;
diff --git a/src/World.cpp b/src/World.cpp
index acec3049e..0ecf9a274 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -3709,6 +3709,36 @@ bool cWorld::HasEntity(UInt32 a_UniqueID)
+OwnedEntity cWorld::RemoveEntity(cEntity & a_Entity)
+{
+ // Check if the entity is in the chunkmap:
+ auto Entity = m_ChunkMap->RemoveEntity(a_Entity);
+ if (Entity != nullptr)
+ {
+ return Entity;
+ }
+
+ // Check if the entity is in the queue to be added to the world:
+ cCSLock Lock(m_CSEntitiesToAdd);
+ auto itr = std::find_if(m_EntitiesToAdd.begin(), m_EntitiesToAdd.end(),
+ [&a_Entity](const OwnedEntity & a_OwnedEntity)
+ {
+ return (a_OwnedEntity.get() == &a_Entity);
+ }
+ );
+
+ if (itr != m_EntitiesToAdd.end())
+ {
+ Entity = std::move(*itr);
+ m_EntitiesToAdd.erase(itr);
+ }
+ return Entity;
+}
+
+
+
+
+
/*
unsigned int cWorld::GetNumPlayers(void)
{
diff --git a/src/World.h b/src/World.h
index cbaf9cb95..b1a5e8d79 100644
--- a/src/World.h
+++ b/src/World.h
@@ -301,6 +301,10 @@ public:
Note: Only loaded chunks are considered. */
bool HasEntity(UInt32 a_UniqueID);
+ /** Removes the entity from the world.
+ Returns an owning reference to the found entity. */
+ OwnedEntity 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); // Exported in ManualBindings.cpp