summaryrefslogtreecommitdiffstats
path: root/src/Chunk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Chunk.cpp')
-rw-r--r--src/Chunk.cpp117
1 files changed, 58 insertions, 59 deletions
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index aa1544c7d..efdce7edc 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -336,13 +336,16 @@ void cChunk::GetAllData(cChunkDataCallback & a_Callback) const
void cChunk::SetAllData(SetChunkData && a_SetChunkData)
{
- std::copy(a_SetChunkData.HeightMap, a_SetChunkData.HeightMap + std::size(a_SetChunkData.HeightMap), m_HeightMap);
- std::copy(a_SetChunkData.BiomeMap, a_SetChunkData.BiomeMap + std::size(a_SetChunkData.BiomeMap), m_BiomeMap);
+ std::copy_n(a_SetChunkData.HeightMap, std::size(a_SetChunkData.HeightMap), m_HeightMap);
+ std::copy_n(a_SetChunkData.BiomeMap, std::size(a_SetChunkData.BiomeMap), m_BiomeMap);
m_BlockData = std::move(a_SetChunkData.BlockData);
m_LightData = std::move(a_SetChunkData.LightData);
m_IsLightValid = a_SetChunkData.IsLightValid;
+ m_PendingSendBlocks.clear();
+ m_PendingSendBlockEntities.clear();
+
// Entities need some extra steps to destroy, so here we're keeping the old ones.
// Move the entities already in the chunk, including player entities, so that we don't lose any:
a_SetChunkData.Entities.insert(
@@ -383,15 +386,17 @@ void cChunk::SetAllData(SetChunkData && a_SetChunkData)
}
#endif
- // Set all block entities' World variable:
+ // Set the chunk data as valid.
+ // This may be needed for some simulators that perform actions upon block adding (Vaporize),
+ // as well as some block entities upon being added to the chunk (Chests).
+ SetPresence(cpPresent);
+
+ // Initialise all block entities:
for (auto & KeyPair : m_BlockEntities)
{
- KeyPair.second->SetWorld(m_World);
+ KeyPair.second->OnAddToWorld(*m_World, *this);
}
- // Set the chunk data as valid. This may be needed for some simulators that perform actions upon block adding (Vaporize)
- SetPresence(cpPresent);
-
// Wake up all simulators for their respective blocks:
WakeUpSimulators();
}
@@ -466,22 +471,34 @@ void cChunk::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlock
} // for y
// Erase all affected block entities:
- cCuboid affectedArea( // In world coordinates
- {BlockStartX, a_MinBlockY, BlockStartZ},
- {BlockEndX, a_MinBlockY + SizeY - 1, BlockEndZ}
- );
- for (auto itr = m_BlockEntities.begin(); itr != m_BlockEntities.end();)
{
- if (affectedArea.IsInside(itr->second->GetPos()))
- {
- itr->second->Destroy();
- itr->second->OnRemoveFromWorld();
- itr = m_BlockEntities.erase(itr);
- }
- else
+ // The affected area, in world coordinates.
+ cCuboid affectedArea(
+ { BlockStartX, a_MinBlockY, BlockStartZ },
+ { BlockEndX, a_MinBlockY + SizeY - 1, BlockEndZ }
+ );
+
+ // Where in the pending block entity send list to start removing the invalidated elements from.
+ auto PendingRemove = m_PendingSendBlockEntities.end();
+
+ for (auto itr = m_BlockEntities.begin(); itr != m_BlockEntities.end();)
{
- ++itr;
+ if (affectedArea.IsInside(itr->second->GetPos()))
+ {
+ itr->second->Destroy();
+ itr->second->OnRemoveFromWorld();
+
+ PendingRemove = std::remove(m_PendingSendBlockEntities.begin(), PendingRemove, itr->second.get()); // Search the remaining valid pending sends.
+ itr = m_BlockEntities.erase(itr);
+ }
+ else
+ {
+ ++itr;
+ }
}
+
+ // Remove all the deleted block entities from the pending send list:
+ m_PendingSendBlockEntities.erase(PendingRemove, m_PendingSendBlockEntities.end());
}
// Clone block entities from a_Area into this chunk:
@@ -500,27 +517,15 @@ void cChunk::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlock
{
continue;
}
- // This block entity is inside the chunk, clone it (and remove any that is there currently):
- auto idx = static_cast<size_t>(cChunkDef::MakeIndex(posX - m_PosX * cChunkDef::Width, posY, posZ - m_PosZ * cChunkDef::Width));
- auto itr = m_BlockEntities.find(idx);
- if (itr != m_BlockEntities.end())
- {
- m_BlockEntities.erase(itr);
- }
- auto clone = be->Clone({posX, posY, posZ});
- clone->SetWorld(m_World);
- AddBlockEntity(std::move(clone));
- }
- }
-}
-
-
+ // This block entity is inside the chunk.
+ // The code above should have removed any that were here before:
+ ASSERT(GetBlockEntityRel(cChunkDef::AbsoluteToRelative({ posX, posY, posZ })) == nullptr);
-
-bool cChunk::HasBlockEntityAt(Vector3i a_BlockPos)
-{
- return (GetBlockEntity(a_BlockPos) != nullptr);
+ // Clone, and add the new one:
+ AddBlockEntity(be->Clone({posX, posY, posZ}));
+ }
+ }
}
@@ -1287,12 +1292,15 @@ void cChunk::SetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_Blo
GetWorld()->GetSimulatorManager()->WakeUp(*this, a_RelPos);
// If there was a block entity, remove it:
- cBlockEntity * BlockEntity = GetBlockEntityRel(a_RelPos);
- if (BlockEntity != nullptr)
+ if (const auto FindResult = m_BlockEntities.find(cChunkDef::MakeIndex(a_RelPos)); FindResult != m_BlockEntities.end())
{
- BlockEntity->Destroy();
- BlockEntity->OnRemoveFromWorld();
- RemoveBlockEntity(BlockEntity);
+ auto & BlockEntity = *FindResult->second;
+
+ BlockEntity.Destroy();
+ BlockEntity.OnRemoveFromWorld();
+
+ m_BlockEntities.erase(FindResult);
+ m_PendingSendBlockEntities.erase(std::remove(m_PendingSendBlockEntities.begin(), m_PendingSendBlockEntities.end(), &BlockEntity), m_PendingSendBlockEntities.end());
}
// If the new block is a block entity, create the entity object:
@@ -1414,11 +1422,14 @@ void cChunk::SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_C
void cChunk::AddBlockEntity(OwnedBlockEntity a_BlockEntity)
{
+ const auto BlockEntityPtr = a_BlockEntity.get();
[[maybe_unused]] const auto Result = m_BlockEntities.emplace(
cChunkDef::MakeIndex(a_BlockEntity->GetRelX(), a_BlockEntity->GetPosY(), a_BlockEntity->GetRelZ()),
std::move(a_BlockEntity)
);
- ASSERT(Result.second); // No block entity already at this position
+
+ ASSERT(Result.second); // No block entity already at this position.
+ BlockEntityPtr->OnAddToWorld(*m_World, *this);
}
@@ -1435,7 +1446,7 @@ cBlockEntity * cChunk::GetBlockEntity(Vector3i a_AbsPos)
return nullptr;
}
- auto itr = m_BlockEntities.find(static_cast<size_t>(cChunkDef::MakeIndexNoCheck(relPos)));
+ auto itr = m_BlockEntities.find(cChunkDef::MakeIndex(relPos));
return (itr == m_BlockEntities.end()) ? nullptr : itr->second.get();
}
@@ -1446,7 +1457,7 @@ cBlockEntity * cChunk::GetBlockEntity(Vector3i a_AbsPos)
cBlockEntity * cChunk::GetBlockEntityRel(Vector3i a_RelPos)
{
ASSERT(cChunkDef::IsValidRelPos(a_RelPos));
- auto itr = m_BlockEntities.find(static_cast<size_t>(cChunkDef::MakeIndexNoCheck(a_RelPos)));
+ auto itr = m_BlockEntities.find(cChunkDef::MakeIndex(a_RelPos));
return (itr == m_BlockEntities.end()) ? nullptr : itr->second.get();
}
@@ -1527,18 +1538,6 @@ void cChunk::SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_Max
-void cChunk::RemoveBlockEntity(cBlockEntity * a_BlockEntity)
-{
- MarkDirty();
- ASSERT(a_BlockEntity != nullptr);
- m_BlockEntities.erase(static_cast<size_t>(cChunkDef::MakeIndex(a_BlockEntity->GetRelX(), a_BlockEntity->GetPosY(), a_BlockEntity->GetRelZ())));
- m_PendingSendBlockEntities.erase(std::remove(m_PendingSendBlockEntities.begin(), m_PendingSendBlockEntities.end(), a_BlockEntity), m_PendingSendBlockEntities.end());
-}
-
-
-
-
-
bool cChunk::AddClient(cClientHandle * a_Client)
{
if (std::find(m_LoadedByClient.begin(), m_LoadedByClient.end(), a_Client) != m_LoadedByClient.end())