feat: implement safe leave, profile reset, and full game reset semantics
This commit is contained in:
+45
-2
@@ -68,11 +68,24 @@ static lifecycle_result_t start_current_game(game_lifecycle_t *lifecycle) {
|
||||
return LIFECYCLE_RESULT_OK;
|
||||
}
|
||||
|
||||
static void return_to_lobby(game_lifecycle_t *lifecycle) {
|
||||
const uint32_t version = lifecycle->game.state.version + 1U;
|
||||
const uint32_t game_id = lifecycle->next_game_id++;
|
||||
game_engine_init(&lifecycle->game);
|
||||
lifecycle->game.state.game_id = game_id;
|
||||
lifecycle->game.state.version = version;
|
||||
lifecycle->bot_reserved = false;
|
||||
lifecycle->rematch_confirmed[0] = false;
|
||||
lifecycle->rematch_confirmed[1] = false;
|
||||
bot_player_cancel_turn(&lifecycle->bot);
|
||||
}
|
||||
|
||||
void game_lifecycle_init(game_lifecycle_t *lifecycle, random_source_t random) {
|
||||
if (lifecycle == NULL) return;
|
||||
memset(lifecycle, 0, sizeof(*lifecycle));
|
||||
lifecycle->random = random;
|
||||
lifecycle->next_game_id = 2U;
|
||||
lifecycle->recovery_generation = 1U;
|
||||
game_engine_init(&lifecycle->game);
|
||||
lifecycle->game.state.game_id = 1U;
|
||||
session_manager_init(&lifecycle->sessions);
|
||||
@@ -110,8 +123,38 @@ lifecycle_result_t game_lifecycle_disconnect(game_lifecycle_t *lifecycle, uint8_
|
||||
}
|
||||
|
||||
lifecycle_result_t game_lifecycle_leave(game_lifecycle_t *lifecycle, uint8_t session_index) {
|
||||
return lifecycle == NULL ? LIFECYCLE_RESULT_UNAUTHORIZED :
|
||||
session_result(session_manager_leave(&lifecycle->sessions, session_index, lifecycle->game.state.phase));
|
||||
if (lifecycle == NULL || session_index >= kSessionCapacity || !lifecycle->sessions.entries[session_index].occupied) return LIFECYCLE_RESULT_UNAUTHORIZED;
|
||||
const bool player = session_index < kPlayerCapacity && lifecycle->sessions.entries[session_index].role == (role_t)session_index;
|
||||
if (player && lifecycle->game.state.phase != PHASE_LOBBY) return_to_lobby(lifecycle);
|
||||
memset(&lifecycle->sessions.entries[session_index], 0, sizeof(session_t));
|
||||
++lifecycle->recovery_generation;
|
||||
lifecycle->recovery_reason = RECOVERY_REASON_SESSION_LEFT;
|
||||
return LIFECYCLE_RESULT_OK;
|
||||
}
|
||||
|
||||
lifecycle_result_t game_lifecycle_reset(game_lifecycle_t *lifecycle, uint8_t session_index, uint32_t game_id) {
|
||||
uint8_t player = 0;
|
||||
if (!is_player(lifecycle, session_index, &player)) return LIFECYCLE_RESULT_FORBIDDEN_ROLE;
|
||||
if (!game_id_matches(lifecycle, game_id)) return LIFECYCLE_RESULT_STALE_GAME;
|
||||
const uint32_t version = lifecycle->game.state.version + 1U;
|
||||
const uint32_t next_game_id = lifecycle->next_game_id++;
|
||||
const random_source_t random = lifecycle->random;
|
||||
const scheduler_t scheduler = lifecycle->bot_scheduler;
|
||||
bot_player_cancel_turn(&lifecycle->bot);
|
||||
memset(lifecycle, 0, sizeof(*lifecycle));
|
||||
lifecycle->random = random;
|
||||
lifecycle->bot_scheduler = scheduler;
|
||||
lifecycle->next_game_id = next_game_id + 1U;
|
||||
lifecycle->recovery_generation = next_game_id;
|
||||
lifecycle->recovery_reason = RECOVERY_REASON_GAME_RESET;
|
||||
game_engine_init(&lifecycle->game);
|
||||
lifecycle->game.state.game_id = next_game_id;
|
||||
lifecycle->game.state.version = version;
|
||||
return LIFECYCLE_RESULT_OK;
|
||||
}
|
||||
|
||||
void game_lifecycle_set_recovery_reason(game_lifecycle_t *lifecycle, recovery_reason_t reason) {
|
||||
if (lifecycle != NULL) lifecycle->recovery_reason = reason;
|
||||
}
|
||||
|
||||
lifecycle_result_t game_lifecycle_configure(game_lifecycle_t *lifecycle, uint8_t session_index,
|
||||
|
||||
Reference in New Issue
Block a user