build(deps): switch card_game/klondike to mainline fb01881f
Build and Deploy / build-and-push (push) Failing after 1m6s
Web E2E / web-e2e (push) Failing after 3m7s

Move both crates off the damaged "hacked" rev 99b49e62 onto mainline
master (card_game 0.4.0->0.4.1, klondike 0.3.0->0.4.0) to pick up the new
serialize implementation.

Mainline drops the serde derives from Deck/Suit/Rank (only Card is serde
now, as a compact transparent NonZeroU8) and gives KlondikeInstruction a
hand-written serde impl. Adapt the repo:
- Rank::value() was removed; the enum discriminant is the 1..=13 value, so
  use `rank as u32/u8` in the three card_to_id helpers (wasm, radial_menu,
  feedback_anim).
- Drop the vestigial Serialize/Deserialize derive on theme::CardKey; theme
  manifests address faces by manifest_name strings, never by serialising
  CardKey, and Suit/Rank no longer implement serde.

GameState's own instruction-mirror serde (schema v3/v4) is insulated from
the klondike serde change, so the on-disk save format is unchanged.

cargo test --workspace and cargo clippy --workspace -- -D warnings pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
funman300
2026-06-10 09:34:56 -07:00
parent 056459619b
commit 2d0359c2ee
7 changed files with 21 additions and 18 deletions
Generated
+6 -4
View File
@@ -2083,11 +2083,12 @@ dependencies = [
[[package]] [[package]]
name = "card_game" name = "card_game"
version = "0.4.0" version = "0.4.1"
source = "git+https://git.aleshym.co/Quaternions/card_game?rev=99b49e62#99b49e629e2372962b082325503c33e20a458818" source = "git+https://git.aleshym.co/Quaternions/card_game?rev=fb01881f#fb01881f629647eb649d044a63a145cc1da54599"
dependencies = [ dependencies = [
"arrayvec 0.7.6 (sparse+https://git.aleshym.co/api/packages/Quaternions/cargo/)", "arrayvec 0.7.6 (sparse+https://git.aleshym.co/api/packages/Quaternions/cargo/)",
"serde", "serde",
"serde_derive",
] ]
[[package]] [[package]]
@@ -4599,12 +4600,13 @@ dependencies = [
[[package]] [[package]]
name = "klondike" name = "klondike"
version = "0.3.0" version = "0.4.0"
source = "git+https://git.aleshym.co/Quaternions/card_game?rev=99b49e62#99b49e629e2372962b082325503c33e20a458818" source = "git+https://git.aleshym.co/Quaternions/card_game?rev=fb01881f#fb01881f629647eb649d044a63a145cc1da54599"
dependencies = [ dependencies = [
"card_game", "card_game",
"rand 0.10.1", "rand 0.10.1",
"serde", "serde",
"serde_derive",
] ]
[[package]] [[package]]
+2 -2
View File
@@ -38,8 +38,8 @@ solitaire_core = { path = "solitaire_core" }
solitaire_sync = { path = "solitaire_sync" } solitaire_sync = { path = "solitaire_sync" }
solitaire_data = { path = "solitaire_data" } solitaire_data = { path = "solitaire_data" }
solitaire_engine = { path = "solitaire_engine" } solitaire_engine = { path = "solitaire_engine" }
klondike = { git = "https://git.aleshym.co/Quaternions/card_game", rev = "99b49e62", features = ["serde"] } klondike = { git = "https://git.aleshym.co/Quaternions/card_game", rev = "fb01881f", features = ["serde"] }
card_game = { git = "https://git.aleshym.co/Quaternions/card_game", rev = "99b49e62", features = ["serde"] } card_game = { git = "https://git.aleshym.co/Quaternions/card_game", rev = "fb01881f", features = ["serde"] }
# Bevy with `default-features = false` to avoid the unused # Bevy with `default-features = false` to avoid the unused
# `bevy_audio → rodio + symphonia + cpal 0.15 + alsa 0.9` chain. # `bevy_audio → rodio + symphonia + cpal 0.15 + alsa 0.9` chain.
+3 -2
View File
@@ -211,8 +211,9 @@ pub fn skip_cards_from_count(skip: usize) -> Option<SkipCards> {
// ── Legacy serde mirror types (kept for backward compatibility) ─────────────── // ── Legacy serde mirror types (kept for backward compatibility) ───────────────
// //
// These types were introduced when upstream `klondike` had no serde feature. // These types were introduced when upstream `klondike` had no serde feature.
// At rev 99b49e62, upstream provides full serde support, and `GameState` // Mainline `klondike` now provides full serde support (with a hand-written
// serialises `saved_moves` directly as `Vec<KlondikeInstruction>` (schema v4). // compact `KlondikeInstruction` impl), and `GameState` serialises
// `saved_moves` directly as `Vec<KlondikeInstruction>` (schema v4).
// //
// The mirror types are retained for three reasons: // The mirror types are retained for three reasons:
// 1. Schema v3 migration: `AnyInstruction` in `game_state.rs` uses // 1. Schema v3 migration: `AnyInstruction` in `game_state.rs` uses
+1 -1
View File
@@ -199,7 +199,7 @@ fn card_to_id(card: &Card) -> u32 {
Suit::Hearts => 2, Suit::Hearts => 2,
Suit::Spades => 3, Suit::Spades => 3,
}; };
suit_index * 13 + (card.rank().value() as u32 - 1) suit_index * 13 + (card.rank() as u32 - 1)
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
+2 -2
View File
@@ -361,7 +361,7 @@ fn pile_cards(game: &GameState, pile: &KlondikePile) -> Vec<(Card, bool)> {
/// Maps a `card_game::Card` to a stable `u32` identity used by `CardEntity` /// Maps a `card_game::Card` to a stable `u32` identity used by `CardEntity`
/// and systems that still track cards by numeric ID. /// and systems that still track cards by numeric ID.
/// Encoding: `suit_index * 13 + (rank.value() - 1)`, range 0..=51. /// Encoding: `suit_index * 13 + (rank as u8 - 1)`, range 0..=51.
fn card_to_id(card: &Card) -> u32 { fn card_to_id(card: &Card) -> u32 {
use solitaire_core::card::Suit; use solitaire_core::card::Suit;
let suit_index: u32 = match card.suit() { let suit_index: u32 = match card.suit() {
@@ -370,7 +370,7 @@ fn card_to_id(card: &Card) -> u32 {
Suit::Hearts => 2, Suit::Hearts => 2,
Suit::Spades => 3, Suit::Spades => 3,
}; };
suit_index * 13 + (card.rank().value() as u32 - 1) suit_index * 13 + (card.rank() as u32 - 1)
} }
const fn foundations() -> [Foundation; 4] { const fn foundations() -> [Foundation; 4] {
+5 -5
View File
@@ -43,11 +43,11 @@ pub use registry::{
/// Hashable lookup key into [`CardTheme::faces`]. /// Hashable lookup key into [`CardTheme::faces`].
/// ///
/// Distinct from `solitaire_core::Card`: the core type carries an `id` /// Distinct from `card_game::Card`, which also encodes a deck id: `CardKey`
/// and a `face_up` flag that vary per deal, neither of which is /// is just the (suit, rank) pair that uniquely identifies which artwork to
/// relevant to image lookup. `CardKey` is just the (suit, rank) pair /// draw. Serialised theme manifests address faces by
/// that uniquely identifies which artwork to draw. /// [`CardKey::manifest_name`] strings, not by serialising `CardKey` itself.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct CardKey { pub struct CardKey {
pub suit: Suit, pub suit: Suit,
pub rank: Rank, pub rank: Rank,
+2 -2
View File
@@ -97,7 +97,7 @@ fn card_to_id(card: &solitaire_core::card::Card) -> u32 {
Suit::Hearts => 2, Suit::Hearts => 2,
Suit::Spades => 3, Suit::Spades => 3,
}; };
suit_index * 13 + (card.rank().value() as u32 - 1) suit_index * 13 + (card.rank() as u32 - 1)
} }
impl From<&(solitaire_core::card::Card, bool)> for CardSnapshot { impl From<&(solitaire_core::card::Card, bool)> for CardSnapshot {
@@ -110,7 +110,7 @@ impl From<&(solitaire_core::card::Card, bool)> for CardSnapshot {
Suit::Hearts => "hearts", Suit::Hearts => "hearts",
Suit::Spades => "spades", Suit::Spades => "spades",
}, },
rank: card.rank().value(), rank: card.rank() as u8,
face_up: *face_up, face_up: *face_up,
} }
} }