Game.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #include "Game.h"
  2. #include "Zeit.h"
  3. #include "Player.h"
  4. #include "OverworldDimension.h"
  5. using namespace Framework;
  6. GameClient::GameClient( Player *zPlayer, FCKlient *client )
  7. : ReferenceCounter(),
  8. zPlayer( zPlayer ),
  9. client( client ),
  10. writer( client->zClient() ),
  11. online( 1 )
  12. {}
  13. GameClient::~GameClient()
  14. {
  15. client->release();
  16. }
  17. void GameClient::sendWorldUpdate( WorldUpdate *zUpdate )
  18. {
  19. cs.Enter();
  20. writer.schreibe( (char *)&Message::WORLD_UPDATE, 1 );
  21. zUpdate->write( &writer );
  22. cs.Leave();
  23. }
  24. void GameClient::reply( Game *zGame )
  25. {
  26. cs.Enter();
  27. for( auto req = requests.getIterator(); req; req++ )
  28. {
  29. // TODO
  30. }
  31. requests.leeren();
  32. cs.Leave();
  33. }
  34. void GameClient::logout()
  35. {
  36. online = 0;
  37. }
  38. void GameClient::addMessage( StreamReader *reader )
  39. {
  40. short len = 0;
  41. reader->lese( (char *)&len, 2 );
  42. InMemoryBuffer *buffer = new InMemoryBuffer();
  43. char *tmp = new char[ len ];
  44. reader->lese( tmp, len );
  45. buffer->schreibe( tmp, len );
  46. delete[]tmp;
  47. cs.Enter();
  48. requests.add( buffer );
  49. cs.Leave();
  50. }
  51. bool GameClient::isOnline() const
  52. {
  53. return online;
  54. }
  55. Player *GameClient::zEntity() const
  56. {
  57. return zPlayer;
  58. }
  59. Game::Game( Framework::Text name, Framework::Text worldsDir )
  60. : Thread(),
  61. name( name ),
  62. dimensions( new RCArray<Dimension>() ),
  63. updates( new RCArray<WorldUpdate>() ),
  64. clients( new RCArray<GameClient>() ),
  65. generator( 0 ),
  66. loader( new WorldLoader( this ) ),
  67. ticker( new TickOrganizer() ),
  68. path( (const char *)( worldsDir + "/" + name ) ),
  69. stop( 0 ),
  70. tickId( 0 )
  71. {
  72. if( !DateiExistiert( worldsDir + "/" + name ) )
  73. DateiPfadErstellen( worldsDir + "/" + name + "/" );
  74. int seed = 0;
  75. int index = 0;
  76. for( char *n = name; n; n++ )
  77. seed += (int)pow( (float)*n * 31, ( float )++index );
  78. generator = new WorldGenerator( seed, this );
  79. start();
  80. }
  81. Game::~Game()
  82. {
  83. dimensions->release();
  84. updates->release();
  85. clients->release();
  86. generator->release();
  87. loader->release();
  88. }
  89. void Game::thread()
  90. {
  91. ZeitMesser m;
  92. while( !stop )
  93. {
  94. m.messungStart();
  95. ticker->nextTick();
  96. int index = 0;
  97. Array<int> removed;
  98. cs.Enter();
  99. for( auto player = clients->getIterator(); player; player++, index++ )
  100. {
  101. if( !player->isOnline() )
  102. {
  103. Datei pFile;
  104. pFile.setDatei( path + "/player/" + player->zEntity()->getName() );
  105. if( pFile.open( Datei::Style::schreiben ) )
  106. PlayerEntityType::INSTANCE->saveEntity( player->zEntity(), &pFile );
  107. removed.add( player, 0 );
  108. }
  109. }
  110. for( auto i = removed.getIterator(); i; i++ )
  111. clients->remove( i );
  112. cs.Leave();
  113. for( auto dim = dimensions->getIterator(); dim; dim++ )
  114. dim->tickEntities( this );
  115. while( updates->z( 0 ) )
  116. {
  117. WorldUpdate *update = updates->z( 0 );
  118. for( auto client = clients->getIterator(); client; client++ )
  119. client->sendWorldUpdate( update );
  120. if( !zDimension( update->getAffectedDimension() ) )
  121. addDimension( new Dimension( update->getAffectedDimension() ) );
  122. update->onUpdate( zDimension( update->getAffectedDimension() ) );
  123. updates->remove( 0 );
  124. }
  125. for( auto client = clients->getIterator(); client; client++ )
  126. client->reply( this );
  127. m.messungEnde();
  128. double sec = m.getSekunden();
  129. if( sec < 0.05 )
  130. Sleep( (int)( ( 0.05 - sec ) * 1000 ) );
  131. }
  132. save();
  133. }
  134. void Game::requestWorldUpdate( WorldUpdate *update )
  135. {
  136. cs.Enter();
  137. updates->add( update );
  138. cs.Leave();
  139. }
  140. GameClient *Game::addPlayer( FCKlient *client, Framework::Text name )
  141. {
  142. cs.Enter();
  143. Datei pFile;
  144. pFile.setDatei( path + "/player/" + name );
  145. Player *player;
  146. if( !pFile.existiert() || !pFile.open( Datei::Style::lesen ) )
  147. {
  148. player = (Player *)PlayerEntityType::INSTANCE->createEntityAt( Vec3<float>( 0, 0, 0 ), OverworldDimension::ID, this );
  149. }
  150. else
  151. {
  152. player = (Player *)PlayerEntityType::INSTANCE->loadEntity( this, &pFile );
  153. pFile.close();
  154. }
  155. requestArea( { (int)player->getPosition().x - 100, (int)player->getPosition().y - 100, (int)player->getPosition().x + 100, (int)player->getPosition().y + 100, player->getCurrentDimensionId() } );
  156. while( !zDimension( OverworldDimension::ID ) )
  157. {
  158. cs.Leave();
  159. Sleep( 1000 );
  160. cs.Enter();
  161. }
  162. zDimension( OverworldDimension::ID )->addEntity( player );
  163. GameClient *gameClient = new GameClient( player, client );
  164. clients->add( gameClient );
  165. cs.Leave();
  166. return dynamic_cast<GameClient *>( gameClient->getThis() );
  167. }
  168. bool Game::doesChunkExist( int x, int y, int dimension ) const
  169. {
  170. Dimension *dim = zDimension( dimension );
  171. return ( dim && dim->hasChunck( x, y ) ) || loader->existsChunk( x, y, dimension );
  172. }
  173. Block *Game::zBlockAt( Framework::Vec3<int> location, int dimension ) const
  174. {
  175. Dimension *dim = zDimension( dimension );
  176. if( dim )
  177. return dim->zBlock( location );
  178. return 0;
  179. }
  180. Dimension *Game::zDimension( int id ) const
  181. {
  182. for( auto dim = dimensions->getIterator(); dim; dim++ )
  183. {
  184. if( dim->getDimensionId() == id )
  185. return dim;
  186. }
  187. return 0;
  188. }
  189. Framework::Punkt Game::getChunkCenter( int x, int y ) const
  190. {
  191. return Punkt( (int)floor( ( (float)x + CHUNK_SIZE / 2 ) / CHUNK_SIZE ), (int)floor( ( (float)y + CHUNK_SIZE / 2 ) / CHUNK_SIZE ) );
  192. }
  193. Framework::Text Game::getWorldDirectory() const
  194. {
  195. return path;
  196. }
  197. void Game::requestArea( Area area )
  198. {
  199. generator->requestGeneration( area );
  200. loader->requestLoading( area );
  201. }
  202. void Game::save() const
  203. {
  204. for( auto dim = dimensions->getIterator(); dim; dim++ )
  205. dim->save( path );
  206. }
  207. void Game::requestStop()
  208. {
  209. stop = 1;
  210. warteAufThread( 1000000 );
  211. }
  212. void Game::addDimension( Dimension *d )
  213. {
  214. dimensions->add( d );
  215. }