bug(engine): auto-complete does not block player drag/tap input #71

Closed
opened 2026-05-28 21:19:06 +00:00 by funman300 · 1 comment
Owner

Summary

When auto-complete is running (AutoCompleteState::active == true), the player can still start a drag or fire a tap-move. Both the auto-complete MoveRequestEvent and the player-initiated one are processed in the same frame, which can corrupt the game state mid-sequence.

Location

solitaire_engine/src/input_plugin.rs:

  • start_drag (~line 571) — no AutoCompleteState check
  • touch_start_drag (~line 858) — no AutoCompleteState check
  • handle_double_tap (~line 1500) — no AutoCompleteState check

Steps to reproduce

  1. Play until the board is auto-completable (all tableau cards face-up)
  2. Rapidly drag a card immediately as auto-complete starts
  3. The dragged card move fires alongside the auto-complete move; game state can desync

Fix

Add an early return in start_drag, touch_start_drag, and handle_double_tap:

if auto_complete.is_some_and(|ac| ac.active) { return; }

Severity

Medium — race condition during a common end-game animation.

## Summary When auto-complete is running (`AutoCompleteState::active == true`), the player can still start a drag or fire a tap-move. Both the auto-complete `MoveRequestEvent` and the player-initiated one are processed in the same frame, which can corrupt the game state mid-sequence. ## Location `solitaire_engine/src/input_plugin.rs`: - `start_drag` (~line 571) — no `AutoCompleteState` check - `touch_start_drag` (~line 858) — no `AutoCompleteState` check - `handle_double_tap` (~line 1500) — no `AutoCompleteState` check ## Steps to reproduce 1. Play until the board is auto-completable (all tableau cards face-up) 2. Rapidly drag a card immediately as auto-complete starts 3. The dragged card move fires alongside the auto-complete move; game state can desync ## Fix Add an early return in `start_drag`, `touch_start_drag`, and `handle_double_tap`: ```rust if auto_complete.is_some_and(|ac| ac.active) { return; } ``` ## Severity Medium — race condition during a common end-game animation.
Author
Owner

Fix (commit f444378)

Added an AutoCompleteState early-return guard to three input entry points so no player-initiated move can race with the auto-complete sequence:

start_drag (mouse drag start)

// Added parameter
auto_complete: Option<Res<AutoCompleteState>>,
// Added guard
if auto_complete.is_some_and(|ac| ac.active) { return; }

touch_start_drag (touch drag start)

auto_complete: Option<Res<AutoCompleteState>>,
if auto_complete.is_some_and(|ac| ac.active) { return; }

handle_double_tap (tap-to-move / tap-to-select)

auto_complete: Option<Res<AutoCompleteState>>,
// Auto-complete owns all moves during its sequence.
if auto_complete.is_some_and(|ac| ac.active) { return; }

All three use Option<Res<...>> so they degrade gracefully under MinimalPlugins (no AutoCompletePlugin registered). When active is true, input is simply ignored — drag state is never dirtied and no MoveRequestEvent is emitted — leaving the auto-complete sequence as the sole source of moves until the game is won.

## Fix (commit `f444378`) Added an `AutoCompleteState` early-return guard to three input entry points so no player-initiated move can race with the auto-complete sequence: **`start_drag`** (mouse drag start) ```rust // Added parameter auto_complete: Option<Res<AutoCompleteState>>, // Added guard if auto_complete.is_some_and(|ac| ac.active) { return; } ``` **`touch_start_drag`** (touch drag start) ```rust auto_complete: Option<Res<AutoCompleteState>>, if auto_complete.is_some_and(|ac| ac.active) { return; } ``` **`handle_double_tap`** (tap-to-move / tap-to-select) ```rust auto_complete: Option<Res<AutoCompleteState>>, // Auto-complete owns all moves during its sequence. if auto_complete.is_some_and(|ac| ac.active) { return; } ``` All three use `Option<Res<...>>` so they degrade gracefully under `MinimalPlugins` (no `AutoCompletePlugin` registered). When `active` is `true`, input is simply ignored — drag state is never dirtied and no `MoveRequestEvent` is emitted — leaving the auto-complete sequence as the sole source of moves until the game is won.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: funman300/Ferrous-Solitaire#71