// 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 struct ChunkDataStore { using Type = std::array; /** Copy assign from another ChunkDataStore. */ void Assign(const ChunkDataStore & 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 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 m_Blocks; ChunkDataStore 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 m_BlockLights; ChunkDataStore 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; /** 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; extern template struct ChunkDataStore; extern template struct ChunkDataStore;