handler.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  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. adderror("Erreur explosion mine");
  436. }
  437. clean_json_encoder(&notif);
  438. }
  439. }
  440. //Nettoyage
  441. clean_json_encoder(&reponse);
  442. free(move);
  443. return SUCCESS;
  444. }
  445. int handler_object_new(int cliId, JsonParser* json) {
  446. char* class;
  447. int index, type, length, playerIndex = 0;
  448. Player* p = NULL;
  449. obj_node* objn;
  450. JsonEncoder reponse;
  451. //Verification arguments
  452. if (get_pos(json, "class") == JSON_ERROR) {
  453. send_err_client(cliId, EREQUEST);
  454. adderror("Le json du client est incorrect");
  455. return FAIL;
  456. }
  457. //Recup valeur
  458. class = get_string(json, "class");
  459. //Verif valeur class
  460. length = strlen(class);
  461. if (strncmp(class, "classic", length) == 0) {
  462. type = OBJ_BCLASSIC;
  463. } else if (strncmp(class, "mine", length) == 0) {
  464. type = OBJ_BMINE;
  465. } else if (strncmp(class, "remote", length) == 0) {
  466. type = OBJ_BREMOTE;
  467. } else if (strncmp(class, "bomb_up", length) == 0) {
  468. type = OBJ_BOMBUP;
  469. } else if (strncmp(class, "bomb_down", length) == 0) {
  470. type = OBJ_BOMBDOWN;
  471. } else if (strncmp(class, "fire_power", length) == 0) {
  472. type = OBJ_FIREPOWER;
  473. } else if (strncmp(class, "scooter", length) == 0) {
  474. type = OBJ_SCOOTER;
  475. } else if (strncmp(class, "broken_legs", length) == 0) {
  476. type = OBJ_BROKENLEG;
  477. } else if (strncmp(class, "life_up", length) == 0) {
  478. type = OBJ_LIFEUP;
  479. } else if (strncmp(class, "life_max", length) == 0) {
  480. type = OBJ_LIFEMAX;
  481. } else if (strncmp(class, "major", length) == 0) {
  482. type = OBJ_MAJOR;
  483. } else {
  484. free(class);
  485. send_err_client(cliId, EREQUEST);
  486. adderror("Le json du client est incorrect");
  487. return FAIL;
  488. }
  489. //Verif game existe
  490. index = search_client_game(cliId);
  491. if (index == ERR) {
  492. free(class);
  493. send_err_client(cliId, EREQUEST);
  494. adderror("La game du client n'existe pas");
  495. return FAIL;
  496. }
  497. //Recup le joueur
  498. pthread_mutex_lock(&gameMutex[index]);
  499. for (int i = 0; i < MAXPLAYER; i++) {
  500. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + i]);
  501. if (game[index].player[i]->ini && game[index].player[i]->id == cliId) {
  502. playerIndex = i;
  503. p = game[index].player[i];
  504. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  505. break;
  506. }
  507. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  508. }
  509. if (p == NULL) {
  510. pthread_mutex_unlock(&gameMutex[index]);
  511. free(class);
  512. send_err_client(cliId, EREQUEST);
  513. adderror("Aucun joueur associé au client");
  514. return FAIL;
  515. }
  516. //Regarde si un objet correspond
  517. objn = object_search(game[index].object, type, p->x, p->y);
  518. if (objn == NULL) {
  519. ini_encoder(&reponse);
  520. add_string(&reponse, "action", "object/new");
  521. add_integer(&reponse, "status", 501);
  522. add_string(&reponse, "message", "No object");
  523. //Envoi
  524. if (!send_client(cliId, &reponse)) {
  525. adderror("Impossible de répondre au client");
  526. clean_json_encoder(&reponse);
  527. free(class);
  528. return FAIL;
  529. }
  530. } else {
  531. //Ajoute l'objet au joueur
  532. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  533. add_player_object(p, type);
  534. //Creation reponse
  535. ini_encoder(&reponse);
  536. describe_player(p, &reponse);
  537. add_integer(&reponse, "status", 201);
  538. add_string(&reponse, "action", "object/new");
  539. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  540. //Envoi
  541. if (!send_client(cliId, &reponse)) {
  542. adderror("Impossible de répondre au client");
  543. clean_json_encoder(&reponse);
  544. free(class);
  545. return FAIL;
  546. }
  547. //Si major lance le timer pour avertir de la fin
  548. if (type == OBJ_MAJOR) {
  549. delay(TIMEMAJOR, index, playerIndex, callback_major_end);
  550. }
  551. }
  552. //Nettoyage
  553. pthread_mutex_unlock(&gameMutex[index]);
  554. free(class);
  555. clean_json_encoder(&reponse);
  556. return SUCCESS;
  557. }
  558. int handler_attack_bomb(int cliId, JsonParser* json) {
  559. char* pos, * class;
  560. int x, y, length, index, playerIndex = 0;
  561. Player* p = NULL;
  562. boolean ok = false;
  563. JsonEncoder reponse, player;
  564. //Verification arguments
  565. if (get_pos(json, "class") == JSON_ERROR) {
  566. send_err_client(cliId, EREQUEST);
  567. adderror("Le json du client est incorrect");
  568. return FAIL;
  569. }
  570. if (get_pos(json, "pos") == JSON_ERROR) {
  571. send_err_client(cliId, EREQUEST);
  572. adderror("Le json du client est incorrect");
  573. return FAIL;
  574. }
  575. //Recup valeur
  576. class = get_string(json, "class");
  577. pos = get_string(json, "pos");
  578. //Parse les valeurs de pos
  579. if (!parse_pos(pos, &x, &y)) {
  580. free(class);
  581. free(pos);
  582. send_err_client(cliId, EREQUEST);
  583. adderror("Le json du client est incorrect");
  584. return FAIL;
  585. }
  586. //Verif game existe
  587. index = search_client_game(cliId);
  588. if (index == ERR) {
  589. free(class);
  590. free(pos);
  591. send_err_client(cliId, EREQUEST);
  592. adderror("La game du client n'existe pas");
  593. return FAIL;
  594. }
  595. //Recup le joueur
  596. pthread_mutex_lock(&gameMutex[index]);
  597. for (int i = 0; i < MAXPLAYER; i++) {
  598. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + i]);
  599. if (game[index].player[i]->ini && game[index].player[i]->id == cliId) {
  600. playerIndex = i;
  601. p = game[index].player[i];
  602. break;
  603. }
  604. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  605. }
  606. if (p == NULL) {
  607. pthread_mutex_unlock(&gameMutex[index]);
  608. free(class);
  609. free(pos);
  610. send_err_client(cliId, EREQUEST);
  611. adderror("Aucun joueur associé au client");
  612. return FAIL;
  613. }
  614. //Verif si la bombe peut être posé et pose
  615. length = strlen(class);
  616. if (strncmp(class, "classic", length) == 0) {
  617. ok = p->classicBomb > 0 && p->nbBomb < p->maxBomb && game[index].map[x][y] == '_' && !player_collision(&game[index], x, y);
  618. if (ok) {
  619. p->nbBomb++;
  620. p->classicBomb--;
  621. game[index].map[x][y] = '1';
  622. //Lance timer
  623. int* tab = malloc(sizeof(int) * 2);
  624. tab[0] = x;
  625. tab[1] = y;
  626. //Ajout bombe
  627. object_add(p->bomb, OBJ_BCLASSIC, x, y);
  628. //Timer
  629. delay_data(TIMEBOMB, index, playerIndex, (void*) tab, callback_bomb_explode);
  630. }
  631. } else if (strncmp(class, "mine", length) == 0) {
  632. ok = p->mine > 0 && p->nbBomb < p->maxBomb && game[index].map[x][y] == '_' && !player_collision(&game[index], x, y);
  633. if (ok) {
  634. p->nbBomb++;
  635. p->mine--;
  636. game[index].map[x][y] = '2';
  637. //Ajout bombe
  638. object_add(p->bomb, OBJ_BMINE, x, y);
  639. }
  640. } else if (strncmp(class, "remote", length) == 0) {
  641. ok = p->remoteBomb > 0 && p->nbBomb < p->maxBomb && game[index].map[x][y] == '_' && !player_collision(&game[index], x, y);
  642. if (ok) {
  643. p->nbBomb++;
  644. p->remoteBomb--;
  645. game[index].map[x][y] = '3';
  646. //Ajoute la bombe dans la liste du joueur
  647. object_add(p->bomb, OBJ_BREMOTE, x, y);
  648. }
  649. } else {
  650. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  651. pthread_mutex_unlock(&gameMutex[index]);
  652. free(pos);
  653. free(class);
  654. send_err_client(cliId, EREQUEST);
  655. adderror("Le json du client est incorrect");
  656. return FAIL;
  657. }
  658. //Initialisation json
  659. ini_encoder(&reponse);
  660. add_string(&reponse, "action", "attack/bomb");
  661. //Reponse
  662. if (ok) {
  663. add_integer(&reponse, "status", 201);
  664. describe_player(p, &player);
  665. add_object(&reponse, "player", &player);
  666. clean_json_encoder(&player);
  667. //Envoi
  668. if (!send_client(cliId, &reponse)) {
  669. adderror("Impossible de répondre au client");
  670. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  671. pthread_mutex_unlock(&gameMutex[index]);
  672. clean_json_encoder(&reponse);
  673. free(pos);
  674. free(class);
  675. return FAIL;
  676. }
  677. //Notification des autre joeurs
  678. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  679. pthread_mutex_unlock(&gameMutex[index]);
  680. clean_json_encoder(&reponse);
  681. add_string(&reponse, "pos", pos);
  682. add_string(&reponse, "class", class);
  683. notify_player(&game[index], "POST", "attack/newbomb", &reponse, -1);
  684. } else {
  685. add_integer(&reponse, "status", 403);
  686. add_string(&reponse, "message", "Forbidden action");
  687. //Envoi
  688. if (!send_client(cliId, &reponse)) {
  689. adderror("Impossible de répondre au client");
  690. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  691. pthread_mutex_unlock(&gameMutex[index]);
  692. clean_json_encoder(&reponse);
  693. free(pos);
  694. free(class);
  695. return FAIL;
  696. }
  697. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  698. pthread_mutex_unlock(&gameMutex[index]);
  699. }
  700. //Nettoyage
  701. clean_json_encoder(&reponse);
  702. free(pos);
  703. free(class);
  704. return SUCCESS;
  705. }
  706. int handler_attack_remote_go(int cliId, JsonParser* json){
  707. int index, playerIndex;
  708. JsonEncoder notif;
  709. Player* p = NULL;
  710. obj_node* objn, *tmp;
  711. //Charche la game
  712. index = search_client_game(cliId);
  713. //Ini json
  714. ini_encoder(&notif);
  715. //Recup le joueur
  716. pthread_mutex_lock(&gameMutex[index]);
  717. for (int i = 0; i < MAXPLAYER; i++) {
  718. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + i]);
  719. if (game[index].player[i]->ini && game[index].player[i]->id == cliId) {
  720. playerIndex = i;
  721. p = game[index].player[i];
  722. break;
  723. }
  724. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  725. }
  726. if (p == NULL) {
  727. pthread_mutex_unlock(&gameMutex[index]);
  728. send_err_client(cliId, EREQUEST);
  729. adderror("Aucun joueur associé au client");
  730. return FAIL;
  731. }
  732. //Explose toutes les remotes du joueur
  733. objn = p->bomb->first;
  734. while(objn != NULL){
  735. tmp = objn->next;
  736. if(objn->type == OBJ_BREMOTE){
  737. //Retire mutex gérés dans fonctions
  738. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  739. pthread_mutex_unlock(&gameMutex[index]);
  740. if(bomb_explode(&game[index], playerIndex, objn->x, objn->y, &notif)){
  741. //Notification joueurs
  742. if(!notify_player(&game[index], "POST", "attack/explose", &notif, -1)){
  743. adderror("Impossible de notifier le joueur de l'explosion");
  744. }
  745. clean_json_encoder(&notif);
  746. }
  747. //Remet mutex
  748. pthread_mutex_lock(&gameMutex[index]);
  749. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  750. }
  751. objn = tmp;
  752. }
  753. //Nettoyage
  754. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  755. pthread_mutex_unlock(&gameMutex[index]);
  756. return SUCCESS;
  757. }