handler.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  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. //Cherche pos de depart random
  217. int x = 0, y = 0;
  218. srand(time(NULL));
  219. do{
  220. x = rand() % game[index].width;
  221. y = rand() % game[index].height;
  222. }while(game[index].map[x][y] != '_');
  223. game[index].player[joueur]->x = x;
  224. game[index].player[joueur]->y = y;
  225. char pos[25];
  226. memset(pos, 0, 25);
  227. snprintf(pos, 25, "%d,%d", x, y);
  228. //Recup info
  229. describe_game(&game[index], joueur, &reponse);
  230. //Ajout infos
  231. msg = new_string(25 + strlen(map));
  232. sprintf(msg, "Game created with %s", map);
  233. add_integer(&reponse, "status", 201);
  234. add_string(&reponse, "message", msg);
  235. add_string(&reponse, "startPos", pos);
  236. free(msg);
  237. //Envoi
  238. if (!send_client(cliId, &reponse)) {
  239. adderror("Impossible de répondre au client");
  240. clean_json_encoder(&reponse);
  241. return FAIL;
  242. }
  243. //Nettoyage
  244. clean_json_encoder(&reponse);
  245. free(map);
  246. free(name);
  247. return SUCCESS;
  248. }
  249. int handler_game_join(int cliId, JsonParser* json) {
  250. char* name;
  251. int index, joueur;
  252. JsonEncoder reponse;
  253. //Verification arguments
  254. if (get_pos(json, "name") == JSON_ERROR) {
  255. send_err_client(cliId, EREQUEST);
  256. adderror("Le json du client est incorrect");
  257. return FAIL;
  258. }
  259. //Recup valeur
  260. name = get_string(json, "name");
  261. //Initialisation json reponse
  262. ini_encoder(&reponse);
  263. add_string(&reponse, "action", "game/join");
  264. //Verif game existe
  265. index = search_game(name);
  266. if (index == 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. //Ajout du joueur dans la partie
  277. joueur = add_player(&game[index], cliId);
  278. if (joueur == ERR) {
  279. add_integer(&reponse, "status", 501);
  280. add_string(&reponse, "message", "Cannot join the game");
  281. if (!send_client(cliId, &reponse)) {
  282. adderror("Impossible de répondre au client");
  283. }
  284. clean_json_encoder(&reponse);
  285. free(name);
  286. return FAIL;
  287. }
  288. //Cherche pos de depart random
  289. int x = 0, y = 0;
  290. srand(time(NULL));
  291. do{
  292. x = rand() % game[index].width;
  293. y = rand() % game[index].height;
  294. }while(game[index].map[x][y] != '_');
  295. game[index].player[joueur]->x = x;
  296. game[index].player[joueur]->y = y;
  297. char pos[25];
  298. memset(pos, 0, 25);
  299. snprintf(pos, 25, "%d,%d", x, y);
  300. //Recup info
  301. describe_game(&game[index], joueur, &reponse);
  302. //Ajout infos
  303. add_integer(&reponse, "status", 201);
  304. add_string(&reponse, "startPos", pos);
  305. //Envoi
  306. if (!send_client(cliId, &reponse)) {
  307. adderror("Impossible de répondre au client");
  308. clean_json_encoder(&reponse);
  309. free(name);
  310. return FAIL;
  311. }
  312. //Nettoyage
  313. clean_json_encoder(&reponse);
  314. free(name);
  315. //Avertit les autres joueurs
  316. add_integer(&reponse, "id", cliId);
  317. add_string(&reponse, "pos", pos);
  318. notify_player(&game[index], "POST", "game/newplayer", &reponse, cliId);
  319. //Nettoyage
  320. clean_json_encoder(&reponse);
  321. return SUCCESS;
  322. }
  323. int handler_game_quit(int cliId, JsonParser* json) {
  324. boolean find = false;
  325. JsonEncoder notif;
  326. //Cherche le client dans les parties
  327. for (int i = 0; i < MAXGAME; i++) {
  328. pthread_mutex_lock(&gameMutex[i]);
  329. if (game[i].active) {
  330. for (int j = 0; j < MAXPLAYER; j++) {
  331. pthread_mutex_lock(&playerMutex[(i * MAXPLAYER) + j]);
  332. if (game[i].player[j]->ini && game[i].player[j]->id == cliId) {
  333. pthread_mutex_unlock(&playerMutex[(i * MAXPLAYER) + j]);
  334. pthread_mutex_unlock(&gameMutex[i]);
  335. find = true;
  336. remove_player(&game[i], j);
  337. //Avertit les autres joueurs
  338. ini_encoder(&notif);
  339. add_integer(&notif, "player", cliId);
  340. notify_player(&game[i], "POST", "game/quit", &notif, cliId);
  341. clean_json_encoder(&notif);
  342. break;
  343. }
  344. pthread_mutex_unlock(&playerMutex[(i * MAXPLAYER) + j]);
  345. }
  346. if (find) {
  347. break;
  348. }
  349. }
  350. pthread_mutex_unlock(&gameMutex[i]);
  351. }
  352. return SUCCESS;
  353. }
  354. int handler_player_move(int cliId, JsonParser* json) {
  355. char* move;
  356. int index, playerIndex = 0, x = 0, y = 0;
  357. Player* p = NULL;
  358. boolean ok = false, mine = false;
  359. JsonEncoder reponse;
  360. //Verification arguments
  361. if (get_pos(json, "move") == JSON_ERROR) {
  362. return FAIL;
  363. }
  364. //Recup valeur
  365. move = get_string(json, "move");
  366. //Verif game existe
  367. index = search_client_game(cliId);
  368. if (index == ERR) {
  369. free(move);
  370. adderror("La game du client n'existe pas");
  371. return FAIL;
  372. }
  373. //Recup le joueur
  374. pthread_mutex_lock(&gameMutex[index]);
  375. for (int i = 0; i < MAXPLAYER; i++) {
  376. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + i]);
  377. if (game[index].player[i]->ini && game[index].player[i]->id == cliId) {
  378. playerIndex = i;
  379. p = game[index].player[i];
  380. break;
  381. }
  382. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  383. }
  384. if (p == NULL) {
  385. pthread_mutex_unlock(&gameMutex[index]);
  386. free(move);
  387. adderror("Aucun joueur associé au client");
  388. return FAIL;
  389. }
  390. //Regarde si le joueur peut bouger
  391. if (strncmp(move, "up", 2) == 0) {
  392. 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*/)) {
  393. ok = true;
  394. //Bouge le joueur sur la carte
  395. p->y--;
  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, "down", 4) == 0) {
  404. 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*/)) {
  405. ok = true;
  406. //Bouge le joueur sur la carte
  407. p->y++;
  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 if (strncmp(move, "left", 4) == 0) {
  416. 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*/)) {
  417. ok = true;
  418. //Bouge le joueur sur la carte
  419. p->x--;
  420. //Si marche sur une mine
  421. if (game[index].map[p->x][p->y] == '2') {
  422. mine = true;
  423. x = p->x;
  424. y = p->y;
  425. }
  426. }
  427. } else if (strncmp(move, "right", 4) == 0) {
  428. 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*/)) {
  429. ok = true;
  430. //Bouge le joueur sur la carte
  431. p->x++;
  432. //Si marche sur une mine
  433. if (game[index].map[p->x][p->y] == '2') {
  434. mine = true;
  435. x = p->x;
  436. y = p->y;
  437. }
  438. }
  439. } else {
  440. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  441. pthread_mutex_unlock(&gameMutex[index]);
  442. free(move);
  443. adderror("Le json du client est incorrect");
  444. return FAIL;
  445. }
  446. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  447. pthread_mutex_unlock(&gameMutex[index]);
  448. //Notifie les joueurs si mouvement ok
  449. if (ok) {
  450. ini_encoder(&reponse);
  451. add_integer(&reponse, "player", cliId);
  452. add_string(&reponse, "dir", move);
  453. notify_player(&game[index], "POST", "player/position/update", &reponse, -1);
  454. //Si marche sur une mine
  455. if (mine) {
  456. JsonEncoder notif;
  457. ini_encoder(&notif);
  458. if (bomb_explode(&game[index], playerIndex, x, y, &notif)) {
  459. //Notification joueurs
  460. if (!notify_player(&game[index], "POST", "attack/explose", &notif, -1)) {
  461. adderror("Impossible de notifier les joueurs");
  462. clean_json_encoder(&notif);
  463. clean_json_encoder(&reponse);
  464. free(move);
  465. return FAIL;
  466. }
  467. }
  468. clean_json_encoder(&notif);
  469. }
  470. }
  471. //Nettoyage
  472. clean_json_encoder(&reponse);
  473. free(move);
  474. return SUCCESS;
  475. }
  476. int handler_object_new(int cliId, JsonParser* json) {
  477. char* class;
  478. int index, type, length, playerIndex = 0;
  479. Player* p = NULL;
  480. obj_node* objn;
  481. JsonEncoder reponse;
  482. //Verification arguments
  483. if (get_pos(json, "class") == JSON_ERROR) {
  484. send_err_client(cliId, EREQUEST);
  485. adderror("Le json du client est incorrect");
  486. return FAIL;
  487. }
  488. //Recup valeur
  489. class = get_string(json, "class");
  490. //Verif valeur class
  491. length = strlen(class);
  492. if (strncmp(class, "classic", length) == 0) {
  493. type = OBJ_BCLASSIC;
  494. } else if (strncmp(class, "mine", length) == 0) {
  495. type = OBJ_BMINE;
  496. } else if (strncmp(class, "remote", length) == 0) {
  497. type = OBJ_BREMOTE;
  498. } else if (strncmp(class, "bomb_up", length) == 0) {
  499. type = OBJ_BOMBUP;
  500. } else if (strncmp(class, "bomb_down", length) == 0) {
  501. type = OBJ_BOMBDOWN;
  502. } else if (strncmp(class, "fire_power", length) == 0) {
  503. type = OBJ_FIREPOWER;
  504. } else if (strncmp(class, "scooter", length) == 0) {
  505. type = OBJ_SCOOTER;
  506. } else if (strncmp(class, "broken_legs", length) == 0) {
  507. type = OBJ_BROKENLEG;
  508. } else if (strncmp(class, "life_up", length) == 0) {
  509. type = OBJ_LIFEUP;
  510. } else if (strncmp(class, "life_max", length) == 0) {
  511. type = OBJ_LIFEMAX;
  512. } else if (strncmp(class, "major", length) == 0) {
  513. type = OBJ_MAJOR;
  514. } else {
  515. free(class);
  516. send_err_client(cliId, EREQUEST);
  517. adderror("Le json du client est incorrect");
  518. return FAIL;
  519. }
  520. //Verif game existe
  521. index = search_client_game(cliId);
  522. if (index == ERR) {
  523. free(class);
  524. send_err_client(cliId, EREQUEST);
  525. adderror("La game du client n'existe pas");
  526. return FAIL;
  527. }
  528. //Recup le joueur
  529. pthread_mutex_lock(&gameMutex[index]);
  530. for (int i = 0; i < MAXPLAYER; i++) {
  531. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + i]);
  532. if (game[index].player[i]->ini && game[index].player[i]->id == cliId) {
  533. playerIndex = i;
  534. p = game[index].player[i];
  535. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  536. break;
  537. }
  538. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  539. }
  540. if (p == NULL) {
  541. pthread_mutex_unlock(&gameMutex[index]);
  542. free(class);
  543. send_err_client(cliId, EREQUEST);
  544. adderror("Aucun joueur associé au client");
  545. return FAIL;
  546. }
  547. //Regarde si un objet correspond
  548. objn = object_search(game[index].object, type, p->x, p->y);
  549. if (objn == NULL) {
  550. ini_encoder(&reponse);
  551. add_string(&reponse, "action", "object/new");
  552. add_integer(&reponse, "status", 501);
  553. add_string(&reponse, "message", "No object");
  554. //Envoi
  555. if (!send_client(cliId, &reponse)) {
  556. adderror("Impossible de répondre au client");
  557. clean_json_encoder(&reponse);
  558. free(class);
  559. return FAIL;
  560. }
  561. } else {
  562. //Ajoute l'objet au joueur
  563. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  564. add_player_object(p, type);
  565. //Creation reponse
  566. ini_encoder(&reponse);
  567. describe_player(p, &reponse);
  568. add_integer(&reponse, "status", 201);
  569. add_string(&reponse, "action", "object/new");
  570. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  571. //Envoi
  572. if (!send_client(cliId, &reponse)) {
  573. adderror("Impossible de répondre au client");
  574. clean_json_encoder(&reponse);
  575. free(class);
  576. return FAIL;
  577. }
  578. //Si major lance le timer pour avertir de la fin
  579. if (type == OBJ_MAJOR) {
  580. delay(TIMEMAJOR, index, playerIndex, callback_major_end);
  581. }
  582. }
  583. //Nettoyage
  584. pthread_mutex_unlock(&gameMutex[index]);
  585. free(class);
  586. clean_json_encoder(&reponse);
  587. return SUCCESS;
  588. }
  589. int handler_attack_bomb(int cliId, JsonParser* json) {
  590. char* pos, * class;
  591. int x, y, length, index, playerIndex = 0;
  592. Player* p = NULL;
  593. boolean ok = false;
  594. JsonEncoder reponse, player;
  595. //Verification arguments
  596. if (get_pos(json, "class") == JSON_ERROR) {
  597. send_err_client(cliId, EREQUEST);
  598. adderror("Le json du client est incorrect");
  599. return FAIL;
  600. }
  601. if (get_pos(json, "pos") == JSON_ERROR) {
  602. send_err_client(cliId, EREQUEST);
  603. adderror("Le json du client est incorrect");
  604. return FAIL;
  605. }
  606. //Recup valeur
  607. class = get_string(json, "class");
  608. pos = get_string(json, "pos");
  609. //Parse les valeurs de pos
  610. if (!parse_pos(pos, &x, &y)) {
  611. free(class);
  612. free(pos);
  613. send_err_client(cliId, EREQUEST);
  614. adderror("Le json du client est incorrect");
  615. return FAIL;
  616. }
  617. //Verif game existe
  618. index = search_client_game(cliId);
  619. if (index == ERR) {
  620. free(class);
  621. free(pos);
  622. send_err_client(cliId, EREQUEST);
  623. adderror("La game du client n'existe pas");
  624. return FAIL;
  625. }
  626. //Recup le joueur
  627. pthread_mutex_lock(&gameMutex[index]);
  628. for (int i = 0; i < MAXPLAYER; i++) {
  629. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + i]);
  630. if (game[index].player[i]->ini && game[index].player[i]->id == cliId) {
  631. playerIndex = i;
  632. p = game[index].player[i];
  633. break;
  634. }
  635. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  636. }
  637. if (p == NULL) {
  638. pthread_mutex_unlock(&gameMutex[index]);
  639. free(class);
  640. free(pos);
  641. send_err_client(cliId, EREQUEST);
  642. adderror("Aucun joueur associé au client");
  643. return FAIL;
  644. }
  645. //Verif si la bombe peut être posé et pose
  646. length = strlen(class);
  647. if (strncmp(class, "classic", length) == 0) {
  648. ok = p->classicBomb > 0 && p->nbBomb < p->maxBomb && game[index].map[x][y] == '_' && !player_collision(&game[index], x, y);
  649. if (ok) {
  650. p->nbBomb++;
  651. p->classicBomb--;
  652. game[index].map[x][y] = '1';
  653. //Lance timer
  654. int* tab = malloc(sizeof (int) * 2);
  655. tab[0] = x;
  656. tab[1] = y;
  657. //Ajout bombe
  658. object_add(p->bomb, OBJ_BCLASSIC, x, y);
  659. //Timer
  660. delay_data(TIMEBOMB, index, playerIndex, (void*) tab, callback_bomb_explode);
  661. }
  662. } else if (strncmp(class, "mine", length) == 0) {
  663. ok = p->mine > 0 && p->nbBomb < p->maxBomb && game[index].map[x][y] == '_' && !player_collision(&game[index], x, y);
  664. if (ok) {
  665. p->nbBomb++;
  666. p->mine--;
  667. game[index].map[x][y] = '2';
  668. //Ajout bombe
  669. object_add(p->bomb, OBJ_BMINE, x, y);
  670. }
  671. } else if (strncmp(class, "remote", length) == 0) {
  672. ok = p->remoteBomb > 0 && p->nbBomb < p->maxBomb && game[index].map[x][y] == '_' && !player_collision(&game[index], x, y);
  673. if (ok) {
  674. p->nbBomb++;
  675. p->remoteBomb--;
  676. game[index].map[x][y] = '3';
  677. //Ajoute la bombe dans la liste du joueur
  678. object_add(p->bomb, OBJ_BREMOTE, x, y);
  679. }
  680. } else {
  681. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  682. pthread_mutex_unlock(&gameMutex[index]);
  683. free(pos);
  684. free(class);
  685. send_err_client(cliId, EREQUEST);
  686. adderror("Le json du client est incorrect");
  687. return FAIL;
  688. }
  689. //Initialisation json
  690. ini_encoder(&reponse);
  691. add_string(&reponse, "action", "attack/bomb");
  692. //Reponse
  693. if (ok) {
  694. add_integer(&reponse, "status", 201);
  695. describe_player(p, &player);
  696. add_object(&reponse, "player", &player);
  697. clean_json_encoder(&player);
  698. //Envoi
  699. if (!send_client(cliId, &reponse)) {
  700. adderror("Impossible de répondre au client");
  701. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  702. pthread_mutex_unlock(&gameMutex[index]);
  703. clean_json_encoder(&reponse);
  704. free(pos);
  705. free(class);
  706. return FAIL;
  707. }
  708. //Notification des autre joeurs
  709. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  710. pthread_mutex_unlock(&gameMutex[index]);
  711. clean_json_encoder(&reponse);
  712. add_string(&reponse, "pos", pos);
  713. add_string(&reponse, "class", class);
  714. notify_player(&game[index], "POST", "attack/newbomb", &reponse, -1);
  715. } else {
  716. add_integer(&reponse, "status", 403);
  717. add_string(&reponse, "message", "Forbidden action");
  718. //Envoi
  719. if (!send_client(cliId, &reponse)) {
  720. adderror("Impossible de répondre au client");
  721. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  722. pthread_mutex_unlock(&gameMutex[index]);
  723. clean_json_encoder(&reponse);
  724. free(pos);
  725. free(class);
  726. return FAIL;
  727. }
  728. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  729. pthread_mutex_unlock(&gameMutex[index]);
  730. }
  731. //Nettoyage
  732. clean_json_encoder(&reponse);
  733. free(pos);
  734. free(class);
  735. return SUCCESS;
  736. }
  737. int handler_attack_remote_go(int cliId, JsonParser* json) {
  738. int index, playerIndex;
  739. JsonEncoder notif;
  740. Player* p = NULL;
  741. obj_node* objn, *tmp;
  742. //Charche la game
  743. index = search_client_game(cliId);
  744. //Ini json
  745. ini_encoder(&notif);
  746. //Recup le joueur
  747. pthread_mutex_lock(&gameMutex[index]);
  748. for (int i = 0; i < MAXPLAYER; i++) {
  749. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + i]);
  750. if (game[index].player[i]->ini && game[index].player[i]->id == cliId) {
  751. playerIndex = i;
  752. p = game[index].player[i];
  753. break;
  754. }
  755. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  756. }
  757. if (p == NULL) {
  758. pthread_mutex_unlock(&gameMutex[index]);
  759. send_err_client(cliId, EREQUEST);
  760. adderror("Aucun joueur associé au client");
  761. return FAIL;
  762. }
  763. //Explose toutes les remotes du joueur
  764. objn = p->bomb->first;
  765. while (objn != NULL) {
  766. tmp = objn->next;
  767. if (objn->type == OBJ_BREMOTE) {
  768. //Retire mutex gérés dans fonctions
  769. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  770. pthread_mutex_unlock(&gameMutex[index]);
  771. if (bomb_explode(&game[index], playerIndex, objn->x, objn->y, &notif)) {
  772. //Notification joueurs
  773. if (!notify_player(&game[index], "POST", "attack/explose", &notif, -1)) {
  774. adderror("Impossible de notifier le joueur de l'explosion");
  775. }
  776. clean_json_encoder(&notif);
  777. }
  778. //Remet mutex
  779. pthread_mutex_lock(&gameMutex[index]);
  780. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  781. //Retourne au debut de liste pour eviter de selectionner bombe non presente
  782. tmp = p->bomb->first;
  783. }
  784. objn = tmp;
  785. }
  786. //Nettoyage
  787. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  788. pthread_mutex_unlock(&gameMutex[index]);
  789. return SUCCESS;
  790. }