diff --git a/subghz/plugins/rock_paper_scissors/rock_paper_scissors.c b/subghz/plugins/rock_paper_scissors/rock_paper_scissors.c index 34f2096..dbfca1b 100644 --- a/subghz/plugins/rock_paper_scissors/rock_paper_scissors.c +++ b/subghz/plugins/rock_paper_scissors/rock_paper_scissors.c @@ -268,12 +268,41 @@ static void rps_receive_data(GameContext* game_context, uint32_t tick) { break; } + case GameRfPurposePlayAgain: { + // IMPORTANT: The code processing the event needs to furi_string_free the senderName! + FuriString* name = furi_string_alloc(); + furi_string_set(name, sender_name); + + GameEvent event = { + .type = GameEventRemotePlayAgain, .sender_name = name, .game_number = game_number}; + furi_message_queue_put(game_context->queue, &event, FuriWaitForever); + break; + } + + case GameRfPurposeQuit: { + // IMPORTANT: The code processing the event needs to furi_string_free the senderName! + FuriString* name = furi_string_alloc(); + furi_string_set(name, sender_name); + + GameEvent event = { + .type = GameEventRemoteQuit, .sender_name = name, .game_number = game_number}; + furi_message_queue_put(game_context->queue, &event, FuriWaitForever); + break; + } + case GameRfPurposeJoin: if(index >= len) { FURI_LOG_W(TAG, "Failed to parse join message. >%s<", message); return; } else { sender_contact = (char*)message + index; + while(index < len) { + if(message[index] == '\n' || message[index] == '\r') { + message[index] = 0; + break; + } + index++; + } FURI_LOG_T(TAG, "Join had contact of >%s<", sender_contact); // IMPORTANT: The code processing the event needs to furi_string_free the senderName! @@ -297,6 +326,13 @@ static void rps_receive_data(GameContext* game_context, uint32_t tick) { return; } else { sender_contact = (char*)message + index; + while(index < len) { + if(message[index] == '\n' || message[index] == '\r') { + message[index] = 0; + break; + } + index++; + } FURI_LOG_T(TAG, "Join acknowledge for game %d.", game_number); FURI_LOG_T(TAG, "Join ack had contact of >%s<", sender_contact); @@ -1015,6 +1051,38 @@ static void rps_broadcast_not_beacon(GameContext* game_context) { rps_broadcast(game_context, data->buffer); } +static void rps_broadcast_play_again(GameContext* game_context) { + GameData* data = game_context->data; + FURI_LOG_I(TAG, "Sending play again"); + + // The message for game 42 should look like... "YourFlip: RPS:PA042\r\n" + furi_string_printf( + data->buffer, + "%s: %s:%c%c%03u\r\n", + furi_hal_version_get_name_ptr(), + RPS_GAME_NAME, + GameRfPurposePlayAgain, + MAJOR_VERSION, + data->game_number); + rps_broadcast(game_context, data->buffer); +} + +static void rps_broadcast_quit(GameContext* game_context) { + GameData* data = game_context->data; + FURI_LOG_I(TAG, "Sending quit"); + + // The message for game 42 should look like... "YourFlip: RPS:QA042\r\n" + furi_string_printf( + data->buffer, + "%s: %s:%c%c%03u\r\n", + furi_hal_version_get_name_ptr(), + RPS_GAME_NAME, + GameRfPurposeQuit, + MAJOR_VERSION, + data->game_number); + rps_broadcast(game_context, data->buffer); +} + // Send message that indicates Flipper is joining a specific game. // We broadcast - "YourFlip: " + "RPS:" + join"J" + version"A" + game"###" + "NYourNameHere" + "\r\n" // @param game_context pointer to a GameContext. @@ -2240,17 +2308,19 @@ int32_t rock_paper_scissors_app(void* p) { event.input.type == InputTypeShort) { switch(event.input.key) { case InputKeyLeft: - game_context->data->keyboard_col = 0; // YES + game_context->data->keyboard_col = 0; // YES - Play again break; case InputKeyRight: - game_context->data->keyboard_col = 1; // NO + game_context->data->keyboard_col = 1; // NO - Back to main menu break; case InputKeyOk: if(game_context->data->keyboard_col == 1) { + rps_broadcast_quit(game_context); game_context->data->local_player = StateMainMenuHost; game_context->data->remote_player = StateUnknown; game_context->data->screen_state = ScreenMainMenu; } else { + rps_broadcast_play_again(game_context); game_context->data->remote_player = StateReady; game_context->data->remote_move_tick = furi_get_tick(); game_context->data->local_player = StateReady; @@ -2335,6 +2405,18 @@ int32_t rock_paper_scissors_app(void* p) { FURI_LOG_I(TAG, "Remote not beacon detected. game number %03u", event.game_number); remote_games_remove(game_context, &event); break; + case GameEventRemotePlayAgain: + game_context->data->remote_player = StateReady; + game_context->data->remote_move_tick = furi_get_tick(); + game_context->data->local_player = StateReady; + game_context->data->local_move_tick = furi_get_tick(); + game_context->data->screen_state = ScreenPlayingGame; + break; + case GameEventRemoteQuit: + game_context->data->local_player = StateMainMenuHost; + game_context->data->remote_player = StateUnknown; + game_context->data->screen_state = ScreenMainMenu; + break; case GameEventRemoteJoined: if(furi_mutex_acquire(game_context->mutex, FuriWaitForever) == FuriStatusOk) { if(event.game_number == game_context->data->game_number) { diff --git a/subghz/plugins/rock_paper_scissors/rock_paper_scissors.h b/subghz/plugins/rock_paper_scissors/rock_paper_scissors.h index e6b92ff..c70ee00 100644 --- a/subghz/plugins/rock_paper_scissors/rock_paper_scissors.h +++ b/subghz/plugins/rock_paper_scissors/rock_paper_scissors.h @@ -170,6 +170,8 @@ typedef enum { GameRfPurposeJoin = 'J', // Join a game. GameRfPurposeJoinAcknowledge = 'A', // Acknowledge a join request. GameRfPurposeMove = 'M', // Player move. + GameRfPurposePlayAgain = 'P', // Play another game. + GameRfPurposeQuit = 'Q', // Quit, don't play another game. } GameRfPurpose; // Messages in our event queue are one of the following types. @@ -182,6 +184,8 @@ typedef enum { GameEventRemoteJoined, GameEventRemoteJoinAcknowledged, GameEventLocalMove, + GameEventRemotePlayAgain, + GameEventRemoteQuit, GameEventRemoteMove, GameEventSendMove, GameEventPlaySong,