// ChunkData.h
// Declares the cChunkData class that represents the block's type, meta, blocklight and skylight storage for a chunk
#pragma once
#include "FunctionRef.h"
#include "ChunkDef.h"
template <class ElementType, size_t ElementCount, ElementType DefaultValue>
struct ChunkDataStore
{
using Type = std::array<ElementType, ElementCount>;
/** Copy assign from another ChunkDataStore. */
void Assign(const ChunkDataStore<ElementType, ElementCount, DefaultValue> & a_Other);
/** Gets one value at the given position.
Returns DefaultValue if the section is not allocated. */
ElementType Get(Vector3i a_Position) const;
/** Returns a raw pointer to the internal representation of the specified section.
Will be nullptr if the section is not allocated. */
Type * GetSection(size_t a_Y) const;
/** Sets one value at the given position.
Allocates a section if needed for the operation. */
void Set(Vector3i a_Position, ElementType a_Value);
/** Copies the data from the specified flat section array into the internal representation.
Allocates a section if needed for the operation. */
void SetSection(const ElementType (& a_Source)[ElementCount], size_t a_Y);
/** Copies the data from the specified flat array into the internal representation.
Allocates sections that are needed for the operation. */
void SetAll(const ElementType (& a_Source)[cChunkDef::NumSections * ElementCount]);
/** Contains all the sections this ChunkDataStore manages. */
std::unique_ptr<Type> Store[cChunkDef::NumSections];
};
class ChunkBlockData
{
public:
static constexpr size_t SectionBlockCount = cChunkDef::SectionHeight * cChunkDef::Width * cChunkDef::Width;
static constexpr size_t SectionMetaCount = SectionBlockCount / 2;
static constexpr BLOCKTYPE DefaultValue = 0x00;
static constexpr NIBBLETYPE DefaultMetaValue = 0x00;
using SectionType = BLOCKTYPE[SectionBlockCount];
using SectionMetaType = NIBBLETYPE[SectionMetaCount];
private:
ChunkDataStore<BLOCKTYPE, SectionBlockCount, DefaultValue> m_Blocks;
ChunkDataStore<NIBBLETYPE, SectionMetaCount, DefaultMetaValue> m_Metas;
public:
using BlockArray = decltype(m_Blocks)::Type;
using MetaArray = decltype(m_Metas)::Type;
void Assign(const ChunkBlockData & a_Other);
BLOCKTYPE GetBlock(Vector3i a_Position) const { return m_Blocks.Get(a_Position); }
NIBBLETYPE GetMeta(Vector3i a_Position) const { return m_Metas.Get(a_Position); }
BlockArray * GetSection(size_t a_Y) const { return m_Blocks.GetSection(a_Y); }
MetaArray * GetMetaSection(size_t a_Y) const { return m_Metas.GetSection(a_Y); }
void SetBlock(Vector3i a_Position, BLOCKTYPE a_Block) { m_Blocks.Set(a_Position, a_Block); }
void SetMeta(Vector3i a_Position, NIBBLETYPE a_Meta) { m_Metas.Set(a_Position, a_Meta); }
void SetAll(const cChunkDef::BlockTypes & a_BlockSource, const cChunkDef::BlockNibbles & a_MetaSource);
void SetSection(const SectionType & a_BlockSource, const SectionMetaType & a_MetaSource, size_t a_Y);
};
class ChunkLightData
{
public:
static constexpr size_t SectionLightCount = (cChunkDef::SectionHeight * cChunkDef::Width * cChunkDef::Width) / 2;
static constexpr NIBBLETYPE DefaultBlockLightValue = 0x00;
static constexpr NIBBLETYPE DefaultSkyLightValue = 0xFF;
using SectionType = NIBBLETYPE[SectionLightCount];
private:
ChunkDataStore<NIBBLETYPE, SectionLightCount, DefaultBlockLightValue> m_BlockLights;
ChunkDataStore<NIBBLETYPE, SectionLightCount, DefaultSkyLightValue> m_SkyLights;
public:
using LightArray = decltype(m_BlockLights)::Type;
void Assign(const ChunkLightData & a_Other);
NIBBLETYPE GetBlockLight(Vector3i a_Position) const { return m_BlockLights.Get(a_Position); }
NIBBLETYPE GetSkyLight(Vector3i a_Position) const { return m_SkyLights.Get(a_Position); }
LightArray * GetBlockLightSection(size_t a_Y) const { return m_BlockLights.GetSection(a_Y); }
LightArray * GetSkyLightSection(size_t a_Y) const { return m_SkyLights.GetSection(a_Y); }
void SetAll(const cChunkDef::BlockNibbles & a_BlockLightSource, const cChunkDef::BlockNibbles & a_SkyLightSource);
void SetSection(const SectionType & a_BlockLightSource, const SectionType & a_SkyLightSource, size_t a_Y);
};
namespace ChunkDef
{
using cForEachSectionCallback = cFunctionRef<void(
size_t,
ChunkBlockData::BlockArray *,
ChunkBlockData::MetaArray *,
ChunkLightData::LightArray *,
ChunkLightData::LightArray *)>;
/** Invokes the callback functor for every chunk section containing at least one present block or light section data.
This is used to collect all data for all sections. */
inline void ForEachSection(const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData, cForEachSectionCallback a_Callback)
{
for (size_t Y = 0; Y < cChunkDef::NumSections; ++Y)
{
const auto Blocks = a_BlockData.GetSection(Y);
const auto Metas = a_BlockData.GetMetaSection(Y);
const auto BlockLights = a_LightData.GetBlockLightSection(Y);
const auto SkyLights = a_LightData.GetSkyLightSection(Y);
if ((Blocks != nullptr) || (Metas != nullptr) || (BlockLights != nullptr) || (SkyLights != nullptr))
{
a_Callback(Y, Blocks, Metas, BlockLights, SkyLights);
}
}
}
}
extern template struct ChunkDataStore<BLOCKTYPE, ChunkBlockData::SectionBlockCount, ChunkBlockData::DefaultValue>;
extern template struct ChunkDataStore<NIBBLETYPE, ChunkBlockData::SectionMetaCount, ChunkLightData::DefaultBlockLightValue>;
extern template struct ChunkDataStore<NIBBLETYPE, ChunkLightData::SectionLightCount, ChunkLightData::DefaultSkyLightValue>;