refactor(engine): ambiguity gate covers the full cluster — batches 1-3, 585 pairs burned to zero
Port the July 7 gate-extender branch onto current master (the You-hub, touch action bar, glass tab bar, Phase L, and hint-ghost work all landed since) and finish batch 3. cluster_app now includes the mode, replay, input, radial, tooltip, cursor, touch-selection, and safe-area plugins on top of batches 1-2; the 585 ambiguous pairs the expansion exposed are annotated down to zero and the gate stays assert_eq!(count, 0). New ordering machinery: - ReplayPlayback: playback driver chain on the pre-mutation spine (PointerInput < ReplayPlayback < overlay chain < GameMutation) - ModeStart: mode-start handlers between the stats abandon-recorder and GameMutation; ChallengeCompletion < DailyCompletion < WeeklyGoalsEval pinned inside ProgressUpdate so `.after(ProgressUpdate)` readers see settled progress - PointerInput: public set wrapping the input chain; AbandonRecord on the stats abandon-recorder; PendingHint around the async hint pipeline; HintGhostFx for the ghost chain (after the full visual spine) - Clubs: MoveRequestWriters, WarningToastWriters join the existing request/toast writer clubs; UiTextFx grows the overlay/tooltip/safe-area chrome painters; SettingsAccess grows the lag-tolerant settings readers Gate: cargo test --workspace green (993 engine tests), clippy --all-targets -D warnings clean, rustfmt applied. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -58,6 +58,14 @@ use crate::touch_selection_plugin::TouchSelectionState;
|
||||
use crate::ui_theme::{MOTION_DRAG_REJECT_SECS, STATE_SUCCESS, STATE_WARNING};
|
||||
use solitaire_core::DrawStockConfig;
|
||||
|
||||
/// Set wrapping the core pointer/keyboard input chain (clicks, drags, touch,
|
||||
/// hotkeys). Runs between [`crate::game_plugin::PreMutation`] (it reads the
|
||||
/// ticked game state) and [`crate::selection_plugin::SelectionKeySet`] (the
|
||||
/// selection keys check `DragState::is_idle`); request events it emits are
|
||||
/// consumed at `GameMutation` in the same frame (#143).
|
||||
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct PointerInput;
|
||||
|
||||
/// System-set labels used to anchor external systems relative to the touch
|
||||
/// drag pipeline without duplicating the internal chain ordering.
|
||||
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
||||
@@ -143,7 +151,13 @@ impl Plugin for InputPlugin {
|
||||
// `.chain()` still orders them relative to each other.
|
||||
handle_keyboard_core
|
||||
.in_set(crate::game_plugin::DrawRequestWriters)
|
||||
.ambiguous_with(crate::game_plugin::DrawRequestWriters),
|
||||
.ambiguous_with(crate::game_plugin::DrawRequestWriters)
|
||||
// N/Z/X/… and U also feed the shared new-game and
|
||||
// undo request streams (#143).
|
||||
.in_set(crate::game_plugin::NewGameRequestWriters)
|
||||
.ambiguous_with(crate::game_plugin::NewGameRequestWriters)
|
||||
.in_set(crate::game_plugin::UndoRequestWriters)
|
||||
.ambiguous_with(crate::game_plugin::UndoRequestWriters),
|
||||
handle_keyboard_hint,
|
||||
handle_keyboard_forfeit,
|
||||
handle_stock_click
|
||||
@@ -159,29 +173,61 @@ impl Plugin for InputPlugin {
|
||||
end_drag.before(GameMutation),
|
||||
// Touch drag pipeline (parallel path through DragState).
|
||||
touch_start_drag.in_set(TouchDragSet::AfterStartDrag),
|
||||
touch_follow_drag,
|
||||
// Moves the dragged card's Transform; UiTextFx members
|
||||
// animate chrome entities only — disjoint domains Bevy
|
||||
// can't prove (#143).
|
||||
touch_follow_drag.ambiguous_with(crate::ui_theme::UiTextFx),
|
||||
handle_double_tap, // before touch_end_drag: reads drag state pre-clear
|
||||
touch_end_drag
|
||||
.after(TouchDragSet::BeforeEndDrag)
|
||||
.before(GameMutation),
|
||||
// Reads StateChangedEvent via cursor — a reset one frame
|
||||
// after the mutation is invisible (the cycle index only
|
||||
// matters on the next H press), so it rides at the end
|
||||
// of the input chain instead of chasing every
|
||||
// StateChanged writer (#143).
|
||||
// It also drains the new-game request stream via its own
|
||||
// cursor, so it joins the writer club the same way
|
||||
// enqueue_toasts does (#143).
|
||||
reset_hint_cycle_on_state_change
|
||||
.in_set(crate::game_plugin::NewGameRequestWriters)
|
||||
.ambiguous_with(crate::game_plugin::NewGameRequestWriters),
|
||||
)
|
||||
.chain(),
|
||||
.chain()
|
||||
.in_set(PointerInput),
|
||||
)
|
||||
.add_systems(Update, reset_hint_cycle_on_state_change);
|
||||
.configure_sets(
|
||||
Update,
|
||||
PointerInput
|
||||
.after(crate::game_plugin::PreMutation)
|
||||
.before(crate::selection_plugin::SelectionKeySet)
|
||||
.before(crate::ui_focus::FocusKeys),
|
||||
);
|
||||
// F11 fullscreen toggle is desktop-only; Android windows are always full-screen.
|
||||
// It writes only `Window.mode`; no system reads the mode, and the
|
||||
// geometry change it triggers arrives via WindowResized events on a
|
||||
// later frame — order against Window readers is provably irrelevant
|
||||
// (#143).
|
||||
#[cfg(not(target_os = "android"))]
|
||||
app.add_systems(Update, handle_fullscreen);
|
||||
app.add_systems(Update, handle_fullscreen.ambiguous_with_all());
|
||||
app
|
||||
// Async hint pipeline: state-change drop runs before the
|
||||
// poll system so a move applied this frame cancels any
|
||||
// in-flight task before its result can be surfaced.
|
||||
// in-flight task before its result can be surfaced. The poll
|
||||
// emits the hint toast and the pile-highlight event the board
|
||||
// painters consume this frame (#143).
|
||||
.add_systems(
|
||||
Update,
|
||||
(
|
||||
crate::pending_hint::drop_pending_hint_on_state_change,
|
||||
crate::pending_hint::poll_pending_hint_task,
|
||||
crate::pending_hint::poll_pending_hint_task
|
||||
.in_set(crate::game_plugin::InfoToastWriters)
|
||||
.ambiguous_with(crate::game_plugin::InfoToastWriters),
|
||||
)
|
||||
.chain(),
|
||||
.chain()
|
||||
.in_set(crate::pending_hint::PendingHint)
|
||||
.after(GameMutation)
|
||||
.before(crate::auto_complete_plugin::AutoComplete),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user