Dimension.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include "Dimension.h"
  2. #include "Constants.h"
  3. #include "Datei.h"
  4. #include "Game.h"
  5. #include "Globals.h"
  6. using namespace Framework;
  7. #define MAX_VIEW_DISTANCE CHUNK_SIZE * 8
  8. Dimension::Dimension( int id )
  9. : dimensionId( id ),
  10. chunks( new Trie<Chunk>() ),
  11. entities( new RCArray<Entity>() )
  12. {}
  13. Dimension::~Dimension()
  14. {
  15. entities->release();
  16. chunks->release();
  17. }
  18. void Dimension::updateVisibility()
  19. {
  20. bool changed = true;
  21. while( changed )
  22. {
  23. changed = false;
  24. cs.lock();
  25. for( auto chunk : chunkList )
  26. {
  27. if( chunk )
  28. {
  29. chunk->getThis();
  30. cs.unlock();
  31. changed |= chunk->updateVisibility();
  32. chunk->release();
  33. cs.lock();
  34. }
  35. }
  36. cs.unlock();
  37. }
  38. }
  39. void Dimension::getAddrOf( Punkt cPos, char* addr ) const
  40. {
  41. *(int*)addr = cPos.x;
  42. *((int*)addr + 1) = cPos.y;
  43. }
  44. void Dimension::getAddrOfWorld( Punkt wPos, char* addr ) const
  45. {
  46. if( wPos.x < 0 )
  47. wPos.x -= CHUNK_SIZE;
  48. if( wPos.y < 0 ) // needed because otherwise would (-8, -8) have the same adress as (8, 8)
  49. wPos.y -= CHUNK_SIZE;
  50. wPos /= CHUNK_SIZE;
  51. getAddrOf( wPos, addr );
  52. }
  53. Chunk* Dimension::zChunk( Punkt wPos ) const
  54. {
  55. char addr[ 8 ];
  56. getAddrOfWorld( wPos, addr );
  57. return chunks->z( addr, 8 );
  58. }
  59. Framework::Either<Block*, int> Dimension::zBlock( Vec3<int> location )
  60. {
  61. Chunk* c = zChunk( currentGame->getChunkCenter( location.x, location.y ) );
  62. if( c )
  63. {
  64. int x = location.x % CHUNK_SIZE;
  65. int y = location.y % CHUNK_SIZE;
  66. if( x < 0 )
  67. x += CHUNK_SIZE;
  68. if( y < 0 )
  69. y += CHUNK_SIZE;
  70. return c->zBlockAt( Vec3<int>( x, y, location.z ) );
  71. }
  72. return 0;
  73. }
  74. void Dimension::addEntity( Entity* entity )
  75. {
  76. entities->add( entity );
  77. }
  78. void Dimension::setChunk( Chunk* chunk, Punkt center )
  79. {
  80. char addr[ 8 ];
  81. getAddrOfWorld( center, addr );
  82. Chunk* old = chunks->z( addr, 8 );
  83. cs.lock();
  84. if( old )
  85. {
  86. for( int i = 0; i < chunkList.getEintragAnzahl(); i++ )
  87. {
  88. if( chunkList.get( i ) == old )
  89. {
  90. chunkList.remove( i );
  91. break;
  92. }
  93. }
  94. }
  95. chunks->set( addr, 8, chunk );
  96. cs.unlock();
  97. if( chunk )
  98. {
  99. chunkList.add( chunk );
  100. chunk->setAdded();
  101. }
  102. getAddrOfWorld( center + Punkt( CHUNK_SIZE, 0 ), addr );
  103. Chunk* zChunk = chunks->z( addr, 8 );
  104. if( zChunk )
  105. {
  106. zChunk->setNeighbor( WEST, chunk );
  107. if( chunk )
  108. chunk->setNeighbor( EAST, zChunk );
  109. }
  110. getAddrOfWorld( center + Punkt( -CHUNK_SIZE, 0 ), addr );
  111. zChunk = chunks->z( addr, 8 );
  112. if( zChunk )
  113. {
  114. zChunk->setNeighbor( EAST, chunk );
  115. if( chunk )
  116. chunk->setNeighbor( WEST, zChunk );
  117. }
  118. getAddrOfWorld( center + Punkt( 0, CHUNK_SIZE ), addr );
  119. zChunk = chunks->z( addr, 8 );
  120. if( zChunk )
  121. {
  122. zChunk->setNeighbor( NORTH, chunk );
  123. if( chunk )
  124. chunk->setNeighbor( SOUTH, zChunk );
  125. }
  126. getAddrOfWorld( center + Punkt( 0, -CHUNK_SIZE ), addr );
  127. zChunk = chunks->z( addr, 8 );
  128. if( zChunk )
  129. {
  130. zChunk->setNeighbor( SOUTH, chunk );
  131. if( chunk )
  132. chunk->setNeighbor( NORTH, zChunk );
  133. }
  134. }
  135. int Dimension::getDimensionId() const
  136. {
  137. return dimensionId;
  138. }
  139. bool Dimension::hasChunck( int x, int y ) const
  140. {
  141. return zChunk( Punkt( x, y ) );
  142. }
  143. void Dimension::removeDistantChunks( Punkt wPos )
  144. {
  145. Array<int> removed;
  146. int index = 0;
  147. for( Chunk* chunk : chunkList )
  148. {
  149. if( (chunk->getCenter() - wPos).getLength() > MAX_VIEW_DISTANCE )
  150. removed.add( index, 0 );
  151. index++;
  152. }
  153. for( int i : removed )
  154. {
  155. Chunk* chunk = chunkList.get( i );
  156. chunk->prepareRemove();
  157. setChunk( 0, chunk->getCenter() );
  158. }
  159. }