Dimension.cpp 5.5 KB

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