Spiel.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. #include "Spiel.h"
  2. #include <Zeit.h>
  3. #ifdef WIN32
  4. #include "..\..\Datenbank\Datenbank.h"
  5. #include "..\SpielServer.h"
  6. #include "Reader\KartenLeser.h"
  7. #else
  8. #include "Datenbank.h"
  9. #include "SpielServer.h"
  10. #include "KartenLeser.h"
  11. #include <unistd.h>
  12. #define Sleep( x ) usleep( (x) * 1000 )
  13. #include <dlfcn.h>
  14. #define LoadLibrary( x ) dlopen( (x), RTLD_LAZY )
  15. #define GetProcAddress dlsym
  16. #define FreeLibrary dlclose
  17. #endif
  18. typedef SpielKlasse*( *DllStart )( );
  19. // Inhalt der Spiel Klasse aus Spiel.h
  20. // Konstruktor
  21. Spiel::Spiel( int id, SpielServer *ss )
  22. : Thread()
  23. {
  24. this->ss = ss;
  25. this->id = id;
  26. klients = new RCArray< SSKlient >();
  27. sts = new SpielerTeamStruktur();
  28. accounts = new Array< int >();
  29. spielerNummern = new Array< int >();
  30. status = new Array< int >();
  31. prozent = new Array< int >();
  32. teamAuswahlFertig = new Array< bool >();
  33. spiel = 0;
  34. state = 0;
  35. spielerAnzahl = 0;
  36. karte = 0;
  37. spielDll = 0;
  38. statistik = 0;
  39. ref = 1;
  40. }
  41. // Destruktor
  42. Spiel::~Spiel()
  43. {
  44. klients->release();
  45. sts->release();
  46. accounts->release();
  47. spielerNummern->release();
  48. status->release();
  49. prozent->release();
  50. teamAuswahlFertig->release();
  51. if( spiel )
  52. spiel->release();
  53. if( statistik )
  54. statistik->release();
  55. if( spielDll )
  56. FreeLibrary( spielDll );
  57. ss->release();
  58. }
  59. int Spiel::findFreeTeam()
  60. {
  61. int free = 0;
  62. int teamIndex = 0;
  63. int teamSize = sts->teamSize->get( teamIndex );
  64. double max = 0;
  65. Array< int > teams;
  66. for( int i = 0; i < sts->spielerAnzahl; i++ ) // suche nach teams die prozentual am wenigsten voll sind
  67. {
  68. bool used = 0;
  69. for( int j = 0; j < spielerAnzahl; j++ )
  70. {
  71. if( spielerNummern->hat( j ) && spielerNummern->get( j ) == i + 1 )
  72. used = 1;
  73. }
  74. if( !used )
  75. free++;
  76. teamSize--;
  77. if( !teamSize )
  78. {
  79. double teamVal = (double)free / sts->teamSize->get( teamIndex );
  80. if( teamVal > max )
  81. {
  82. teams.leeren();
  83. max = teamVal;
  84. }
  85. if( teamVal >= max )
  86. teams.add( teamIndex );
  87. free = 0;
  88. if( !sts->teamSize->hat( ++teamIndex ) )
  89. break;
  90. else
  91. teamSize = sts->teamSize->get( teamIndex );
  92. }
  93. } // suche aus den teams eines zufällig aus
  94. double randomVal = rand() / ( (double)RAND_MAX + 1 );
  95. double diff = 1.0 / teams.getEintragAnzahl();
  96. teamIndex = -1;
  97. while( randomVal >= 0 )
  98. {
  99. randomVal -= diff;
  100. teamIndex++;
  101. }
  102. if( teams.hat( teamIndex ) )
  103. return teams.get( teamIndex );
  104. else
  105. return teams.get( 0 );
  106. }
  107. void Spiel::teamAusgleich()
  108. {
  109. for( int i = 0; i < spielerAnzahl; i++ )
  110. {
  111. int sNum = spielerNummern->hat( i ) ? spielerNummern->get( i ) : 0;
  112. if( !sNum )
  113. {
  114. int team = findFreeTeam();
  115. for( int j = 0; j < team; j++ )
  116. sNum += sts->teamSize->get( j );
  117. while( true )
  118. {
  119. sNum++;
  120. bool gefunden = 0;
  121. for( int k = 0; k < spielerAnzahl; k++ )
  122. {
  123. if( spielerNummern->hat( k ) && spielerNummern->get( k ) == sNum )
  124. {
  125. gefunden = 1;
  126. break;
  127. }
  128. }
  129. if( !gefunden )
  130. break;
  131. }
  132. spielerNummern->set( sNum, i );
  133. }
  134. }
  135. }
  136. // nicht constant
  137. void Spiel::setAccounts( int anzahl, Array< int > *zAccounts )
  138. {
  139. for( int i = 0; i < anzahl; i++ )
  140. accounts->set( zAccounts->hat( i ) ? zAccounts->get( i ) : 0, i );
  141. spielerAnzahl = anzahl;
  142. }
  143. void Spiel::setKlients( int anzahl, RCArray< SSKlient > *zKlients )
  144. {
  145. for( int i = 0; i < anzahl; i++ )
  146. klients->set( zKlients->get( i ), i );
  147. }
  148. void Spiel::setKarteId( int karteId )
  149. {
  150. karte = karteId;
  151. KartenLeser *reader = new KartenLeser( id, karte, ss->getThis() );
  152. reader->ladeSpielerTeamStruktur( sts );
  153. reader->release();
  154. start();
  155. }
  156. bool Spiel::klientVerbunden( SSKlient *klient )
  157. {
  158. int accId = klient->getAccountId();
  159. bool ret = 0;
  160. for( int i = 0; i < spielerAnzahl; i++ )
  161. {
  162. if( accounts->hat( i ) && accounts->get( i ) == accId )
  163. {
  164. if( state == 1 )
  165. {
  166. klient->erstellungInitialisierung( sts );
  167. for( int j = 0; j < spielerAnzahl; j++ )
  168. {
  169. if( accounts->hat( j ) && accounts->get( j ) != accId )
  170. {
  171. SSKlient *tmp = klients->z( j );
  172. tmp->erstellungAddSpieler( accId );
  173. klient->erstellungAddSpieler( accounts->get( j ) );
  174. if( spielerNummern->hat( j ) )
  175. klient->erstellungSpielerTeam( accounts->get( j ), spielerNummern->get( j ) );
  176. }
  177. }
  178. }
  179. if( state == 5 && spiel )
  180. spiel->klientOnline( klient->getAccountId(), klient );
  181. klients->set( klient, i );
  182. status->set( 1, i );
  183. klient->setSpiel( this );
  184. ret = 1;
  185. break;
  186. }
  187. }
  188. if( !ret )
  189. klient->release();
  190. return ret;
  191. }
  192. bool Spiel::klientWechseltTeam( int accountId, int team )
  193. {
  194. if( state != 1 )
  195. return 0;
  196. if( team == 0 )
  197. {
  198. for( int i = 0; i < spielerAnzahl; i++ )
  199. {
  200. if( accounts->hat( i ) && accounts->get( i ) == accountId )
  201. spielerNummern->set( 0, i );
  202. SSKlient *tmp = klients->z( i );
  203. if( tmp )
  204. tmp->erstellungSpielerTeam( accountId, 0 );
  205. }
  206. return 1;
  207. }
  208. int von = 1;
  209. for( int i = 0; i < team - 1; i++ )
  210. {
  211. if( sts->teamSize->hat( i ) )
  212. von += sts->teamSize->get( i );
  213. }
  214. int bis = von + ( sts->teamSize->hat( team - 1 ) ? sts->teamSize->get( team - 1 ) : 0 );
  215. for( int i = von; i < bis; i++ )
  216. {
  217. bool verwendet = 0;
  218. for( int j = 0; j < spielerAnzahl; j++ )
  219. {
  220. if( spielerNummern->hat( j ) && spielerNummern->get( j ) == i )
  221. {
  222. verwendet = 1;
  223. break;
  224. }
  225. }
  226. if( !verwendet )
  227. {
  228. for( int j = 0; j < spielerAnzahl; j++ )
  229. {
  230. if( accounts->hat( j ) && accounts->get( j ) == accountId )
  231. spielerNummern->set( i, j );
  232. SSKlient *tmp = klients->z( j );
  233. if( tmp )
  234. tmp->erstellungSpielerTeam( accountId, i );
  235. }
  236. return 1;
  237. }
  238. }
  239. return 0;
  240. }
  241. bool Spiel::chatNachricht( char *nachricht )
  242. {
  243. if( state != 1 )
  244. return 0;
  245. for( int i = 0; i < spielerAnzahl; i++ )
  246. {
  247. SSKlient *tmp = klients->z( i );
  248. if( tmp )
  249. tmp->erstellungChatNachricht( nachricht );
  250. }
  251. return 1;
  252. }
  253. bool Spiel::klientGetrennt( SSKlient *zKlient )
  254. {
  255. int accId = zKlient->getAccountId();
  256. bool ret = 0;
  257. for( int i = 0; i < spielerAnzahl; i++ )
  258. {
  259. if( accounts->hat( i ) && accounts->get( i ) == accId )
  260. {
  261. if( status->hat( i ) && status->get( i ) != 0 )
  262. {
  263. if( state == 1 )
  264. {
  265. for( int j = 0; j < spielerAnzahl; j++ )
  266. {
  267. if( accounts->hat( j ) && accounts->get( j ) != accId )
  268. {
  269. SSKlient *tmp = klients->z( j );
  270. tmp->erstellungRemoveSpieler( accId );
  271. }
  272. }
  273. }
  274. if( state == 5 && spiel )
  275. spiel->klientOffline( zKlient->getAccountId() );
  276. if( state == 6 )
  277. {
  278. if( statistik )
  279. statistik->klientOffline( zKlient->getAccountId() );
  280. }
  281. zKlient->setSpielErstellt( 0 );
  282. spielerNummern->set( 0, i );
  283. status->set( 0, i );
  284. klients->set( 0, i );
  285. ret = 1;
  286. }
  287. break;
  288. }
  289. }
  290. return ret;
  291. }
  292. bool Spiel::klientTeamAuswahlFertig( int accountId )
  293. {
  294. for( int i = 0; i < spielerAnzahl; i++ )
  295. {
  296. if( accounts->hat( i ) && accounts->get( i ) == accountId )
  297. {
  298. teamAuswahlFertig->set( 1, i );
  299. return 1;
  300. }
  301. }
  302. return 0;
  303. }
  304. bool Spiel::klientBereitZumLaden( int accountId )
  305. {
  306. if( state != 2 )
  307. return 0;
  308. for( int i = 0; i < spielerAnzahl; i++ )
  309. {
  310. if( accounts->hat( i ) && accounts->get( i ) == accountId )
  311. {
  312. status->set( 2, i );
  313. return 1;
  314. }
  315. }
  316. return 0;
  317. }
  318. bool Spiel::klientSpielLadenProzent( int accountId, int prozent )
  319. {
  320. if( state != 3 && state != 2 )
  321. return 0;
  322. for( int i = 0; i < spielerAnzahl; i++ )
  323. {
  324. if( accounts->hat( i ) && accounts->get( i ) == accountId )
  325. {
  326. this->prozent->set( prozent, i );
  327. return 1;
  328. }
  329. }
  330. return 0;
  331. }
  332. bool Spiel::klientBereitZumSpiel( int accountId )
  333. {
  334. if( state != 4 )
  335. return 0;
  336. for( int i = 0; i < spielerAnzahl; i++ )
  337. {
  338. if( accounts->hat( i ) && accounts->get( i ) == accountId )
  339. {
  340. status->set( 3, i );
  341. return 1;
  342. }
  343. }
  344. return 0;
  345. }
  346. bool Spiel::spielNachricht( int accountId, int len, char *bytes )
  347. {
  348. if( state != 5 )
  349. return 0;
  350. if( spiel )
  351. {
  352. spiel->nachricht( accountId, len, bytes );
  353. return 1;
  354. }
  355. return 0;
  356. }
  357. bool Spiel::statistikNachricht( int accountId, int len, char *bytes )
  358. {
  359. if( state != 6 )
  360. return 0;
  361. if( statistik )
  362. {
  363. statistik->statistikAnfrage( accountId, (short)len, bytes );
  364. return 1;
  365. }
  366. return 0;
  367. }
  368. void Spiel::thread()
  369. {
  370. // Klients aktualisieren
  371. for( int i = 0; i < spielerAnzahl; i++ )
  372. {
  373. SSKlient *tmp = klients->z( i );
  374. if( tmp )
  375. {
  376. tmp->setSpielErstellt( 0 );
  377. tmp->setSpiel( this );
  378. }
  379. }
  380. // Vortsetzung senden
  381. for( int i = 0; i < spielerAnzahl; i++ )
  382. {
  383. SSKlient *tmp = klients->z( i );
  384. if( tmp )
  385. tmp->erstellungInitialisierung( sts );
  386. }
  387. for( int i = 0; i < spielerAnzahl; i++ )
  388. {
  389. SSKlient *tmp = klients->z( i );
  390. if( tmp )
  391. tmp->erstellungFortsetzen();
  392. }
  393. for( int i = 0; i < spielerAnzahl; i++ )
  394. {
  395. SSKlient *tmp = klients->z( i );
  396. if( tmp )
  397. {
  398. for( int j = 0; j < spielerAnzahl; j++ )
  399. {
  400. if( accounts->hat( j ) )
  401. tmp->erstellungAddSpieler( accounts->get( j ) );
  402. }
  403. }
  404. }
  405. // warten bis alle ein Team gewählt haben
  406. double time = 0;
  407. state = 1;
  408. ZeitMesser *zeit = new ZeitMesser();
  409. while( time < 40 )
  410. {
  411. zeit->messungStart();
  412. Sleep( 100 );
  413. char verbleibend = (char)( 40 - (char)time );
  414. bool weiter = 1;
  415. for( int i = 0; i < spielerAnzahl; i++ )
  416. weiter &= teamAuswahlFertig->hat( i ) && teamAuswahlFertig->get( i );
  417. if( verbleibend < 0 || weiter )
  418. {
  419. verbleibend = 0;
  420. time = 40;
  421. }
  422. for( int i = 0; i < spielerAnzahl; i++ )
  423. {
  424. SSKlient *tmp = klients->z( i );
  425. if( tmp )
  426. tmp->zeitVerbleibend( verbleibend );
  427. }
  428. zeit->messungEnde();
  429. time += zeit->getSekunden();
  430. } // Spielernummern Aufteilen
  431. zeit->release();
  432. state = 2;
  433. teamAusgleich();
  434. Array< int > *teams = new Array< int >();
  435. for( int i = 0; i < spielerAnzahl; i++ )
  436. {
  437. int sNum = spielerNummern->hat( i ) ? spielerNummern->get( i ) : 0;
  438. int tg = 1;
  439. for( int j = 0; j < sts->teamAnzahl; j++ )
  440. {
  441. tg += sts->teamSize->hat( j ) ? sts->teamSize->get( j ) : 0;
  442. if( sNum < tg )
  443. {
  444. teams->set( j, i );
  445. break;
  446. }
  447. }
  448. }
  449. ss->zDB()->spielSetTeams( id, spielerAnzahl, accounts, teams );
  450. ss->zDB()->spielSetSpielerNummern( id, spielerAnzahl, accounts, spielerNummern );
  451. teams->release();
  452. // Fortsetzung senden
  453. for( int i = 0; i < spielerAnzahl; i++ )
  454. {
  455. SSKlient *tmp = klients->z( i );
  456. if( tmp )
  457. tmp->spielLadenBeginn();
  458. }
  459. // Auf bereitschaft warten
  460. while( 1 )
  461. {
  462. Sleep( 100 );
  463. bool br = 1;
  464. for( int i = 0; i < spielerAnzahl; i++ )
  465. {
  466. if( klients->z( i ) )
  467. br = br && status->hat( i ) && status->get( i ) == 2;
  468. }
  469. if( br )
  470. break;
  471. } // Spieler hinzufügen
  472. for( int i = 0; i < spielerAnzahl; i++ )
  473. spielerNummern->set( ( spielerNummern->hat( i ) ? spielerNummern->get( i ) : 0 ) - 1, i );
  474. for( int i = 0; i < spielerAnzahl; i++ )
  475. {
  476. SSKlient *tmp = klients->z( i );
  477. if( tmp )
  478. {
  479. for( int j = 0; j < spielerAnzahl; j++ )
  480. tmp->spielLadenSpielerAdd( accounts->hat( j ) ? accounts->get( j ) : 0, spielerNummern->hat( j ) ? spielerNummern->get( j ) : 0 );
  481. }
  482. }
  483. state = 3;
  484. // Warten auf laden
  485. while( 1 )
  486. {
  487. Sleep( 1000 );
  488. bool br = 1;
  489. for( int i = 0; i < spielerAnzahl; i++ )
  490. {
  491. SSKlient *tmp = klients->z( i );
  492. if( tmp )
  493. {
  494. int ping = (int)( tmp->ping() * 1000 + 0.5 );
  495. for( int j = 0; j < spielerAnzahl; j++ )
  496. {
  497. SSKlient *k = klients->z( j );
  498. if( k )
  499. {
  500. k->spielLadenSetSpielerPing( accounts->hat( i ) ? accounts->get( i ) : 0, ping );
  501. k->spielLadenSetSpielerProzent( accounts->hat( i ) ? accounts->get( i ) : 0, prozent->hat( i ) ? prozent->get( i ) : 0 );
  502. }
  503. }
  504. br = br && prozent->hat( i ) && prozent->get( i ) == 100;
  505. }
  506. }
  507. if( br )
  508. break;
  509. }
  510. state = 4;
  511. // Sende Fortsetzung
  512. for( int i = 0; i < spielerAnzahl; i++ )
  513. {
  514. SSKlient *tmp = klients->z( i );
  515. if( tmp )
  516. tmp->spielLadenFertig();
  517. }
  518. // Spiel Initialisieren
  519. Text *pfad = new Text( ss->zInit()->zWert( "SpielePfad" )->getText() );
  520. pfad->append( "/" );
  521. pfad->append( ss->zDB()->getSpielArtId( karte ) );
  522. pfad->append( "/bin/game" );
  523. #ifdef WIN32
  524. pfad->append( ".dll" );
  525. #else
  526. pfad->append( ".so" );
  527. #endif
  528. spielDll = LoadLibrary( pfad->getText() );
  529. if( !spielDll )
  530. {
  531. // error
  532. }
  533. pfad->release();
  534. DllStart getSpielKlasse = (DllStart)GetProcAddress( spielDll, "getSpielKlasse" );
  535. if( !getSpielKlasse )
  536. {
  537. // error
  538. }
  539. spiel = getSpielKlasse();
  540. spiel->setPSQLK( ss->zDB()->getThis() );
  541. spiel->setSpielId( id );
  542. spiel->setKarteId( karte );
  543. Text tmp = ss->zInit()->zWert( "TempMapPfad" )->getText();
  544. tmp += "/";
  545. tmp += id;
  546. spiel->setTempPfad( tmp );
  547. spiel->setAccounts( spielerAnzahl, accounts );
  548. spiel->setKlients( spielerAnzahl, ( RCArray< SSKlientV >* )klients );
  549. spiel->setSpielerNummern( spielerAnzahl, spielerNummern );
  550. // auf klients warten
  551. while( 1 )
  552. {
  553. Sleep( 100 );
  554. bool br = 1;
  555. for( int i = 0; i < spielerAnzahl; i++ )
  556. {
  557. if( klients->z( i ) )
  558. br = br && status->hat( i ) && status->get( i ) == 3;
  559. }
  560. if( br )
  561. break;
  562. }
  563. // Spiel starten
  564. state = 5;
  565. ss->zDB()->setSpielStatusIsRunning( id );
  566. spiel->run();
  567. // Spiel ist zuende
  568. state = 6;
  569. statistik = spiel->getStatistik();
  570. spiel = spiel->release();
  571. statistik->run();
  572. // Statistik ist zuende
  573. state = 7;
  574. statistik = statistik->release();
  575. FreeLibrary( spielDll );
  576. spielDll = 0;
  577. DateiRemove( tmp );
  578. ss->removeSpiel( id ); // delete this
  579. }
  580. // constant
  581. int Spiel::getId() const
  582. {
  583. return id;
  584. }
  585. int Spiel::getSpielerNummer( int accountId ) const
  586. {
  587. for( int i = 0; i < spielerAnzahl; i++ )
  588. {
  589. if( accounts->hat( i ) && accounts->get( i ) == accountId )
  590. return spielerNummern->hat( i ) ? spielerNummern->get( i ) : 0;
  591. }
  592. return 0;
  593. }
  594. // Reference Counting
  595. Spiel *Spiel::getThis()
  596. {
  597. ref++;
  598. return this;
  599. }
  600. Spiel *Spiel::release()
  601. {
  602. ref--;
  603. if( !ref )
  604. delete this;
  605. return 0;
  606. }