Dimension.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. #include "Dimension.h"
  2. #include "Constants.h"
  3. #include "Datei.h"
  4. #include "Game.h"
  5. using namespace Framework;
  6. Dimension::Dimension( int id )
  7. : dimensionId( id ),
  8. chunks( new Trie<Chunk>() ),
  9. entities( new RCArray<Entity>() )
  10. {}
  11. Dimension::~Dimension()
  12. {
  13. entities->release();
  14. chunks->release();
  15. }
  16. void Dimension::api( Framework::StreamReader* zRequest, NetworkResponse* zResponse )
  17. {
  18. // TODO: switch type chunck, block, entity
  19. }
  20. void Dimension::tickEntities( Game* zGame )
  21. {
  22. int index = 0;
  23. Array<int> removed;
  24. for( auto entity : *entities )
  25. {
  26. if( zChunk( Punkt( (int)entity->getPosition().x, (int)entity->getPosition().y ) ) )
  27. entity->tick( this, zGame );
  28. if( entity->isRemoved() )
  29. removed.add( index, 0 );
  30. index++;
  31. }
  32. for( int i : removed )
  33. entities->remove( i );
  34. }
  35. void Dimension::getAddrOf( Punkt cPos, char* addr ) const
  36. {
  37. *(int*)addr = cPos.x;
  38. *((int*)addr + 1) = cPos.y;
  39. }
  40. void Dimension::getAddrOfWorld( Punkt wPos, char* addr ) const
  41. {
  42. if( wPos.x < 0 )
  43. wPos.x -= CHUNK_SIZE;
  44. if( wPos.y < 0 ) // needed because otherwise would (-8, -8) have the same adress as (8, 8)
  45. wPos.y -= CHUNK_SIZE;
  46. wPos /= CHUNK_SIZE;
  47. getAddrOf( wPos, addr );
  48. }
  49. Chunk* Dimension::zChunk( Punkt wPos ) const
  50. {
  51. char addr[ 8 ];
  52. getAddrOfWorld( wPos, addr );
  53. return chunks->z( addr, 8 );
  54. }
  55. Framework::Either<Block*, int> Dimension::zBlock( Vec3<int> location, const Game* zGame )
  56. {
  57. Chunk* c = zChunk( zGame->getChunkCenter( location.x, location.y ) );
  58. if( c )
  59. {
  60. int x = location.x % CHUNK_SIZE;
  61. int y = location.y % CHUNK_SIZE;
  62. if( x < 0 )
  63. x += CHUNK_SIZE;
  64. if( y < 0 )
  65. y += CHUNK_SIZE;
  66. return c->zBlockAt( Vec3<int>( x, y, location.z ) );
  67. }
  68. return 0;
  69. }
  70. void Dimension::addEntity( Entity* entity )
  71. {
  72. entities->add( entity );
  73. }
  74. void Dimension::setChunk( Chunk* chunk, Punkt center )
  75. {
  76. char addr[ 8 ];
  77. getAddrOfWorld( center, addr );
  78. Chunk* old = chunks->z( addr, 8 );
  79. if( old )
  80. {
  81. for( int i = 0; i < chunkList.getEintragAnzahl(); i++ )
  82. {
  83. if( chunkList.get( i ) == old )
  84. {
  85. chunkList.remove( i );
  86. break;
  87. }
  88. }
  89. }
  90. chunks->set( addr, 8, chunk );
  91. if( chunk )
  92. {
  93. chunkList.add( chunk );
  94. chunk->setAdded();
  95. }
  96. getAddrOfWorld( center + Punkt( CHUNK_SIZE, 0 ), addr );
  97. Chunk* zChunk = chunks->z( addr, 8 );
  98. if( zChunk )
  99. {
  100. zChunk->setNeighbor( WEST, chunk );
  101. if( chunk )
  102. chunk->setNeighbor( EAST, zChunk );
  103. }
  104. getAddrOfWorld( center + Punkt( -CHUNK_SIZE, 0 ), addr );
  105. zChunk = chunks->z( addr, 8 );
  106. if( zChunk )
  107. {
  108. zChunk->setNeighbor( EAST, chunk );
  109. if( chunk )
  110. chunk->setNeighbor( WEST, zChunk );
  111. }
  112. getAddrOfWorld( center + Punkt( 0, CHUNK_SIZE ), addr );
  113. zChunk = chunks->z( addr, 8 );
  114. if( zChunk )
  115. {
  116. zChunk->setNeighbor( NORTH, chunk );
  117. if( chunk )
  118. chunk->setNeighbor( SOUTH, zChunk );
  119. }
  120. getAddrOfWorld( center + Punkt( 0, -CHUNK_SIZE ), addr );
  121. zChunk = chunks->z( addr, 8 );
  122. if( zChunk )
  123. {
  124. zChunk->setNeighbor( SOUTH, chunk );
  125. if( chunk )
  126. chunk->setNeighbor( NORTH, zChunk );
  127. }
  128. }
  129. void Dimension::save( Text worldDir ) const
  130. {
  131. for( auto chunk = chunks->getIterator(); chunk; chunk++ )
  132. {
  133. if( !chunk._ )
  134. continue;
  135. Datei* file = new Datei();
  136. Text filePath = worldDir + "/dim/" + dimensionId + "/";
  137. filePath.appendHex( chunk->getCenter().x );
  138. filePath += "_";
  139. filePath.appendHex( chunk->getCenter().y );
  140. filePath += ".chunk";
  141. file->setDatei( filePath );
  142. if( file->open( Datei::Style::schreiben ) )
  143. chunk->save( file );
  144. file->close();
  145. file->release();
  146. }
  147. Text filePath = worldDir + "/dim/" + dimensionId + "/entities";
  148. Datei* file = new Datei();
  149. file->setDatei( filePath );
  150. if( file->open( Datei::Style::schreiben ) )
  151. {
  152. for( Entity* entity : *entities )
  153. {
  154. if( entity->zType()->getId() != PlayerEntityType::ID )
  155. {
  156. if( !entity->isRemoved() )
  157. {
  158. int type = entity->zType()->getId();
  159. file->schreibe( (char*)&type, 4 );
  160. StaticRegistry<EntityType>::INSTANCE.zElement( type )->saveEntity( entity, file );
  161. }
  162. }
  163. else
  164. {
  165. Datei pFile;
  166. pFile.setDatei( worldDir + "/player/" + ((Player*)entity)->getName() );
  167. if( pFile.open( Datei::Style::schreiben ) )
  168. PlayerEntityType::INSTANCE->saveEntity( entity, &pFile );
  169. }
  170. }
  171. file->close();
  172. }
  173. }
  174. int Dimension::getDimensionId() const
  175. {
  176. return dimensionId;
  177. }
  178. bool Dimension::hasChunck( int x, int y ) const
  179. {
  180. return zChunk( Punkt( x, y ) );
  181. }
  182. void Dimension::removeOldChunks()
  183. {
  184. Array<int> removed;
  185. int index = 0;
  186. for( Chunk* chunk : chunkList )
  187. {
  188. if( !chunk->hasViews() )
  189. removed.add( index, 0 );
  190. index++;
  191. }
  192. for( int i : removed )
  193. {
  194. Chunk* chunk = chunkList.get( i );
  195. // TODO: save chunk
  196. chunk->prepareRemove();
  197. setChunk( 0, chunk->getCenter() );
  198. }
  199. }