commit
1139b117c4
122
src/Chunk.cpp
122
src/Chunk.cpp
@ -240,11 +240,24 @@ void cChunk::GetAllData(cChunkDataCallback & a_Callback)
|
|||||||
{
|
{
|
||||||
a_Callback.HeightMap (&m_HeightMap);
|
a_Callback.HeightMap (&m_HeightMap);
|
||||||
a_Callback.BiomeData (&m_BiomeMap);
|
a_Callback.BiomeData (&m_BiomeMap);
|
||||||
a_Callback.BlockTypes (m_BlockTypes);
|
|
||||||
a_Callback.BlockMeta (m_BlockMeta);
|
COMPRESSED_BLOCKTYPE Blocks = m_BlockTypes;
|
||||||
|
Blocks.resize(NumBlocks);
|
||||||
|
a_Callback.BlockTypes (&Blocks[0]);
|
||||||
|
|
||||||
|
COMPRESSED_NIBBLETYPE Metas = m_BlockMeta;
|
||||||
|
Metas.resize(NumBlocks / 2);
|
||||||
|
a_Callback.BlockMeta (&Metas[0]);
|
||||||
|
|
||||||
a_Callback.LightIsValid (m_IsLightValid);
|
a_Callback.LightIsValid (m_IsLightValid);
|
||||||
a_Callback.BlockLight (m_BlockLight);
|
|
||||||
a_Callback.BlockSkyLight(m_BlockSkyLight);
|
COMPRESSED_NIBBLETYPE BlockLights = m_BlockLight;
|
||||||
|
BlockLights.resize(NumBlocks / 2);
|
||||||
|
a_Callback.BlockLight (&BlockLights[0]);
|
||||||
|
|
||||||
|
COMPRESSED_NIBBLETYPE BlockSkyLights = m_BlockSkyLight;
|
||||||
|
BlockSkyLights.resize(NumBlocks / 2, 0xff);
|
||||||
|
a_Callback.BlockSkyLight(&BlockSkyLights[0]);
|
||||||
|
|
||||||
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
|
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
|
||||||
{
|
{
|
||||||
@ -278,24 +291,56 @@ void cChunk::SetAllData(
|
|||||||
memcpy(m_HeightMap, a_HeightMap, sizeof(m_HeightMap));
|
memcpy(m_HeightMap, a_HeightMap, sizeof(m_HeightMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(m_BlockTypes, a_BlockTypes, sizeof(m_BlockTypes));
|
if (a_HeightMap == NULL)
|
||||||
memcpy(m_BlockMeta, a_BlockMeta, sizeof(m_BlockMeta));
|
{
|
||||||
|
CalculateHeightmap(a_BlockTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
int IdxWhereNonEmptyStarts = 0;
|
||||||
|
{ // Blocktype compression
|
||||||
|
unsigned char Highest = 0;
|
||||||
|
int X = 0, Z = 0;
|
||||||
|
m_BlockTypes.clear();
|
||||||
|
|
||||||
|
for (int x = 0; x < Width; x++)
|
||||||
|
{
|
||||||
|
for (int z = 0; z < Width; z++)
|
||||||
|
{
|
||||||
|
unsigned char Height = m_HeightMap[x + z * Width];
|
||||||
|
if (Height > Highest)
|
||||||
|
{
|
||||||
|
Highest = Height;
|
||||||
|
X = x; Z = z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IdxWhereNonEmptyStarts = MakeIndexNoCheck(X, Highest + 1, Z);
|
||||||
|
|
||||||
|
m_BlockTypes.insert(m_BlockTypes.end(), &a_BlockTypes[0], &a_BlockTypes[IdxWhereNonEmptyStarts]);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // Blockmeta compression
|
||||||
|
m_BlockMeta.clear();
|
||||||
|
m_BlockMeta.insert(m_BlockMeta.end(), &a_BlockMeta[0], &a_BlockMeta[IdxWhereNonEmptyStarts / 2]);
|
||||||
|
}
|
||||||
|
|
||||||
if (a_BlockLight != NULL)
|
if (a_BlockLight != NULL)
|
||||||
{
|
{
|
||||||
memcpy(m_BlockLight, a_BlockLight, sizeof(m_BlockLight));
|
// Compress blocklight
|
||||||
|
m_BlockLight.clear();
|
||||||
|
m_BlockLight.insert(m_BlockLight.end(), &a_BlockLight[0], &a_BlockLight[IdxWhereNonEmptyStarts / 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a_BlockSkyLight != NULL)
|
if (a_BlockSkyLight != NULL)
|
||||||
{
|
{
|
||||||
memcpy(m_BlockSkyLight, a_BlockSkyLight, sizeof(m_BlockSkyLight));
|
// Compress skylight
|
||||||
|
m_BlockSkyLight.clear();
|
||||||
|
m_BlockSkyLight.insert(m_BlockSkyLight.end(), &a_BlockSkyLight[0], &a_BlockSkyLight[IdxWhereNonEmptyStarts / 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_IsLightValid = (a_BlockLight != NULL) && (a_BlockSkyLight != NULL);
|
m_IsLightValid = (a_BlockLight != NULL) && (a_BlockSkyLight != NULL);
|
||||||
|
|
||||||
if (a_HeightMap == NULL)
|
|
||||||
{
|
|
||||||
CalculateHeightmap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the block entities present - either the loader / saver has better, or we'll create empty ones:
|
// Clear the block entities present - either the loader / saver has better, or we'll create empty ones:
|
||||||
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
|
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
|
||||||
{
|
{
|
||||||
@ -332,8 +377,17 @@ void cChunk::SetLight(
|
|||||||
{
|
{
|
||||||
// TODO: We might get cases of wrong lighting when a chunk changes in the middle of a lighting calculation.
|
// TODO: We might get cases of wrong lighting when a chunk changes in the middle of a lighting calculation.
|
||||||
// Postponing until we see how bad it is :)
|
// Postponing until we see how bad it is :)
|
||||||
memcpy(m_BlockLight, a_BlockLight, sizeof(m_BlockLight));
|
|
||||||
memcpy(m_BlockSkyLight, a_SkyLight, sizeof(m_BlockSkyLight));
|
{ // Compress blocklight
|
||||||
|
m_BlockLight.clear();
|
||||||
|
m_BlockLight.insert(m_BlockLight.end(), &a_BlockLight[0], &a_BlockLight[m_BlockTypes.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // Compress skylight
|
||||||
|
m_BlockSkyLight.clear();
|
||||||
|
m_BlockSkyLight.insert(m_BlockSkyLight.end(), &a_SkyLight[0], &a_SkyLight[m_BlockTypes.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
m_IsLightValid = true;
|
m_IsLightValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,7 +397,8 @@ void cChunk::SetLight(
|
|||||||
|
|
||||||
void cChunk::GetBlockTypes(BLOCKTYPE * a_BlockTypes)
|
void cChunk::GetBlockTypes(BLOCKTYPE * a_BlockTypes)
|
||||||
{
|
{
|
||||||
memcpy(a_BlockTypes, m_BlockTypes, NumBlocks);
|
std::copy(m_BlockTypes.begin(), m_BlockTypes.end(), a_BlockTypes);
|
||||||
|
std::fill_n(&a_BlockTypes[m_BlockTypes.size()], NumBlocks - m_BlockTypes.size(), E_BLOCK_AIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -630,7 +685,7 @@ void cChunk::Tick(float a_Dt)
|
|||||||
void cChunk::TickBlock(int a_RelX, int a_RelY, int a_RelZ)
|
void cChunk::TickBlock(int a_RelX, int a_RelY, int a_RelZ)
|
||||||
{
|
{
|
||||||
unsigned Index = MakeIndex(a_RelX, a_RelY, a_RelZ);
|
unsigned Index = MakeIndex(a_RelX, a_RelY, a_RelZ);
|
||||||
cBlockHandler * Handler = BlockHandler(m_BlockTypes[Index]);
|
cBlockHandler * Handler = BlockHandler(GetBlock(Index));
|
||||||
ASSERT(Handler != NULL); // Happenned on server restart, FS #243
|
ASSERT(Handler != NULL); // Happenned on server restart, FS #243
|
||||||
cChunkInterface ChunkInterface(this->GetWorld()->GetChunkMap());
|
cChunkInterface ChunkInterface(this->GetWorld()->GetChunkMap());
|
||||||
cBlockInServerPluginInterface PluginInterface(*this->GetWorld());
|
cBlockInServerPluginInterface PluginInterface(*this->GetWorld());
|
||||||
@ -751,7 +806,7 @@ void cChunk::BroadcastPendingBlockChanges(void)
|
|||||||
|
|
||||||
void cChunk::CheckBlocks()
|
void cChunk::CheckBlocks()
|
||||||
{
|
{
|
||||||
if (m_ToTickBlocks.size() == 0)
|
if (m_ToTickBlocks.empty())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -811,7 +866,7 @@ void cChunk::TickBlocks(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Index = MakeIndexNoCheck(m_BlockTickX, m_BlockTickY, m_BlockTickZ);
|
unsigned int Index = MakeIndexNoCheck(m_BlockTickX, m_BlockTickY, m_BlockTickZ);
|
||||||
cBlockHandler * Handler = BlockHandler(m_BlockTypes[Index]);
|
cBlockHandler * Handler = BlockHandler(GetBlock(Index));
|
||||||
ASSERT(Handler != NULL); // Happenned on server restart, FS #243
|
ASSERT(Handler != NULL); // Happenned on server restart, FS #243
|
||||||
Handler->OnUpdate(ChunkInterface, *this->GetWorld(), PluginInterface, *this, m_BlockTickX, m_BlockTickY, m_BlockTickZ);
|
Handler->OnUpdate(ChunkInterface, *this->GetWorld(), PluginInterface, *this, m_BlockTickX, m_BlockTickY, m_BlockTickZ);
|
||||||
} // for i - tickblocks
|
} // for i - tickblocks
|
||||||
@ -1296,7 +1351,7 @@ void cChunk::CreateBlockEntities(void)
|
|||||||
{
|
{
|
||||||
for (int y = 0; y < Height; y++)
|
for (int y = 0; y < Height; y++)
|
||||||
{
|
{
|
||||||
BLOCKTYPE BlockType = cChunkDef::GetBlock(m_BlockTypes, x, y, z);
|
BLOCKTYPE BlockType = GetBlock(x, y, z);
|
||||||
switch (BlockType)
|
switch (BlockType)
|
||||||
{
|
{
|
||||||
case E_BLOCK_BEACON:
|
case E_BLOCK_BEACON:
|
||||||
@ -1349,7 +1404,7 @@ void cChunk::WakeUpSimulators(void)
|
|||||||
int BlockZ = z + BaseZ;
|
int BlockZ = z + BaseZ;
|
||||||
for (int y = GetHeight(x, z); y >= 0; y--)
|
for (int y = GetHeight(x, z); y >= 0; y--)
|
||||||
{
|
{
|
||||||
BLOCKTYPE Block = cChunkDef::GetBlock(m_BlockTypes, x, y, z);
|
BLOCKTYPE Block = GetBlock(x, y, z);
|
||||||
|
|
||||||
// The redstone sim takes multiple blocks, use the inbuilt checker
|
// The redstone sim takes multiple blocks, use the inbuilt checker
|
||||||
if (RedstoneSimulator->IsAllowedBlock(Block))
|
if (RedstoneSimulator->IsAllowedBlock(Block))
|
||||||
@ -1384,7 +1439,7 @@ void cChunk::WakeUpSimulators(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunk::CalculateHeightmap()
|
void cChunk::CalculateHeightmap(const BLOCKTYPE * a_BlockTypes)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < Width; x++)
|
for (int x = 0; x < Width; x++)
|
||||||
{
|
{
|
||||||
@ -1393,7 +1448,7 @@ void cChunk::CalculateHeightmap()
|
|||||||
for (int y = Height - 1; y > -1; y--)
|
for (int y = Height - 1; y > -1; y--)
|
||||||
{
|
{
|
||||||
int index = MakeIndex( x, y, z );
|
int index = MakeIndex( x, y, z );
|
||||||
if (m_BlockTypes[index] != E_BLOCK_AIR)
|
if (a_BlockTypes[index] != E_BLOCK_AIR)
|
||||||
{
|
{
|
||||||
m_HeightMap[x + z * Width] = (unsigned char)y;
|
m_HeightMap[x + z * Width] = (unsigned char)y;
|
||||||
break;
|
break;
|
||||||
@ -1517,7 +1572,7 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
|
|||||||
ASSERT(IsValid());
|
ASSERT(IsValid());
|
||||||
|
|
||||||
const int index = MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
|
const int index = MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
|
||||||
const BLOCKTYPE OldBlockType = cChunkDef::GetBlock(m_BlockTypes, index);
|
const BLOCKTYPE OldBlockType = GetBlock(index);
|
||||||
const BLOCKTYPE OldBlockMeta = GetNibble(m_BlockMeta, index);
|
const BLOCKTYPE OldBlockMeta = GetNibble(m_BlockMeta, index);
|
||||||
if ((OldBlockType == a_BlockType) && (OldBlockMeta == a_BlockMeta))
|
if ((OldBlockType == a_BlockType) && (OldBlockMeta == a_BlockMeta))
|
||||||
{
|
{
|
||||||
@ -1526,6 +1581,10 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
|
|||||||
|
|
||||||
MarkDirty();
|
MarkDirty();
|
||||||
|
|
||||||
|
if ((size_t)index >= m_BlockTypes.size())
|
||||||
|
{
|
||||||
|
m_BlockTypes.resize(index + 1);
|
||||||
|
}
|
||||||
m_BlockTypes[index] = a_BlockType;
|
m_BlockTypes[index] = a_BlockType;
|
||||||
|
|
||||||
// The client doesn't need to distinguish between stationary and nonstationary fluids:
|
// The client doesn't need to distinguish between stationary and nonstationary fluids:
|
||||||
@ -1565,7 +1624,7 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
|
|||||||
{
|
{
|
||||||
for (int y = a_RelY - 1; y > 0; --y)
|
for (int y = a_RelY - 1; y > 0; --y)
|
||||||
{
|
{
|
||||||
if (m_BlockTypes[MakeIndexNoCheck(a_RelX, y, a_RelZ)] != E_BLOCK_AIR)
|
if (GetBlock(MakeIndexNoCheck(a_RelX, y, a_RelZ)) != E_BLOCK_AIR)
|
||||||
{
|
{
|
||||||
m_HeightMap[a_RelX + a_RelZ * Width] = (unsigned char)y;
|
m_HeightMap[a_RelX + a_RelZ * Width] = (unsigned char)y;
|
||||||
break;
|
break;
|
||||||
@ -2452,7 +2511,7 @@ BLOCKTYPE cChunk::GetBlock(int a_RelX, int a_RelY, int a_RelZ) const
|
|||||||
return 0; // Clip
|
return 0; // Clip
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_BlockTypes[MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ)];
|
return GetBlock(MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2467,7 +2526,12 @@ BLOCKTYPE cChunk::GetBlock(int a_BlockIdx) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_BlockTypes[ a_BlockIdx ];
|
if ((size_t)a_BlockIdx >= m_BlockTypes.size())
|
||||||
|
{
|
||||||
|
return E_BLOCK_AIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_BlockTypes[a_BlockIdx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2477,7 +2541,7 @@ BLOCKTYPE cChunk::GetBlock(int a_BlockIdx) const
|
|||||||
void cChunk::GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta)
|
void cChunk::GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta)
|
||||||
{
|
{
|
||||||
int Idx = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
|
int Idx = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
|
||||||
a_BlockType = cChunkDef::GetBlock (m_BlockTypes, Idx);
|
a_BlockType = GetBlock(Idx);
|
||||||
a_BlockMeta = cChunkDef::GetNibble(m_BlockMeta, Idx);
|
a_BlockMeta = cChunkDef::GetNibble(m_BlockMeta, Idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2488,7 +2552,7 @@ void cChunk::GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_
|
|||||||
void cChunk::GetBlockInfo(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight)
|
void cChunk::GetBlockInfo(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight)
|
||||||
{
|
{
|
||||||
int Idx = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
|
int Idx = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
|
||||||
a_BlockType = cChunkDef::GetBlock (m_BlockTypes, Idx);
|
a_BlockType = GetBlock(Idx);
|
||||||
a_Meta = cChunkDef::GetNibble(m_BlockMeta, Idx);
|
a_Meta = cChunkDef::GetNibble(m_BlockMeta, Idx);
|
||||||
a_SkyLight = cChunkDef::GetNibble(m_BlockSkyLight, Idx);
|
a_SkyLight = cChunkDef::GetNibble(m_BlockSkyLight, Idx);
|
||||||
a_BlockLight = cChunkDef::GetNibble(m_BlockLight, Idx);
|
a_BlockLight = cChunkDef::GetNibble(m_BlockLight, Idx);
|
||||||
|
14
src/Chunk.h
14
src/Chunk.h
@ -267,7 +267,7 @@ public:
|
|||||||
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); // [x, y, z] in world block coords
|
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); // [x, y, z] in world block coords
|
||||||
|
|
||||||
void CalculateLighting(); // Recalculate right now
|
void CalculateLighting(); // Recalculate right now
|
||||||
void CalculateHeightmap();
|
void CalculateHeightmap(const BLOCKTYPE * a_BlockTypes);
|
||||||
|
|
||||||
// Broadcast various packets to all clients of this chunk:
|
// Broadcast various packets to all clients of this chunk:
|
||||||
// (Please keep these alpha-sorted)
|
// (Please keep these alpha-sorted)
|
||||||
@ -326,9 +326,9 @@ public:
|
|||||||
inline void SetMeta(int a_BlockIdx, NIBBLETYPE a_Meta) { cChunkDef::SetNibble(m_BlockMeta, a_BlockIdx, a_Meta); }
|
inline void SetMeta(int a_BlockIdx, NIBBLETYPE a_Meta) { cChunkDef::SetNibble(m_BlockMeta, a_BlockIdx, a_Meta); }
|
||||||
|
|
||||||
inline NIBBLETYPE GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockLight, a_RelX, a_RelY, a_RelZ); }
|
inline NIBBLETYPE GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockLight, a_RelX, a_RelY, a_RelZ); }
|
||||||
inline NIBBLETYPE GetSkyLight (int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockSkyLight, a_RelX, a_RelY, a_RelZ); }
|
inline NIBBLETYPE GetSkyLight (int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockSkyLight, a_RelX, a_RelY, a_RelZ, true); }
|
||||||
inline NIBBLETYPE GetBlockLight(int a_Idx) const {return cChunkDef::GetNibble(m_BlockLight, a_Idx); }
|
inline NIBBLETYPE GetBlockLight(int a_Idx) const {return cChunkDef::GetNibble(m_BlockLight, a_Idx); }
|
||||||
inline NIBBLETYPE GetSkyLight (int a_Idx) const {return cChunkDef::GetNibble(m_BlockSkyLight, a_Idx); }
|
inline NIBBLETYPE GetSkyLight (int a_Idx) const {return cChunkDef::GetNibble(m_BlockSkyLight, a_Idx, true); }
|
||||||
|
|
||||||
/** Same as GetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
|
/** Same as GetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
|
||||||
bool UnboundedRelGetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const;
|
bool UnboundedRelGetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const;
|
||||||
@ -421,10 +421,10 @@ private:
|
|||||||
cChunkMap * m_ChunkMap;
|
cChunkMap * m_ChunkMap;
|
||||||
|
|
||||||
// TODO: Make these pointers and don't allocate what isn't needed
|
// TODO: Make these pointers and don't allocate what isn't needed
|
||||||
BLOCKTYPE m_BlockTypes [cChunkDef::NumBlocks];
|
COMPRESSED_BLOCKTYPE m_BlockTypes;
|
||||||
NIBBLETYPE m_BlockMeta [cChunkDef::NumBlocks / 2];
|
COMPRESSED_NIBBLETYPE m_BlockMeta;
|
||||||
NIBBLETYPE m_BlockLight [cChunkDef::NumBlocks / 2];
|
COMPRESSED_NIBBLETYPE m_BlockLight;
|
||||||
NIBBLETYPE m_BlockSkyLight[cChunkDef::NumBlocks / 2];
|
COMPRESSED_NIBBLETYPE m_BlockSkyLight;
|
||||||
|
|
||||||
cChunkDef::HeightMap m_HeightMap;
|
cChunkDef::HeightMap m_HeightMap;
|
||||||
cChunkDef::BiomeMap m_BiomeMap;
|
cChunkDef::BiomeMap m_BiomeMap;
|
||||||
|
@ -84,6 +84,12 @@ public:
|
|||||||
/// The type used for block data in nibble format, AXIS_ORDER ordering
|
/// The type used for block data in nibble format, AXIS_ORDER ordering
|
||||||
typedef NIBBLETYPE BlockNibbles[NumBlocks / 2];
|
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:
|
/// 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 )
|
inline static void AbsoluteToRelative(/* in-out */ int & a_X, int & a_Y, int & a_Z, /* out */ int & a_ChunkX, int & a_ChunkZ )
|
||||||
@ -221,44 +227,65 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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))
|
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!");
|
ASSERT(!"cChunkDef::GetNibble(): index out of chunk range!");
|
||||||
return 0;
|
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))
|
||||||
|
{
|
||||||
|
int Index = MakeIndexNoCheck(x, y, z);
|
||||||
|
if ((size_t)(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)
|
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))
|
if ((x < Width) && (x > -1) && (y < Height) && (y > -1) && (z < Width) && (z > -1))
|
||||||
{
|
{
|
||||||
int Index = MakeIndexNoCheck(x, y, z);
|
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!");
|
ASSERT(!"cChunkDef::GetNibble(): coords out of chunk range!");
|
||||||
return 0;
|
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))
|
if ((a_BlockIdx < 0) || (a_BlockIdx >= NumBlocks))
|
||||||
{
|
{
|
||||||
ASSERT(!"cChunkDef::SetNibble(): index out of range!");
|
ASSERT(!"cChunkDef::SetNibble(): index out of range!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
a_Buffer[a_BlockIdx / 2] = static_cast<NIBBLETYPE>(
|
if ((size_t)(a_BlockIdx / 2) >= a_Buffer.size())
|
||||||
(a_Buffer[a_BlockIdx / 2] & (0xf0 >> ((a_BlockIdx & 1) * 4))) | // The untouched nibble
|
{
|
||||||
((a_Nibble & 0x0f) << ((a_BlockIdx & 1) * 4)) // The nibble being set
|
a_Buffer.resize((size_t)((a_BlockIdx / 2) + 1));
|
||||||
);
|
}
|
||||||
|
a_Buffer[(size_t)(a_BlockIdx / 2)] = PackNibble(a_Buffer, 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 (
|
if (
|
||||||
(x >= Width) || (x < 0) ||
|
(x >= Width) || (x < 0) ||
|
||||||
@ -271,24 +298,32 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Index = MakeIndexNoCheck(x, y, z);
|
int Index = MakeIndexNoCheck(x, y, z);
|
||||||
a_Buffer[Index / 2] = static_cast<NIBBLETYPE>(
|
if ((size_t)(Index / 2) >= a_Buffer.size())
|
||||||
(a_Buffer[Index / 2] & (0xf0 >> ((Index & 1) * 4))) | // The untouched nibble
|
{
|
||||||
((a_Nibble & 0x0f) << ((Index & 1) * 4)) // The nibble being set
|
a_Buffer.resize((size_t)((Index / 2) + 1));
|
||||||
|
}
|
||||||
|
a_Buffer[(size_t)(Index / 2)] = PackNibble(a_Buffer, Index, a_Nibble);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
inline static NIBBLETYPE PackNibble(const COMPRESSED_NIBBLETYPE & a_Buffer, int a_Index, NIBBLETYPE a_Nibble)
|
||||||
|
{
|
||||||
|
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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline static NIBBLETYPE GetNibble(const NIBBLETYPE * a_Buffer, const Vector3i & a_BlockPos )
|
inline static NIBBLETYPE ExpandNibble(const COMPRESSED_NIBBLETYPE & a_Buffer, int a_Index)
|
||||||
{
|
{
|
||||||
return GetNibble(a_Buffer, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z );
|
return (a_Buffer[a_Index / 2] >> ((a_Index & 1) * 4)) & 0x0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user