1
0
Fork 0
cuberite-2a/src/ChunkData.cpp

235 lines
5.3 KiB
C++
Raw Permalink Normal View History

2014-05-29 16:25:08 +00:00
// ChunkData.cpp
// Implements the cChunkData class that represents the block's type, meta, blocklight and skylight storage for a chunk
#include "Globals.h"
2014-05-21 18:58:48 +00:00
#include "ChunkData.h"
#include "BlockType.h"
2014-05-29 16:25:08 +00:00
namespace
2014-05-29 16:25:08 +00:00
{
struct SectionIndices
2014-05-29 16:25:08 +00:00
{
size_t Section = 0; // Index into m_Sections
size_t Index = 0; // Index into a single sChunkSection
};
inline SectionIndices IndicesFromRelPos(const Vector3i a_RelPos)
{
ASSERT(cChunkDef::IsValidRelPos(a_RelPos));
2014-05-24 12:37:25 +00:00
return
2014-05-24 12:37:25 +00:00
{
static_cast<size_t>(a_RelPos.y / cChunkDef::SectionHeight),
cChunkDef::MakeIndex(a_RelPos.x, a_RelPos.y % cChunkDef::SectionHeight, a_RelPos.z)
};
}
2014-05-28 09:35:55 +00:00
bool IsCompressed(const size_t ElementCount)
2014-05-24 12:37:25 +00:00
{
return ElementCount != ChunkBlockData::SectionBlockCount;
2014-05-24 12:37:25 +00:00
}
template <size_t ElementCount, typename ValueType>
ValueType UnpackDefaultValue(const ValueType DefaultValue)
2014-05-24 12:37:25 +00:00
{
if (IsCompressed(ElementCount))
2014-05-24 12:37:25 +00:00
{
return DefaultValue & 0xF;
2014-05-24 12:37:25 +00:00
}
return DefaultValue;
2014-05-24 12:37:25 +00:00
}
} // namespace (anonymous)
2014-05-24 12:37:25 +00:00
2014-05-28 09:35:55 +00:00
template<class ElementType, size_t ElementCount, ElementType DefaultValue>
void ChunkDataStore<ElementType, ElementCount, DefaultValue>::Assign(const ChunkDataStore<ElementType, ElementCount, DefaultValue> & a_Other)
2014-05-24 12:37:25 +00:00
{
for (size_t Y = 0; Y != cChunkDef::NumSections; Y++)
2014-05-24 12:37:25 +00:00
{
Store[Y].reset();
2014-05-24 12:37:25 +00:00
if (const auto & Other = a_Other.Store[Y]; Other != nullptr)
2014-05-24 12:37:25 +00:00
{
Store[Y] = std::make_unique<Type>(*Other);
2014-05-24 12:37:25 +00:00
}
}
}
2014-05-28 09:35:55 +00:00
template<class ElementType, size_t ElementCount, ElementType DefaultValue>
ElementType ChunkDataStore<ElementType, ElementCount, DefaultValue>::Get(const Vector3i a_Position) const
2014-05-24 12:37:25 +00:00
{
const auto Indices = IndicesFromRelPos(a_Position);
const auto & Section = Store[Indices.Section];
2014-05-28 09:35:55 +00:00
if (Section != nullptr)
2014-05-24 12:37:25 +00:00
{
if (IsCompressed(ElementCount))
2014-05-24 12:37:25 +00:00
{
return cChunkDef::ExpandNibble(Section->data(), Indices.Index);
2014-05-24 12:37:25 +00:00
}
else
{
return (*Section)[Indices.Index];
2014-05-24 12:37:25 +00:00
}
}
return UnpackDefaultValue<ElementCount>(DefaultValue);
}
template<class ElementType, size_t ElementCount, ElementType DefaultValue>
typename ChunkDataStore<ElementType, ElementCount, DefaultValue>::Type * ChunkDataStore<ElementType, ElementCount, DefaultValue>::GetSection(const size_t a_Y) const
{
return Store[a_Y].get();
}
template<class ElementType, size_t ElementCount, ElementType DefaultValue>
void ChunkDataStore<ElementType, ElementCount, DefaultValue>::Set(const Vector3i a_Position, const ElementType a_Value)
{
const auto Indices = IndicesFromRelPos(a_Position);
auto & Section = Store[Indices.Section];
if (Section == nullptr)
{
if (a_Value == UnpackDefaultValue<ElementCount>(DefaultValue))
2014-04-27 14:38:16 +00:00
{
return;
2014-04-27 14:38:16 +00:00
}
Section = cpp20::make_unique_for_overwrite<Type>();
std::fill(Section->begin(), Section->end(), DefaultValue);
2017-08-20 22:23:23 +00:00
}
if (IsCompressed(ElementCount))
2017-08-20 22:23:23 +00:00
{
cChunkDef::PackNibble(Section->data(), Indices.Index, a_Value);
2017-08-20 22:23:23 +00:00
}
else
2017-08-20 22:23:23 +00:00
{
(*Section)[Indices.Index] = a_Value;
2017-08-20 22:23:23 +00:00
}
}
template<class ElementType, size_t ElementCount, ElementType DefaultValue>
void ChunkDataStore<ElementType, ElementCount, DefaultValue>::SetSection(const ElementType (& a_Source)[ElementCount], const size_t a_Y)
2017-08-20 22:23:23 +00:00
{
auto & Section = Store[a_Y];
const auto SourceEnd = std::end(a_Source);
2017-08-20 22:23:23 +00:00
if (Section != nullptr)
2017-08-20 22:23:23 +00:00
{
std::copy(a_Source, SourceEnd, Section->begin());
2017-08-20 22:23:23 +00:00
}
else if (std::any_of(a_Source, SourceEnd, [](const auto Value) { return Value != DefaultValue; }))
2017-08-20 22:23:23 +00:00
{
Section = cpp20::make_unique_for_overwrite<Type>();
std::copy(a_Source, SourceEnd, Section->begin());
2017-08-20 22:23:23 +00:00
}
}
template<class ElementType, size_t ElementCount, ElementType DefaultValue>
void ChunkDataStore<ElementType, ElementCount, DefaultValue>::SetAll(const ElementType (& a_Source)[cChunkDef::NumSections * ElementCount])
2017-08-20 22:23:23 +00:00
{
for (size_t Y = 0; Y != cChunkDef::NumSections; Y++)
2017-08-20 22:23:23 +00:00
{
SetSection(*reinterpret_cast<const ElementType (*)[ElementCount]>(a_Source + Y * ElementCount), Y);
}
}
void ChunkBlockData::Assign(const ChunkBlockData & a_Other)
{
m_Blocks.Assign(a_Other.m_Blocks);
m_Metas.Assign(a_Other.m_Metas);
}
2014-05-29 16:25:08 +00:00
void ChunkBlockData::SetAll(const cChunkDef::BlockTypes & a_BlockSource, const cChunkDef::BlockNibbles & a_MetaSource)
{
m_Blocks.SetAll(a_BlockSource);
m_Metas.SetAll(a_MetaSource);
}
void ChunkBlockData::SetSection(const SectionType & a_BlockSource, const SectionMetaType & a_MetaSource, const size_t a_Y)
{
m_Blocks.SetSection(a_BlockSource, a_Y);
m_Metas.SetSection(a_MetaSource, a_Y);
}
void ChunkLightData::Assign(const ChunkLightData & a_Other)
{
m_BlockLights.Assign(a_Other.m_BlockLights);
m_SkyLights.Assign(a_Other.m_SkyLights);
}
void ChunkLightData::SetAll(const cChunkDef::BlockNibbles & a_BlockLightSource, const cChunkDef::BlockNibbles & a_SkyLightSource)
{
m_BlockLights.SetAll(a_BlockLightSource);
m_SkyLights.SetAll(a_SkyLightSource);
}
2014-05-28 09:35:55 +00:00
void ChunkLightData::SetSection(const SectionType & a_BlockLightSource, const SectionType & a_SkyLightSource, const size_t a_Y)
{
m_BlockLights.SetSection(a_BlockLightSource, a_Y);
m_SkyLights.SetSection(a_SkyLightSource, a_Y);
}
2014-05-28 09:35:55 +00:00
template struct ChunkDataStore<BLOCKTYPE, ChunkBlockData::SectionBlockCount, ChunkBlockData::DefaultValue>;
template struct ChunkDataStore<NIBBLETYPE, ChunkBlockData::SectionMetaCount, ChunkLightData::DefaultBlockLightValue>;
template struct ChunkDataStore<NIBBLETYPE, ChunkLightData::SectionLightCount, ChunkLightData::DefaultSkyLightValue>;