From 868cd94ee9a5a0638c014a4cc42224f01ff234c8 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 5 Mar 2021 13:03:55 +0000 Subject: Prepare ChunkData for BlockState storage (#5105) * Rename ChunkData Creatable test * Add missing Y-check in RedstoneWireHandler * Remove ChunkDef.h dependency in Scoreboard * Prepare ChunkData for BlockState storage + Split chunk block, meta, block & sky light storage + Load the height map from disk - Reduce duplicated code in ChunkData - Remove saving MCSBiomes, there aren't any - Remove the allocation pool, ref #4315, #3864 * fixed build * fixed test * fixed the debug compile Co-authored-by: 12xx12 <44411062+12xx12@users.noreply.github.com> --- src/ChunkData.h | 193 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 110 insertions(+), 83 deletions(-) (limited to 'src/ChunkData.h') diff --git a/src/ChunkData.h b/src/ChunkData.h index 3b4c9c867..a984b752e 100644 --- a/src/ChunkData.h +++ b/src/ChunkData.h @@ -9,132 +9,159 @@ #pragma once +#include "FunctionRef.h" +#include "ChunkDef.h" -#include -#include "AllocationPool.h" -#include "ChunkDef.h" -class cChunkData + +template +struct ChunkDataStore { -public: + using Type = std::array; - static const int SectionHeight = 16; - static const size_t NumSections = (cChunkDef::Height / SectionHeight); - static const size_t SectionBlockCount = SectionHeight * cChunkDef::Width * cChunkDef::Width; + /** Copy assign from another ChunkDataStore. */ + void Assign(const ChunkDataStore & a_Other); - struct sChunkSection - { - BLOCKTYPE m_BlockTypes[SectionBlockCount]; - NIBBLETYPE m_BlockMetas[SectionBlockCount / 2]; - NIBBLETYPE m_BlockLight[SectionBlockCount / 2]; - NIBBLETYPE m_BlockSkyLight[SectionBlockCount / 2]; - }; + /** Gets one value at the given position. + Returns DefaultValue if the section is not allocated. */ + ElementType Get(Vector3i a_Position) const; - cChunkData(cAllocationPool & a_Pool); - cChunkData(cChunkData && a_Other); - ~cChunkData(); + /** 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; - cChunkData & operator = (cChunkData && a_Other) - { - Assign(std::move(a_Other)); - return *this; - } + /** 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); - /** Copy assign from another cChunkData */ - void Assign(const cChunkData & a_Other); + /** 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]); - /** Move assign from another cChunkData */ - void Assign(cChunkData && a_Other); + /** Contains all the sections this ChunkDataStore manages. */ + std::unique_ptr Store[cChunkDef::NumSections]; +}; + + + + + +class ChunkBlockData +{ +public: - BLOCKTYPE GetBlock(Vector3i a_RelPos) const; - void SetBlock(Vector3i a_RelPos, BLOCKTYPE a_Block); + static constexpr size_t SectionBlockCount = cChunkDef::SectionHeight * cChunkDef::Width * cChunkDef::Width; + static constexpr size_t SectionMetaCount = SectionBlockCount / 2; - NIBBLETYPE GetMeta(Vector3i a_RelPos) const; - bool SetMeta(Vector3i a_RelPos, NIBBLETYPE a_Nibble); + static constexpr BLOCKTYPE DefaultValue = 0x00; + static constexpr NIBBLETYPE DefaultMetaValue = 0x00; - NIBBLETYPE GetBlockLight(Vector3i a_RelPos) const; + using SectionType = BLOCKTYPE[SectionBlockCount]; + using SectionMetaType = NIBBLETYPE[SectionMetaCount]; - NIBBLETYPE GetSkyLight(Vector3i a_RelPos) const; +private: - /** Return a pointer to the chunk section or nullptr if all air */ - const sChunkSection * GetSection(size_t a_SectionNum) const; + ChunkDataStore m_Blocks; + ChunkDataStore m_Metas; - /** Returns a bitmask of chunk sections which are currently stored. */ - UInt16 GetSectionBitmask() const; +public: - /** Clears all data */ - void Clear(); + using BlockArray = decltype(m_Blocks)::Type; + using MetaArray = decltype(m_Metas)::Type; - /** Copies the blocktype data into the specified flat array. - Optionally, only a part of the data is copied, as specified by the a_Idx and a_Length parameters. */ - void CopyBlockTypes(BLOCKTYPE * a_Dest, size_t a_Idx = 0, size_t a_Length = cChunkDef::NumBlocks) const; + void Assign(const ChunkBlockData & a_Other); - /** Copies the metadata into the specified flat array. */ - void CopyMetas(NIBBLETYPE * a_Dest) const; + BLOCKTYPE GetBlock(Vector3i a_Position) const { return m_Blocks.Get(a_Position); } + NIBBLETYPE GetMeta(Vector3i a_Position) const { return m_Metas.Get(a_Position); } - /** Copies the block light data into the specified flat array. */ - void CopyBlockLight(NIBBLETYPE * a_Dest) const; + 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); } - /** Copies the skylight data into the specified flat array. */ - void CopySkyLight (NIBBLETYPE * a_Dest) const; + 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); } - /** Fills the chunk with the specified block. */ - void FillBlockTypes(BLOCKTYPE a_Value); + 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); +}; - /** Fills the chunk with the specified meta value. */ - void FillMetas (NIBBLETYPE a_Value); - /** Fills the chunk with the specified block light. */ - void FillBlockLight(NIBBLETYPE a_Value); - /** Fills the chunk with the specified sky light. */ - void FillSkyLight (NIBBLETYPE a_Value); - /** Copies the blocktype data from the specified flat array into the internal representation. - Allocates sections that are needed for the operation. - Requires that a_Src is a valid pointer. */ - void SetBlockTypes(const BLOCKTYPE * a_Src); - /** Copies the metadata from the specified flat array into the internal representation. - Allocates sectios that are needed for the operation. - Requires that a_Src is a valid pointer. */ - void SetMetas(const NIBBLETYPE * a_Src); +class ChunkLightData +{ +public: - /** Copies the blocklight data from the specified flat array into the internal representation. - Allocates sectios that are needed for the operation. - Allows a_Src to be nullptr, in which case it doesn't do anything. */ - void SetBlockLight(const NIBBLETYPE * a_Src); + static constexpr size_t SectionLightCount = (cChunkDef::SectionHeight * cChunkDef::Width * cChunkDef::Width) / 2; - /** Copies the skylight data from the specified flat array into the internal representation. - Allocates sectios that are needed for the operation. - Allows a_Src to be nullptr, in which case it doesn't do anything. */ - void SetSkyLight(const NIBBLETYPE * a_Src); + static constexpr NIBBLETYPE DefaultBlockLightValue = 0x00; + static constexpr NIBBLETYPE DefaultSkyLightValue = 0xFF; - /** Returns the number of sections present (i.e. non-air). */ - UInt32 NumPresentSections() const; + using SectionType = NIBBLETYPE[SectionLightCount]; private: - sChunkSection * m_Sections[NumSections]; + ChunkDataStore m_BlockLights; + ChunkDataStore m_SkyLights; + +public: - cAllocationPool & m_Pool; + using LightArray = decltype(m_BlockLights)::Type; - /** Allocates a new section. Entry-point to custom allocators. */ - sChunkSection * Allocate(void); + void Assign(const ChunkLightData & a_Other); - /** Frees the specified section, previously allocated using Allocate(). - Note that a_Section may be nullptr. */ - void Free(sChunkSection * a_Section); + NIBBLETYPE GetBlockLight(Vector3i a_Position) const { return m_BlockLights.Get(a_Position); } + NIBBLETYPE GetSkyLight(Vector3i a_Position) const { return m_SkyLights.Get(a_Position); } - /** Sets the data in the specified section to their default values. */ - void ZeroSection(sChunkSection * a_Section) const; + 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; -- cgit v1.2.3