feat(lobby): implement bounded WebSocket sessions and countdown

This commit is contained in:
2026-09-04 02:13:26 +03:00
parent b10c7f5972
commit 996bda9567
21 changed files with 2040 additions and 64 deletions
@@ -0,0 +1,82 @@
#ifndef MAZE32_LOBBY_H
#define MAZE32_LOBBY_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MAZE32_PLAYER_LIMIT 2U
#define MAZE32_OBSERVER_LIMIT 4U
#define MAZE32_SESSION_LIMIT (MAZE32_PLAYER_LIMIT + MAZE32_OBSERVER_LIMIT)
#define MAZE32_PLAYER_NAME_MAX_BYTES 32U
#define MAZE32_SESSION_TOKEN_BYTES 16U
#define MAZE32_SESSION_TOKEN_HEX_LENGTH (MAZE32_SESSION_TOKEN_BYTES * 2U)
#define MAZE32_COUNTDOWN_DURATION_MS 3000U
typedef enum {
MAZE32_ROLE_NONE = 0,
MAZE32_ROLE_PLAYER,
MAZE32_ROLE_OBSERVER,
} maze32_role_t;
typedef enum {
MAZE32_LOBBY_WAITING = 0,
MAZE32_LOBBY_COUNTDOWN,
MAZE32_LOBBY_ACTIVE,
} maze32_lobby_phase_t;
typedef enum {
MAZE32_LOBBY_OK = 0,
MAZE32_LOBBY_INVALID_NAME,
MAZE32_LOBBY_DUPLICATE_NAME,
MAZE32_LOBBY_ROLE_FULL,
MAZE32_LOBBY_INVALID_TOKEN,
MAZE32_LOBBY_SESSION_CONNECTED,
MAZE32_LOBBY_NOT_OWNER,
MAZE32_LOBBY_NOT_READY,
MAZE32_LOBBY_INVALID_PHASE,
} maze32_lobby_result_t;
typedef struct {
int connection_id;
maze32_role_t role;
unsigned int player_slot;
int connected;
char name[MAZE32_PLAYER_NAME_MAX_BYTES + 1U];
char token[MAZE32_SESSION_TOKEN_HEX_LENGTH + 1U];
} maze32_session_t;
typedef struct {
maze32_session_t sessions[MAZE32_SESSION_LIMIT];
maze32_lobby_phase_t phase;
uint64_t countdown_started_ms;
uint64_t activation_ms;
uint32_t revision;
} maze32_lobby_t;
void maze32_lobby_init(maze32_lobby_t* lobby);
maze32_lobby_result_t maze32_lobby_join_player(maze32_lobby_t* lobby, int connection_id,
const char* name, const char* token,
maze32_session_t** session);
maze32_lobby_result_t maze32_lobby_join_observer(maze32_lobby_t* lobby, int connection_id,
const char* token, maze32_session_t** session);
maze32_lobby_result_t maze32_lobby_restore(maze32_lobby_t* lobby, int connection_id,
const char* token, maze32_session_t** session);
void maze32_lobby_disconnect(maze32_lobby_t* lobby, int connection_id);
maze32_lobby_result_t maze32_lobby_start(maze32_lobby_t* lobby, int connection_id, uint64_t now_ms);
int maze32_lobby_activate_if_due(maze32_lobby_t* lobby, uint64_t now_ms);
const maze32_session_t* maze32_lobby_session_for_connection(const maze32_lobby_t* lobby,
int connection_id);
unsigned int maze32_lobby_connected_observers(const maze32_lobby_t* lobby);
int maze32_lobby_ready(const maze32_lobby_t* lobby);
int maze32_lobby_can_reconfigure(const maze32_lobby_t* lobby);
const char* maze32_lobby_phase_name(maze32_lobby_phase_t phase);
#ifdef __cplusplus
}
#endif
#endif