Dimension.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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->getIterator(); entity; entity++, index++ )
  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. }
  31. for( auto i = removed.getIterator(); i; i++ )
  32. entities->remove( i );
  33. }
  34. void Dimension::getAddrOf( Punkt cPos, char *addr ) const
  35. {
  36. *(int *)addr = cPos.x;
  37. *( (int *)addr + 1 ) = cPos.y;
  38. addr[ 8 ] = 0;
  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[ 9 ];
  52. getAddrOfWorld( wPos, addr );
  53. return chunks->z( addr, 9 );
  54. }
  55. Block *Dimension::zBlock( Vec3<int> location )
  56. {
  57. Chunk *c = zChunk( Punkt( location.x, location.y ) );
  58. if( c )
  59. return c->zBlockAt( Vec3<int>( location.x % CHUNK_SIZE, location.y % CHUNK_SIZE, location.z ) );
  60. return 0;
  61. }
  62. void Dimension::addEntity( Entity *entity )
  63. {
  64. entities->add( entity );
  65. }
  66. void Dimension::addChunk( Chunk *chunk )
  67. {
  68. char addr[ 9 ];
  69. getAddrOfWorld( chunk->getCenter(), addr );
  70. if( !chunks->z( addr, 9 ) )
  71. {
  72. chunks->set( addr, 9, chunk );
  73. getAddrOfWorld( chunk->getCenter() + Punkt( CHUNK_SIZE, 0 ), addr );
  74. Chunk *zChunk = chunks->z( addr, 9 );
  75. if( zChunk )
  76. {
  77. zChunk->setNeighbor( WEST, chunk );
  78. chunk->setNeighbor( EAST, chunk );
  79. }
  80. getAddrOfWorld( chunk->getCenter() + Punkt( -CHUNK_SIZE, 0 ), addr );
  81. zChunk = chunks->z( addr, 9 );
  82. if( zChunk )
  83. {
  84. zChunk->setNeighbor( EAST, chunk );
  85. chunk->setNeighbor( WEST, chunk );
  86. }
  87. getAddrOfWorld( chunk->getCenter() + Punkt( 0, CHUNK_SIZE ), addr );
  88. zChunk = chunks->z( addr, 9 );
  89. if( zChunk )
  90. {
  91. zChunk->setNeighbor( NORTH, chunk );
  92. chunk->setNeighbor( SOUTH, chunk );
  93. }
  94. getAddrOfWorld( chunk->getCenter() + Punkt( 0, -CHUNK_SIZE ), addr );
  95. zChunk = chunks->z( addr, 9 );
  96. if( zChunk )
  97. {
  98. zChunk->setNeighbor( SOUTH, chunk );
  99. chunk->setNeighbor( NORTH, chunk );
  100. }
  101. }
  102. else
  103. chunk->release();
  104. }
  105. void Dimension::save( Text worldDir ) const
  106. {
  107. for( auto chunk = chunks->getIterator(); chunk; chunk++ )
  108. {
  109. if( !chunk._ )
  110. continue;
  111. Datei *file = new Datei();
  112. Text filePath = worldDir + "/dim/" + dimensionId + "/";
  113. filePath.appendHex( chunk->getCenter().x );
  114. filePath += "_";
  115. filePath.appendHex( chunk->getCenter().y );
  116. filePath += ".chunk";
  117. file->setDatei( filePath );
  118. if( file->open( Datei::Style::schreiben ) )
  119. chunk->save( file );
  120. file->close();
  121. file->release();
  122. }
  123. Text filePath = worldDir + "/dim/" + dimensionId + "/entities";
  124. Datei *file = new Datei();
  125. file->setDatei( filePath );
  126. if( file->open( Datei::Style::schreiben ) )
  127. {
  128. for( auto entity = entities->getIterator(); entity; entity++ )
  129. {
  130. if( entity->zType()->getId() != PlayerEntityType::ID )
  131. {
  132. if( !entity->isRemoved() )
  133. {
  134. int type = entity->zType()->getId();
  135. file->schreibe( (char *)&type, 4 );
  136. StaticRegistry<EntityType>::INSTANCE.zElement( type )->saveEntity( entity, file );
  137. }
  138. }
  139. else
  140. {
  141. Datei pFile;
  142. pFile.setDatei( worldDir + "/player/" + ( (Player *)entity.val() )->getName() );
  143. if( pFile.open( Datei::Style::schreiben ) )
  144. PlayerEntityType::INSTANCE->saveEntity( entity, &pFile );
  145. }
  146. }
  147. file->close();
  148. }
  149. }
  150. int Dimension::getDimensionId() const
  151. {
  152. return dimensionId;
  153. }
  154. bool Dimension::hasChunck( int x, int y ) const
  155. {
  156. return zChunk( Punkt( x, y ) );
  157. }