fix(engine): toast on challenge exhaustion, block input during auto-complete (#71, #72)

- challenge_plugin: replace silent warn+return with InfoToast when all
  challenges are completed so the player gets clear feedback (#72)
- input_plugin: add AutoCompleteState guard to start_drag,
  touch_start_drag, and handle_double_tap so player input cannot race
  with the auto-complete move sequence (#71)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
funman300
2026-05-28 14:24:09 -07:00
parent 927598202e
commit f444378184
2 changed files with 17 additions and 1 deletions
+3 -1
View File
@@ -93,7 +93,9 @@ fn handle_start_challenge_request(
return;
}
let Some(seed) = challenge_seed_for(progress.0.challenge_index) else {
warn!("challenge seed list is empty");
info_toast.write(InfoToastEvent(
"You've completed all challenges! More coming soon.".into(),
));
return;
};
new_game.write(NewGameRequestEvent {
+14
View File
@@ -31,6 +31,7 @@ use solitaire_core::game_state::GameState;
use solitaire_core::pile::PileType;
use solitaire_core::rules::{can_place_on_foundation, can_place_on_tableau};
use crate::auto_complete_plugin::AutoCompleteState;
use crate::card_animation::tuning::AnimationTuning;
use crate::card_animation::{CardAnimation, MotionCurve};
use crate::card_plugin::{CardEntity, HintHighlight, HintHighlightTimer, STACK_FAN_FRAC};
@@ -572,6 +573,7 @@ fn start_drag(
buttons: Res<ButtonInput<MouseButton>>,
touches: Option<Res<Touches>>,
paused: Option<Res<PausedResource>>,
auto_complete: Option<Res<AutoCompleteState>>,
windows: Query<&Window, With<PrimaryWindow>>,
cameras: Query<(&Camera, &GlobalTransform)>,
layout: Option<Res<LayoutResource>>,
@@ -581,6 +583,9 @@ fn start_drag(
if paused.is_some_and(|p| p.0) {
return;
}
if auto_complete.is_some_and(|ac| ac.active) {
return;
}
// Only start a new drag when idle (no touch drag running either).
if !buttons.just_pressed(MouseButton::Left) || !drag.is_idle() {
return;
@@ -858,6 +863,7 @@ fn end_drag(
fn touch_start_drag(
mut touch_events: MessageReader<TouchInput>,
paused: Option<Res<PausedResource>>,
auto_complete: Option<Res<AutoCompleteState>>,
cameras: Query<(&Camera, &GlobalTransform)>,
layout: Option<Res<LayoutResource>>,
game: Res<GameStateResource>,
@@ -866,6 +872,9 @@ fn touch_start_drag(
if paused.is_some_and(|p| p.0) {
return;
}
if auto_complete.is_some_and(|ac| ac.active) {
return;
}
// Only one drag at a time.
if !drag.is_idle() {
return;
@@ -1503,6 +1512,7 @@ fn handle_double_tap(
mut touch_events: MessageReader<TouchInput>,
paused: Option<Res<PausedResource>>,
radial: Option<Res<RightClickRadialState>>,
auto_complete: Option<Res<AutoCompleteState>>,
drag: Res<DragState>,
game: Res<GameStateResource>,
settings: Option<Res<SettingsResource>>,
@@ -1522,6 +1532,10 @@ fn handle_double_tap(
if radial.is_some_and(|r| r.is_active()) {
return;
}
// Auto-complete owns all moves during its sequence.
if auto_complete.is_some_and(|ac| ac.active) {
return;
}
let Some(active_id) = drag.active_touch_id else {
return;