handler.c 26 KB

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