game.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  2. * File: game.c
  3. * Author: Arthur Brandao
  4. *
  5. * Created on 28 novembre 2018
  6. */
  7. #define _XOPEN_SOURCE 500
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include "error.h"
  11. #include "str.h"
  12. #include "file.h"
  13. #include "game.h"
  14. #include "bomberstudent_server.h"
  15. /* --- Extern --- */
  16. Game game[MAXGAME];
  17. int nbGame = 0;
  18. /* --- Fonctions privées --- */
  19. /**
  20. * Transforme le fichier map en un tableau 2D
  21. * @param char* Le contenu du fichier map
  22. * @param int Largeur de la map
  23. * @param int Hauteur de la map
  24. * @return char** La map parser
  25. */
  26. char** parse_map(char* mapContent, int width, int height){
  27. char** map = malloc(sizeof(char*) * width);
  28. //Creation des colonnes
  29. for(int i = 0; i < width; i++){
  30. map[i] = malloc(sizeof(char) * height);
  31. }
  32. //Remplissage
  33. for(int i = 0; i < height; i++){
  34. for(int j = 0; j < width; j++){
  35. map[j][i] = *mapContent;
  36. mapContent++;
  37. }
  38. mapContent++;
  39. }
  40. return map;
  41. }
  42. /* --- Fonctions publiques --- */
  43. void ini_games(){
  44. for(int i = 0; i < MAXGAME; i++){
  45. game[i].active = false;
  46. }
  47. }
  48. void list_map(JsonArray* res){
  49. char** result;
  50. int nbResult;
  51. //Regarde les fichiers dans le dossier
  52. result = file_list(MAPDIR, &nbResult);
  53. for(int i = 0; i < nbResult; i++){
  54. add_array_string(res, result[i]);
  55. free(result[i]);
  56. }
  57. free(result);
  58. }
  59. int list_game(JsonArray* res){
  60. JsonEncoder gameJson;
  61. int compteur = 0, i = 0;
  62. //Si il n' y a aucune game
  63. if(nbGame == 0){
  64. return 0;
  65. }
  66. //Initialisation json
  67. ini_encoder(&gameJson);
  68. //Ajoute chaque game
  69. while(compteur < nbGame && i < MAXGAME){
  70. if(!game[i].active){
  71. i++;
  72. continue;
  73. }
  74. //Creation objet json
  75. add_string(&gameJson, "name", game[i].name);
  76. add_integer(&gameJson, "nbPlayer", game[i].nbPlayer);
  77. add_string(&gameJson, "map", game[i].mapName);
  78. //Ajout dans le tableau
  79. add_array_object(res, &gameJson);
  80. //Nettoyage encoder objet
  81. clean_json_encoder(&gameJson);
  82. //Incremente
  83. i++;
  84. compteur++;
  85. }
  86. return nbGame;
  87. }
  88. int* map_size(char* map){
  89. int* res;
  90. res = malloc(sizeof(int) * 2);
  91. res[WIDTH] = 0;
  92. res[HEIGHT] = 1;
  93. //Parcours la 1er ligne pour compter le nombre de caractère
  94. while(*map != '\n' && *map != '\0'){
  95. res[WIDTH]++;
  96. map++;
  97. }
  98. if(*map == '\0'){
  99. return res;
  100. }
  101. //Compte les lignes
  102. map++;
  103. while(*map != '\0'){
  104. if(*map == '\n'){
  105. res[HEIGHT]++;
  106. }
  107. map++;
  108. }
  109. return res;
  110. }
  111. int create_game(char* name, char* map){
  112. int length, index = 0;
  113. char* path;
  114. int* size;
  115. //Regarde si il reste une game de disponnible
  116. if(nbGame == MAXGAME){
  117. return ERR;
  118. }
  119. //Cherche une game libre
  120. while(index < MAXGAME){
  121. if(game[index].active == false){
  122. break;
  123. }
  124. index++;
  125. }
  126. //Recup la map
  127. length = strlen(MAPDIR) + strlen(map);
  128. path = new_string(length);
  129. snprintf(path, length + 1, "%s%s", MAPDIR, map);
  130. game[index].mapContent = file_get_content(path);
  131. //Calcul taille de la map
  132. size = map_size(game[index].mapContent);
  133. //Set Up
  134. game[index].active = true;
  135. game[index].name = string_copy(name);
  136. game[index].nbPlayer = 0;
  137. game[index].mapName = string_copy(map);
  138. game[index].width = size[WIDTH];
  139. game[index].height = size[HEIGHT];
  140. game[index].map = parse_map(game[index].mapContent, size[WIDTH], size[HEIGHT]);
  141. for(int i = 0; i < MAXPLAYER; i++){
  142. game[index].player[i] = malloc(sizeof(Player));
  143. game[index].player[i]->ini = false;
  144. }
  145. //Retourne la position de la partie dans le tableau
  146. nbGame++;
  147. free(path);
  148. free(size);
  149. return index;
  150. }
  151. int add_player(Game* g, int cliId){
  152. int index = 0;
  153. Client* cli;
  154. //Verif que la game n'est pas deja pleine
  155. if(g->nbPlayer >= MAXPLAYER){
  156. return ERR;
  157. }
  158. //Cherche un joueur non initialisé
  159. while(index < MAXPLAYER){
  160. if(!g->player[index]->ini){
  161. break;
  162. }
  163. index++;
  164. }
  165. //Recup du client
  166. cli = get_client(cliId);
  167. if(cli == NULL){
  168. return ERR;
  169. }
  170. //Creation du joueur
  171. create_player(g->player[index], cli);
  172. g->nbPlayer++;
  173. return index;
  174. }
  175. void describe_game(Game* g, int playerIndex, JsonEncoder* desc){
  176. JsonEncoder player;
  177. JsonEncoder map;
  178. JsonArray players;
  179. char* content;
  180. //Initialisation
  181. ini_encoder(&player);
  182. ini_encoder(&map);
  183. ini_array_encoder(&players);
  184. //Info map
  185. content = remove_char(g->mapContent, '\n'); //La map sans \n car interdit en JSON
  186. add_integer(&map, "width", g->width);
  187. add_integer(&map, "height", g->height);
  188. add_string(&map, "content", content);
  189. free(content);
  190. //Ajout info
  191. add_integer(desc, "nbPlayers", g->nbPlayer);
  192. add_object(desc, "map", &map);
  193. //Ajout info courte joueur
  194. //printf("Add players\n");
  195. for(int i = 0; i < MAXPLAYER; i++){
  196. if(g->player[i]->ini){
  197. describe_short_player(g->player[i], &player);
  198. add_array_object(&players, &player);
  199. clean_json_encoder(&player);
  200. }
  201. }
  202. //printf("Fin Add players\n");
  203. add_array(desc, "players", &players);
  204. //Si besoins ajout un joueur
  205. if(playerIndex >= 0 && playerIndex < MAXPLAYER && g->player[playerIndex]->ini){
  206. describe_player(g->player[playerIndex], &player);
  207. add_object(desc, "player", &player);
  208. clean_json_encoder(&player);
  209. }
  210. //Nettoyage
  211. clean_json_encoder(&map);
  212. clean_json_array(&players);
  213. }
  214. boolean notify_player(Game* g, char* method, char* ressource, JsonEncoder* param, int excludePlayerId){
  215. boolean res = true;
  216. //Regarde si la game est active
  217. if(!g->active){
  218. return false;
  219. }
  220. //Parcours les joeurs de la game
  221. for(int i = 0; i < MAXPLAYER; i++){
  222. //Si joueur actif
  223. if(g->player[i]->ini && g->player[i]->id != excludePlayerId){
  224. res = res && notify_client(g->player[i]->cli, method, ressource, param);
  225. }
  226. }
  227. return res;
  228. }
  229. boolean player_collision(Game* g, int x, int y){
  230. for(int i = 0; i < MAXPLAYER; i++){
  231. if(g->player[i]->ini){
  232. if(g->player[i]->x == x && g->player[i]->y == y){
  233. return true;
  234. }
  235. }
  236. }
  237. return false;
  238. }
  239. void remove_player(Game* g, int playerIndex){
  240. g->nbPlayer--;
  241. delete_player(g->player[playerIndex]);
  242. }
  243. void stop_game(Game* g){
  244. //Indique comme inactive
  245. g->active = false;
  246. //Suppr les joueurs
  247. for(int i = 0; i < MAXPLAYER; i++){
  248. if(g->player[i]->ini){
  249. delete_player(g->player[i]);
  250. }
  251. free(g->player[i]);
  252. }
  253. //Libere la memoire
  254. for(int i = 0; i < g->width; i++){
  255. free(g->map[i]);
  256. }
  257. free(g->map);
  258. free(g->mapName);
  259. free(g->mapContent);
  260. //Retire une game
  261. nbGame--;
  262. }
  263. void clean_games(){
  264. for(int i = 0; i < MAXGAME; i++){
  265. if(game[i].active){
  266. stop_game(&game[i]);
  267. }
  268. }
  269. }