feat(engine): add AchievementPlugin with persistent unlock tracking
On GameWonEvent, build an AchievementContext from StatsResource + GameState + wall-clock hour, evaluate ALL_ACHIEVEMENTS, flip newly-satisfied records to unlocked, persist atomically, and emit AchievementUnlockedEvent for each new unlock. AnimationPlugin's toast resolves the event's ID to the achievement's display name via achievement_plugin::display_name_for. Introduces StatsUpdate system set so AchievementPlugin can reliably run after StatsResource reflects the win. AchievementPlugin::headless() used in tests to avoid touching ~/.local/share/solitaire_quest/achievements.json. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
//! Bevy integration layer for Solitaire Quest.
|
||||
|
||||
pub mod achievement_plugin;
|
||||
pub mod animation_plugin;
|
||||
pub mod card_plugin;
|
||||
pub mod events;
|
||||
@@ -10,6 +11,7 @@ pub mod resources;
|
||||
pub mod stats_plugin;
|
||||
pub mod table_plugin;
|
||||
|
||||
pub use achievement_plugin::{AchievementPlugin, AchievementsResource};
|
||||
pub use animation_plugin::{AnimationPlugin, CardAnim};
|
||||
pub use card_plugin::{CardEntity, CardLabel, CardPlugin};
|
||||
pub use events::{
|
||||
@@ -20,5 +22,5 @@ pub use game_plugin::{GameMutation, GamePlugin};
|
||||
pub use input_plugin::InputPlugin;
|
||||
pub use layout::{compute_layout, Layout, LayoutResource};
|
||||
pub use resources::{DragState, GameStateResource, SyncStatus, SyncStatusResource};
|
||||
pub use stats_plugin::{StatsPlugin, StatsResource, StatsScreen};
|
||||
pub use stats_plugin::{StatsPlugin, StatsResource, StatsScreen, StatsUpdate};
|
||||
pub use table_plugin::{PileMarker, TableBackground, TablePlugin};
|
||||
|
||||
Reference in New Issue
Block a user