SpielClient.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. #include "SpielClient.h"
  2. #include <Klient.h>
  3. #include "Keys.h"
  4. using namespace KSGClient;
  5. // Inhalt der SpielClient Klasse
  6. // Konstruktor
  7. SpielClient::SpielClient( int klientId, unsigned short port, char *ip, char *key, unsigned char keyLen )
  8. {
  9. ref = 1;
  10. this->ip = ip;
  11. this->port = port;
  12. cId = klientId;
  13. senden = 0;
  14. empfangen = 0;
  15. this->key = new char[ keyLen ];
  16. memcpy( this->key, key, keyLen );
  17. this->keyLen = keyLen;
  18. }
  19. // Destruktor
  20. SpielClient::~SpielClient()
  21. {
  22. trenne();
  23. delete[] key;
  24. }
  25. // verbindet sich mit dem zugewiesenen Karten Server
  26. // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
  27. bool SpielClient::verbinde()
  28. {
  29. cs.lock();
  30. if( senden )
  31. {
  32. cs.unlock();
  33. return 1;
  34. }
  35. if( !senden )
  36. senden = new Network::Klient();
  37. int keyLen = 0;
  38. char *key = 0;
  39. Keys::getServerKey( &key, keyLen, Keys::SPIEL, Keys::SENDEN );
  40. senden->setSendeKey( key, keyLen );
  41. delete[] key;
  42. Keys::getServerKey( &key, keyLen, Keys::SPIEL, Keys::EMPFANGEN );
  43. senden->setEmpfangKey( key, keyLen );
  44. delete[] key;
  45. if( senden->verbinde( port, ip ) )
  46. {
  47. if( senden->sendeEncrypted( "\1", 1 ) )
  48. {
  49. char serverReturn = 0;
  50. senden->sendeEncrypted( (char*)&cId, 4 );
  51. char ret = 0;
  52. senden->getNachrichtEncrypted( &ret, 1 );
  53. if( ret != 1 )
  54. {
  55. if( ret == 3 )
  56. {
  57. char byte = 0;
  58. senden->getNachrichtEncrypted( &byte, 1 );
  59. char *f = new char[ byte + 1 ];
  60. f[ byte ] = 0;
  61. senden->getNachrichtEncrypted( f, byte );
  62. err = f;
  63. delete[]f;
  64. }
  65. senden->sendeEncrypted( "\3", 1 );
  66. senden->getNachrichtEncrypted( &serverReturn, 1 );
  67. senden->trenne();
  68. senden = senden->release();
  69. err = "Server akzeptiert den Klient nicht.";
  70. cs.unlock();
  71. return 0;
  72. }
  73. senden->setSendeKey( this->key, this->keyLen );
  74. senden->setEmpfangKey( this->key, this->keyLen );
  75. if( !empfangen )
  76. empfangen = new Network::Klient();
  77. int keyLen = 0;
  78. char *key = 0;
  79. Keys::getServerKey( &key, keyLen, Keys::SPIEL, Keys::SENDEN );
  80. empfangen->setSendeKey( key, keyLen );
  81. delete[] key;
  82. Keys::getServerKey( &key, keyLen, Keys::SPIEL, Keys::EMPFANGEN );
  83. empfangen->setEmpfangKey( key, keyLen );
  84. delete[] key;
  85. if( empfangen->verbinde( senden->getServerPort(), senden->getServerIp() ) )
  86. {
  87. empfangen->sendeEncrypted( "\1", 1 );
  88. empfangen->sendeEncrypted( (char*)&cId, 4 );
  89. char res = 0;
  90. empfangen->getNachrichtEncrypted( &res, 1 );
  91. if( res == 3 )
  92. {
  93. char län = 0;
  94. empfangen->getNachrichtEncrypted( &län, 1 );
  95. char *nachricht = new char[ län + 1 ];
  96. nachricht[ län ] = 0;
  97. empfangen->getNachrichtEncrypted( nachricht, län );
  98. err = nachricht;
  99. delete[] nachricht;
  100. }
  101. if( res == 1 )
  102. {
  103. empfangen->setSendeKey( this->key, this->keyLen );
  104. empfangen->setEmpfangKey( this->key, this->keyLen );
  105. }
  106. else if( res != 0 )
  107. {
  108. err = "Fehler beim Verbinden mit dem Spiel Server.";
  109. senden->sendeEncrypted( "\3", 1 );
  110. char serverReturn = 0;
  111. senden->getNachrichtEncrypted( &serverReturn, 1 );
  112. senden->trenne();
  113. senden = senden->release();
  114. empfangen->trenne();
  115. empfangen = empfangen->release();
  116. return 0;
  117. }
  118. cs.unlock();
  119. return 1;
  120. }
  121. else
  122. {
  123. empfangen = empfangen->release();
  124. senden->sendeEncrypted( "\3", 1 );
  125. char serverReturn = 0;
  126. senden->getNachrichtEncrypted( &serverReturn, 1 );
  127. senden->trenne();
  128. senden = senden->release();
  129. err = "Der dir zugewiesene Spiel Server kann dir keine Nachrichten senden.";
  130. cs.unlock();
  131. return 0;
  132. }
  133. }
  134. else
  135. {
  136. senden->trenne();
  137. senden = senden->release();
  138. err = "Der dir zugewiesene Spiel Server hat die Verbindung abgebrochen. Bitte versuche es Später erneut.";
  139. cs.unlock();
  140. return 0;
  141. }
  142. }
  143. else
  144. {
  145. err = "Der dir zugewiesene Spiel Server antwortet nicht. Bitte versuche es Später erneut.";
  146. senden = senden->release();
  147. cs.unlock();
  148. return 0;
  149. }
  150. err = "Unbekannter Fehler";
  151. cs.unlock();
  152. return 0;
  153. }
  154. // Betritt das Vorgeschlagene Spiel
  155. // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
  156. bool SpielClient::spielErstelltAnnehmen()
  157. {
  158. cs.lock();
  159. if( !senden )
  160. {
  161. err = "Der Client ist nicht verbunden.";
  162. cs.unlock();
  163. return 0;
  164. }
  165. char ret = 0;
  166. senden->sendeEncrypted( "\4", 1 );
  167. senden->getNachrichtEncrypted( &ret, 1 );
  168. if( ret != 1 )
  169. err = "Fehler beim annehmen des Spiels.";
  170. cs.unlock();
  171. return ret == 1;
  172. }
  173. // Lehnt das Vorgeschlagene Spiel ab
  174. // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
  175. bool SpielClient::spielErstelltAblehnen()
  176. {
  177. cs.lock();
  178. if( !senden )
  179. {
  180. err = "Der Client ist nicht verbunden.";
  181. cs.unlock();
  182. return 0;
  183. }
  184. char ret = 0;
  185. senden->sendeEncrypted( "\5", 1 );
  186. senden->getNachrichtEncrypted( &ret, 1 );
  187. if( ret != 1 )
  188. err = "Fehler beim ablehnen des Spiels.";
  189. cs.unlock();
  190. return ret == 1;
  191. }
  192. // Wechselt zu einem bestimmten Team
  193. // team: Die Id des teams
  194. // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
  195. bool SpielClient::spielErstelltTeamWechseln( int team )
  196. {
  197. cs.lock();
  198. if( !senden )
  199. {
  200. err = "Der Client ist nicht verbunden.";
  201. cs.unlock();
  202. return 0;
  203. }
  204. char ret = 0;
  205. senden->sendeEncrypted( "\6", 1 );
  206. senden->getNachrichtEncrypted( &ret, 1 );
  207. if( !ret )
  208. {
  209. err = "Fehler beim wechseln des Teams.";
  210. cs.unlock();
  211. return 0;
  212. }
  213. senden->sendeEncrypted( (char*)&team, 4 );
  214. senden->getNachrichtEncrypted( &ret, 1 );
  215. if( ret != 1 )
  216. err = "Fehler beim wechseln des Teams.";
  217. cs.unlock();
  218. return ret == 1;
  219. }
  220. // Bestätigt die Teamauswahl so dass das Spiel früher beginnen kann
  221. // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
  222. bool SpielClient::spielErstelltTeamFertig()
  223. {
  224. cs.lock();
  225. if( !senden )
  226. {
  227. err = "Der Client ist nicht verbunden.";
  228. cs.unlock();
  229. return 0;
  230. }
  231. char ret = 0;
  232. senden->sendeEncrypted( "\xE", 1 );
  233. senden->getNachrichtEncrypted( &ret, 1 );
  234. if( ret != 1 )
  235. err = "Fehler beim setzen der Bereitschaft.";
  236. cs.unlock();
  237. return ret == 1;
  238. }
  239. // sendet eine Chat Nachricht an die mitglieder des erstellten Spiels
  240. // nachricht: Die Nachricht
  241. // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
  242. bool SpielClient::spielErstelltChatNachricht( char *nachricht )
  243. {
  244. char län = textLength( nachricht );
  245. if( !län )
  246. return 1;
  247. cs.lock();
  248. if( !senden )
  249. {
  250. err = "Der Client ist nicht verbunden.";
  251. cs.unlock();
  252. return 0;
  253. }
  254. char ret = 0;
  255. senden->sendeEncrypted( "\7", 1 );
  256. senden->getNachrichtEncrypted( &ret, 1 );
  257. if( !ret )
  258. {
  259. err = "Fehler beim senden der Chat Nachricht.";
  260. cs.unlock();
  261. return 0;
  262. }
  263. senden->sendeEncrypted( &län, 1 );
  264. senden->sendeEncrypted( nachricht, län );
  265. senden->getNachrichtEncrypted( &ret, 1 );
  266. if( ret != 1 )
  267. err = "Fehler beim senden der Chat Nachricht.";
  268. cs.unlock();
  269. return ret == 1;
  270. }
  271. // Teilt dem Server mit, dass der Client bereit ist das Spiel zu laden
  272. // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
  273. bool SpielClient::bereitZumLaden()
  274. {
  275. cs.lock();
  276. if( !senden )
  277. {
  278. err = "Der Client ist nicht verbunden.";
  279. cs.unlock();
  280. return 0;
  281. }
  282. char ret = 0;
  283. senden->sendeEncrypted( "\x9", 1 );
  284. senden->getNachrichtEncrypted( &ret, 1 );
  285. if( ret != 1 )
  286. err = "Fehler beim setzen der Bereitschaft.";
  287. cs.unlock();
  288. return ret == 1;
  289. }
  290. // Teilt dem Server mit, zu wie viel Prozent der Client das Spiel geladen hat
  291. // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
  292. bool SpielClient::setLadenProzent( int prozent )
  293. {
  294. cs.lock();
  295. if( !senden )
  296. {
  297. err = "Der Client ist nicht verbunden.";
  298. cs.unlock();
  299. return 0;
  300. }
  301. char ret = 0;
  302. senden->sendeEncrypted( "\xC", 1 );
  303. senden->getNachrichtEncrypted( &ret, 1 );
  304. if( ret )
  305. {
  306. senden->sendeEncrypted( (char*)&prozent, 4 );
  307. senden->getNachrichtEncrypted( &ret, 1 );
  308. }
  309. if( ret != 1 )
  310. err = "Fehler beim setzen des Fortschritts.";
  311. cs.unlock();
  312. return ret == 1;
  313. }
  314. // Teilt dem Server mit, dass das Spiel fertig geladen wurde
  315. // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
  316. bool SpielClient::bereitZumSpiel()
  317. {
  318. cs.lock();
  319. if( !senden )
  320. {
  321. err = "Der Client ist nicht verbunden.";
  322. cs.unlock();
  323. return 0;
  324. }
  325. char ret = 0;
  326. senden->sendeEncrypted( "\xA", 1 );
  327. senden->getNachrichtEncrypted( &ret, 1 );
  328. if( ret != 1 )
  329. err = "Fehler beim setzen der Bereitschaft.";
  330. cs.unlock();
  331. return ret == 1;
  332. }
  333. // Sendet während des Spiels eine Nachricht an den Server
  334. // län: Die Länge der Nachricht
  335. // bytes: Ein Zeiger auf die Nachricht
  336. // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
  337. bool SpielClient::spielNachricht( short län, char *bytes )
  338. {
  339. cs.lock();
  340. if( !senden )
  341. {
  342. err = "Der Client ist nicht verbunden.";
  343. cs.unlock();
  344. return 0;
  345. }
  346. senden->sendeEncrypted( "\xB", 1 );
  347. senden->sende( (char*)&län, 2 );
  348. senden->sende( bytes, län );
  349. cs.unlock();
  350. return 1;
  351. }
  352. // Sendet während der Statistik eine Nachricht an den Server
  353. // län: Die Länge der Nachricht
  354. // bytes: Ein Zeiger auf die Nachricht
  355. // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
  356. bool SpielClient::statistikNachricht( short län, char *bytes )
  357. {
  358. cs.lock();
  359. if( !senden )
  360. {
  361. err = "Der Client ist nicht verbunden.";
  362. cs.unlock();
  363. return 0;
  364. }
  365. char ret = 0;
  366. senden->sendeEncrypted( "\xD", 1 );
  367. senden->getNachrichtEncrypted( &ret, 1 );
  368. if( ret )
  369. {
  370. senden->sendeEncrypted( (char*)&län, 2 );
  371. senden->sendeEncrypted( bytes, län );
  372. senden->getNachrichtEncrypted( &ret, 1 );
  373. }
  374. if( ret != 1 )
  375. err = "Fehler beim setzen der Statistik Nachricht.";
  376. cs.unlock();
  377. return ret == 1;
  378. }
  379. // Wartet auf eine Nachricht vom Spiel Server.
  380. // Gibt bei Erfolg 1 zurück, 0 sonnst
  381. // nachricht: Eine Referenz auf die Struktur, in der die Nachricht gespeichert werden soll
  382. bool SpielClient::getNextMessage( SpielServerNachricht &nachricht )
  383. {
  384. do
  385. {
  386. if( !empfangen->getNachrichtEncrypted( &nachricht.type, 1 ) )
  387. {
  388. return 0;
  389. }
  390. switch( nachricht.type )
  391. {
  392. case 0: // verbindung getrennt
  393. trenne();
  394. break;
  395. case 1: // verbleibende Zeit
  396. empfangen->getNachrichtEncrypted( &nachricht.sekunden, 1 );
  397. break;
  398. case 2: // SpielErstellt abbruch
  399. if( 1 )
  400. {
  401. char län = 0;
  402. empfangen->getNachrichtEncrypted( &län, 1 );
  403. char *grund = new char[ län + 1 ];
  404. grund[ län ] = 0;
  405. empfangen->getNachrichtEncrypted( grund, län );
  406. nachricht.message = grund;
  407. delete[] grund;
  408. }
  409. break;
  410. case 3: // Fehler
  411. if( 1 )
  412. {
  413. char länge = 0;
  414. empfangen->getNachrichtEncrypted( &länge, 1 );
  415. char *txt = new char[ länge + 1 ];
  416. txt[ länge ] = 0;
  417. empfangen->getNachrichtEncrypted( txt, länge );
  418. nachricht.message = txt;
  419. delete[]txt;
  420. }
  421. break;
  422. case 4: // zurück in Warteschlange
  423. empfangen->getNachrichtEncrypted( &nachricht.stunden, 1 );
  424. empfangen->getNachrichtEncrypted( &nachricht.minuten, 1 );
  425. empfangen->getNachrichtEncrypted( &nachricht.sekunden, 1 );
  426. break;
  427. case 6: // SpielErstellt Initialisierung
  428. empfangen->getNachrichtEncrypted( (char*)&nachricht.sts->spielerAnzahl, 4 );
  429. empfangen->getNachrichtEncrypted( (char*)&nachricht.sts->teamAnzahl, 4 );
  430. for( int i = 0; i < nachricht.sts->spielerAnzahl; i++ )
  431. {
  432. int farbe = 0;
  433. empfangen->getNachrichtEncrypted( (char*)&farbe, 4 );
  434. nachricht.sts->spielerFarbe->set( farbe, i );
  435. }
  436. for( int i = 0; i < nachricht.sts->teamAnzahl; i++ )
  437. {
  438. int farbe = 0;
  439. empfangen->getNachrichtEncrypted( (char*)&farbe, 4 );
  440. nachricht.sts->teamFarbe->set( farbe, i );
  441. }
  442. for( int i = 0; i < nachricht.sts->teamAnzahl; i++ )
  443. {
  444. char län = 0;
  445. empfangen->getNachrichtEncrypted( &län, 1 );
  446. char *name = new char[ län + 1 ];
  447. name[ län ] = 0;
  448. if( län )
  449. empfangen->getNachrichtEncrypted( name, län );
  450. Text *tmp = new Text( name );
  451. delete[] name;
  452. nachricht.sts->teamName->set( tmp, i );
  453. }
  454. for( int i = 0; i < nachricht.sts->teamAnzahl; i++ )
  455. {
  456. int größe = 0;
  457. empfangen->getNachrichtEncrypted( (char*)&größe, 4 );
  458. nachricht.sts->teamGröße->set( größe, i );
  459. }
  460. break;
  461. case 7: // SpielErstellt Spieler hinzugefügt
  462. empfangen->getNachrichtEncrypted( (char*)&nachricht.accountId, 4 );
  463. break;
  464. case 8: // SpielErstellt Spieler entfernt
  465. empfangen->getNachrichtEncrypted( (char*)&nachricht.accountId, 4 );
  466. break;
  467. case 9: // SpielErstellt Spieler wechselt Team
  468. empfangen->getNachrichtEncrypted( (char*)&nachricht.accountId, 4 );
  469. empfangen->getNachrichtEncrypted( (char*)&nachricht.spielerNummer, 4 );
  470. break;
  471. case 0xA: // SpielErstellt Chat Nachricht
  472. if( 1 )
  473. {
  474. char län = 0;
  475. empfangen->getNachrichtEncrypted( &län, 1 );
  476. char *txt = new char[ län + 1 ];
  477. txt[ län ] = 0;
  478. if( län )
  479. empfangen->getNachrichtEncrypted( txt, län );
  480. nachricht.message = txt;
  481. delete[] txt;
  482. }
  483. break;
  484. case 0xB: // Spiel gefunden
  485. empfangen->getNachrichtEncrypted( (char*)&nachricht.karteId, 4 );
  486. break;
  487. case 0xD: // Spiel Laden Spieler hinzufügen
  488. empfangen->getNachrichtEncrypted( (char*)&nachricht.accountId, 4 );
  489. empfangen->getNachrichtEncrypted( (char*)&nachricht.spielerNummer, 4 );
  490. break;
  491. case 0xE: // Spiel Laden Spieler Prozent
  492. empfangen->getNachrichtEncrypted( (char*)&nachricht.accountId, 4 );
  493. empfangen->getNachrichtEncrypted( (char*)&nachricht.prozent, 4 );
  494. break;
  495. case 0xF: // Spiel Laden Spieler Ping
  496. empfangen->getNachrichtEncrypted( (char*)&nachricht.accountId, 4 );
  497. empfangen->getNachrichtEncrypted( (char*)&nachricht.ping, 4 );
  498. break;
  499. case 0x10: // ping
  500. empfangen->sendeEncrypted( "\1", 1 );
  501. break;
  502. case 0x12: // Spiel Nachricht
  503. empfangen->getNachricht( (char*)&nachricht.län, 2 );
  504. nachricht.data = new char[ nachricht.län ];
  505. empfangen->getNachricht( nachricht.data, nachricht.län );
  506. break;
  507. case 0x13: // Statistik Nachricht
  508. empfangen->getNachrichtEncrypted( (char*)&nachricht.län, 2 );
  509. nachricht.data = new char[ nachricht.län ];
  510. empfangen->getNachrichtEncrypted( nachricht.data, nachricht.län );
  511. break;
  512. case 0x14: // ping
  513. empfangen->sendeEncrypted( "\1", 1 );
  514. break;
  515. }
  516. } while( nachricht.type == 0x10 || nachricht.type == 0x14 );
  517. }
  518. // Erhält die Verbindung aufrecht
  519. // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
  520. // Sollte während einer bestehenden Verbindung etwa einmal alle 60 Sekunden aufgerufen werden, da sonst der Router die Verbindung automatisch trennt
  521. bool SpielClient::keepAlive()
  522. {
  523. if( !senden )
  524. return 0;
  525. char res = 0;
  526. if( !cs.tryLock() )
  527. return 1;
  528. bool ok = senden->sendeEncrypted( "\xF", 1 );
  529. ok &= senden->getNachrichtEncrypted( &res, 1 );
  530. cs.unlock();
  531. if( res != 1 || !ok )
  532. {
  533. err = "Die Verbindung zum Spiel Server ist abgebrochen.";
  534. trenne();
  535. return 0;
  536. }
  537. return res == 1;
  538. }
  539. // Trennt die Verbindung zum Server
  540. // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
  541. // Sollte erst nach einem erfolgreichen Aufruf von verbinde aufgerufen werden
  542. bool SpielClient::trenne()
  543. {
  544. cs.lock();
  545. if( !senden )
  546. {
  547. cs.unlock();
  548. return 1;
  549. }
  550. senden->sendeEncrypted( "\3", 1 );
  551. char serverReturn = 0;
  552. senden->getNachrichtEncrypted( &serverReturn, 1 );
  553. senden->trenne();
  554. senden = senden->release();
  555. empfangen->trenne();
  556. empfangen = empfangen->release();
  557. cs.unlock();
  558. return 1;
  559. }
  560. // Gibt 1 zurück, falls der Client verbunden ist, 0 sonst
  561. bool SpielClient::istVerbunden() const
  562. {
  563. return senden != 0;
  564. }
  565. // gibt den Letzten Fehlertext zuück
  566. // sollte erst aufgerufen werden, nachdem eine andere aufgerufene Methode fehlgeschlagen ist
  567. char *SpielClient::getLetzterFehler() const
  568. {
  569. return err;
  570. }
  571. // Erhöht den Reference Counter um 1 un gibt this zurück
  572. SpielServerClient *SpielClient::getThis()
  573. {
  574. ref++;
  575. return this;
  576. }
  577. // Verringert den Reference Counter um 1 und gibt 0 zurück.
  578. // Falls der Reference Counter nach dem Aufruf auf 0 ist löscht sich das Objekt selbst
  579. SpielServerClient *SpielClient::release()
  580. {
  581. if( !--ref )
  582. delete this;
  583. return 0;
  584. }