From 77c40142b3746b6f67caaf8380cb15a9b3c792e3 Mon Sep 17 00:00:00 2001 From: Valiance Date: Sun, 20 Apr 2025 16:53:10 +0200 Subject: [PATCH 1/5] doc(server): add doxygen doc for server --- Doxyfile | 6 ++-- Server/include/app.h | 11 ++++++ Server/include/cleanup.h | 22 ++++++++++++ Server/include/data_structure.h | 7 ++++ Server/include/error_handler.h | 8 +++++ Server/include/instructions.h | 35 +++++++++++++++++++ Server/include/map.h | 8 +++++ Server/include/player.h | 23 +++++++++++++ Server/include/server.h | 60 +++++++++++++++++++++++++++++++++ 9 files changed, 177 insertions(+), 3 deletions(-) diff --git a/Doxyfile b/Doxyfile index 0343341..874da00 100644 --- a/Doxyfile +++ b/Doxyfile @@ -534,7 +534,7 @@ TIMESTAMP = NO # normally produced when WARNINGS is set to YES. # The default value is: NO. -EXTRACT_ALL = NO +EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. @@ -574,7 +574,7 @@ EXTRACT_LOCAL_CLASSES = YES # included. # The default value is: NO. -EXTRACT_LOCAL_METHODS = NO +EXTRACT_LOCAL_METHODS = YES # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called @@ -991,7 +991,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = Client/src/JetpackClient Client/src/Display Client/src/Player Client/src/Network Client/src/Network/socket Client/src/Network/Poll +INPUT = Client/src/JetpackClient Client/src/Display Client/src/Player Client/src/Network Client/src/Network/socket Client/src/Network/Poll Server/include diff --git a/Server/include/app.h b/Server/include/app.h index 4bdde98..eaa92bb 100644 --- a/Server/include/app.h +++ b/Server/include/app.h @@ -8,6 +8,17 @@ #ifndef APP_H_ #define APP_H_ +/** + * @brief Main server application entry point. + * + * Initializes and runs the game server on the specified port, + * loading the given map file, and optionally enabling debug mode. + * + * @param port Port number as C-string on which to listen. + * @param map Path to the map file to load. + * @param debug If non-null and enable debug logging. + * @return Zero on clean exit, non-zero on error. + */ int run_app(const char *port, const char *map, const char *debug); #endif diff --git a/Server/include/cleanup.h b/Server/include/cleanup.h index d1a2735..9440a0d 100644 --- a/Server/include/cleanup.h +++ b/Server/include/cleanup.h @@ -11,10 +11,32 @@ #include "player.h" #include "server.h" +/** + * @brief Safely free a dynamically allocated pointer and NULL it. + * + * @param ptr Double-pointer to the memory to free. + */ void simple_free(void **ptr); +/** + * @brief Destroy and free a server instance. + * + * Invokes the server's destroy method, closes sockets, + * frees resources, and sets the pointer to NULL. + * + * @param server Double-pointer to the server_t instance. + */ void free_server(server_t **server); + +/** + * @brief Destroy and free a player instance. + * + * Cleans up player resources such as buffers and sockets, + * then frees the structure and sets the pointer to NULL. + * + * @param player Double-pointer to the player_t instance. + */ void free_player(player_t **player); #endif /* ifndef CLEANUP_H_*/ diff --git a/Server/include/data_structure.h b/Server/include/data_structure.h index 930cec7..d28766d 100644 --- a/Server/include/data_structure.h +++ b/Server/include/data_structure.h @@ -8,6 +8,13 @@ #ifndef DATA_STRUCTURE_H_ #define DATA_STRUCTURE_H_ +/** + * @struct position_s + * @brief Represents a 2D vector of ints. + * + * Each component is an integer, used to store + * the position in the game. + */ typedef struct position_s { int xPos; int yPos; diff --git a/Server/include/error_handler.h b/Server/include/error_handler.h index 9d7c358..76b86e6 100644 --- a/Server/include/error_handler.h +++ b/Server/include/error_handler.h @@ -10,6 +10,14 @@ #include +/** + * @struct error_s + * @brief Error context for try/catch emulation. + * + * @details + * Contains the jump buffer for setjmp/longjmp and an error + * message describing the exception that was thrown. + */ typedef struct error_s { jmp_buf buf; char *message; diff --git a/Server/include/instructions.h b/Server/include/instructions.h index 60ec542..7efc3f2 100644 --- a/Server/include/instructions.h +++ b/Server/include/instructions.h @@ -11,6 +11,15 @@ #include "server.h" #include "player.h" +/** + * @struct command_s + * @brief Descriptor for a server command and its handler. + * + * @details + * Associates a command name with the function that implements + * its behavior, taking the server context and the target player + * as parameters. + */ typedef struct command_s { const char *name; void (*function)(server_t *server, player_t *player); @@ -18,8 +27,34 @@ typedef struct command_s { extern const command_t commands[]; +/** + * @brief Send current position and state to a player. + * + * Constructs a position update message and transmits it. + * + * @param server Server context. + * @param player Target player. + */ void send_pos(server_t *server, player_t *player); + +/** + * @brief Move the player's character upward. + * + * Applies velocity boost or upward movement per game physics. + * + * @param server Server context. + * @param player Target player. + */ void move_up(server_t *server, player_t *player); + +/** + * @brief Execute an instruction for one player. + * + * @param server Server context. + * @param player Target player. + * @param i Index of the player in the server players list. + * @return Number of instructions actually processed. + */ int execute_instructions(server_t *server, player_t *player, size_t i); #endif diff --git a/Server/include/map.h b/Server/include/map.h index f457e38..4c25558 100644 --- a/Server/include/map.h +++ b/Server/include/map.h @@ -14,6 +14,14 @@ typedef struct server_s server_t; +/** + * @brief Load the game map into server memory. + * + * Reads map file specified in server->map_file, + * populates server->map array, and validates dimensions. + * + * @param server Server instance to load map into. + */ void load_map(server_t *server); #endif diff --git a/Server/include/player.h b/Server/include/player.h index b5b9ac8..0f5a1ee 100644 --- a/Server/include/player.h +++ b/Server/include/player.h @@ -13,11 +13,25 @@ #include #include +/** + * @struct vector2_s + * @brief Représente un vecteur 2D à virgule flottante. + * + * Chaque composante est un double, utilisé pour stocker + * la position dans le jeu. + */ typedef struct vector2_s { double x; double y; } vector2_t; +/** + * @struct player_s + * @brief Represents a connected player in the game server. + * + * @details + * Tracks the player's game state, position, and communication socket. + */ typedef struct player_s { size_t score; int ended; @@ -29,6 +43,15 @@ typedef struct player_s { struct pollfd *socket; } player_t; +/** + * @brief Allocate and initialize a new player. + * + * Creates a player_t, assigns the given socket descriptor, + * initializes default state, and returns the instance. + * + * @param socket Pointer to the pollfd for the new connection. + * @return Pointer to newly created player_t, or NULL on failure. + */ player_t *create_player(struct pollfd *socket); #endif /* ifndef PLAYER_H_ */ diff --git a/Server/include/server.h b/Server/include/server.h index 63df706..7a9b09a 100644 --- a/Server/include/server.h +++ b/Server/include/server.h @@ -15,6 +15,19 @@ #define NB_PLAYER_MAX 2 +/** + * @enum GameState + * @brief Represents the different lifecycle states of the game server. + * + * @var GameState::WAITING_PLAYER + * Waiting for players to connect before initialization. + * @var GameState::INIT + * Performing initialization (loading map, setting up game). + * @var GameState::STARTED + * Game is actively running. + * @var GameState::ENDED + * Game has finished and is awaiting shutdown. + */ enum GameState { WAITING_PLAYER, INIT, @@ -22,6 +35,13 @@ enum GameState { ENDED }; +/** + * @struct server_s + * @brief Core server context for the Jetpack Joyride multiplayer game. + * + * Contains configuration flags, sockets, game state, connected players, + * and function pointers for all server operations. + */ typedef struct server_s { int is_debug; int is_running; @@ -48,9 +68,49 @@ typedef struct server_s { void (*load_map)(struct server_s *server); } server_t; +/** + * @brief Allocate and initialize a new server. + * + * Sets up listening socket on @p port, loads the map file, + * configures poll descriptors, and assigns virtual methods. + * + * @param port TCP port number to listen on. + * @param map Path to map file. + * @param debug Debug flag (non-zero to enable debug mode). + * @return Pointer to initialized server_t, or NULL on error. + */ server_t *create_server(int port, const char *map, int debug); + +/** + * @brief Run the server's main loop. + * + * Enters polling loop, accepts new connections, + * handles input, updates game state, and sends updates. + * + * @param this Pointer to server instance. + * @return Zero on clean shutdown, non-zero on error. + */ int run_server(struct server_s *this); + +/** + * @brief Send full map data to all connected players. + * + * Iterates over server->players and transmits the map contents. + * + * @param server Server instance. + */ void send_map(server_t *server); + +/** + * @brief Log debug information on socket. + * + * If @p is_send is true, writes @p data as send data; otherwise, + * write them as received data + * + * @param server Server context. + * @param data Debug message text. + * @param is_send Is the data received or send. + */ void debug(server_t *server, const char *data, int is_send); #endif /* ifndef SERVER_H_ */ From 9123abd1757e418184203870d9e59f3fbce06412 Mon Sep 17 00:00:00 2001 From: Valiance Date: Sun, 20 Apr 2025 17:08:00 +0200 Subject: [PATCH 2/5] doc(rfc): add map layout and update protocol --- doc.txt | 72 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/doc.txt b/doc.txt index d625659..7eb0800 100644 --- a/doc.txt +++ b/doc.txt @@ -82,7 +82,8 @@ Table of Contents (Connection State) - --> WAITING_PLAYERS : You are connected but we still need to wait for other players + --> WAITING_PLAYERS : You are connected but we still need to wait for other + players (Init state) --> SEND_MAP: All players are connected, about to send the map @@ -92,40 +93,16 @@ Table of Contents <-- READY: when the player is ready to start the game --> GAME_START: when all player are ready and thus beginning the game - (Game State) The client command can be send in any order and the response will always be the pos + score + (Game State) The client command can be send in any order and the response + will always be the pos + score <-- PRESSED: When the player press the touch to use the jetpack <-- GETPOS: When the player doesn't press the touch to use the jetpack - --> "$(xPos):$(yPos):$(scoreP1):$(scoreP2)": pos and score - --> ENDGAME: when the game is over - - - ALL: - SERVER: - `WAITING_PLAYERS` - `GAME_START:PLAYER_NUMBER` - Client: - `CLIENT_READY` - - PLAYER: - SERVER: - `NEW_POS:$POSX:$POSY:$COLL` - `SCORE:$PLAYER:$SCORE:$COLL` - Client: - `PRESSED` - - PIECE: - SERVER: - `PIECE_STATE:$POSX:$POSY` - Client: - - MAP: - Server: - `SEND_MAP` -> send map - `$ASSET_NAME_MAP:$POSX:$POSY` -> send the map asset and it position - `END_MAP` -> end map - Client: - `MAP_OKAY` -> if the map is correctly loaded - `MAP_NOT_OKAY` -> if the map is not correctly loaded + --> "$(xPos):$(yPos):$(yPos2):$(scoreP1):$(scoreP2)": pos and score, 1 or + none is for p1 and 2 for p2 + --> WIN: When the game is over to tell if a player won + --> LOSE: When the game is over to tell if a player losed + --> DRAW: When the game is over to tell the player it's a draw + 3.2 Map Data Format: This section describes the structure used to represent the game map. @@ -133,6 +110,35 @@ Table of Contents metadata necessary to ensure that the map is correctly rendered and interpreted by both clients and the server. + Map Layout: + + The map must be composed of 10 lines, each containing exactly the same + number of characters and at most 10 000 characters.The characters used in + the map are as follows: + + c: Represents a coin. + e: Represents a laser. + _: Represents empty space but any character other than c and e can be used. + + Map Representation + + Below is the map representation with each line containing 75 characters: + + ___________________________e________________________________________________ + ___________________________e______cccccc____________________________________ + ___________________________e_____ccccccc________________________eeeeeeeeeeee + ___________________________e____cc__________________________________________ + ___________________________e___cc______e_________________________cccc_______ + ______________________________cc_______e_________________________cccc_______ + ________________________ccccccc________e____________________________________ + ________________________cccccc_________e_________________eeeeeeeeeeeee______ + _______________________________________e____________________________________ + _______________________________________e____________________________________ + + This structured format ensures that the map is correctly interpreted by both + the client and server, facilitating accurate rendering and interaction + within the game. + 4. Security Considerations As the Jetpack Protocol is designed for use in a controlled academic From 2ae5b6812401a7097cc5dca31518bbf7fdfcab47 Mon Sep 17 00:00:00 2001 From: Valiance Date: Sun, 20 Apr 2025 17:15:34 +0200 Subject: [PATCH 3/5] fix(server): free last getline from map --- Server/src/clean_up.c | 7 +++++++ Server/src/map.c | 7 +++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Server/src/clean_up.c b/Server/src/clean_up.c index 80ca30d..c7f2300 100644 --- a/Server/src/clean_up.c +++ b/Server/src/clean_up.c @@ -6,6 +6,7 @@ */ #include "cleanup.h" +#include "map.h" #include "player.h" #include "server.h" #include @@ -56,6 +57,12 @@ void free_player(player_t **player) free((*player)->socket); (*player)->socket = NULL; } + for (size_t i = 0; i < MAP_HEIGHT; i += 1) { + if ((*player)->map[i]) { + free((*player)->map[i]); + (*player)->map[i] = NULL; + } + } free(*player); *player = NULL; } diff --git a/Server/src/map.c b/Server/src/map.c index b3961f7..93fdcd9 100644 --- a/Server/src/map.c +++ b/Server/src/map.c @@ -65,8 +65,7 @@ static void send_map_line(server_t *server, size_t i) } debug(server, server->map[i], TRUE); server->players[j]->map[i] = strdup(server->map[i]); - if (send(server->players[j]->socket->fd, "\n", - 1, 0) < 0) { + if (send(server->players[j]->socket->fd, "\n", 1, 0) < 0) { fprintf(stderr, "Unable to send map\n"); server->destroy(&server); exit(EXIT_FAILURE); @@ -167,6 +166,10 @@ void load_map(server_t *server) buff = NULL; } } + if (buff != NULL) { + free(buff); + buff = NULL; + } check_map_height(server, nb_lines); fclose(file); } From f46e30d74a40ba9d6528083e7a933384e54fc15a Mon Sep 17 00:00:00 2001 From: Valiance Date: Sun, 20 Apr 2025 17:16:59 +0200 Subject: [PATCH 4/5] refacto(server): fix coding style --- Server/src/clean_up.c | 2 +- Server/src/map.c | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Server/src/clean_up.c b/Server/src/clean_up.c index c7f2300..097ea00 100644 --- a/Server/src/clean_up.c +++ b/Server/src/clean_up.c @@ -62,7 +62,7 @@ void free_player(player_t **player) free((*player)->map[i]); (*player)->map[i] = NULL; } - } + } free(*player); *player = NULL; } diff --git a/Server/src/map.c b/Server/src/map.c index 93fdcd9..f2125fa 100644 --- a/Server/src/map.c +++ b/Server/src/map.c @@ -166,10 +166,8 @@ void load_map(server_t *server) buff = NULL; } } - if (buff != NULL) { + if (buff != NULL) free(buff); - buff = NULL; - } check_map_height(server, nb_lines); fclose(file); } From 3234acc439632715de519961fb29dd722f2bad11 Mon Sep 17 00:00:00 2001 From: Valiance Date: Sun, 20 Apr 2025 17:23:11 +0200 Subject: [PATCH 5/5] fix(server): send win when the other player disconnect --- Server/src/instructions.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Server/src/instructions.c b/Server/src/instructions.c index 36ea220..5615211 100644 --- a/Server/src/instructions.c +++ b/Server/src/instructions.c @@ -157,6 +157,10 @@ static int check_early_return(server_t *server, player_t *player) return TRUE; if (check_collision(server, player)) return TRUE; + if (server->nb_player == 1) { + send_first_win(server, player->score, 0); + return TRUE; + } return FALSE; }