Chunk.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #include "Chunk.h"
  2. #include "Constants.h"
  3. #include "Block.h"
  4. #include "Globals.h"
  5. Chunk::Chunk( Framework::Punkt location, int dimensionId )
  6. : ReferenceCounter(),
  7. dimensionId( dimensionId ),
  8. location( location )
  9. {
  10. blocks = new Block * [ CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT ];
  11. memset( blocks, AIR_BLOCK, sizeof( Block * ) * CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT );
  12. zNeighbours[ 0 ] = 0;
  13. zNeighbours[ 1 ] = 0;
  14. zNeighbours[ 2 ] = 0;
  15. zNeighbours[ 3 ] = 0;
  16. }
  17. Chunk::Chunk( Framework::Punkt location, int dimensionId, Framework::StreamReader *zReader )
  18. : Chunk( location, dimensionId )
  19. {
  20. load( zReader );
  21. }
  22. Chunk::~Chunk()
  23. {
  24. for( int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++ )
  25. {
  26. if( IS_BLOCK( blocks[ i ] ) )
  27. blocks[ i ]->release();
  28. }
  29. delete[] blocks;
  30. }
  31. bool Chunk::updateVisibility()
  32. {
  33. bool update = false;
  34. for( int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++ )
  35. {
  36. if( IS_BLOCK( blocks[ i ] ) )
  37. update |= blocks[ i ]->updateVisibility();
  38. }
  39. return update;
  40. }
  41. Block *Chunk::getBlockAt( Framework::Vec3<int> location ) const
  42. {
  43. location.x += CHUNK_SIZE / 2;
  44. location.y += CHUNK_SIZE / 2;
  45. Block *result = dynamic_cast<Block *>( blocks[ ( location.x * CHUNK_SIZE + location.y ) * CHUNK_SIZE + location.z ]->getThis() );
  46. return result;
  47. }
  48. Block *Chunk::zBlockAt( Framework::Vec3<int> location ) const
  49. {
  50. location.x += CHUNK_SIZE / 2;
  51. location.y += CHUNK_SIZE / 2;
  52. return blocks[ ( location.x * CHUNK_SIZE + location.y ) * CHUNK_SIZE + location.z ];
  53. }
  54. void Chunk::putBlockAt( Framework::Vec3<int> location, Block *block )
  55. {
  56. location.x -= this->location.x - CHUNK_SIZE / 2;
  57. location.y -= this->location.x - CHUNK_SIZE / 2;
  58. int index = ( location.x * CHUNK_SIZE + location.y ) * CHUNK_SIZE + location.z;
  59. Block *old = blocks[ index ];
  60. blocks[ index ] = block;
  61. Block *neighbor = currentGame->zBlockAt( location + getDirection( NORTH ), dimensionId );
  62. if( IS_BLOCK( neighbor ) )
  63. neighbor->setNeighbour( SOUTH, block );
  64. block->setNeighbour( NORTH, neighbor );
  65. neighbor = currentGame->zBlockAt( location + getDirection( EAST ), dimensionId );
  66. if( IS_BLOCK( neighbor ) )
  67. neighbor->setNeighbour( WEST, block );
  68. block->setNeighbour( EAST, neighbor );
  69. neighbor = currentGame->zBlockAt( location + getDirection( SOUTH ), dimensionId );
  70. if( IS_BLOCK( neighbor ) ) {}
  71. neighbor->setNeighbour( NORTH, block );
  72. block->setNeighbour( SOUTH, neighbor );
  73. neighbor = currentGame->zBlockAt( location + getDirection( WEST ), dimensionId );
  74. if( IS_BLOCK( neighbor ) )
  75. neighbor->setNeighbour( EAST, block );
  76. block->setNeighbour( WEST, neighbor );
  77. neighbor = currentGame->zBlockAt( location + getDirection( TOP ), dimensionId );
  78. if( IS_BLOCK( neighbor ) )
  79. neighbor->setNeighbour( BOTTOM, block );
  80. block->setNeighbour( TOP, neighbor );
  81. neighbor = currentGame->zBlockAt( location + getDirection( BOTTOM ), dimensionId );
  82. if( IS_BLOCK( neighbor ) )
  83. neighbor->setNeighbour( TOP, block );
  84. block->setNeighbour( BOTTOM, neighbor );
  85. if( IS_BLOCK( old ) )
  86. old->release();
  87. }
  88. void Chunk::setNeighbor( Direction dir, Chunk *zChunk )
  89. {
  90. zNeighbours[ dir ] = zChunk;
  91. for( int i = 0; i < CHUNK_SIZE; i++ )
  92. {
  93. for( int z = 0; z < WORLD_HEIGHT; z++ )
  94. {
  95. if( dir == NORTH )
  96. {
  97. int index = i * CHUNK_SIZE * CHUNK_SIZE + z;
  98. if( blocks[ index ] )
  99. blocks[ index ]->setNeighbour( NORTH, zChunk->blocks[ ( i * CHUNK_SIZE + CHUNK_SIZE - 1 ) * CHUNK_SIZE + z ] );
  100. }
  101. else if( dir == EAST )
  102. {
  103. int index = ( ( CHUNK_SIZE - 1 ) * CHUNK_SIZE + i ) * CHUNK_SIZE + z;
  104. if( blocks[ index ] )
  105. blocks[ index ]->setNeighbour( EAST, zChunk->blocks[ i * CHUNK_SIZE + z ] );
  106. }
  107. else if( dir == SOUTH )
  108. {
  109. int index = ( i * CHUNK_SIZE + CHUNK_SIZE - 1 ) * CHUNK_SIZE + z;
  110. if( blocks[ index ] )
  111. blocks[ index ]->setNeighbour( SOUTH, zChunk->blocks[ i * CHUNK_SIZE * CHUNK_SIZE + z ] );
  112. }
  113. else if( dir == WEST )
  114. {
  115. int index = i * CHUNK_SIZE + z;
  116. if( blocks[ index ] )
  117. blocks[ index ]->setNeighbour( WEST, zChunk->blocks[ ( ( CHUNK_SIZE - 1 ) * CHUNK_SIZE + i ) * CHUNK_SIZE + z ] );
  118. }
  119. }
  120. }
  121. }
  122. void Chunk::load( Framework::StreamReader *zReader )
  123. {
  124. for( int x = 0; x < CHUNK_SIZE; x++ )
  125. {
  126. for( int y = 0; y < CHUNK_SIZE; y++ )
  127. {
  128. for( int z = 0; z < WORLD_HEIGHT; z++ )
  129. {
  130. int blockType;
  131. zReader->lese( (char *)&blockType, 4 );
  132. if( blockType >= 0 )
  133. {
  134. Block *block = StaticRegistry<BlockType>::INSTANCE.zElement( blockType )->loadBlock( Framework::Vec3<int>( x, y, z ), zReader );
  135. putBlockAt( { x, y, z }, block );
  136. }
  137. }
  138. }
  139. }
  140. }
  141. int Chunk::getDimensionId() const
  142. {
  143. return dimensionId;
  144. }
  145. Framework::Punkt Chunk::getCenter() const
  146. {
  147. return location;
  148. }
  149. Framework::Vec3<int> Chunk::getMin() const
  150. {
  151. return { location.x - CHUNK_SIZE / 2, location.y - CHUNK_SIZE / 2, 0 };
  152. }
  153. Framework::Vec3<int> Chunk::getMax() const
  154. {
  155. return { location.x + CHUNK_SIZE / 2, location.y + CHUNK_SIZE / 2, WORLD_HEIGHT };
  156. }