refactor(engine,wasm,data): route all klondike/card_game imports through solitaire_core
Build and Deploy / build-and-push (push) Failing after 53s
Web E2E / web-e2e (push) Failing after 4m16s

All downstream crates now import Foundation, KlondikePile, Tableau,
Klondike, Session, Suit, Rank exclusively from solitaire_core.
solitaire_core is the single version-pin point for the upstream crates.

- solitaire_engine: 19 files updated, klondike direct dep removed
- solitaire_wasm: use statement updated, klondike direct dep removed
- solitaire_data: unused klondike dep removed
- Cargo.lock: klondike no longer a direct dep of engine/wasm/data
- Full workspace clippy clean, all tests pass

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-06-08 11:04:05 -07:00
parent ae1ecc8559
commit d864d985c8
27 changed files with 180 additions and 126 deletions
+37 -8
View File
@@ -6,7 +6,7 @@
use bevy::prelude::*;
use bevy::window::WindowResized;
use klondike::{Foundation, KlondikePile, Tableau};
use solitaire_core::{Foundation, KlondikePile, Tableau};
use solitaire_core::card::Suit;
use crate::events::{HintVisualEvent, StateChangedEvent};
@@ -22,15 +22,28 @@ use crate::ui_theme::TEXT_PRIMARY;
use solitaire_data::Theme;
/// Default tint applied to every empty-pile marker sprite. Pure white
/// at 8% alpha — soft enough that the marker reads as a "hint of a
/// slot" rather than a panel, but visible against every felt
/// background.
/// at 15% alpha — soft enough that the marker reads as a "hint of a
/// slot" rather than a panel, but discernible even against a very dark
/// felt background under bright ambient light (the old 8% alpha vanished
/// on a #151515 felt during on-device Android testing).
///
/// Re-exported as the source of truth for `cursor_plugin::MARKER_DEFAULT`,
/// which used to duplicate the literal alongside a "kept in sync" doc
/// comment. Pulling both call sites through this const makes drift a
/// compile error instead of a stale comment.
pub const PILE_MARKER_DEFAULT_COLOUR: Color = Color::srgba(1.0, 1.0, 1.0, 0.08);
pub const PILE_MARKER_DEFAULT_COLOUR: Color = Color::srgba(1.0, 1.0, 1.0, 0.15);
/// Tint applied to the thin outline rectangle sitting behind every
/// empty-pile marker. A slightly brighter white at 28% alpha gives the
/// slot a defined edge — the standard solitaire "empty pile" affordance —
/// without competing with real cards. Rendered as a marginally larger
/// child rectangle one z-step behind the fill, so the fill overlaps it
/// and only a hairline frame remains visible.
const PILE_MARKER_OUTLINE_COLOUR: Color = Color::srgba(1.0, 1.0, 1.0, 0.28);
/// Width in logical pixels of the visible outline frame around an empty
/// pile marker (the outline rect is this much larger on each side).
const PILE_MARKER_OUTLINE_WIDTH: f32 = 2.0;
/// Holds pre-loaded [`Handle<Image>`]s for the 5 selectable table backgrounds.
///
@@ -286,6 +299,22 @@ fn spawn_pile_markers(commands: &mut Commands, layout: &Layout) {
PileMarker(pile),
));
// Outline frame: a marginally larger rectangle sitting one z-step
// behind the fill. The fill overlaps its centre, leaving only a
// hairline border visible — a defined slot edge without an extra
// asset or 9-slice. Untagged so the `PileMarker` count is unchanged.
let outline_size = marker_size + Vec2::splat(PILE_MARKER_OUTLINE_WIDTH * 2.0);
entity.with_children(|b| {
b.spawn((
Sprite {
color: PILE_MARKER_OUTLINE_COLOUR,
custom_size: Some(outline_size),
..default()
},
Transform::from_xyz(0.0, 0.0, -0.05),
));
});
// Tableau markers show "K" (only a King may start an empty column).
// Foundation markers show "A" (only an Ace may claim an empty slot).
// Neither label carries a suit because any suit may start any slot.
@@ -577,7 +606,7 @@ mod tests {
.world_mut()
.query::<&PileMarker>()
.iter(app.world())
.map(|m| m.0.clone())
.map(|m| m.0)
.collect();
types.sort_by_key(|p| format!("{p:?}"));
types.dedup();
@@ -607,9 +636,9 @@ mod tests {
let mut visible_piles: Vec<KlondikePile> = Vec::new();
for (marker, visibility) in q.iter(app.world()) {
if matches!(visibility, Visibility::Hidden) {
hidden_piles.push(marker.0.clone());
hidden_piles.push(marker.0);
} else {
visible_piles.push(marker.0.clone());
visible_piles.push(marker.0);
}
}