Chunk.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #include "Chunk.h"
  2. #include "Constants.h"
  3. #include "Game.h"
  4. Chunk::Chunk( Framework::Punkt location, Game *zGame, int dimensionId )
  5. : ReferenceCounter(),
  6. zGame( zGame ),
  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, Game *zGame, int dimensionId, Framework::StreamReader *zReader )
  18. : Chunk( location, zGame, 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. void Chunk::api( Framework::StreamReader *zRequest, NetworkResponse *zResponse )
  32. {
  33. // TODO: answer api messages
  34. }
  35. Block *Chunk::getBlockAt( Framework::Vec3<int> location ) const
  36. {
  37. location.x += CHUNK_SIZE / 2;
  38. location.y += CHUNK_SIZE / 2;
  39. Block *result = dynamic_cast<Block *>( blocks[ ( location.x * CHUNK_SIZE + location.y ) * CHUNK_SIZE + location.z ]->getThis() );
  40. return result;
  41. }
  42. Block *Chunk::zBlockAt( Framework::Vec3<int> location ) const
  43. {
  44. location.x += CHUNK_SIZE / 2;
  45. location.y += CHUNK_SIZE / 2;
  46. return blocks[ ( location.x * CHUNK_SIZE + location.y ) * CHUNK_SIZE + location.z ];
  47. }
  48. void Chunk::putBlockAt( Framework::Vec3<int> location, Block *block )
  49. {
  50. location.x -= this->location.x - CHUNK_SIZE / 2;
  51. location.y -= this->location.x - CHUNK_SIZE / 2;
  52. int index = ( location.x * CHUNK_SIZE + location.y ) * CHUNK_SIZE + location.z;
  53. Block *old = blocks[ index ];
  54. blocks[ index ] = block;
  55. Block *neighbor = zGame->zBlockAt( location + getDirection( NORTH ), dimensionId );
  56. if( IS_BLOCK( neighbor ) )
  57. neighbor->setNeighbour( SOUTH, block );
  58. block->setNeighbour( NORTH, neighbor );
  59. neighbor = zGame->zBlockAt( location + getDirection( EAST ), dimensionId );
  60. if( IS_BLOCK( neighbor ) )
  61. neighbor->setNeighbour( WEST, block );
  62. block->setNeighbour( EAST, neighbor );
  63. neighbor = zGame->zBlockAt( location + getDirection( SOUTH ), dimensionId );
  64. if( IS_BLOCK( neighbor ) ) {}
  65. neighbor->setNeighbour( NORTH, block );
  66. block->setNeighbour( SOUTH, neighbor );
  67. neighbor = zGame->zBlockAt( location + getDirection( WEST ), dimensionId );
  68. if( IS_BLOCK( neighbor ) )
  69. neighbor->setNeighbour( EAST, block );
  70. block->setNeighbour( WEST, neighbor );
  71. neighbor = zGame->zBlockAt( location + getDirection( TOP ), dimensionId );
  72. if( IS_BLOCK( neighbor ) )
  73. neighbor->setNeighbour( BOTTOM, block );
  74. block->setNeighbour( TOP, neighbor );
  75. neighbor = zGame->zBlockAt( location + getDirection( BOTTOM ), dimensionId );
  76. if( IS_BLOCK( neighbor ) )
  77. neighbor->setNeighbour( TOP, block );
  78. block->setNeighbour( BOTTOM, neighbor );
  79. if( IS_BLOCK( old ) )
  80. old->release();
  81. }
  82. void Chunk::setNeighbor( Direction dir, Chunk *zChunk )
  83. {
  84. zNeighbours[ dir ] = zChunk;
  85. for( int i = 0; i < CHUNK_SIZE; i++ )
  86. {
  87. for( int z = 0; z < WORLD_HEIGHT; z++ )
  88. {
  89. if( dir == NORTH )
  90. {
  91. int index = i * CHUNK_SIZE * CHUNK_SIZE + z;
  92. if( blocks[ index ] )
  93. blocks[ index ]->setNeighbour( NORTH, zChunk->blocks[ ( i * CHUNK_SIZE + CHUNK_SIZE - 1 ) * CHUNK_SIZE + z ] );
  94. }
  95. else if( dir == EAST )
  96. {
  97. int index = ( ( CHUNK_SIZE - 1 ) * CHUNK_SIZE + i ) * CHUNK_SIZE + z;
  98. if( blocks[ index ] )
  99. blocks[ index ]->setNeighbour( EAST, zChunk->blocks[ i * CHUNK_SIZE + z ] );
  100. }
  101. else if( dir == SOUTH )
  102. {
  103. int index = ( i * CHUNK_SIZE + CHUNK_SIZE - 1 ) * CHUNK_SIZE + z;
  104. if( blocks[ index ] )
  105. blocks[ index ]->setNeighbour( SOUTH, zChunk->blocks[ i * CHUNK_SIZE * CHUNK_SIZE + z ] );
  106. }
  107. else if( dir == WEST )
  108. {
  109. int index = i * CHUNK_SIZE + z;
  110. if( blocks[ index ] )
  111. blocks[ index ]->setNeighbour( WEST, zChunk->blocks[ ( ( CHUNK_SIZE - 1 ) * CHUNK_SIZE + i ) * CHUNK_SIZE + z ] );
  112. }
  113. }
  114. }
  115. }
  116. void Chunk::load( Framework::StreamReader *zReader )
  117. {
  118. for( int x = 0; x < CHUNK_SIZE; x++ )
  119. {
  120. for( int y = 0; y < CHUNK_SIZE; y++ )
  121. {
  122. for( int z = 0; z < WORLD_HEIGHT; z++ )
  123. {
  124. int blockType;
  125. zReader->lese( (char *)&blockType, 4 );
  126. if( blockType >= 0 )
  127. {
  128. Block *block = StaticRegistry<BlockType>::INSTANCE.zElement( blockType )->loadBlock( Framework::Vec3<int>( x, y, z ), zGame, zReader );
  129. putBlockAt( { x, y, z }, block );
  130. }
  131. }
  132. }
  133. }
  134. }
  135. void Chunk::save( Framework::StreamWriter *zWriter )
  136. {
  137. for( int x = 0; x < CHUNK_SIZE; x++ )
  138. {
  139. for( int y = 0; y < CHUNK_SIZE; y++ )
  140. {
  141. for( int z = 0; z < WORLD_HEIGHT; z++ )
  142. {
  143. int index = ( x * CHUNK_SIZE + y ) * CHUNK_SIZE + z;
  144. int blockType = blocks[ index ] ? blocks[ ( x * CHUNK_SIZE + y ) * CHUNK_SIZE + z ]->zBlockType()->getId() : -1;
  145. zWriter->schreibe( (char *)&blockType, 4 );
  146. if( blockType >= 0 )
  147. StaticRegistry<BlockType>::INSTANCE.zElement( blockType )->saveBlock( blocks[ index ], zWriter );
  148. }
  149. }
  150. }
  151. }
  152. int Chunk::getDimensionId() const
  153. {
  154. return dimensionId;
  155. }
  156. Framework::Punkt Chunk::getCenter() const
  157. {
  158. return location;
  159. }
  160. Framework::Vec3<int> Chunk::getMin() const
  161. {
  162. return { location.x - CHUNK_SIZE / 2, location.y - CHUNK_SIZE / 2, 0 };
  163. }
  164. Framework::Vec3<int> Chunk::getMax() const
  165. {
  166. return { location.x + CHUNK_SIZE / 2, location.y + CHUNK_SIZE / 2, WORLD_HEIGHT };
  167. }
  168. Game *Chunk::zGameObj() const
  169. {
  170. return zGame;
  171. }