handler.c 25 KB

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