1
0

Add cWorld::RemoveEntity and use in cEntity (#4003)

* Add cWorld::RemoveEntity and use in cEntity

* cEntity: Remove uneeded asserts from Destroy and DoMoveToWorld
This commit is contained in:
peterbell10 2017-09-05 15:11:35 +01:00 committed by Alexander Harkness
parent 028a35ef0d
commit ef1f371dab
3 changed files with 44 additions and 11 deletions

View File

@ -223,8 +223,6 @@ cChunk * cEntity::GetParentChunk()
void cEntity::Destroy(bool a_ShouldBroadcast) void cEntity::Destroy(bool a_ShouldBroadcast)
{ {
ASSERT(IsTicking());
ASSERT(GetParentChunk() != nullptr);
SetIsTicking(false); SetIsTicking(false);
// Unleash leashed mobs // Unleash leashed mobs
@ -238,17 +236,17 @@ void cEntity::Destroy(bool a_ShouldBroadcast)
m_World->BroadcastDestroyEntity(*this); m_World->BroadcastDestroyEntity(*this);
} }
cChunk * ParentChunk = GetParentChunk(); auto ParentChunkCoords = cChunkDef::BlockToChunk(GetPosition());
m_World->QueueTask([this, ParentChunk](cWorld & a_World) m_World->QueueTask([this, ParentChunkCoords](cWorld & a_World)
{ {
LOGD("Destroying entity #%i (%s) from chunk (%d, %d)", LOGD("Destroying entity #%i (%s) from chunk (%d, %d)",
this->GetUniqueID(), this->GetClass(), this->GetUniqueID(), this->GetClass(),
ParentChunk->GetPosX(), ParentChunk->GetPosZ() ParentChunkCoords.m_ChunkX, ParentChunkCoords.m_ChunkZ
); );
// Make sure that RemoveEntity returned a valid smart pointer // Make sure that RemoveEntity returned a valid smart pointer
// Also, not storing the returned pointer means automatic destruction // Also, not storing the returned pointer means automatic destruction
VERIFY(ParentChunk->RemoveEntity(*this)); VERIFY(a_World.RemoveEntity(*this));
}); });
Destroyed(); Destroyed();
} }
@ -1565,7 +1563,6 @@ bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d
{ {
UNUSED(a_ShouldSendRespawn); UNUSED(a_ShouldSendRespawn);
ASSERT(a_World != nullptr); ASSERT(a_World != nullptr);
ASSERT(IsTicking());
if (GetWorld() == a_World) if (GetWorld() == a_World)
{ {
@ -1586,6 +1583,9 @@ bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d
// Tell others we are gone // Tell others we are gone
GetWorld()->BroadcastDestroyEntity(*this); GetWorld()->BroadcastDestroyEntity(*this);
// Take note of old chunk coords
auto OldChunkCoords = cChunkDef::BlockToChunk(GetPosition());
// Set position to the new position // Set position to the new position
SetPosition(a_NewPosition); 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 // Queue add to new world and removal from the old one
cWorld * OldWorld = GetWorld(); cWorld * OldWorld = GetWorld();
cChunk * ParentChunk = GetParentChunk();
SetWorld(a_World); // Chunks may be streamed before cWorld::AddPlayer() sets the world to the new value 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) ", LOGD("Warping entity #%i (%s) from world \"%s\" to \"%s\". Source chunk: (%d, %d) ",
this->GetUniqueID(), this->GetClass(), this->GetUniqueID(), this->GetClass(),
a_OldWorld.GetName().c_str(), a_World->GetName().c_str(), 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); cRoot::Get()->GetPluginManager()->CallHookEntityChangedWorld(*this, a_OldWorld);
}); });
return true; return true;

View File

@ -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) unsigned int cWorld::GetNumPlayers(void)
{ {

View File

@ -301,6 +301,10 @@ public:
Note: Only loaded chunks are considered. */ Note: Only loaded chunks are considered. */
bool HasEntity(UInt32 a_UniqueID); 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 */ /** 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 bool ForEachEntity(cEntityCallback & a_Callback); // Exported in ManualBindings.cpp