handler.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  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. //Regarde si un objet correspond
  520. objn = object_search(game[index].object, type, p->x, p->y);
  521. if (objn == NULL) {
  522. ini_encoder(&reponse);
  523. add_string(&reponse, "action", "object/new");
  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. ini_encoder(&reponse);
  539. describe_player(p, &reponse);
  540. add_integer(&reponse, "status", 201);
  541. add_string(&reponse, "action", "object/new");
  542. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  543. //Envoi
  544. if (!send_client(cliId, &reponse)) {
  545. adderror("Impossible de répondre au client");
  546. clean_json_encoder(&reponse);
  547. free(class);
  548. return FAIL;
  549. }
  550. //Si major lance le timer pour avertir de la fin
  551. if (type == OBJ_MAJOR) {
  552. delay(TIMEMAJOR, index, playerIndex, callback_major_end);
  553. }
  554. }
  555. //Nettoyage
  556. pthread_mutex_unlock(&gameMutex[index]);
  557. free(class);
  558. clean_json_encoder(&reponse);
  559. return SUCCESS;
  560. }
  561. int handler_attack_bomb(int cliId, JsonParser* json) {
  562. char* pos, * class;
  563. int x, y, length, index, playerIndex = 0;
  564. Player* p = NULL;
  565. boolean ok = false;
  566. JsonEncoder reponse, player;
  567. //Verification arguments
  568. if (get_pos(json, "class") == JSON_ERROR) {
  569. send_err_client(cliId, EREQUEST);
  570. adderror("Le json du client est incorrect");
  571. return FAIL;
  572. }
  573. if (get_pos(json, "pos") == JSON_ERROR) {
  574. send_err_client(cliId, EREQUEST);
  575. adderror("Le json du client est incorrect");
  576. return FAIL;
  577. }
  578. //Recup valeur
  579. class = get_string(json, "class");
  580. pos = get_string(json, "pos");
  581. //Parse les valeurs de pos
  582. if (!parse_pos(pos, &x, &y)) {
  583. free(class);
  584. free(pos);
  585. send_err_client(cliId, EREQUEST);
  586. adderror("Le json du client est incorrect");
  587. return FAIL;
  588. }
  589. //Verif game existe
  590. index = search_client_game(cliId);
  591. if (index == ERR) {
  592. free(class);
  593. free(pos);
  594. send_err_client(cliId, EREQUEST);
  595. adderror("La game du client n'existe pas");
  596. return FAIL;
  597. }
  598. //Recup le joueur
  599. pthread_mutex_lock(&gameMutex[index]);
  600. for (int i = 0; i < MAXPLAYER; i++) {
  601. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + i]);
  602. if (game[index].player[i]->ini && game[index].player[i]->id == cliId) {
  603. playerIndex = i;
  604. p = game[index].player[i];
  605. break;
  606. }
  607. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  608. }
  609. if (p == NULL) {
  610. pthread_mutex_unlock(&gameMutex[index]);
  611. free(class);
  612. free(pos);
  613. send_err_client(cliId, EREQUEST);
  614. adderror("Aucun joueur associé au client");
  615. return FAIL;
  616. }
  617. //Verif si la bombe peut être posé et pose
  618. length = strlen(class);
  619. if (strncmp(class, "classic", length) == 0) {
  620. ok = p->classicBomb > 0 && p->nbBomb < p->maxBomb && game[index].map[x][y] == '_' && !player_collision(&game[index], x, y);
  621. if (ok) {
  622. p->nbBomb++;
  623. p->classicBomb--;
  624. game[index].map[x][y] = '1';
  625. //Lance timer
  626. int* tab = malloc(sizeof(int) * 2);
  627. tab[0] = x;
  628. tab[1] = y;
  629. //Ajout bombe
  630. object_add(p->bomb, OBJ_BCLASSIC, x, y);
  631. //Timer
  632. delay_data(TIMEBOMB, index, playerIndex, (void*) tab, callback_bomb_explode);
  633. }
  634. } else if (strncmp(class, "mine", length) == 0) {
  635. ok = p->mine > 0 && p->nbBomb < p->maxBomb && game[index].map[x][y] == '_' && !player_collision(&game[index], x, y);
  636. if (ok) {
  637. p->nbBomb++;
  638. p->mine--;
  639. game[index].map[x][y] = '2';
  640. //Ajout bombe
  641. object_add(p->bomb, OBJ_BMINE, x, y);
  642. }
  643. } else if (strncmp(class, "remote", length) == 0) {
  644. ok = p->remoteBomb > 0 && p->nbBomb < p->maxBomb && game[index].map[x][y] == '_' && !player_collision(&game[index], x, y);
  645. if (ok) {
  646. p->nbBomb++;
  647. p->remoteBomb--;
  648. game[index].map[x][y] = '3';
  649. //Ajoute la bombe dans la liste du joueur
  650. object_add(p->bomb, OBJ_BREMOTE, x, y);
  651. }
  652. } else {
  653. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  654. pthread_mutex_unlock(&gameMutex[index]);
  655. free(pos);
  656. free(class);
  657. send_err_client(cliId, EREQUEST);
  658. adderror("Le json du client est incorrect");
  659. return FAIL;
  660. }
  661. //Initialisation json
  662. ini_encoder(&reponse);
  663. add_string(&reponse, "action", "attack/bomb");
  664. //Reponse
  665. if (ok) {
  666. add_integer(&reponse, "status", 201);
  667. describe_player(p, &player);
  668. add_object(&reponse, "player", &player);
  669. clean_json_encoder(&player);
  670. //Envoi
  671. if (!send_client(cliId, &reponse)) {
  672. adderror("Impossible de répondre au client");
  673. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  674. pthread_mutex_unlock(&gameMutex[index]);
  675. clean_json_encoder(&reponse);
  676. free(pos);
  677. free(class);
  678. return FAIL;
  679. }
  680. //Notification des autre joeurs
  681. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  682. pthread_mutex_unlock(&gameMutex[index]);
  683. clean_json_encoder(&reponse);
  684. add_string(&reponse, "pos", pos);
  685. add_string(&reponse, "class", class);
  686. notify_player(&game[index], "POST", "attack/newbomb", &reponse, -1);
  687. } else {
  688. add_integer(&reponse, "status", 403);
  689. add_string(&reponse, "message", "Forbidden action");
  690. //Envoi
  691. if (!send_client(cliId, &reponse)) {
  692. adderror("Impossible de répondre au client");
  693. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  694. pthread_mutex_unlock(&gameMutex[index]);
  695. clean_json_encoder(&reponse);
  696. free(pos);
  697. free(class);
  698. return FAIL;
  699. }
  700. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  701. pthread_mutex_unlock(&gameMutex[index]);
  702. }
  703. //Nettoyage
  704. clean_json_encoder(&reponse);
  705. free(pos);
  706. free(class);
  707. return SUCCESS;
  708. }
  709. int handler_attack_remote_go(int cliId, JsonParser* json){
  710. int index, playerIndex;
  711. JsonEncoder notif;
  712. Player* p = NULL;
  713. obj_node* objn, *tmp;
  714. //Charche la game
  715. index = search_client_game(cliId);
  716. //Ini json
  717. ini_encoder(&notif);
  718. //Recup le joueur
  719. pthread_mutex_lock(&gameMutex[index]);
  720. for (int i = 0; i < MAXPLAYER; i++) {
  721. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + i]);
  722. if (game[index].player[i]->ini && game[index].player[i]->id == cliId) {
  723. playerIndex = i;
  724. p = game[index].player[i];
  725. break;
  726. }
  727. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + i]);
  728. }
  729. if (p == NULL) {
  730. pthread_mutex_unlock(&gameMutex[index]);
  731. send_err_client(cliId, EREQUEST);
  732. adderror("Aucun joueur associé au client");
  733. return FAIL;
  734. }
  735. //Explose toutes les remotes du joueur
  736. objn = p->bomb->first;
  737. while(objn != NULL){
  738. tmp = objn->next;
  739. if(objn->type == OBJ_BREMOTE){
  740. //Retire mutex gérés dans fonctions
  741. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  742. pthread_mutex_unlock(&gameMutex[index]);
  743. if(bomb_explode(&game[index], playerIndex, objn->x, objn->y, &notif)){
  744. //Notification joueurs
  745. if(!notify_player(&game[index], "POST", "attack/explose", &notif, -1)){
  746. adderror("Impossible de notifier le joueur de l'explosion");
  747. }
  748. clean_json_encoder(&notif);
  749. }
  750. //Remet mutex
  751. pthread_mutex_lock(&gameMutex[index]);
  752. pthread_mutex_lock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  753. }
  754. objn = tmp;
  755. }
  756. //Nettoyage
  757. pthread_mutex_unlock(&playerMutex[(index * MAXPLAYER) + playerIndex]);
  758. pthread_mutex_unlock(&gameMutex[index]);
  759. return SUCCESS;
  760. }