SpielK.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. #include "../KSGKlient.h"
  2. #include "../KSGServer.h"
  3. #include "../../Global/Variablen.h"
  4. #include "../Keys.h"
  5. // Inhalt der SpielKlient Klasse aus KSGKlient.h
  6. // Konstruktor
  7. SpielKlient::SpielKlient()
  8. : Thread()
  9. {
  10. verbunden = 0;
  11. senden = 0;
  12. empfangen = 0;
  13. fehler = new Text( "" );
  14. klientId = getKlientId();
  15. ref = 1;
  16. }
  17. // Destruktor
  18. SpielKlient::~SpielKlient()
  19. {
  20. cs.lock();
  21. if( senden )
  22. {
  23. char serverReturn = 0;
  24. if( verbunden )
  25. {
  26. senden->sendeEncrypted( "\3", 1 );
  27. senden->getNachrichtEncrypted( &serverReturn, 1 );
  28. senden->trenne();
  29. }
  30. senden = senden->release();
  31. verbunden = 0;
  32. if( empfangen )
  33. {
  34. warteAufThread( 5000 );
  35. ende();
  36. empfangen->trenne();
  37. empfangen = empfangen->release();
  38. }
  39. }
  40. fehler = fehler->release();
  41. cs.unlock();
  42. }
  43. // nicht constant
  44. bool SpielKlient::verbinde( unsigned short port, char *ip ) // verbindet ich mit dem Spiel Server
  45. {
  46. cs.lock();
  47. if( verbunden )
  48. {
  49. cs.unlock();
  50. return 1;
  51. }
  52. if( !senden )
  53. senden = new Klient();
  54. int keyLen = 0;
  55. char *key = 0;
  56. Keys::getServerKey( &key, keyLen, Keys::SPIEL, Keys::SENDEN );
  57. senden->setSendeKey( key, keyLen );
  58. delete[] key;
  59. Keys::getServerKey( &key, keyLen, Keys::SPIEL, Keys::EMPFANGEN );
  60. senden->setEmpfangKey( key, keyLen );
  61. delete[] key;
  62. if( senden->verbinde( port, ip ) )
  63. {
  64. if( senden->sendeEncrypted( "\1", 1 ) )
  65. {
  66. char serverReturn = 0;
  67. senden->sendeEncrypted( (char*)&klientId, 4 );
  68. char ret = 0;
  69. senden->getNachrichtEncrypted( &ret, 1 );
  70. if( ret != 1 )
  71. {
  72. if( ret == 3 )
  73. {
  74. char byte = 0;
  75. senden->getNachrichtEncrypted( &byte, 1 );
  76. char *f = new char[ byte + 1 ];
  77. f[ byte ] = 0;
  78. senden->getNachrichtEncrypted( f, byte );
  79. fehler->setText( f );
  80. delete[]f;
  81. }
  82. senden->sendeEncrypted( "\3", 1 );
  83. senden->getNachrichtEncrypted( &serverReturn, 1 );
  84. senden->trenne();
  85. WMessageBox( 0, new Text( "Fehler" ), new Text( "Server akzeptiert den Klient nicht" ), MB_ICONERROR );
  86. cs.unlock();
  87. return 0;
  88. }
  89. char *sl = 0;
  90. char slLän = getSchlüssel( &sl );
  91. senden->setSendeKey( sl, slLän );
  92. senden->setEmpfangKey( sl, slLän );
  93. delete[] sl;
  94. if( !empfangen )
  95. empfangen = new Klient();
  96. int keyLen = 0;
  97. char *key = 0;
  98. Keys::getServerKey( &key, keyLen, Keys::SPIEL, Keys::SENDEN );
  99. empfangen->setSendeKey( key, keyLen );
  100. delete[] key;
  101. Keys::getServerKey( &key, keyLen, Keys::SPIEL, Keys::EMPFANGEN );
  102. empfangen->setEmpfangKey( key, keyLen );
  103. delete[] key;
  104. if( empfangen->verbinde( senden->getServerPort(), senden->getServerIp() ) )
  105. {
  106. start();
  107. verbunden = 1;
  108. cs.unlock();
  109. return 1;
  110. }
  111. else
  112. {
  113. fehler->setText( "Der dir zugewiesene Spiel Server kann dir keine Nachrichten senden." );
  114. cs.unlock();
  115. return 1;
  116. }
  117. }
  118. else
  119. {
  120. fehler->setText( "Der dir zugewiesene Spiel Server hat die Verbindung abgebrochen. Bitte versuche es Später erneut." );
  121. senden = senden->release();
  122. }
  123. }
  124. else
  125. {
  126. fehler->setText( "Der dir zugewiesene Spiel Server antwortet nicht. Bitte versuche es Später erneut." );
  127. senden = senden->release();
  128. }
  129. cs.unlock();
  130. return 0;
  131. }
  132. bool SpielKlient::spielErstelltAnnehmen() // klient ist bereit dem erstellten Spiel beizutreten
  133. {
  134. if( !senden )
  135. return 0;
  136. char ret = 0;
  137. cs.lock();
  138. senden->sendeEncrypted( "\4", 1 );
  139. senden->getNachrichtEncrypted( &ret, 1 );
  140. cs.unlock();
  141. return ret == 1;
  142. }
  143. bool SpielKlient::spielErstelltAblehnen() // klient ist nicht bereit dem erstellten Spiel beizutreten
  144. {
  145. if( !senden )
  146. return 0;
  147. char ret = 0;
  148. cs.lock();
  149. senden->sendeEncrypted( "\5", 1 );
  150. senden->getNachrichtEncrypted( &ret, 1 );
  151. cs.unlock();
  152. return ret == 1;
  153. }
  154. bool SpielKlient::spielErstelltTeamWechseln( int team ) // wechselt das Team
  155. {
  156. if( !senden )
  157. return 0;
  158. char ret = 0;
  159. cs.lock();
  160. senden->sendeEncrypted( "\6", 1 );
  161. senden->getNachrichtEncrypted( &ret, 1 );
  162. if( !ret )
  163. {
  164. cs.unlock();
  165. return 0;
  166. }
  167. senden->sendeEncrypted( (char*)&team, 4 );
  168. senden->getNachrichtEncrypted( &ret, 1 );
  169. cs.unlock();
  170. return ret == 1;
  171. }
  172. bool SpielKlient::spielErstelltTeamFertig() // bestetigt die Team Auswahl
  173. {
  174. if( !senden )
  175. return 0;
  176. char ret = 0;
  177. cs.lock();
  178. senden->sendeEncrypted( "\xE", 1 );
  179. senden->getNachrichtEncrypted( &ret, 1 );
  180. cs.unlock();
  181. return ret == 1;
  182. }
  183. bool SpielKlient::spielErstelltChatNachricht( char *nachricht ) // sendet eine Chat Nachricht an die mitglieder des erstellten Spiels
  184. {
  185. char län = textLength( nachricht );
  186. if( !län )
  187. return 1;
  188. if( !senden )
  189. return 0;
  190. char ret = 0;
  191. cs.lock();
  192. senden->sendeEncrypted( "\7", 1 );
  193. senden->getNachrichtEncrypted( &ret, 1 );
  194. if( !ret )
  195. {
  196. cs.unlock();
  197. return 0;
  198. }
  199. senden->sendeEncrypted( &län, 1 );
  200. senden->sendeEncrypted( nachricht, län );
  201. senden->getNachrichtEncrypted( &ret, 1 );
  202. cs.unlock();
  203. return ret == 1;
  204. }
  205. bool SpielKlient::bereitZumLaden() // Klient ist bereit zum Laden
  206. {
  207. if( !senden )
  208. return 0;
  209. char ret = 0;
  210. cs.lock();
  211. senden->sendeEncrypted( "\x9", 1 );
  212. senden->getNachrichtEncrypted( &ret, 1 );
  213. cs.unlock();
  214. return ret == 1;
  215. }
  216. bool SpielKlient::setLadenProzent( int prozent ) // Setzt den Fortschritt des Klients
  217. {
  218. if( !senden )
  219. return 0;
  220. char ret = 0;
  221. cs.lock();
  222. senden->sendeEncrypted( "\xC", 1 );
  223. senden->getNachrichtEncrypted( &ret, 1 );
  224. if( ret )
  225. {
  226. senden->sendeEncrypted( (char*)&prozent, 4 );
  227. senden->getNachrichtEncrypted( &ret, 1 );
  228. }
  229. cs.unlock();
  230. return ret == 1;
  231. }
  232. bool SpielKlient::bereitZumSpiel() // Klient ist bereit zum Spiel
  233. {
  234. if( !senden )
  235. return 0;
  236. char ret = 0;
  237. cs.lock();
  238. senden->sendeEncrypted( "\xA", 1 );
  239. senden->getNachrichtEncrypted( &ret, 1 );
  240. cs.unlock();
  241. return ret == 1;
  242. }
  243. bool SpielKlient::spielNachricht( short län, char *bytes ) // Nachricht während des Spiels
  244. {
  245. if( !senden )
  246. return 0;
  247. cs.lock();
  248. senden->sendeEncrypted( "\xB", 1 );
  249. senden->sende( (char*)&län, 2 );
  250. senden->sende( bytes, län );
  251. cs.unlock();
  252. return 1;
  253. }
  254. bool SpielKlient::statistikNachricht( short län, char *bytes ) // Nachricht während der Statistik
  255. {
  256. if( !senden )
  257. return 0;
  258. char ret = 0;
  259. cs.lock();
  260. senden->sendeEncrypted( "\xD", 1 );
  261. senden->getNachrichtEncrypted( &ret, 1 );
  262. if( ret )
  263. {
  264. senden->sendeEncrypted( (char*)&län, 2 );
  265. senden->sendeEncrypted( bytes, län );
  266. senden->getNachrichtEncrypted( &ret, 1 );
  267. }
  268. cs.unlock();
  269. return ret == 1;
  270. }
  271. bool SpielKlient::keepAlive() // Erhält die Verbindung aufrecht
  272. {
  273. if( !verbunden )
  274. return 0;
  275. char res = 0;
  276. if( !cs.tryLock() )
  277. return 1;
  278. senden->sendeEncrypted( "\xF", 1 );
  279. senden->getNachrichtEncrypted( &res, 1 );
  280. cs.unlock();
  281. if( res != 1 )
  282. trenne();
  283. return res == 1;
  284. }
  285. bool SpielKlient::trenne() // trennt sich von dem Chat Server
  286. {
  287. if( !verbunden )
  288. return 1;
  289. verbunden = 0;
  290. cs.lock();
  291. senden->sendeEncrypted( "\3", 1 );
  292. char serverReturn = 0;
  293. senden->getNachrichtEncrypted( &serverReturn, 1 );
  294. senden->trenne();
  295. warteAufThread( 2000 );
  296. empfangen->trenne();
  297. cs.unlock();
  298. run = 0;
  299. ende();
  300. return 1;
  301. }
  302. void SpielKlient::thread() // empfangen von Nachrichten
  303. {
  304. if( !verbunden || !empfangen || !senden )
  305. return;
  306. empfangen->sendeEncrypted( "\1", 1 );
  307. empfangen->sendeEncrypted( (char*)&klientId, 4 );
  308. char res = 0;
  309. empfangen->getNachrichtEncrypted( &res, 1 );
  310. if( res == 3 )
  311. {
  312. char län = 0;
  313. empfangen->getNachrichtEncrypted( &län, 1 );
  314. char *nachricht = new char[ län + 1 ];
  315. nachricht[ län ] = 0;
  316. empfangen->getNachrichtEncrypted( nachricht, län );
  317. fehler->setText( nachricht );
  318. delete[]nachricht;
  319. }
  320. if( res == 1 )
  321. {
  322. char *sl = 0;
  323. char slLän = getSchlüssel( &sl );
  324. empfangen->setSendeKey( sl, slLän );
  325. empfangen->setEmpfangKey( sl, slLän );
  326. delete[] sl;
  327. }
  328. else if( res != 0 )
  329. {
  330. WMessageBox( 0, new Text( "Fehler" ), new Text( "Server hat keine Verwendung für den Client." ), MB_ICONERROR );
  331. return;
  332. }
  333. char befehl = 0;
  334. while( verbunden )
  335. {
  336. if( !empfangen->getNachrichtEncrypted( &befehl, 1 ) )
  337. {
  338. run = 0;
  339. return;
  340. }
  341. switch( befehl )
  342. {
  343. case 0: // verbindung getrennt
  344. trenne();
  345. run = 0;
  346. return;
  347. case 1: // verbleibende Zeit
  348. if( 1 )
  349. {
  350. char sekunden = 0;
  351. empfangen->getNachrichtEncrypted( &sekunden, 1 );
  352. if( nachLogin && nachLogin->zSpielenFenster() )
  353. nachLogin->zSpielenFenster()->spielGefundenZeitVerbleibend( sekunden );
  354. }
  355. break;
  356. case 2: // SpielErstellt abbruch
  357. if( 1 )
  358. {
  359. char län = 0;
  360. empfangen->getNachrichtEncrypted( &län, 1 );
  361. char *grund = new char[ län + 1 ];
  362. grund[ län ] = 0;
  363. empfangen->getNachrichtEncrypted( grund, län );
  364. if( nachLogin && nachLogin->zNachrichtenListe() )
  365. nachLogin->zNachrichtenListe()->addNachricht( new Text( "Spiel Abgebrochen" ), new Text( grund ), new Text( "Ok" ), 0, NachrichtType::nachricht, 0 );
  366. if( nachLogin && nachLogin->zSpielenFenster() )
  367. nachLogin->zSpielenFenster()->spielGefundenAbbruch();
  368. delete[] grund;
  369. }
  370. break;
  371. case 3: // Fehler
  372. if( 1 )
  373. {
  374. char länge = 0;
  375. empfangen->getNachrichtEncrypted( &länge, 1 );
  376. char *txt = new char[ länge + 1 ];
  377. txt[ länge ] = 0;
  378. empfangen->getNachrichtEncrypted( txt, länge );
  379. hauptScreen->lock();
  380. if( nachLogin && nachLogin->zNachrichtenListe() )
  381. nachLogin->zNachrichtenListe()->addNachricht( new Text( "Fehler" ), new Text( txt ), new Text( "Ok" ), 0, NachrichtType::nachricht, 0 );
  382. hauptScreen->unlock();
  383. delete[]txt;
  384. }
  385. break;
  386. case 4: // zurück in Warteschlange
  387. if( 1 )
  388. {
  389. char stunden = 0;
  390. char minuten = 0;
  391. char sekunden = 0;
  392. empfangen->getNachrichtEncrypted( &stunden, 1 );
  393. empfangen->getNachrichtEncrypted( &minuten, 1 );
  394. empfangen->getNachrichtEncrypted( &sekunden, 1 );
  395. if( nachLogin && nachLogin->zSpielenFenster() )
  396. nachLogin->zSpielenFenster()->zurückInWarteschlange( stunden, minuten, sekunden );
  397. }
  398. break;
  399. case 5: // Erstellung fortsetzen
  400. if( nachLogin && nachLogin->zSpielenFenster() )
  401. nachLogin->zSpielenFenster()->teamAuswahlBetreten();
  402. break;
  403. case 6: // SpielErstellt Initialisierung
  404. if( 1 )
  405. {
  406. SpielerTeamStruktur *sts = new SpielerTeamStruktur();
  407. empfangen->getNachrichtEncrypted( (char*)&sts->spielerAnzahl, 4 );
  408. empfangen->getNachrichtEncrypted( (char*)&sts->teamAnzahl, 4 );
  409. for( int i = 0; i < sts->spielerAnzahl; i++ )
  410. {
  411. int farbe = 0;
  412. empfangen->getNachrichtEncrypted( (char*)&farbe, 4 );
  413. sts->spielerFarbe->set( farbe, i );
  414. }
  415. for( int i = 0; i < sts->teamAnzahl; i++ )
  416. {
  417. int farbe = 0;
  418. empfangen->getNachrichtEncrypted( (char*)&farbe, 4 );
  419. sts->teamFarbe->set( farbe, i );
  420. }
  421. for( int i = 0; i < sts->teamAnzahl; i++ )
  422. {
  423. char län = 0;
  424. empfangen->getNachrichtEncrypted( &län, 1 );
  425. char *name = new char[ län + 1 ];
  426. name[ län ] = 0;
  427. if( län )
  428. empfangen->getNachrichtEncrypted( name, län );
  429. Text *tmp = new Text( name );
  430. delete[] name;
  431. sts->teamName->set( tmp, i );
  432. }
  433. for( int i = 0; i < sts->teamAnzahl; i++ )
  434. {
  435. int größe = 0;
  436. empfangen->getNachrichtEncrypted( (char*)&größe, 4 );
  437. sts->teamGröße->set( größe, i );
  438. }
  439. if( nachLogin && nachLogin->zSpielenFenster() )
  440. nachLogin->zSpielenFenster()->teamAuswahlInit( sts );
  441. else
  442. sts->release();
  443. }
  444. break;
  445. case 7: // SpielErstellt Spieler hinzugefügt
  446. if( 1 )
  447. {
  448. int accountId = 0;
  449. empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
  450. if( nachLogin && nachLogin->zSpielenFenster() )
  451. nachLogin->zSpielenFenster()->teamAuswahlAddSpieler( accountId );
  452. }
  453. break;
  454. case 8: // SpielErstellt Spieler entfernt
  455. if( 1 )
  456. {
  457. int accountId = 0;
  458. empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
  459. if( nachLogin && nachLogin->zSpielenFenster() )
  460. nachLogin->zSpielenFenster()->teamAuswahlRemoveSpieler( accountId );
  461. }
  462. break;
  463. case 9: // SpielErstellt Spieler wechselt Team
  464. if( 1 )
  465. {
  466. int accountId = 0;
  467. int spielerNummer = 0;
  468. empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
  469. empfangen->getNachrichtEncrypted( (char*)&spielerNummer, 4 );
  470. if( nachLogin && nachLogin->zSpielenFenster() )
  471. nachLogin->zSpielenFenster()->teamAuswahlSpielerWehseltTeam( accountId, spielerNummer );
  472. }
  473. break;
  474. case 0xA: // SpielErstellt Chat Nachricht
  475. if( 1 )
  476. {
  477. char län = 0;
  478. empfangen->getNachrichtEncrypted( &län, 1 );
  479. char *nachricht = new char[ län + 1 ];
  480. nachricht[ län ] = 0;
  481. if( län )
  482. empfangen->getNachrichtEncrypted( nachricht, län );
  483. if( nachLogin && nachLogin->zSpielenFenster() )
  484. nachLogin->zSpielenFenster()->teamAuswahlChatNachricht( nachricht );
  485. delete[] nachricht;
  486. }
  487. break;
  488. case 0xB: // Spiel gefunden
  489. if( 1 )
  490. {
  491. int karteId = 0;
  492. empfangen->getNachrichtEncrypted( (char*)&karteId, 4 );
  493. if( nachLogin && nachLogin->zSpielenFenster() )
  494. nachLogin->zSpielenFenster()->spielGefunden( karteId );
  495. }
  496. break;
  497. case 0xC: // Spiel Laden beginnen
  498. aktion = 5;
  499. break;
  500. case 0xD: // Spiel Laden Spieler hinzufügen
  501. if( 1 )
  502. {
  503. int accId = 0;
  504. int spielerNummer = 0;
  505. empfangen->getNachrichtEncrypted( (char*)&accId, 4 );
  506. empfangen->getNachrichtEncrypted( (char*)&spielerNummer, 4 );
  507. if( nachLogin->zImSpiel() && nachLogin->zImSpiel()->istSichtbar() )
  508. nachLogin->zImSpiel()->lBAddSpieler( accId, spielerNummer );
  509. }
  510. break;
  511. case 0xE: // Spiel Laden Spieler Prozent
  512. if( 1 )
  513. {
  514. int accId = 0;
  515. int prozent = 0;
  516. empfangen->getNachrichtEncrypted( (char*)&accId, 4 );
  517. empfangen->getNachrichtEncrypted( (char*)&prozent, 4 );
  518. if( nachLogin->zImSpiel() && nachLogin->zImSpiel()->istSichtbar() )
  519. nachLogin->zImSpiel()->lBSetSpielerProzent( accId, prozent );
  520. }
  521. break;
  522. case 0xF: // Spiel Laden Spieler Ping
  523. if( 1 )
  524. {
  525. int accId = 0;
  526. int ping = 0;
  527. empfangen->getNachrichtEncrypted( (char*)&accId, 4 );
  528. empfangen->getNachrichtEncrypted( (char*)&ping, 4 );
  529. if( nachLogin->zImSpiel() && nachLogin->zImSpiel()->istSichtbar() )
  530. nachLogin->zImSpiel()->lBSetSpielerPing( accId, ping );
  531. }
  532. break;
  533. case 0x10: // ping
  534. empfangen->sendeEncrypted( "\1", 1 );
  535. break;
  536. case 0x11: // Spiel Laden Fertig
  537. if( nachLogin->zImSpiel() && nachLogin->zImSpiel()->istSichtbar() )
  538. nachLogin->zImSpiel()->endLaden();
  539. break;
  540. case 0x12: // Spiel Nachricht
  541. if( 1 )
  542. {
  543. short län = 0;
  544. empfangen->getNachricht( (char*)&län, 2 );
  545. char *n = new char[ län ];
  546. empfangen->getNachricht( n, län );
  547. if( nachLogin->zImSpiel() && nachLogin->zImSpiel()->istSichtbar() )
  548. nachLogin->zImSpiel()->spielNachricht( län, n );
  549. delete[] n;
  550. }
  551. break;
  552. case 0x13: // Statistik Nachricht
  553. if( 1 )
  554. {
  555. short län = 0;
  556. empfangen->getNachrichtEncrypted( (char*)&län, 2 );
  557. char *n = new char[ län ];
  558. empfangen->getNachrichtEncrypted( n, län );
  559. if( nachLogin && nachLogin->zSpielenFenster() )
  560. nachLogin->zSpielenFenster()->statistikNachricht( län, n );
  561. delete[] n;
  562. }
  563. break;
  564. case 0x14: // ping
  565. empfangen->sendeEncrypted( "\1", 1 );
  566. break;
  567. default: // Unbekannte Servernachricht
  568. if( nachLogin && nachLogin->zNachrichtenListe() )
  569. {
  570. hauptScreen->lock();
  571. nachLogin->zNachrichtenListe()->addNachricht( new Text( "Fehler" ),
  572. new Text( "Unbekannte Nachricht vom Server. Eventuel ist der Client nicht mehr Aktuell." ),
  573. new Text( "Ok" ), 0, NachrichtType::nachricht, 0 );
  574. hauptScreen->unlock();
  575. }
  576. break;
  577. }
  578. }
  579. run = 0;
  580. }
  581. // constant
  582. bool SpielKlient::istVerbunden() const // prüft, ob mit Chat Server verbunden
  583. {
  584. return verbunden;
  585. }
  586. char *SpielKlient::getLetzterFehler() const // gibt den Letzten Fehlertext zuück
  587. {
  588. return fehler->getText();
  589. }
  590. // Reference Counting
  591. SpielKlientV *SpielKlient::getThis()
  592. {
  593. ref++;
  594. return this;
  595. }
  596. SpielKlientV *SpielKlient::release()
  597. {
  598. ref--;
  599. if( !ref )
  600. delete this;
  601. return 0;
  602. }