diff --git a/include/sk_player.h b/include/sk_player.h index 39efe08..139ab6a 100644 --- a/include/sk_player.h +++ b/include/sk_player.h @@ -42,7 +42,7 @@ static const char * const sk_player_kinds[] = { [SK_PLAYER_KIND_JETT] = "jett" }; -sk_player sk_player_create(sk_player_kind kind); +sk_player sk_player_create(i8 lobby_id, i8 lobby_slot_idx, sk_player_kind kind); void sk_player_destroy(sk_player *p); diff --git a/include/sk_server.h b/include/sk_server.h index 6d1d8b2..25b4053 100644 --- a/include/sk_server.h +++ b/include/sk_server.h @@ -28,7 +28,7 @@ #define SK_SERVER_TICK_RATE 128 #define SK_SERVER_MSG_MAX_SIZE 1024 #define SK_SERVER_MSG_HELLO SK_SERVER_NAME "::hello" -#define SK_SERVER_MSG_HOWDY SK_SERVER_NAME "::howdy::%u/%u" +#define SK_SERVER_MSG_HOWDY SK_SERVER_NAME "::howdy::%hhd/%hhd" i32 sk_server_socket_create(void); diff --git a/include/sk_state.h b/include/sk_state.h index dfdaa94..399fda8 100644 --- a/include/sk_state.h +++ b/include/sk_state.h @@ -42,6 +42,8 @@ typedef struct { sk_state_global sk_state_global_create(void); +void sk_state_global_assign_lobby(sk_state_global *sg, i8 *lobby_id, i8 *lobby_slot_idx); + sk_state sk_state_create_offline(void); sk_state sk_state_create_online(u8 lobby_id); diff --git a/src/sk_client.c b/src/sk_client.c index 6539973..9ee316e 100644 --- a/src/sk_client.c +++ b/src/sk_client.c @@ -19,7 +19,9 @@ */ +#include #include +#include #include #include #include @@ -66,18 +68,22 @@ static i8 online_mode(const char *ip) { i32 howdy_msg_n = recv(sock_fd, howdy_msg, sizeof(howdy_msg), MSG_WAITALL); if (howdy_msg_n == -1) { SK_LOG_ERROR("recv(2) :: %s", strerror(errno)); + SK_LOG_ERROR("Unable to communicate with `%s`. Exiting...", ip); close(sock_fd); return -1; } howdy_msg[howdy_msg_n] = 0; - // TODO: hardcoded now to 0/0 ... change this to save the received IDs - if (strcmp(howdy_msg, TextFormat(SK_SERVER_MSG_HOWDY, 0, 0))) { - SK_LOG_ERROR("Unable to communicate with `%s`. Exiting...", ip); + i8 assigned_lobby_id = -1; + i8 assigned_lobby_slot_idx = -1; + u8 matched_data = sscanf(howdy_msg, SK_SERVER_MSG_HOWDY, &assigned_lobby_id, &assigned_lobby_slot_idx); + assert(matched_data == 2); + if (assigned_lobby_id == -1 || assigned_lobby_slot_idx == -1) { + SK_LOG_ERROR("Connection rejected from `%s`. Exiting...", ip); close(sock_fd); return -1; } - SK_LOG_INFO("Connected successfully to `%s`", ip); - SK_LOG_WARN("Exit due to not being implemented yet"); + SK_LOG_INFO("Connected successfully to `%s` (lobby %i, slot %i)", ip, assigned_lobby_id, assigned_lobby_slot_idx); + SK_LOG_WARN("Exiting due to not being fully implemented yet"); sk_server_socket_destroy(sock_fd); return 0; } diff --git a/src/sk_player.c b/src/sk_player.c index 27d584f..0645099 100644 --- a/src/sk_player.c +++ b/src/sk_player.c @@ -20,20 +20,22 @@ #include +#include #include #include -#define FILEPATH_BUFFER_MAX_SIZE 64 #define PLAYER_HEIGHT 2 #define GRAVITY 19 #define JUMP_INIT_VELOCITY 9 #define PEEK_ACCELERATION 1.5 #define WALK_VELOCITY 0.1 -sk_player sk_player_create(sk_player_kind kind) { +sk_player sk_player_create(i8 lobby_id, i8 lobby_slot_idx, sk_player_kind kind) { + assert(lobby_id != -1); + assert(lobby_slot_idx != -1); return (sk_player) { - .lobby_id = -1, - .lobby_slot_idx = -1, + .lobby_id = lobby_id, + .lobby_slot_idx = lobby_slot_idx, .kind = kind, .camera = (Camera3D) { .position = (Vector3) { 0, PLAYER_HEIGHT, 4 }, @@ -52,9 +54,7 @@ void sk_player_destroy(sk_player *p) { } void sk_player_load(sk_player *p, sk_weapon_kind initial_weapon_kind) { - char filepath[FILEPATH_BUFFER_MAX_SIZE] = {0}; - sprintf(filepath, "assets/models/%s.glb", sk_player_kinds[p->kind]); - p->model = LoadModel(filepath); + p->model = LoadModel(TextFormat("assets/models/%s.glb", sk_player_kinds[p->kind])); p->weapon = sk_weapon_create(initial_weapon_kind); } diff --git a/src/sk_server.c b/src/sk_server.c index 79d5f1d..731a869 100644 --- a/src/sk_server.c +++ b/src/sk_server.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -83,12 +84,13 @@ i32 sk_server_socket_bind(i32 sock_fd) { SK_LOG_ERROR("sk_server_socket_bind :: %s", strerror(errno)); sk_server_socket_destroy(sock_fd); } - else SK_LOG_INFO("UDP socket binded to 127.0.0.1:%d", SK_SERVER_PORT); + else SK_LOG_INFO("UDP socket binded to 127.0.0.1:%u", SK_SERVER_PORT); return result; } u8 sk_server_run(void) { SK_LOG_INFO("Initializing %s", SK_SERVER_NAME); + sk_state_global state_global = sk_state_global_create(); i32 sock_fd = sk_server_socket_create(); if (sock_fd == -1) return 1; if (sk_server_socket_bind(sock_fd) == -1) return 1; @@ -115,22 +117,26 @@ u8 sk_server_run(void) { } msg[msg_n] = 0; if (!strcmp(msg, SK_SERVER_MSG_HELLO)) { - SK_LOG_INFO("Connection from client (%s:%d) requested", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); - u8 assigned_lobby_id = 0; - u8 assigned_lobby_slot_id = 0; - // TODO: check if there is a free slot in a lobby - // TODO: assign him a lobby and a player slot inside it - const char * const response = TextFormat(SK_SERVER_MSG_HOWDY, assigned_lobby_id, assigned_lobby_slot_id); + SK_LOG_INFO("Connection from client (%s:%u) requested", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + i8 assigned_lobby_id = -1; + i8 assigned_lobby_slot_idx = -1; + sk_state_global_assign_lobby(&state_global, &assigned_lobby_id, &assigned_lobby_slot_idx); if (sendto(sock_fd, - response, - strlen(response), + TextFormat(SK_SERVER_MSG_HOWDY, assigned_lobby_id, assigned_lobby_slot_idx), + strlen(TextFormat(SK_SERVER_MSG_HOWDY, assigned_lobby_id, assigned_lobby_slot_idx)), 0, (struct sockaddr *) &client_addr, client_addr_len) == -1) { SK_LOG_ERROR("sendto(2) :: %s", strerror(errno)); + SK_LOG_WARN("Connection from client (%s:%u) dropped", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); continue; } - SK_LOG_INFO("Connection from client (%s:%d) accepted", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + if (assigned_lobby_id == -1 || assigned_lobby_slot_idx == -1) { + SK_LOG_INFO("Connection from client (%s:%u) rejected", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + continue; + } + SK_LOG_INFO("Connection from client (%s:%u) accepted", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + state_global.lobbies[assigned_lobby_id].players[assigned_lobby_slot_idx] = sk_player_create(assigned_lobby_id, assigned_lobby_slot_idx, SK_PLAYER_KIND_JETT); } wait_next_tick(dt); } diff --git a/src/sk_state.c b/src/sk_state.c index 67b64d6..03df879 100644 --- a/src/sk_state.c +++ b/src/sk_state.c @@ -19,14 +19,35 @@ */ +#include #include sk_state_global sk_state_global_create(void) { - sk_state_global s = { .lobbies_count = 0 }; + sk_state_global sg = { .lobbies_count = 0 }; for (u16 i = 0; i < SK_STATE_MAX_LOBBIES; ++i) { - s.lobbies[i] = sk_lobby_create(i); + sg.lobbies[i] = sk_lobby_create(i); } - return s; + return sg; +} + +void sk_state_global_assign_lobby(sk_state_global *sg, i8 *lobby_id, i8 *lobby_slot_idx) { + for (u16 i = 0; i < SK_STATE_MAX_LOBBIES; ++i) { + if (sg->lobbies[i].players_count == SK_LOBBY_MAX_PLAYERS) continue; + for (u8 j = 0; j < SK_LOBBY_MAX_PLAYERS; ++j) { + if (sg->lobbies[i].players[j].lobby_id == -1 && + sg->lobbies[i].players[j].lobby_slot_idx == -1) { + *lobby_id = i; + *lobby_slot_idx = j; + SK_LOG_INFO("sk_state_global_assign_lobby :: assigned lobby %i, slot %i", + *lobby_id, + *lobby_slot_idx); + return; + } + } + } + *lobby_id = -1; + *lobby_slot_idx = -1; + SK_LOG_WARN("sk_state_global_assign_lobby :: all lobbies are full"); } sk_state sk_state_create_online(u8 lobby_id) { @@ -41,6 +62,6 @@ sk_state sk_state_create_offline(void) { return (sk_state) { .is_online = 0, .curr_scene = (sk_scene) { .kind = SK_SCENE_KIND_MAIN_MENU }, - .player = sk_player_create(SK_PLAYER_KIND_JETT) + .player = sk_player_create(0, 0, SK_PLAYER_KIND_JETT) }; } diff --git a/src/sk_weapon.c b/src/sk_weapon.c index 10a3d77..95c82b2 100644 --- a/src/sk_weapon.c +++ b/src/sk_weapon.c @@ -24,20 +24,15 @@ #include #include -#define FILEPATH_BUFFER_MAX_SIZE 64 - sk_weapon sk_weapon_create(sk_weapon_kind kind) { sk_weapon w = {0}; - char filepath[FILEPATH_BUFFER_MAX_SIZE] = {0}; - sprintf(filepath, "assets/models/%s.glb", sk_weapon_kinds[kind]); - w.model = LoadModel(filepath); - w.model_anims = LoadModelAnimations(filepath, (int *) &w.model_anims_count); + w.model = LoadModel(TextFormat("assets/models/%s.glb", sk_weapon_kinds[kind])); + w.model_anims = LoadModelAnimations(TextFormat("assets/models/%s.glb", sk_weapon_kinds[kind]), + (int *) &w.model_anims_count); assert(w.model_anims_count == 1); assert(IsModelAnimationValid(w.model, w.model_anims[0])); w.model_anim_frame_count = 0; - memset(filepath, 0, sizeof(filepath)); - sprintf(filepath, "assets/sounds/%s/shoot.wav", sk_weapon_kinds[kind]); - w.sound_shoot = LoadSound(filepath); + w.sound_shoot = LoadSound(TextFormat("assets/sounds/%s/shoot.wav", sk_weapon_kinds[kind])); w.kind = kind; return w; }