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,6 +1,7 @@
|
||||
use bevy::prelude::*;
|
||||
use solitaire_engine::{
|
||||
AnimationPlugin, CardPlugin, GamePlugin, InputPlugin, StatsPlugin, TablePlugin,
|
||||
AchievementPlugin, AnimationPlugin, CardPlugin, GamePlugin, InputPlugin, StatsPlugin,
|
||||
TablePlugin,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
@@ -21,5 +22,6 @@ fn main() {
|
||||
.add_plugins(InputPlugin)
|
||||
.add_plugins(AnimationPlugin)
|
||||
.add_plugins(StatsPlugin::default())
|
||||
.add_plugins(AchievementPlugin::default())
|
||||
.run();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user