game.c 7.1 KB

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