|
@@ -10,7 +10,7 @@ Chunk::Chunk( Framework::Punkt location, Game *zGame, int dimensionId )
|
|
location( location )
|
|
location( location )
|
|
{
|
|
{
|
|
blocks = new Block * [ CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT ];
|
|
blocks = new Block * [ CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT ];
|
|
- Block *val = (Block*)AIR_BLOCK;
|
|
|
|
|
|
+ Block *val = (Block *)AIR_BLOCK;
|
|
std::uninitialized_fill_n( blocks, CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT, val );
|
|
std::uninitialized_fill_n( blocks, CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT, val );
|
|
zNeighbours[ 0 ] = 0;
|
|
zNeighbours[ 0 ] = 0;
|
|
zNeighbours[ 1 ] = 0;
|
|
zNeighbours[ 1 ] = 0;
|
|
@@ -34,6 +34,15 @@ Chunk::~Chunk()
|
|
delete[] blocks;
|
|
delete[] blocks;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+Block *Chunk::zBlockNeighbor( Framework::Vec3<int> location )
|
|
|
|
+{
|
|
|
|
+ if( location.x >= 0 && location.x < CHUNK_SIZE && location.y <= 0 && location.y < CHUNK_SIZE && location.z >= 0 && location.z < WORLD_HEIGHT )
|
|
|
|
+ return blocks[ (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z ];
|
|
|
|
+ if( location.z >= 0 && location.z < WORLD_HEIGHT )
|
|
|
|
+ return zGame->zBlockAt( { location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z }, dimensionId );
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
void Chunk::api( Framework::StreamReader *zRequest, NetworkResponse *zResponse )
|
|
void Chunk::api( Framework::StreamReader *zRequest, NetworkResponse *zResponse )
|
|
{
|
|
{
|
|
// TODO: answer api messages
|
|
// TODO: answer api messages
|
|
@@ -41,7 +50,8 @@ void Chunk::api( Framework::StreamReader *zRequest, NetworkResponse *zResponse )
|
|
|
|
|
|
Block *Chunk::getBlockAt( Framework::Vec3<int> location ) const
|
|
Block *Chunk::getBlockAt( Framework::Vec3<int> location ) const
|
|
{
|
|
{
|
|
- Block *result = zBlockAt(location);
|
|
|
|
|
|
+ assert( (location.x * CHUNK_SIZE + location.y) * CHUNK_SIZE + location.z < CHUNK_SIZE *CHUNK_SIZE *WORLD_HEIGHT );
|
|
|
|
+ Block *result = zBlockAt( location );
|
|
if( result )
|
|
if( result )
|
|
return dynamic_cast<Block *>(result->getThis());
|
|
return dynamic_cast<Block *>(result->getThis());
|
|
return 0;
|
|
return 0;
|
|
@@ -49,38 +59,46 @@ Block *Chunk::getBlockAt( Framework::Vec3<int> location ) const
|
|
|
|
|
|
Block *Chunk::zBlockAt( Framework::Vec3<int> location ) const
|
|
Block *Chunk::zBlockAt( Framework::Vec3<int> location ) const
|
|
{
|
|
{
|
|
|
|
+ assert( (location.x * CHUNK_SIZE + location.y) * CHUNK_SIZE + location.z < CHUNK_SIZE *CHUNK_SIZE *WORLD_HEIGHT );
|
|
return blocks[ (location.x * CHUNK_SIZE + location.y) * CHUNK_SIZE + location.z ];
|
|
return blocks[ (location.x * CHUNK_SIZE + location.y) * CHUNK_SIZE + location.z ];
|
|
}
|
|
}
|
|
|
|
|
|
void Chunk::putBlockAt( Framework::Vec3<int> location, Block *block )
|
|
void Chunk::putBlockAt( Framework::Vec3<int> location, Block *block )
|
|
{
|
|
{
|
|
int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
|
|
int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
|
|
|
|
+ assert( index < CHUNK_SIZE *CHUNK_SIZE *WORLD_HEIGHT );
|
|
Block *old = blocks[ index ];
|
|
Block *old = blocks[ index ];
|
|
blocks[ index ] = block;
|
|
blocks[ index ] = block;
|
|
- Block *neighbor = zGame->zBlockAt( location + getDirection( NORTH ), dimensionId );
|
|
|
|
|
|
+ Block *neighbor = zBlockNeighbor( location + getDirection( NORTH ) );
|
|
if( IS_BLOCK( neighbor ) )
|
|
if( IS_BLOCK( neighbor ) )
|
|
neighbor->setNeighbour( SOUTH, block );
|
|
neighbor->setNeighbour( SOUTH, block );
|
|
- block->setNeighbour( NORTH, neighbor );
|
|
|
|
- neighbor = zGame->zBlockAt( location + getDirection( EAST ), dimensionId );
|
|
|
|
|
|
+ if( IS_BLOCK( block ) )
|
|
|
|
+ block->setNeighbour( NORTH, neighbor );
|
|
|
|
+ neighbor = zBlockNeighbor( location + getDirection( EAST ) );
|
|
if( IS_BLOCK( neighbor ) )
|
|
if( IS_BLOCK( neighbor ) )
|
|
neighbor->setNeighbour( WEST, block );
|
|
neighbor->setNeighbour( WEST, block );
|
|
- block->setNeighbour( EAST, neighbor );
|
|
|
|
- neighbor = zGame->zBlockAt( location + getDirection( SOUTH ), dimensionId );
|
|
|
|
|
|
+ if( IS_BLOCK( block ) )
|
|
|
|
+ block->setNeighbour( EAST, neighbor );
|
|
|
|
+ neighbor = zBlockNeighbor( location + getDirection( SOUTH ) );
|
|
if( IS_BLOCK( neighbor ) )
|
|
if( IS_BLOCK( neighbor ) )
|
|
neighbor->setNeighbour( NORTH, block );
|
|
neighbor->setNeighbour( NORTH, block );
|
|
- block->setNeighbour( SOUTH, neighbor );
|
|
|
|
- neighbor = zGame->zBlockAt( location + getDirection( WEST ), dimensionId );
|
|
|
|
|
|
+ if( IS_BLOCK( block ) )
|
|
|
|
+ block->setNeighbour( SOUTH, neighbor );
|
|
|
|
+ neighbor = zBlockNeighbor( location + getDirection( WEST ) );
|
|
if( IS_BLOCK( neighbor ) )
|
|
if( IS_BLOCK( neighbor ) )
|
|
neighbor->setNeighbour( EAST, block );
|
|
neighbor->setNeighbour( EAST, block );
|
|
- block->setNeighbour( WEST, neighbor );
|
|
|
|
- neighbor = zGame->zBlockAt( location + getDirection( TOP ), dimensionId );
|
|
|
|
|
|
+ if( IS_BLOCK( block ) )
|
|
|
|
+ block->setNeighbour( WEST, neighbor );
|
|
|
|
+ neighbor = zBlockNeighbor( location + getDirection( TOP ) );
|
|
if( IS_BLOCK( neighbor ) )
|
|
if( IS_BLOCK( neighbor ) )
|
|
neighbor->setNeighbour( BOTTOM, block );
|
|
neighbor->setNeighbour( BOTTOM, block );
|
|
- block->setNeighbour( TOP, neighbor );
|
|
|
|
- neighbor = zGame->zBlockAt( location + getDirection( BOTTOM ), dimensionId );
|
|
|
|
|
|
+ if( IS_BLOCK( block ) )
|
|
|
|
+ block->setNeighbour( TOP, neighbor );
|
|
|
|
+ neighbor = zBlockNeighbor( location + getDirection( BOTTOM ) );
|
|
if( IS_BLOCK( neighbor ) )
|
|
if( IS_BLOCK( neighbor ) )
|
|
neighbor->setNeighbour( TOP, block );
|
|
neighbor->setNeighbour( TOP, block );
|
|
- block->setNeighbour( BOTTOM, neighbor );
|
|
|
|
|
|
+ if( IS_BLOCK( block ) )
|
|
|
|
+ block->setNeighbour( BOTTOM, neighbor );
|
|
if( IS_BLOCK( old ) )
|
|
if( IS_BLOCK( old ) )
|
|
old->release();
|
|
old->release();
|
|
}
|
|
}
|
|
@@ -95,25 +113,25 @@ void Chunk::setNeighbor( Direction dir, Chunk *zChunk )
|
|
if( dir == NORTH )
|
|
if( dir == NORTH )
|
|
{
|
|
{
|
|
int index = i * CHUNK_SIZE * WORLD_HEIGHT + z;
|
|
int index = i * CHUNK_SIZE * WORLD_HEIGHT + z;
|
|
- if( IS_BLOCK(blocks[ index ]) )
|
|
|
|
|
|
+ if( IS_BLOCK( blocks[ index ] ) )
|
|
blocks[ index ]->setNeighbour( NORTH, zChunk->blocks[ (i * CHUNK_SIZE + CHUNK_SIZE - 1) * WORLD_HEIGHT + z ] );
|
|
blocks[ index ]->setNeighbour( NORTH, zChunk->blocks[ (i * CHUNK_SIZE + CHUNK_SIZE - 1) * WORLD_HEIGHT + z ] );
|
|
}
|
|
}
|
|
else if( dir == EAST )
|
|
else if( dir == EAST )
|
|
{
|
|
{
|
|
int index = ((CHUNK_SIZE - 1) * CHUNK_SIZE + i) * WORLD_HEIGHT + z;
|
|
int index = ((CHUNK_SIZE - 1) * CHUNK_SIZE + i) * WORLD_HEIGHT + z;
|
|
- if( IS_BLOCK(blocks[ index ]) )
|
|
|
|
|
|
+ if( IS_BLOCK( blocks[ index ] ) )
|
|
blocks[ index ]->setNeighbour( EAST, zChunk->blocks[ i * WORLD_HEIGHT + z ] );
|
|
blocks[ index ]->setNeighbour( EAST, zChunk->blocks[ i * WORLD_HEIGHT + z ] );
|
|
}
|
|
}
|
|
else if( dir == SOUTH )
|
|
else if( dir == SOUTH )
|
|
{
|
|
{
|
|
int index = (i * CHUNK_SIZE + CHUNK_SIZE - 1) * WORLD_HEIGHT + z;
|
|
int index = (i * CHUNK_SIZE + CHUNK_SIZE - 1) * WORLD_HEIGHT + z;
|
|
- if( IS_BLOCK(blocks[ index ]) )
|
|
|
|
|
|
+ if( IS_BLOCK( blocks[ index ] ) )
|
|
blocks[ index ]->setNeighbour( SOUTH, zChunk->blocks[ i * CHUNK_SIZE * WORLD_HEIGHT + z ] );
|
|
blocks[ index ]->setNeighbour( SOUTH, zChunk->blocks[ i * CHUNK_SIZE * WORLD_HEIGHT + z ] );
|
|
}
|
|
}
|
|
else if( dir == WEST )
|
|
else if( dir == WEST )
|
|
{
|
|
{
|
|
int index = i * WORLD_HEIGHT + z;
|
|
int index = i * WORLD_HEIGHT + z;
|
|
- if( IS_BLOCK(blocks[ index ]) )
|
|
|
|
|
|
+ if( IS_BLOCK( blocks[ index ] ) )
|
|
blocks[ index ]->setNeighbour( WEST, zChunk->blocks[ ((CHUNK_SIZE - 1) * CHUNK_SIZE + i) * WORLD_HEIGHT + z ] );
|
|
blocks[ index ]->setNeighbour( WEST, zChunk->blocks[ ((CHUNK_SIZE - 1) * CHUNK_SIZE + i) * WORLD_HEIGHT + z ] );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -149,7 +167,7 @@ void Chunk::save( Framework::StreamWriter *zWriter )
|
|
for( int z = 0; z < WORLD_HEIGHT; z++ )
|
|
for( int z = 0; z < WORLD_HEIGHT; z++ )
|
|
{
|
|
{
|
|
int index = (x * CHUNK_SIZE + y) * WORLD_HEIGHT + z;
|
|
int index = (x * CHUNK_SIZE + y) * WORLD_HEIGHT + z;
|
|
- int blockType = blocks[ index ] ? blocks[ (x * CHUNK_SIZE + y) * WORLD_HEIGHT + z ]->zBlockType()->getId() : -1;
|
|
|
|
|
|
+ int blockType = IS_BLOCK(blocks[ index ]) ? blocks[ index ]->zBlockType()->getId() : -1;
|
|
zWriter->schreibe( (char *)&blockType, 4 );
|
|
zWriter->schreibe( (char *)&blockType, 4 );
|
|
if( blockType >= 0 )
|
|
if( blockType >= 0 )
|
|
StaticRegistry<BlockType>::INSTANCE.zElement( blockType )->saveBlock( blocks[ index ], zWriter );
|
|
StaticRegistry<BlockType>::INSTANCE.zElement( blockType )->saveBlock( blocks[ index ], zWriter );
|
|
@@ -158,6 +176,26 @@ void Chunk::save( Framework::StreamWriter *zWriter )
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void Chunk::removeUnusedBlocks()
|
|
|
|
+{
|
|
|
|
+ bool removed = true;
|
|
|
|
+ while( removed )
|
|
|
|
+ {
|
|
|
|
+ removed = false;
|
|
|
|
+ for( int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++ )
|
|
|
|
+ {
|
|
|
|
+ if( IS_BLOCK( blocks[ i ] ) && !blocks[ i ]->isVisible() )
|
|
|
|
+ {
|
|
|
|
+ int x = (i / WORLD_HEIGHT) / CHUNK_SIZE;
|
|
|
|
+ int y = (i / WORLD_HEIGHT) % CHUNK_SIZE;
|
|
|
|
+ int z = i % WORLD_HEIGHT;
|
|
|
|
+ putBlockAt( { x,y,z }, 0 );
|
|
|
|
+ removed = true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
int Chunk::getDimensionId() const
|
|
int Chunk::getDimensionId() const
|
|
{
|
|
{
|
|
return dimensionId;
|
|
return dimensionId;
|