Spiel.cpp 13 KB

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