diff options
Diffstat (limited to 'src/ChunkDef.h')
-rw-r--r-- | src/ChunkDef.h | 211 |
1 files changed, 58 insertions, 153 deletions
diff --git a/src/ChunkDef.h b/src/ChunkDef.h index 9c7753820..f89e16ed1 100644 --- a/src/ChunkDef.h +++ b/src/ChunkDef.h @@ -77,13 +77,19 @@ public: idx = x + Width * z // Need to verify this with the protocol spec, currently unknown! */ typedef EMCSBiome BiomeMap[Width * Width]; - + /// The type used for block type operations and storage, AXIS_ORDER ordering typedef BLOCKTYPE BlockTypes[NumBlocks]; - + /// The type used for block data in nibble format, AXIS_ORDER ordering typedef NIBBLETYPE BlockNibbles[NumBlocks / 2]; + /** The storage wrapper used for compressed blockdata residing in RAMz */ + typedef std::vector<BLOCKTYPE> COMPRESSED_BLOCKTYPE; + + /** The storage wrapper used for compressed nibbledata residing in RAMz */ + typedef std::vector<NIBBLETYPE> COMPRESSED_NIBBLETYPE; + /// Converts absolute block coords into relative (chunk + block) coords: inline static void AbsoluteToRelative(/* in-out */ int & a_X, int & a_Y, int & a_Z, /* out */ int & a_ChunkX, int & a_ChunkZ ) @@ -219,46 +225,67 @@ public: ASSERT((a_Z >= 0) && (a_Z <= Width)); a_BiomeMap[a_X + Width * a_Z] = a_Biome; } - - - static NIBBLETYPE GetNibble(const NIBBLETYPE * a_Buffer, int a_BlockIdx) + + + static NIBBLETYPE GetNibble(const COMPRESSED_NIBBLETYPE & a_Buffer, int a_BlockIdx, bool a_IsSkyLightNibble = false) { if ((a_BlockIdx > -1) && (a_BlockIdx < NumBlocks)) { - return (a_Buffer[a_BlockIdx / 2] >> ((a_BlockIdx & 1) * 4)) & 0x0f; + if ((size_t)(a_BlockIdx / 2) >= a_Buffer.size()) + { + return (a_IsSkyLightNibble ? 0xff : 0); + } + return (a_Buffer[(size_t)(a_BlockIdx / 2)] >> ((a_BlockIdx & 1) * 4)) & 0x0f; } ASSERT(!"cChunkDef::GetNibble(): index out of chunk range!"); return 0; } - - + + + static NIBBLETYPE GetNibble(const COMPRESSED_NIBBLETYPE & a_Buffer, int x, int y, int z, bool a_IsSkyLightNibble = false) + { + if ((x < Width) && (x > -1) && (y < Height) && (y > -1) && (z < Width) && (z > -1)) + { + size_t Index = (size_t)MakeIndexNoCheck(x, y, z); + if ((Index / 2) >= a_Buffer.size()) + { + return (a_IsSkyLightNibble ? 0xff : 0); + } + return ExpandNibble(a_Buffer, Index); + } + ASSERT(!"cChunkDef::GetNibble(): coords out of chunk range!"); + return 0; + } + + static NIBBLETYPE GetNibble(const NIBBLETYPE * a_Buffer, int x, int y, int z) { if ((x < Width) && (x > -1) && (y < Height) && (y > -1) && (z < Width) && (z > -1)) { int Index = MakeIndexNoCheck(x, y, z); - return (a_Buffer[Index / 2] >> ((Index & 1) * 4)) & 0x0f; + return (a_Buffer[(size_t)(Index / 2)] >> ((Index & 1) * 4)) & 0x0f; } ASSERT(!"cChunkDef::GetNibble(): coords out of chunk range!"); return 0; } - static void SetNibble(NIBBLETYPE * a_Buffer, int a_BlockIdx, NIBBLETYPE a_Nibble) + static void SetNibble(COMPRESSED_NIBBLETYPE & a_Buffer, int a_BlockIdx, NIBBLETYPE a_Nibble) { if ((a_BlockIdx < 0) || (a_BlockIdx >= NumBlocks)) { ASSERT(!"cChunkDef::SetNibble(): index out of range!"); return; } - a_Buffer[a_BlockIdx / 2] = static_cast<NIBBLETYPE>( - (a_Buffer[a_BlockIdx / 2] & (0xf0 >> ((a_BlockIdx & 1) * 4))) | // The untouched nibble - ((a_Nibble & 0x0f) << ((a_BlockIdx & 1) * 4)) // The nibble being set - ); + if ((size_t)(a_BlockIdx / 2) >= a_Buffer.size()) + { + a_Buffer.resize((size_t)((a_BlockIdx / 2) + 1)); + } + a_Buffer[(size_t)(a_BlockIdx / 2)] = PackNibble(a_Buffer, (size_t)a_BlockIdx, a_Nibble); } - - - static void SetNibble(NIBBLETYPE * a_Buffer, int x, int y, int z, NIBBLETYPE a_Nibble) + + + static void SetNibble(COMPRESSED_NIBBLETYPE & a_Buffer, int x, int y, int z, NIBBLETYPE a_Nibble) { if ( (x >= Width) || (x < 0) || @@ -270,155 +297,33 @@ public: return; } - int Index = MakeIndexNoCheck(x, y, z); - a_Buffer[Index / 2] = static_cast<NIBBLETYPE>( - (a_Buffer[Index / 2] & (0xf0 >> ((Index & 1) * 4))) | // The untouched nibble - ((a_Nibble & 0x0f) << ((Index & 1) * 4)) // The nibble being set - ); - } - - - inline static NIBBLETYPE GetNibble(const NIBBLETYPE * a_Buffer, const Vector3i & a_BlockPos ) - { - return GetNibble(a_Buffer, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z ); - } - - - inline static void SetNibble(NIBBLETYPE * a_Buffer, const Vector3i & a_BlockPos, NIBBLETYPE a_Value ) - { - SetNibble( a_Buffer, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_Value ); - } - -} ; - - - - - -/** Interface class used for getting data out of a chunk using the GetAllData() function. -Implementation must use the pointers immediately and NOT store any of them for later use -The virtual methods are called in the same order as they're declared here. -*/ -class cChunkDataCallback abstract -{ -public: - - virtual ~cChunkDataCallback() {} - - /** Called before any other callbacks to inform of the current coords - (only in processes where multiple chunks can be processed, such as cWorld::ForEachChunkInRect()). - If false is returned, the chunk is skipped. - */ - virtual bool Coords(int a_ChunkX, int a_ChunkZ) { UNUSED(a_ChunkX); UNUSED(a_ChunkZ); return true; }; - - /// Called once to provide heightmap data - virtual void HeightMap(const cChunkDef::HeightMap * a_HeightMap) {UNUSED(a_HeightMap); }; - - /// Called once to provide biome data - virtual void BiomeData (const cChunkDef::BiomeMap * a_BiomeMap) {UNUSED(a_BiomeMap); }; - - /// Called once to export block types - virtual void BlockTypes (const BLOCKTYPE * a_Type) {UNUSED(a_Type); }; - - /// Called once to export block meta - virtual void BlockMeta (const NIBBLETYPE * a_Meta) {UNUSED(a_Meta); }; - - /// Called once to let know if the chunk lighting is valid. Return value is used to control if BlockLight() and BlockSkyLight() are called next (if true) - virtual bool LightIsValid(bool a_IsLightValid) {UNUSED(a_IsLightValid); return true; }; - - /// Called once to export block light - virtual void BlockLight (const NIBBLETYPE * a_BlockLight) {UNUSED(a_BlockLight); }; - - /// Called once to export sky light - virtual void BlockSkyLight(const NIBBLETYPE * a_SkyLight) {UNUSED(a_SkyLight); }; - - /// Called for each entity in the chunk - virtual void Entity(cEntity * a_Entity) {UNUSED(a_Entity); }; - - /// Called for each blockentity in the chunk - virtual void BlockEntity(cBlockEntity * a_Entity) {UNUSED(a_Entity); }; -} ; - - - - - -/** A simple implementation of the cChunkDataCallback interface that collects all block data into a single buffer -*/ -class cChunkDataCollector : - public cChunkDataCallback -{ -public: - - // Must be unsigned char instead of BLOCKTYPE or NIBBLETYPE, because it houses both. - unsigned char m_BlockData[cChunkDef::BlockDataSize]; - -protected: - - virtual void BlockTypes(const BLOCKTYPE * a_BlockTypes) override - { - memcpy(m_BlockData, a_BlockTypes, sizeof(cChunkDef::BlockTypes)); - } - - - virtual void BlockMeta(const NIBBLETYPE * a_BlockMeta) override - { - memcpy(m_BlockData + cChunkDef::NumBlocks, a_BlockMeta, cChunkDef::NumBlocks / 2); - } - - - virtual void BlockLight(const NIBBLETYPE * a_BlockLight) override - { - memcpy(m_BlockData + 3 * cChunkDef::NumBlocks / 2, a_BlockLight, cChunkDef::NumBlocks / 2); - } - - - virtual void BlockSkyLight(const NIBBLETYPE * a_BlockSkyLight) override - { - memcpy(m_BlockData + 2 * cChunkDef::NumBlocks, a_BlockSkyLight, cChunkDef::NumBlocks / 2); + size_t Index = (size_t)MakeIndexNoCheck(x, y, z); + if ((Index / 2) >= a_Buffer.size()) + { + a_Buffer.resize(((Index / 2) + 1)); + } + a_Buffer[(Index / 2)] = PackNibble(a_Buffer, Index, a_Nibble); } -} ; - +private: -/** A simple implementation of the cChunkDataCallback interface that collects all block data into a separate buffers -*/ -class cChunkDataSeparateCollector : - public cChunkDataCallback -{ -public: - - cChunkDef::BlockTypes m_BlockTypes; - cChunkDef::BlockNibbles m_BlockMetas; - cChunkDef::BlockNibbles m_BlockLight; - cChunkDef::BlockNibbles m_BlockSkyLight; - -protected: - - virtual void BlockTypes(const BLOCKTYPE * a_BlockTypes) override + inline static NIBBLETYPE PackNibble(const COMPRESSED_NIBBLETYPE & a_Buffer, size_t a_Index, NIBBLETYPE a_Nibble) { - memcpy(m_BlockTypes, a_BlockTypes, sizeof(m_BlockTypes)); - } - - - virtual void BlockMeta(const NIBBLETYPE * a_BlockMeta) override - { - memcpy(m_BlockMetas, a_BlockMeta, sizeof(m_BlockMetas)); + return static_cast<NIBBLETYPE>( + (a_Buffer[a_Index / 2] & (0xf0 >> ((a_Index & 1) * 4))) | // The untouched nibble + ((a_Nibble & 0x0f) << ((a_Index & 1) * 4)) // The nibble being set + ); } - virtual void BlockLight(const NIBBLETYPE * a_BlockLight) override + inline static NIBBLETYPE ExpandNibble(const COMPRESSED_NIBBLETYPE & a_Buffer, size_t a_Index) { - memcpy(m_BlockLight, a_BlockLight, sizeof(m_BlockLight)); + return (a_Buffer[a_Index / 2] >> ((a_Index & 1) * 4)) & 0x0f; } - virtual void BlockSkyLight(const NIBBLETYPE * a_BlockSkyLight) override - { - memcpy(m_BlockSkyLight, a_BlockSkyLight, sizeof(m_BlockSkyLight)); - } } ; |