Chunk.cpp 5.9 KB

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