Optimise chunk set (#4260)
Closes #1244 Initially I was just going to add the cChunkData to cSetChunkData but profiling revealed that the copying wasn't even the biggest slowdown. Much more time was being spent in cChunk::CreateBlockEntities and cChunk::WakeUpSimulators than was in memcpy so I've made those significantly faster as well. Optimisations performed: * cSetChunkData now stores blocks in a cChunkData object * cChunkData objects can now perform moves even if they are using different pools * cChunk::CreateBlockEntities now iterates in the correct order and only over present chunk sections * Similarly for cChunk::WakeUpSimulators * cSetChunkData::CalculateHeightMap now shortcuts to the highest present chunk section before checking blocks directly
This commit is contained in:
@@ -8,6 +8,17 @@
|
||||
#include "BlockEntities/BlockEntity.h"
|
||||
#include "Entities/Entity.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct sMemCallbacks:
|
||||
cAllocationPool<cChunkData::sChunkSection>::cStarvationCallbacks
|
||||
{
|
||||
virtual void OnStartUsingReserve() override {}
|
||||
virtual void OnEndUsingReserve() override {}
|
||||
virtual void OnOutOfReserve() override {}
|
||||
};
|
||||
} // namespace (anonymous)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15,6 +26,8 @@
|
||||
cSetChunkData::cSetChunkData(int a_ChunkX, int a_ChunkZ, bool a_ShouldMarkDirty) :
|
||||
m_ChunkX(a_ChunkX),
|
||||
m_ChunkZ(a_ChunkZ),
|
||||
m_Pool(cpp14::make_unique<sMemCallbacks>(), cChunkData::NumSections),
|
||||
m_ChunkData(m_Pool),
|
||||
m_IsLightValid(false),
|
||||
m_IsHeightMapValid(false),
|
||||
m_AreBiomesValid(false),
|
||||
@@ -38,29 +51,23 @@ cSetChunkData::cSetChunkData(
|
||||
cBlockEntities && a_BlockEntities,
|
||||
bool a_ShouldMarkDirty
|
||||
) :
|
||||
m_ChunkX(a_ChunkX),
|
||||
m_ChunkZ(a_ChunkZ),
|
||||
m_ShouldMarkDirty(a_ShouldMarkDirty)
|
||||
cSetChunkData(a_ChunkX, a_ChunkZ, a_ShouldMarkDirty)
|
||||
{
|
||||
// Check the params' validity:
|
||||
ASSERT(a_BlockTypes != nullptr);
|
||||
ASSERT(a_BlockMetas != nullptr);
|
||||
|
||||
// Copy block types and metas:
|
||||
memcpy(m_BlockTypes, a_BlockTypes, sizeof(cChunkDef::BlockTypes));
|
||||
memcpy(m_BlockMetas, a_BlockMetas, sizeof(cChunkDef::BlockNibbles));
|
||||
m_ChunkData.SetBlockTypes(a_BlockTypes);
|
||||
m_ChunkData.SetMetas(a_BlockMetas);
|
||||
|
||||
// Copy lights, if both given:
|
||||
if ((a_BlockLight != nullptr) && (a_SkyLight != nullptr))
|
||||
{
|
||||
memcpy(m_BlockLight, a_BlockLight, sizeof(m_BlockLight));
|
||||
memcpy(m_SkyLight, a_SkyLight, sizeof(m_SkyLight));
|
||||
m_ChunkData.SetBlockLight(a_BlockLight);
|
||||
m_ChunkData.SetSkyLight(a_SkyLight);
|
||||
m_IsLightValid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IsLightValid = false;
|
||||
}
|
||||
|
||||
// Copy the heightmap, if available:
|
||||
if (a_HeightMap != nullptr)
|
||||
@@ -68,10 +75,6 @@ cSetChunkData::cSetChunkData(
|
||||
memcpy(m_HeightMap, a_HeightMap, sizeof(m_HeightMap));
|
||||
m_IsHeightMapValid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IsHeightMapValid = false;
|
||||
}
|
||||
|
||||
// Copy biomes, if available:
|
||||
if (a_Biomes != nullptr)
|
||||
@@ -79,10 +82,6 @@ cSetChunkData::cSetChunkData(
|
||||
memcpy(m_Biomes, a_Biomes, sizeof(m_Biomes));
|
||||
m_AreBiomesValid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_AreBiomesValid = false;
|
||||
}
|
||||
|
||||
// Move entities and blockentities:
|
||||
m_Entities = std::move(a_Entities);
|
||||
@@ -95,14 +94,25 @@ cSetChunkData::cSetChunkData(
|
||||
|
||||
void cSetChunkData::CalculateHeightMap(void)
|
||||
{
|
||||
// Find the heighest present section in the chunk
|
||||
size_t MaxSection = 0;
|
||||
for (size_t i = cChunkData::NumSections - 1; i != 0; --i)
|
||||
{
|
||||
if (m_ChunkData.GetSection(i) != nullptr)
|
||||
{
|
||||
MaxSection = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const int MaxHeight = static_cast<int>(MaxSection + 1) * cChunkData::SectionHeight - 1;
|
||||
|
||||
for (int x = 0; x < cChunkDef::Width; x++)
|
||||
{
|
||||
for (int z = 0; z < cChunkDef::Width; z++)
|
||||
{
|
||||
for (int y = cChunkDef::Height - 1; y > -1; y--)
|
||||
for (int y = MaxHeight; y > -1; y--)
|
||||
{
|
||||
int index = cChunkDef::MakeIndexNoCheck(x, y, z);
|
||||
if (m_BlockTypes[index] != E_BLOCK_AIR)
|
||||
if (m_ChunkData.GetBlock({x, y, z}) != E_BLOCK_AIR)
|
||||
{
|
||||
m_HeightMap[x + z * cChunkDef::Width] = static_cast<HEIGHTTYPE>(y);
|
||||
break;
|
||||
@@ -124,7 +134,7 @@ void cSetChunkData::RemoveInvalidBlockEntities(void)
|
||||
{
|
||||
cBlockEntity * BlockEntity = itr->second;
|
||||
BLOCKTYPE EntityBlockType = BlockEntity->GetBlockType();
|
||||
BLOCKTYPE WorldBlockType = cChunkDef::GetBlock(m_BlockTypes, BlockEntity->GetRelX(), BlockEntity->GetPosY(), BlockEntity->GetRelZ());
|
||||
BLOCKTYPE WorldBlockType = m_ChunkData.GetBlock({BlockEntity->GetRelX(), BlockEntity->GetPosY(), BlockEntity->GetRelZ()});
|
||||
if (EntityBlockType != WorldBlockType)
|
||||
{
|
||||
// Bad blocktype, remove the block entity:
|
||||
|
||||
Reference in New Issue
Block a user