Spiel.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. #include "Spiel.h"
  2. #include <time.h>
  3. #include <DateiSystem.h>
  4. #include "Define.h"
  5. #include "SSKlient.h"
  6. #include "KartenLeser.h"
  7. #include "Statistik.h"
  8. #include "Team.h"
  9. #include "Laser.h"
  10. #ifdef WIN32
  11. #include <random>
  12. #else
  13. #include <math.h>
  14. #include <unistd.h>
  15. #include <stdlib.h>
  16. #define Sleep( x ) usleep( (x) * 1000 )
  17. #endif
  18. // Inhalt der Spiel Klasse aus Spiel.h
  19. // Konstruktor
  20. Spiel::Spiel()
  21. {
  22. zAccounts = 0;
  23. zKlients = 0;
  24. stat = new Statistik();
  25. teams = new RCArray< Team >();
  26. teamAnzahl = 0;
  27. spieler = new RCArray< Spieler >();
  28. shots = new RCArray< Laser >();
  29. objekte = new RCArray< SpielObjekt >();
  30. welt = new Welt2D();
  31. welt->setCircular( 1 );
  32. welt->setAirResistance( 0.001f );
  33. psqldb = 0;
  34. spielId = 0;
  35. karteId = 0;
  36. spielerAnzahl = 0;
  37. karte = 0;
  38. InitializeCriticalSection( &cs );
  39. sts = 0;
  40. log = 0;
  41. isRunning = 0;
  42. spielZeit = 0;
  43. ende = 1;
  44. nextSchussId = 1;
  45. ref = 1;
  46. }
  47. // Destruktor
  48. Spiel::~Spiel()
  49. {
  50. teams->release();
  51. stat->release();
  52. spieler->release();
  53. objekte->release();
  54. welt->release();
  55. if( psqldb )
  56. psqldb->release();
  57. if( karte )
  58. karte->release();
  59. if( sts )
  60. sts->release();
  61. DeleteCriticalSection( &cs );
  62. }
  63. // privat
  64. int Spiel::getTeamVonSpieler( int sNum )
  65. {
  66. for( int i = 0; i < spielerAnzahl; i++ )
  67. {
  68. Spieler *tmp = spieler->z( i );
  69. if( tmp && tmp->getSpielerNummer() == sNum )
  70. return tmp->zTeam() ? tmp->zTeam()->id : 0;
  71. }
  72. return 0;
  73. }
  74. // nicht constant
  75. void Spiel::setPSQLK( SSDatenbankV *psqldb )
  76. {
  77. if( this->psqldb )
  78. this->psqldb->release();
  79. this->psqldb = psqldb;
  80. stat->setPSQLDB( psqldb->getThis() );
  81. }
  82. void Spiel::setSpielId( int id )
  83. {
  84. spielId = id;
  85. stat->setSpielId( id );
  86. }
  87. void Spiel::setKarteId( int karteId )
  88. {
  89. this->karteId = karteId;
  90. stat->setKarteId( karteId );
  91. }
  92. void Spiel::setTempPfad( char *pfad )
  93. {
  94. mapPfad = pfad;
  95. mapPfad += "/";
  96. }
  97. void Spiel::setAccounts( int anzahl, Array< int > *zAccounts )
  98. {
  99. this->zAccounts = zAccounts->getThis();
  100. spielerAnzahl = anzahl;
  101. }
  102. void Spiel::setKlients( int anzahl, RCArray< SSKlientV > *zKlients )
  103. {
  104. this->zKlients = zKlients->getThis();
  105. }
  106. void Spiel::setSpielerNummern( int anzahl, Array< int > *spielerNummern )
  107. {
  108. if( !sts )
  109. {
  110. sts = new SpielerTeamStruktur();
  111. KartenLeser *reader = new KartenLeser( karteId, psqldb->getThis(), mapPfad );
  112. reader->ladeSpielerTeamStruktur( sts );
  113. if( karte )
  114. karte->release();
  115. karte = reader->ladeKarte( sts );
  116. reader->release();
  117. for( int i = 0; i < sts->teamAnzahl; i++ )
  118. teams->set( karte->createTeam( i ), i );
  119. stat->setTeamNamen( sts->teamName->getThis() );
  120. int objektAnzahl = karte->getObjektAnzahl();
  121. for( int i = 0; i < objektAnzahl; i++ )
  122. {
  123. SpielObjekt *obj = karte->createObjekt( i );
  124. welt->addObject( obj->getThis() );
  125. objekte->set( obj, i );
  126. }
  127. welt->setSize( karte->getSize().x, karte->getSize().y );
  128. welt->setSize( 1 );
  129. }
  130. for( int i = 0; i < anzahl; i++ )
  131. {
  132. Spieler *tmp = karte->createSpieler( spielerNummern->get( i ) );
  133. if( tmp )
  134. {
  135. int team = 0;
  136. int von = 0;
  137. int bis = 0;
  138. for( int j = 0; j < sts->teamAnzahl; j++ )
  139. {
  140. bis = von + ( sts->teamSize->hat( j ) ? sts->teamSize->get( j ) : 0 );
  141. if( tmp->getSpielerNummer() >= von && tmp->getSpielerNummer() < bis )
  142. {
  143. team = j;
  144. break;
  145. }
  146. von = bis;
  147. }
  148. tmp->setTeam( teams->get( team ) );
  149. teams->z( team )->spieler->add( tmp );
  150. }
  151. welt->addObject( tmp->getThis() );
  152. spieler->set( tmp, i );
  153. }
  154. for( int i = 0; i < anzahl; i++ )
  155. spieler->z( i )->setAccountId( zAccounts->hat( i ) ? zAccounts->get( i ) : 0 );
  156. for( int i = 0; i < anzahl; i++ )
  157. spieler->z( i )->setKlient( new Klient( zKlients->get( i ) ) );
  158. stat->setSpieler( spielerAnzahl, spieler );
  159. zAccounts = zAccounts->release();
  160. zKlients = zKlients->release();
  161. teamAnzahl = 0;
  162. for( int i = 0; i < sts->teamAnzahl; i++ )
  163. if( teams->z( i )->spieler->getEintragAnzahl() )
  164. teamAnzahl++;
  165. }
  166. void Spiel::klientOffline( int accountId )
  167. {
  168. for( int i = 0; i < spielerAnzahl; i++ )
  169. {
  170. if( spieler->z( i )->getAccountId() == accountId )
  171. spieler->z( i )->offline();
  172. }
  173. }
  174. void Spiel::klientOnline( int accountId, SSKlientV *zKlient )
  175. {
  176. for( int i = 0; i < spielerAnzahl; i++ )
  177. {
  178. if( spieler->z( i )->getAccountId() == accountId )
  179. {
  180. EnterCriticalSection( &cs );
  181. Spieler *s = spieler->z( i );
  182. s->online( zKlient );
  183. Klient *tmp = spieler->z( i )->zKlient();
  184. tmp->sendeSpielerNummer( s->getSpielerNummer(), 0 );
  185. //--------------------------
  186. LeaveCriticalSection( &cs );
  187. }
  188. }
  189. }
  190. void Spiel::nachricht( int accountId, int len, char *bytes )
  191. {
  192. if( !isRunning || ende )
  193. return;
  194. EnterCriticalSection( &cs );
  195. if( ende )
  196. {
  197. LeaveCriticalSection( &cs );
  198. return;
  199. }
  200. char *msgBeg = bytes;
  201. int msgLen = len;
  202. int msgAccount = accountId;
  203. bool saveMSG = 1;
  204. len--;
  205. switch( *bytes )
  206. {
  207. case 0:
  208. case 1:
  209. case 2:
  210. case 3:
  211. case 4:
  212. case 5:
  213. case 6:
  214. case 7:
  215. for( int i = 0; i < spielerAnzahl; i++ )
  216. {
  217. Spieler *tmp = spieler->z( i );
  218. if( tmp && tmp->getAccountId() == accountId )
  219. {
  220. if( !tmp->istAmLeben() )
  221. break;
  222. if( !tmp->setTastataturStatus( (TastaturStatus)( (int)( *bytes ) / 2 ), ( (int)( *bytes ) % 2 ) == 0 ) )
  223. {
  224. saveMSG = 0;
  225. break;
  226. }
  227. if( *bytes != 6 && *bytes != 7 )
  228. {
  229. for( int j = 0; j < spielerAnzahl; j++ )
  230. {
  231. Spieler *s = spieler->z( j );
  232. if( s && s->zKlient() )
  233. s->zKlient()->sendeTastaturStatus( tmp->getSpielerNummer(), (TastaturStatus)( (int)( *bytes ) / 2 ), ( (int)( *bytes ) % 2 ) == 0, spielZeit, tmp->getPosition(), tmp->getSpeed(), tmp->getDrehung(), tmp->getDrehungSpeed() );
  234. }
  235. }
  236. break;
  237. }
  238. }
  239. break;
  240. case 8: // chat Nachricht
  241. if( 1 )
  242. {
  243. bytes++;
  244. Text *txt = psqldb->getAccountRufName( accountId );
  245. txt->append( ": " );
  246. txt->append( bytes, len );
  247. for( int i = 0; i < spielerAnzahl; i++ )
  248. {
  249. Spieler *tmp = spieler->z( i );
  250. if( tmp && tmp->zKlient() )
  251. tmp->zKlient()->sendeChatNachricht( txt->getText(), spielZeit );
  252. }
  253. txt->release();
  254. len = 0;
  255. }
  256. break;
  257. case 9: // Skill verwendung
  258. if( 1 )
  259. {
  260. bytes++;
  261. char art = *bytes;
  262. len--;
  263. for( int i = 0; i < spielerAnzahl; i++ )
  264. {
  265. Spieler *tmp = spieler->z( i );
  266. if( tmp && tmp->getAccountId() == accountId )
  267. {
  268. if( !tmp->istAmLeben() )
  269. break;
  270. if( !tmp->setSkill( art ) )
  271. {
  272. saveMSG = 0;
  273. break;
  274. }
  275. for( int j = 0; j < spielerAnzahl; j++ )
  276. {
  277. Spieler *s = spieler->z( j );
  278. if( s && s->zKlient() )
  279. s->zKlient()->sendeSkillNachricht( tmp->getSpielerNummer(), art, spielZeit );
  280. }
  281. break;
  282. }
  283. }
  284. break;
  285. }
  286. break;
  287. default:
  288. saveMSG = 0;
  289. }
  290. if( len )
  291. {
  292. // error
  293. }
  294. if( log && log->istOffen() && saveMSG )
  295. {
  296. char c = 1;
  297. log->schreibe( &c, 1 );
  298. int spielerNum = 0;
  299. for( int i = 0; i < spielerAnzahl; i++ )
  300. {
  301. Spieler *tmp = spieler->z( i );
  302. if( tmp && tmp->getAccountId() == msgAccount )
  303. {
  304. spielerNum = tmp->getSpielerNummer();
  305. break;
  306. }
  307. }
  308. log->schreibe( (char*)&spielerNum, 4 );
  309. short l = (short)msgLen;
  310. log->schreibe( (char*)&l, 2 );
  311. log->schreibe( msgBeg, l );
  312. }
  313. LeaveCriticalSection( &cs );
  314. }
  315. void Spiel::tick( double zeit )
  316. {
  317. // Objekte updaten
  318. welt->tick( zeit );
  319. // Spieler Updaten
  320. for( int i = 0; i < spielerAnzahl; i++ )
  321. {
  322. Spieler *tmp = spieler->z( i );
  323. if( tmp )
  324. {
  325. if( tmp->doNeedWiederbelebung() )
  326. { // Wiederbelebung
  327. tmp->wiederbeleben();
  328. for( int j = 0; j < spielerAnzahl; j++ )
  329. {
  330. Spieler *s = spieler->z( j );
  331. if( s )
  332. s->zKlient()->sendeWiederbelebung( tmp->getSpielerNummer(), spielZeit );
  333. }
  334. }
  335. }
  336. }
  337. // Schüsse Collision
  338. int anz = shots->getEintragAnzahl();
  339. for( int i = 0; i < anz; i++ )
  340. {
  341. Laser *tmp = shots->z( i );
  342. if( tmp )
  343. {
  344. if( tmp->getIntensity() <= 0 )
  345. { // Schuss existiert nicht mehr
  346. for( int j = 0; j < spielerAnzahl; j++ )
  347. {
  348. Spieler *s = spieler->z( j );
  349. if( s )
  350. s->zKlient()->sendeTreffer( tmp->getId(), -1, spielZeit );
  351. }
  352. welt->removeObject( tmp );
  353. shots->remove( i );
  354. anz--;
  355. i--;
  356. }
  357. else
  358. { // Schuss existiert noch
  359. int team = getTeamVonSpieler( tmp->getSpieler() );
  360. for( int j = 0; j < spielerAnzahl; j++ )
  361. {
  362. Spieler *s = spieler->z( j );
  363. if( s && s->zTeam() && s->zTeam()->id != team && ( s->istTreffer( tmp->getPosition() ) ||
  364. s->istTreffer( tmp->getPosition() + karte->getSize() ) || s->istTreffer( tmp->getPosition() - karte->getSize() ) ) )
  365. { // Treffer
  366. double intens = tmp->getIntensity() * ( ( tmp->getSpeed() - s->getSpeed() ).getLength() / 200 );
  367. bool kill = s->nimmSchaden( intens );
  368. if( tmp->getSpeed().getLengthSq() > 0 )
  369. s->impuls( tmp->getPosition() - tmp->getSpeed(), tmp->getSpeed() * 0.3f );
  370. for( int k = 0; k < spielerAnzahl; k++ )
  371. {
  372. Spieler *sp = spieler->z( k );
  373. if( sp )
  374. sp->zKlient()->sendeTreffer( tmp->getId(), s->getSpielerNummer(), spielZeit );
  375. if( sp && sp->getSpielerNummer() == tmp->getSpieler() )
  376. sp->machSchaden( intens, kill );
  377. if( kill && sp )
  378. sp->zKlient()->sendeTod( s->getSpielerNummer(), tmp->getSpieler(), spielZeit );
  379. }
  380. if( kill )
  381. {
  382. if( teams->z( team - 1 ) )
  383. teams->z( team - 1 )->punkte++;
  384. if( teams->z( team - 1 )->punkte == teams->z( team - 1 )->maxPunkte )
  385. ende = 1;
  386. }
  387. welt->removeObject( tmp );
  388. shots->remove( i );
  389. anz--;
  390. i--;
  391. break;
  392. }
  393. }
  394. }
  395. }
  396. }
  397. // Neue Schüsse hinzufügen
  398. for( int i = 0; i < spielerAnzahl; i++ )
  399. {
  400. Spieler *tmp = spieler->z( i );
  401. if( tmp )
  402. {
  403. Laser *nL = tmp->getLaser( nextSchussId );
  404. if( nL )
  405. {
  406. nextSchussId++;
  407. welt->addObject( nL->getThis() );
  408. shots->add( nL );
  409. for( int j = 0; j < spielerAnzahl; j++ )
  410. {
  411. if( spieler->z( j ) && spieler->z( j )->zKlient() )
  412. spieler->z( j )->zKlient()->sendeSchuss( nL->getId(), nL->getSpieler(), nL->getPosition(), nL->getSpeed(), nL->getIntensity(), spielZeit );
  413. }
  414. }
  415. }
  416. }
  417. }
  418. void Spiel::run()
  419. {
  420. log = new Datei();
  421. Text *pfad = new Text( "../spiel log/" );
  422. pfad->append( spielId );
  423. pfad->append( "/verlauf.ksggl" );
  424. log->setDatei( pfad );
  425. log->remove();
  426. log->erstellen();
  427. log->open( Datei::Style::schreiben );
  428. time_t t;
  429. time( &t );
  430. srand( (unsigned int)t );
  431. log->schreibe( (char*)&spielerAnzahl, 4 );
  432. for( int i = 0; i < spielerAnzahl; i++ )
  433. {
  434. Spieler *tmp = spieler->z( i );
  435. if( tmp && tmp->zKlient() )
  436. {
  437. tmp->zKlient()->sendeInit( spieler, -1 );
  438. log->schreibe( (char*)&i, 4 );
  439. int sNum = tmp->getSpielerNummer();
  440. log->schreibe( (char*)&sNum, 4 );
  441. tmp->zKlient()->sendeSpielerNummer( sNum, -1 );
  442. int team = tmp->zTeam()->id;
  443. log->schreibe( (char*)&team, 4 );
  444. int farbe = tmp->getSpielerFarbe();
  445. log->schreibe( (char*)&farbe, 4 );
  446. farbe = tmp->zTeam()->farbe;
  447. log->schreibe( (char*)&farbe, 4 );
  448. Text *name = psqldb->getAccountRufName( tmp->getAccountId() );
  449. char len = (char)( name ? name->getLength() : 0 );
  450. log->schreibe( &len, 1 );
  451. if( len )
  452. log->schreibe( name->getText(), len );
  453. if( name )
  454. name->release();
  455. name = sts->teamName->z( team );
  456. len = (char)( name ? name->getLength() : 0 );
  457. log->schreibe( &len, 1 );
  458. if( len )
  459. log->schreibe( name->getText(), len );
  460. }
  461. }
  462. Array< char > spielerStatus;
  463. ZeitMesser *zeit = new ZeitMesser();
  464. zeit->messungStart();
  465. isRunning = 1;
  466. ende = 0;
  467. double ausgleich = 0;
  468. double sZ = 0;
  469. spielZeit = -1;
  470. for( int i = 0; i < spielerAnzahl; i++ )
  471. {
  472. Spieler *tmp = spieler->z( i );
  473. if( tmp && tmp->zKlient() )
  474. tmp->zKlient()->sendeStart( spielZeit );
  475. }
  476. double rZeit = 0;
  477. while( !ende )
  478. {
  479. zeit->messungEnde();
  480. zeit->messungStart();
  481. double z = zeit->getSekunden();
  482. ausgleich += 1.0 / 25 - z;
  483. if( ausgleich > 0 )
  484. Sleep( (int)( ausgleich * 1000 ) );
  485. rZeit += z;
  486. while( sZ + TICK < rZeit && !ende )
  487. {
  488. EnterCriticalSection( &cs );
  489. sZ += TICK;
  490. spielZeit++;
  491. char c = 0;
  492. log->schreibe( &c, 1 );
  493. tick( TICK );
  494. LeaveCriticalSection( &cs );
  495. }
  496. }
  497. zeit->messungEnde();
  498. zeit->release();
  499. for( int i = 0; i < spielerAnzahl; i++ )
  500. {
  501. if( spieler->z( i ) && spieler->z( i )->zKlient() )
  502. {
  503. if( spieler->z( i )->zTeam()->punkte < spieler->z( i )->zTeam()->maxPunkte )
  504. {
  505. spielerStatus.set( 1, i ); // Datenbank Verloren
  506. spieler->z( i )->zKlient()->sendeSpielEnde( 0, 0 );
  507. }
  508. else
  509. {
  510. spielerStatus.set( 2, i ); // Datenbank Gewonnen
  511. spieler->z( i )->zKlient()->sendeSpielEnde( 1, 0 );
  512. }
  513. }
  514. if( spieler->z( i ) && ( !spieler->z( i )->zKlient() || !spieler->z( i )->istOnline() ) )
  515. spielerStatus.set( 3, i );
  516. }
  517. if( teamAnzahl == 1 )
  518. psqldb->setSpielStatusBeendet( spielId, 6 );
  519. else
  520. psqldb->setSpielStatusBeendet( spielId, 5 );
  521. for( int i = 0; i < spielerAnzahl; i++ )
  522. {
  523. Spieler *tmp = spieler->z( i );
  524. if( tmp )
  525. {
  526. psqldb->setSpielSpielerStatus( spielId, tmp->getAccountId(), tmp->getPunkte(), spielerStatus.get( i ) );
  527. if( teamAnzahl > 1 )
  528. psqldb->addSpielerStatistik( tmp->getAccountId(), spielId );
  529. }
  530. }
  531. log->close();
  532. log = log->release();
  533. isRunning = 0;
  534. }
  535. // constant
  536. StatistikV *Spiel::getStatistik() const
  537. {
  538. return stat->getThis();
  539. }
  540. // Reference Counting
  541. SpielKlasse *Spiel::getThis()
  542. {
  543. ref++;
  544. return this;
  545. }
  546. SpielKlasse *Spiel::release()
  547. {
  548. ref--;
  549. if( !ref )
  550. delete this;
  551. return 0;
  552. }