handler.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. /*
  2. * File: handler.c
  3. * Author: Arthur Brandao
  4. *
  5. * Created on 23 novembre 2018
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <unistd.h>
  10. #include "error.h"
  11. #include "bomberstudent_server.h"
  12. #include "client.h"
  13. #include "player.h"
  14. #include "delay.h"
  15. #include "handler.h"
  16. /* --- Extern --- */
  17. extern Game game[MAXGAME];
  18. extern int nbGame;
  19. pthread_mutex_t gameMutex[MAXGAME];
  20. pthread_mutex_t playerMutex[MAXGAME * MAXPLAYER];
  21. /* --- Fonctions privées --- */
  22. /**
  23. * Cherche dans quel partie est un client
  24. * @param int L'id du client
  25. * @return int L'index de la partie
  26. */
  27. int search_client_game(int cliId) {
  28. int index = ERR;
  29. for (int i = 0; i < MAXGAME; i++) {
  30. pthread_mutex_lock(&gameMutex[i]);
  31. //Regarde si la game est active et avec des joueurs
  32. if (game[i].active && game[i].nbPlayer > 0) {
  33. //Parcours les joueurs
  34. for (int j = 0; j < MAXPLAYER; j++) {
  35. pthread_mutex_lock(&playerMutex[(i * MAXPLAYER) + j]);
  36. //Si le joueur est actif
  37. if (game[i].player[j]->ini) {
  38. //Si l'id est le bon
  39. if (game[i].player[j]->id == cliId) {
  40. index = i;
  41. pthread_mutex_unlock(&playerMutex[(i * MAXPLAYER) + j]);
  42. break;
  43. }
  44. }
  45. pthread_mutex_unlock(&playerMutex[(i * MAXPLAYER) + j]);
  46. }
  47. }
  48. pthread_mutex_unlock(&gameMutex[i]);
  49. //Si on a un resultat
  50. if (index != ERR) {
  51. break;
  52. }
  53. }
  54. //Retour
  55. return index;
  56. }
  57. /**
  58. * Cherche une partie par son nom
  59. * @param char* Le nom de la partie
  60. * @return int L'index dans le tableau
  61. */
  62. int search_game(char* name) {
  63. int index = ERR;
  64. for (int i = 0; i < MAXGAME; i++) {
  65. pthread_mutex_lock(&gameMutex[i]);
  66. //Regarde si la game est active et le nom
  67. if (game[i].active && strncmp(game[i].name, name, strlen(game[i].name)) == 0) {
  68. index = i;
  69. pthread_mutex_unlock(&gameMutex[i]);
  70. break;
  71. }
  72. pthread_mutex_unlock(&gameMutex[i]);
  73. }
  74. return index;
  75. }
  76. /**
  77. * Parse une postion en 2 entier X et Y
  78. * @param char* La position
  79. * @param int* Le resultat en X
  80. * @param int Le resultat en Y
  81. * @return Reussite
  82. */
  83. boolean parse_pos(char* pos, int* x, int* y) {
  84. int index = 0;
  85. char* cy, * cx;
  86. //Cherche la separation
  87. while (pos[index] != '\0' && pos[index] != ',') {
  88. index++;
  89. }
  90. if (pos[index] == '\0') {
  91. return false;
  92. }
  93. //Separation chaine
  94. cx = malloc(sizeof (char) * index + 1);
  95. memset(cx, 0, index + 1);
  96. strncpy(cx, pos, index);
  97. cy = pos + index + 1;
  98. //Parse
  99. *x = atoi(cx);
  100. *y = atoi(cy);
  101. //Nettoyage
  102. free(cx);
  103. return true;
  104. }
  105. /* --- Fonctions publiques --- */
  106. void ini_handler() {
  107. //Get
  108. add_handler("GET", "game/list", handler_game_list);
  109. //Post
  110. add_handler("POST", "client/end", handler_client_end);
  111. add_handler("POST", "game/create", handler_game_create);
  112. add_handler("POST", "game/join", handler_game_join);
  113. add_handler("POST", "game/quit", handler_game_quit);
  114. add_handler("POST", "player/move", handler_player_move);
  115. add_handler("POST", "object/new", handler_object_new);
  116. add_handler("POST", "attack/bomb", handler_attack_bomb);
  117. add_handler("POST", "attack/remote/go", handler_attack_remote_go);
  118. }
  119. int handler_client_end(int cliId, JsonParser* json) {
  120. //Verif que le client est toujours actif
  121. if (get_client(cliId) != NULL) {
  122. printf("Deconnexion du client %d\n", cliId);
  123. handler_game_quit(cliId, json);
  124. remove_client(cliId);
  125. }
  126. return SUCCESS;
  127. }
  128. int handler_game_list(int cliId, JsonParser* json) {
  129. JsonEncoder reponse;
  130. JsonArray game;
  131. JsonArray map;
  132. int nb;
  133. //Recup la liste des parties et des cartes
  134. ini_array_encoder(&game);
  135. ini_array_encoder(&map);
  136. nb = list_game(&game);
  137. list_map(&map);
  138. //Creation reponse
  139. ini_encoder(&reponse);
  140. add_string(&reponse, "action", "game/list");
  141. add_integer(&reponse, "status", 200);
  142. add_string(&reponse, "message", "ok");
  143. if (nb == 0) {
  144. add_integer(&reponse, "numberGameList", 0);
  145. add_value(&reponse, ", \"games\": []");
  146. } else {
  147. add_integer(&reponse, "numberGameList", nb);
  148. add_array(&reponse, "games", &game);
  149. }
  150. add_array(&reponse, "maps", &map);
  151. //Envoi reponse au client
  152. if (!send_client(cliId, &reponse)) {
  153. adderror("Impossible de répondre au client");
  154. return FAIL;
  155. }
  156. //Nettoyage
  157. clean_json_encoder(&reponse);
  158. clean_json_array(&map);
  159. clean_json_array(&game);
  160. return SUCCESS;
  161. }
  162. int handler_game_create(int cliId, JsonParser* json) {
  163. char* map, * name, * msg;
  164. int index, joueur;
  165. JsonEncoder reponse;
  166. //Verification arguments
  167. if (get_pos(json, "name") == JSON_ERROR) {
  168. send_err_client(cliId, EREQUEST);
  169. adderror("Le json du client est incorrect");
  170. return FAIL;
  171. }
  172. if (get_pos(json, "map") == JSON_ERROR) {
  173. send_err_client(cliId, EREQUEST);
  174. adderror("Le json du client est incorrect");
  175. return FAIL;
  176. }
  177. //Recup valeur
  178. map = get_string(json, "map");
  179. name = get_string(json, "name");
  180. //Initialisation reponse JSON
  181. ini_encoder(&reponse);
  182. add_string(&reponse, "action", "game/create");
  183. //Verif nom non existant
  184. if (search_game(name) != ERR) {
  185. add_integer(&reponse, "status", 501);
  186. add_string(&reponse, "message", "Cannot create game");
  187. if (!send_client(cliId, &reponse)) {
  188. adderror("Impossible de répondre au client");
  189. }
  190. clean_json_encoder(&reponse);
  191. return FAIL;
  192. }
  193. //Creation
  194. index = create_game(name, map);
  195. if (index == ERR) {
  196. add_integer(&reponse, "status", 501);
  197. add_string(&reponse, "message", "Cannot create game");
  198. if (!send_client(cliId, &reponse)) {
  199. adderror("Impossible de répondre au client");
  200. }
  201. clean_json_encoder(&reponse);
  202. return FAIL;
  203. }
  204. //Ajout du joueur dans la partie
  205. joueur = add_player(&game[index], cliId);
  206. if (joueur == ERR) {
  207. stop_game(&game[index]);
  208. add_integer(&reponse, "status", 501);
  209. add_string(&reponse, "message", "Cannot create game");
  210. if (!send_client(cliId, &reponse)) {
  211. adderror("Impossible de répondre au client");
  212. }
  213. clean_json_encoder(&reponse);
  214. return FAIL;
  215. }
  216. //Recup info
  217. describe_game(&game[index], joueur, &reponse);
  218. //Ajout infos
  219. msg = new_string(25 + strlen(map));
  220. sprintf(msg, "Game created with %s", map);
  221. add_integer(&reponse, "status", 201);
  222. add_string(&reponse, "message", msg);
  223. add_string(&reponse, "startPos", "1,1");
  224. free(msg);
  225. //Envoi
  226. if (!send_client(cliId, &reponse)) {
  227. adderror("Impossible de répondre au client");
  228. clean_json_encoder(&reponse);
  229. return FAIL;
  230. }
  231. //Nettoyage
  232. clean_json_encoder(&reponse);
  233. free(map);
  234. free(name);
  235. return SUCCESS;
  236. }
  237. int handler_game_join(int cliId, JsonParser* json) {
  238. char* name;
  239. int index, joueur;
  240. JsonEncoder reponse;
  241. //Verification arguments
  242. if (get_pos(json, "name") == JSON_ERROR) {
  243. send_err_client(cliId, EREQUEST);
  244. adderror("Le json du client est incorrect");
  245. return FAIL;
  246. }
  247. //Recup valeur
  248. name = get_string(json, "name");
  249. //Initialisation json reponse
  250. ini_encoder(&reponse);
  251. add_string(&reponse, "action", "game/join");
  252. //Verif game existe
  253. index = search_game(name);
  254. if (index == ERR) {
  255. add_integer(&reponse, "status", 501);
  256. add_string(&reponse, "message", "Cannot join the game");
  257. if (!send_client(cliId, &reponse)) {
  258. adderror("Impossible de répondre au client");
  259. }
  260. clean_json_encoder(&reponse);
  261. free(name);
  262. return FAIL;
  263. }
  264. //Ajout du joueur dans la partie
  265. joueur = add_player(&game[index], cliId);
  266. if (joueur == ERR) {
  267. add_integer(&reponse, "status", 501);
  268. add_string(&reponse, "message", "Cannot join the game");
  269. if (!send_client(cliId, &reponse)) {
  270. adderror("Impossible de répondre au client");
  271. }
  272. clean_json_encoder(&reponse);
  273. free(name);
  274. return FAIL;
  275. }
  276. //Recup info
  277. describe_game(&game[index], joueur, &reponse);
  278. //Ajout infos
  279. add_integer(&reponse, "status", 201);
  280. add_string(&reponse, "startPos", "1,1");
  281. //Envoi
  282. if (!send_client(cliId, &reponse)) {
  283. adderror("Impossible de répondre au client");
  284. clean_json_encoder(&reponse);
  285. free(name);
  286. return FAIL;
  287. }
  288. //Nettoyage
  289. clean_json_encoder(&reponse);
  290. free(name);
  291. //Avertit les autres joueurs
  292. add_integer(&reponse, "id", cliId);
  293. add_string(&reponse, "pos", "1,1");
  294. notify_player(&game[index], "POST", "game/newplayer", &reponse, cliId);
  295. //Nettoyage
  296. clean_json_encoder(&reponse);
  297. return SUCCESS;
  298. }
  299. int handler_game_quit(int cliId, JsonParser* json) {
  300. boolean find = false;
  301. JsonEncoder notif;
  302. //Cherche le client dans les parties
  303. for (int i = 0; i < MAXGAME; i++) {
  304. pthread_mutex_lock(&gameMutex[i]);
  305. if (game[i].active) {
  306. for (int j = 0; j < MAXPLAYER; j++) {
  307. pthread_mutex_lock(&playerMutex[(i * MAXPLAYER) + j]);
  308. if (game[i].player[j]->ini && game[i].player[j]->id == cliId) {
  309. pthread_mutex_unlock(&playerMutex[(i * MAXPLAYER) + j]);
  310. pthread_mutex_unlock(&gameMutex[i]);
  311. find = true;
  312. remove_player(&game[i], j);
  313. //Avertit les autres joueurs
  314. ini_encoder(&notif);
  315. add_integer(&notif, "player", cliId);
  316. notify_player(&game[i], "POST", "game/quit", &notif, cliId);
  317. clean_json_encoder(&notif);
  318. break;
  319. }
  320. pthread_mutex_unlock(&playerMutex[(i * MAXPLAYER) + j]);
  321. }
  322. if (find) {
  323. break;
  324. }
  325. }
  326. pthread_mutex_unlock(&gameMutex[i]);
  327. }
  328. return SUCCESS;
  329. }
  330. int handler_player_move(int cliId, JsonParser* json) {
  331. char* move;
  332. int index, playerIndex = 0, x = 0, y = 0;
  333. Player* p = NULL;
  334. boolean ok = false, mine = false;
  335. JsonEncoder reponse;
  336. //Verification arguments
  337. if (get_pos(json, "move") == JSON_ERROR) {
  338. return FAIL;
  339. }
  340. //Recup valeur
  341. move = get_string(json, "move");
  342. //Verif game existe
  343. index = search_client_game(cliId);
  344. if (index == ERR) {
  345. free(move);
  346. adderror("La game du client n'existe pas");
  347. return FAIL;
  348. }
  349. //Recup le joueur
  350. pthread_mutex_lock(&gameMutex[index]);
  351. for (int i = 0; i < MAXPLAYER; i++) {
  352. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + i]);
  353. if (game[index].player[i]->ini && game[index].player[i]->id == cliId) {
  354. playerIndex = i;
  355. p = game[index].player[i];
  356. break;
  357. }
  358. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  359. }
  360. if (p == NULL) {
  361. pthread_mutex_unlock(&gameMutex[index]);
  362. free(move);
  363. adderror("Aucun joueur associé au client");
  364. return FAIL;
  365. }
  366. //Regarde si le joueur peut bouger
  367. if (strncmp(move, "up", 2) == 0) {
  368. if (p->y > 0 && !player_collision(&game[index], p->x, p->y - 1) && (game[index].map[p->x][p->y - 1] == '_' /*Vide*/ || game[index].map[p->x][p->y - 1] == '2' /*Mine*/)) {
  369. ok = true;
  370. //Bouge le joueur sur la carte
  371. p->y--;
  372. //Si marche sur une mine
  373. if (game[index].map[p->x][p->y] == '2') {
  374. mine = true;
  375. x = p->x;
  376. y = p->y;
  377. }
  378. }
  379. } else if (strncmp(move, "down", 4) == 0) {
  380. if (p->y < game[index].height && !player_collision(&game[index], p->x, p->y + 1) && (game[index].map[p->x][p->y + 1] == '_' /*Vide*/ || game[index].map[p->x][p->y + 1] == '2' /*Mine*/)) {
  381. ok = true;
  382. //Bouge le joueur sur la carte
  383. p->y++;
  384. //Si marche sur une mine
  385. if (game[index].map[p->x][p->y] == '2') {
  386. mine = true;
  387. x = p->x;
  388. y = p->y;
  389. }
  390. }
  391. } else if (strncmp(move, "left", 4) == 0) {
  392. if (p->x > 0 && !player_collision(&game[index], p->x - 1, p->y) && (game[index].map[p->x - 1][p->y] == '_' /*Vide*/ || game[index].map[p->x - 1][p->y] == '2' /*Mine*/)) {
  393. ok = true;
  394. //Bouge le joueur sur la carte
  395. p->x--;
  396. //Si marche sur une mine
  397. if (game[index].map[p->x][p->y] == '2') {
  398. mine = true;
  399. x = p->x;
  400. y = p->y;
  401. }
  402. }
  403. } else if (strncmp(move, "right", 4) == 0) {
  404. if (p->x < game[index].width && !player_collision(&game[index], p->x + 1, p->y) && (game[index].map[p->x + 1][p->y] == '_' /*Vide*/ || game[index].map[p->x + 1][p->y] == '2' /*Mine*/)) {
  405. ok = true;
  406. //Bouge le joueur sur la carte
  407. p->x++;
  408. //Si marche sur une mine
  409. if (game[index].map[p->x][p->y] == '2') {
  410. mine = true;
  411. x = p->x;
  412. y = p->y;
  413. }
  414. }
  415. } else {
  416. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  417. pthread_mutex_unlock(&gameMutex[index]);
  418. free(move);
  419. adderror("Le json du client est incorrect");
  420. return FAIL;
  421. }
  422. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  423. pthread_mutex_unlock(&gameMutex[index]);
  424. //Notifie les joueurs si mouvement ok
  425. if (ok) {
  426. ini_encoder(&reponse);
  427. add_integer(&reponse, "player", cliId);
  428. add_string(&reponse, "dir", move);
  429. notify_player(&game[index], "POST", "player/position/update", &reponse, -1);
  430. //Si marche sur une mine
  431. if (mine) {
  432. JsonEncoder notif;
  433. ini_encoder(&notif);
  434. if(bomb_explode(&game[index], -1, x, y, &notif)){
  435. //Notification joueurs
  436. if(!notify_player(&game[index], "POST", "attack/explose", &notif, -1)){
  437. clean_json_encoder(&notif);
  438. }
  439. }
  440. clean_json_encoder(&notif);
  441. }
  442. }
  443. //Nettoyage
  444. clean_json_encoder(&reponse);
  445. free(move);
  446. return SUCCESS;
  447. }
  448. int handler_object_new(int cliId, JsonParser* json) {
  449. char* class;
  450. int index, type, length, playerIndex = 0;
  451. Player* p = NULL;
  452. obj_node* objn;
  453. JsonEncoder reponse;
  454. //Verification arguments
  455. if (get_pos(json, "class") == JSON_ERROR) {
  456. send_err_client(cliId, EREQUEST);
  457. adderror("Le json du client est incorrect");
  458. return FAIL;
  459. }
  460. //Recup valeur
  461. class = get_string(json, "class");
  462. //Verif valeur class
  463. length = strlen(class);
  464. if (strncmp(class, "classic", length) == 0) {
  465. type = OBJ_BCLASSIC;
  466. } else if (strncmp(class, "mine", length) == 0) {
  467. type = OBJ_BMINE;
  468. } else if (strncmp(class, "remote", length) == 0) {
  469. type = OBJ_BREMOTE;
  470. } else if (strncmp(class, "bomb_up", length) == 0) {
  471. type = OBJ_BOMBUP;
  472. } else if (strncmp(class, "bomb_down", length) == 0) {
  473. type = OBJ_BOMBDOWN;
  474. } else if (strncmp(class, "fire_power", length) == 0) {
  475. type = OBJ_FIREPOWER;
  476. } else if (strncmp(class, "scooter", length) == 0) {
  477. type = OBJ_SCOOTER;
  478. } else if (strncmp(class, "broken_legs", length) == 0) {
  479. type = OBJ_BROKENLEG;
  480. } else if (strncmp(class, "life_up", length) == 0) {
  481. type = OBJ_LIFEUP;
  482. } else if (strncmp(class, "life_max", length) == 0) {
  483. type = OBJ_LIFEMAX;
  484. } else if (strncmp(class, "major", length) == 0) {
  485. type = OBJ_MAJOR;
  486. } else {
  487. free(class);
  488. send_err_client(cliId, EREQUEST);
  489. adderror("Le json du client est incorrect");
  490. return FAIL;
  491. }
  492. //Verif game existe
  493. index = search_client_game(cliId);
  494. if (index == ERR) {
  495. free(class);
  496. send_err_client(cliId, EREQUEST);
  497. adderror("La game du client n'existe pas");
  498. return FAIL;
  499. }
  500. //Recup le joueur
  501. pthread_mutex_lock(&gameMutex[index]);
  502. for (int i = 0; i < MAXPLAYER; i++) {
  503. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + i]);
  504. if (game[index].player[i]->ini && game[index].player[i]->id == cliId) {
  505. playerIndex = i;
  506. p = game[index].player[i];
  507. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  508. break;
  509. }
  510. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  511. }
  512. if (p == NULL) {
  513. pthread_mutex_unlock(&gameMutex[index]);
  514. free(class);
  515. send_err_client(cliId, EREQUEST);
  516. adderror("Aucun joueur associé au client");
  517. return FAIL;
  518. }
  519. //Initialisation json
  520. ini_encoder(&reponse);
  521. add_string(&reponse, "action", "object/new");
  522. //Regarde si un objet correspond
  523. objn = object_search(game[index].object, type, p->x, p->y);
  524. if (objn == NULL) {
  525. add_integer(&reponse, "status", 501);
  526. add_string(&reponse, "message", "No object");
  527. //Envoi
  528. if (!send_client(cliId, &reponse)) {
  529. adderror("Impossible de répondre au client");
  530. clean_json_encoder(&reponse);
  531. free(class);
  532. return FAIL;
  533. }
  534. } else {
  535. //Ajoute l'objet au joueur
  536. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  537. add_player_object(p, type);
  538. //Creation reponse
  539. add_integer(&reponse, "status", 201);
  540. describe_player(p, &reponse);
  541. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  542. //Envoi
  543. if (!send_client(cliId, &reponse)) {
  544. adderror("Impossible de répondre au client");
  545. clean_json_encoder(&reponse);
  546. free(class);
  547. return FAIL;
  548. }
  549. //Si major lance le timer pour avertir de la fin
  550. if (type == OBJ_MAJOR) {
  551. delay(TIMEMAJOR, index, playerIndex, callback_major_end);
  552. }
  553. }
  554. //Nettoyage
  555. pthread_mutex_unlock(&gameMutex[index]);
  556. free(class);
  557. clean_json_encoder(&reponse);
  558. return SUCCESS;
  559. }
  560. int handler_attack_bomb(int cliId, JsonParser* json) {
  561. char* pos, * class;
  562. int x, y, length, index, playerIndex = 0;
  563. Player* p = NULL;
  564. boolean ok = false;
  565. JsonEncoder reponse, player;
  566. //Verification arguments
  567. if (get_pos(json, "class") == JSON_ERROR) {
  568. send_err_client(cliId, EREQUEST);
  569. adderror("Le json du client est incorrect");
  570. return FAIL;
  571. }
  572. if (get_pos(json, "pos") == JSON_ERROR) {
  573. send_err_client(cliId, EREQUEST);
  574. adderror("Le json du client est incorrect");
  575. return FAIL;
  576. }
  577. //Recup valeur
  578. class = get_string(json, "class");
  579. pos = get_string(json, "pos");
  580. //Parse les valeurs de pos
  581. if (!parse_pos(pos, &x, &y)) {
  582. free(class);
  583. free(pos);
  584. send_err_client(cliId, EREQUEST);
  585. adderror("Le json du client est incorrect");
  586. return FAIL;
  587. }
  588. //Verif game existe
  589. index = search_client_game(cliId);
  590. if (index == ERR) {
  591. free(class);
  592. free(pos);
  593. send_err_client(cliId, EREQUEST);
  594. adderror("La game du client n'existe pas");
  595. return FAIL;
  596. }
  597. //Recup le joueur
  598. pthread_mutex_lock(&gameMutex[index]);
  599. for (int i = 0; i < MAXPLAYER; i++) {
  600. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + i]);
  601. if (game[index].player[i]->ini && game[index].player[i]->id == cliId) {
  602. playerIndex = i;
  603. p = game[index].player[i];
  604. break;
  605. }
  606. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  607. }
  608. if (p == NULL) {
  609. pthread_mutex_unlock(&gameMutex[index]);
  610. free(class);
  611. free(pos);
  612. send_err_client(cliId, EREQUEST);
  613. adderror("Aucun joueur associé au client");
  614. return FAIL;
  615. }
  616. //Verif si la bombe peut être posé et pose
  617. length = strlen(class);
  618. if (strncmp(class, "classic", length) == 0) {
  619. ok = p->classicBomb > 0 && p->nbBomb < p->maxBomb && game[index].map[x][y] == '_' && !player_collision(&game[index], x, y);
  620. if (ok) {
  621. p->nbBomb++;
  622. p->classicBomb--;
  623. game[index].map[x][y] = '1';
  624. //Lance timer
  625. int* tab = malloc(sizeof(int) * 2);
  626. tab[0] = x;
  627. tab[1] = y;
  628. //Ajout bombe
  629. object_add(p->bomb, OBJ_BCLASSIC, x, y);
  630. //Timer
  631. delay_data(TIMEBOMB, index, playerIndex, (void*) tab, callback_bomb_explode);
  632. }
  633. } else if (strncmp(class, "mine", length) == 0) {
  634. ok = p->mine > 0 && p->nbBomb < p->maxBomb && game[index].map[x][y] == '_' && !player_collision(&game[index], x, y);
  635. if (ok) {
  636. p->nbBomb++;
  637. p->mine--;
  638. game[index].map[x][y] = '2';
  639. //Ajout bombe
  640. object_add(p->bomb, OBJ_BMINE, x, y);
  641. }
  642. } else if (strncmp(class, "remote", length) == 0) {
  643. ok = p->remoteBomb > 0 && p->nbBomb < p->maxBomb && game[index].map[x][y] == '_' && !player_collision(&game[index], x, y);
  644. if (ok) {
  645. p->nbBomb++;
  646. p->remoteBomb--;
  647. game[index].map[x][y] = '3';
  648. //Ajoute la bombe dans la liste du joueur
  649. object_add(p->bomb, OBJ_BREMOTE, x, y);
  650. }
  651. } else {
  652. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  653. pthread_mutex_unlock(&gameMutex[index]);
  654. free(pos);
  655. free(class);
  656. send_err_client(cliId, EREQUEST);
  657. adderror("Le json du client est incorrect");
  658. return FAIL;
  659. }
  660. //Initialisation json
  661. ini_encoder(&reponse);
  662. add_string(&reponse, "action", "attack/bomb");
  663. //Reponse
  664. if (ok) {
  665. add_integer(&reponse, "status", 201);
  666. describe_player(p, &player);
  667. add_object(&reponse, "player", &player);
  668. clean_json_encoder(&player);
  669. //Envoi
  670. if (!send_client(cliId, &reponse)) {
  671. adderror("Impossible de répondre au client");
  672. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  673. pthread_mutex_unlock(&gameMutex[index]);
  674. clean_json_encoder(&reponse);
  675. free(pos);
  676. free(class);
  677. return FAIL;
  678. }
  679. //Notification des autre joeurs
  680. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  681. pthread_mutex_unlock(&gameMutex[index]);
  682. clean_json_encoder(&reponse);
  683. add_string(&reponse, "pos", pos);
  684. add_string(&reponse, "class", class);
  685. notify_player(&game[index], "POST", "attack/newbomb", &reponse, -1);
  686. } else {
  687. add_integer(&reponse, "status", 403);
  688. add_string(&reponse, "message", "Forbidden action");
  689. //Envoi
  690. if (!send_client(cliId, &reponse)) {
  691. adderror("Impossible de répondre au client");
  692. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  693. pthread_mutex_unlock(&gameMutex[index]);
  694. clean_json_encoder(&reponse);
  695. free(pos);
  696. free(class);
  697. return FAIL;
  698. }
  699. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  700. pthread_mutex_unlock(&gameMutex[index]);
  701. }
  702. //Nettoyage
  703. clean_json_encoder(&reponse);
  704. free(pos);
  705. free(class);
  706. return SUCCESS;
  707. }
  708. int handler_attack_remote_go(int cliId, JsonParser* json){
  709. int index, playerIndex;
  710. JsonEncoder notif;
  711. Player* p = NULL;
  712. obj_node* objn, *tmp;
  713. //Charche la game
  714. index = search_client_game(cliId);
  715. //Ini json
  716. ini_encoder(&notif);
  717. //Recup le joueur
  718. pthread_mutex_lock(&gameMutex[index]);
  719. for (int i = 0; i < MAXPLAYER; i++) {
  720. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + i]);
  721. if (game[index].player[i]->ini && game[index].player[i]->id == cliId) {
  722. playerIndex = i;
  723. p = game[index].player[i];
  724. break;
  725. }
  726. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  727. }
  728. if (p == NULL) {
  729. pthread_mutex_unlock(&gameMutex[index]);
  730. send_err_client(cliId, EREQUEST);
  731. adderror("Aucun joueur associé au client");
  732. return FAIL;
  733. }
  734. //Explose toutes les remotes du joueur
  735. objn = p->bomb->first;
  736. while(objn != NULL){
  737. tmp = objn->next;
  738. if(objn->type == OBJ_BREMOTE){
  739. //Retire mutex gérés dans fonctions
  740. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  741. pthread_mutex_unlock(&gameMutex[index]);
  742. if(bomb_explode(&game[index], playerIndex, objn->x, objn->y, &notif)){
  743. //Notification joueurs
  744. if(!notify_player(&game[index], "POST", "attack/explose", &notif, -1)){
  745. adderror("Impossible de notifier le joueur de l'explosion");
  746. }
  747. clean_json_encoder(&notif);
  748. }
  749. //Remet mutex
  750. pthread_mutex_lock(&gameMutex[index]);
  751. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  752. }
  753. objn = tmp;
  754. }
  755. //Nettoyage
  756. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  757. pthread_mutex_unlock(&gameMutex[index]);
  758. return SUCCESS;
  759. }