|
@@ -0,0 +1,170 @@
|
|
|
+#include "Chunk.h"
|
|
|
+#include "Constants.h"
|
|
|
+#include "Block.h"
|
|
|
+#include "Globals.h"
|
|
|
+
|
|
|
+
|
|
|
+Chunk::Chunk( Framework::Punkt location, int dimensionId )
|
|
|
+ : ReferenceCounter(),
|
|
|
+ dimensionId( dimensionId ),
|
|
|
+ location( location )
|
|
|
+{
|
|
|
+ blocks = new Block * [ CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT ];
|
|
|
+ memset( blocks, AIR_BLOCK, sizeof( Block * ) * CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT );
|
|
|
+ zNeighbours[ 0 ] = 0;
|
|
|
+ zNeighbours[ 1 ] = 0;
|
|
|
+ zNeighbours[ 2 ] = 0;
|
|
|
+ zNeighbours[ 3 ] = 0;
|
|
|
+}
|
|
|
+
|
|
|
+Chunk::Chunk( Framework::Punkt location, int dimensionId, Framework::StreamReader *zReader )
|
|
|
+ : Chunk( location, dimensionId )
|
|
|
+{
|
|
|
+ load( zReader );
|
|
|
+}
|
|
|
+
|
|
|
+Chunk::~Chunk()
|
|
|
+{
|
|
|
+ for( int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++ )
|
|
|
+ {
|
|
|
+ if( IS_BLOCK( blocks[ i ] ) )
|
|
|
+ blocks[ i ]->release();
|
|
|
+ }
|
|
|
+ delete[] blocks;
|
|
|
+}
|
|
|
+
|
|
|
+bool Chunk::updateVisibility()
|
|
|
+{
|
|
|
+ bool update = false;
|
|
|
+ for( int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++ )
|
|
|
+ {
|
|
|
+ if( IS_BLOCK( blocks[ i ] ) )
|
|
|
+ update |= blocks[ i ]->updateVisibility();
|
|
|
+ }
|
|
|
+ return update;
|
|
|
+}
|
|
|
+
|
|
|
+Block *Chunk::getBlockAt( Framework::Vec3<int> location ) const
|
|
|
+{
|
|
|
+ location.x += CHUNK_SIZE / 2;
|
|
|
+ location.y += CHUNK_SIZE / 2;
|
|
|
+ Block *result = dynamic_cast<Block *>( blocks[ ( location.x * CHUNK_SIZE + location.y ) * CHUNK_SIZE + location.z ]->getThis() );
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+Block *Chunk::zBlockAt( Framework::Vec3<int> location ) const
|
|
|
+{
|
|
|
+ location.x += CHUNK_SIZE / 2;
|
|
|
+ location.y += CHUNK_SIZE / 2;
|
|
|
+ return blocks[ ( location.x * CHUNK_SIZE + location.y ) * CHUNK_SIZE + location.z ];
|
|
|
+}
|
|
|
+
|
|
|
+void Chunk::putBlockAt( Framework::Vec3<int> location, Block *block )
|
|
|
+{
|
|
|
+ location.x -= this->location.x - CHUNK_SIZE / 2;
|
|
|
+ location.y -= this->location.x - CHUNK_SIZE / 2;
|
|
|
+ int index = ( location.x * CHUNK_SIZE + location.y ) * CHUNK_SIZE + location.z;
|
|
|
+ Block *old = blocks[ index ];
|
|
|
+ blocks[ index ] = block;
|
|
|
+ Block *neighbor = currentGame->zBlockAt( location + getDirection( NORTH ), dimensionId );
|
|
|
+ if( IS_BLOCK( neighbor ) )
|
|
|
+ neighbor->setNeighbour( SOUTH, block );
|
|
|
+ block->setNeighbour( NORTH, neighbor );
|
|
|
+ neighbor = currentGame->zBlockAt( location + getDirection( EAST ), dimensionId );
|
|
|
+ if( IS_BLOCK( neighbor ) )
|
|
|
+ neighbor->setNeighbour( WEST, block );
|
|
|
+ block->setNeighbour( EAST, neighbor );
|
|
|
+ neighbor = currentGame->zBlockAt( location + getDirection( SOUTH ), dimensionId );
|
|
|
+ if( IS_BLOCK( neighbor ) ) {}
|
|
|
+ neighbor->setNeighbour( NORTH, block );
|
|
|
+ block->setNeighbour( SOUTH, neighbor );
|
|
|
+ neighbor = currentGame->zBlockAt( location + getDirection( WEST ), dimensionId );
|
|
|
+ if( IS_BLOCK( neighbor ) )
|
|
|
+ neighbor->setNeighbour( EAST, block );
|
|
|
+ block->setNeighbour( WEST, neighbor );
|
|
|
+ neighbor = currentGame->zBlockAt( location + getDirection( TOP ), dimensionId );
|
|
|
+ if( IS_BLOCK( neighbor ) )
|
|
|
+ neighbor->setNeighbour( BOTTOM, block );
|
|
|
+ block->setNeighbour( TOP, neighbor );
|
|
|
+ neighbor = currentGame->zBlockAt( location + getDirection( BOTTOM ), dimensionId );
|
|
|
+ if( IS_BLOCK( neighbor ) )
|
|
|
+ neighbor->setNeighbour( TOP, block );
|
|
|
+ block->setNeighbour( BOTTOM, neighbor );
|
|
|
+ if( IS_BLOCK( old ) )
|
|
|
+ old->release();
|
|
|
+}
|
|
|
+
|
|
|
+void Chunk::setNeighbor( Direction dir, Chunk *zChunk )
|
|
|
+{
|
|
|
+ zNeighbours[ dir ] = zChunk;
|
|
|
+ for( int i = 0; i < CHUNK_SIZE; i++ )
|
|
|
+ {
|
|
|
+ for( int z = 0; z < WORLD_HEIGHT; z++ )
|
|
|
+ {
|
|
|
+ if( dir == NORTH )
|
|
|
+ {
|
|
|
+ int index = i * CHUNK_SIZE * CHUNK_SIZE + z;
|
|
|
+ if( blocks[ index ] )
|
|
|
+ blocks[ index ]->setNeighbour( NORTH, zChunk->blocks[ ( i * CHUNK_SIZE + CHUNK_SIZE - 1 ) * CHUNK_SIZE + z ] );
|
|
|
+ }
|
|
|
+ else if( dir == EAST )
|
|
|
+ {
|
|
|
+ int index = ( ( CHUNK_SIZE - 1 ) * CHUNK_SIZE + i ) * CHUNK_SIZE + z;
|
|
|
+ if( blocks[ index ] )
|
|
|
+ blocks[ index ]->setNeighbour( EAST, zChunk->blocks[ i * CHUNK_SIZE + z ] );
|
|
|
+ }
|
|
|
+ else if( dir == SOUTH )
|
|
|
+ {
|
|
|
+ int index = ( i * CHUNK_SIZE + CHUNK_SIZE - 1 ) * CHUNK_SIZE + z;
|
|
|
+ if( blocks[ index ] )
|
|
|
+ blocks[ index ]->setNeighbour( SOUTH, zChunk->blocks[ i * CHUNK_SIZE * CHUNK_SIZE + z ] );
|
|
|
+ }
|
|
|
+ else if( dir == WEST )
|
|
|
+ {
|
|
|
+ int index = i * CHUNK_SIZE + z;
|
|
|
+ if( blocks[ index ] )
|
|
|
+ blocks[ index ]->setNeighbour( WEST, zChunk->blocks[ ( ( CHUNK_SIZE - 1 ) * CHUNK_SIZE + i ) * CHUNK_SIZE + z ] );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Chunk::load( Framework::StreamReader *zReader )
|
|
|
+{
|
|
|
+ for( int x = 0; x < CHUNK_SIZE; x++ )
|
|
|
+ {
|
|
|
+ for( int y = 0; y < CHUNK_SIZE; y++ )
|
|
|
+ {
|
|
|
+ for( int z = 0; z < WORLD_HEIGHT; z++ )
|
|
|
+ {
|
|
|
+ int blockType;
|
|
|
+ zReader->lese( (char *)&blockType, 4 );
|
|
|
+ if( blockType >= 0 )
|
|
|
+ {
|
|
|
+ Block *block = StaticRegistry<BlockType>::INSTANCE.zElement( blockType )->loadBlock( Framework::Vec3<int>( x, y, z ), zReader );
|
|
|
+ putBlockAt( { x, y, z }, block );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int Chunk::getDimensionId() const
|
|
|
+{
|
|
|
+ return dimensionId;
|
|
|
+}
|
|
|
+
|
|
|
+Framework::Punkt Chunk::getCenter() const
|
|
|
+{
|
|
|
+ return location;
|
|
|
+}
|
|
|
+
|
|
|
+Framework::Vec3<int> Chunk::getMin() const
|
|
|
+{
|
|
|
+ return { location.x - CHUNK_SIZE / 2, location.y - CHUNK_SIZE / 2, 0 };
|
|
|
+}
|
|
|
+
|
|
|
+Framework::Vec3<int> Chunk::getMax() const
|
|
|
+{
|
|
|
+ return { location.x + CHUNK_SIZE / 2, location.y + CHUNK_SIZE / 2, WORLD_HEIGHT };
|
|
|
+}
|