use bevy::prelude::*;
use super::components::SaveMetadata;
use super::events::*;
use super::resources::{SaveLoadConfig, SaveSlotInfo, SaveSlotRegistry};
use super::systems::*;
use crate::IssunSet;
#[derive(Default)]
pub struct SaveLoadPlugin {
pub config: SaveLoadConfig,
}
impl SaveLoadPlugin {
pub fn with_config(mut self, config: SaveLoadConfig) -> Self {
self.config = config;
self
}
pub fn with_auto_save(mut self, period_days: u32) -> Self {
self.config.enable_auto_save = true;
self.config.auto_save_period = period_days;
self
}
pub fn with_save_directory(mut self, dir: impl Into<String>) -> Self {
self.config.save_directory = dir.into();
self
}
pub fn with_max_slots(mut self, max_slots: usize) -> Self {
self.config.max_save_slots = max_slots;
self
}
}
impl Plugin for SaveLoadPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(self.config.clone());
app.insert_resource(SaveSlotRegistry::new());
app.add_message::<SaveRequested>()
.add_message::<LoadRequested>()
.add_message::<DeleteSaveRequested>()
.add_message::<ListSavesRequested>()
.add_message::<SaveCompleted>()
.add_message::<LoadCompleted>()
.add_message::<SaveFailed>()
.add_message::<LoadFailed>()
.add_message::<SavesListed>();
app.register_type::<SaveLoadConfig>()
.register_type::<SaveSlotRegistry>();
app.register_type::<SaveMetadata>();
app.register_type::<SaveSlotInfo>();
app.register_type::<SaveRequested>()
.register_type::<LoadRequested>()
.register_type::<DeleteSaveRequested>()
.register_type::<ListSavesRequested>()
.register_type::<SaveCompleted>()
.register_type::<LoadCompleted>()
.register_type::<SaveFailed>()
.register_type::<LoadFailed>()
.register_type::<SavesListed>();
app.add_systems(
Update,
(
auto_save_system.in_set(IssunSet::Input),
),
);
app.add_systems(
Update,
(
process_save_requests,
process_load_requests,
process_delete_requests,
process_list_requests,
)
.chain()
.in_set(IssunSet::Logic),
);
app.add_systems(
Update,
(
verify_save_completion,
verify_load_completion,
)
.chain()
.in_set(IssunSet::PostLogic),
);
app.add_observer(moonshine_save::prelude::save_on_default_event);
app.add_observer(moonshine_save::prelude::load_on_default_event);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_plugin_default() {
let plugin = SaveLoadPlugin::default();
assert_eq!(plugin.config.save_directory, "./saves");
assert!(!plugin.config.enable_auto_save);
}
#[test]
fn test_plugin_with_config() {
let config = SaveLoadConfig {
save_directory: "./my_saves".to_string(),
enable_auto_save: true,
auto_save_period: 2,
max_save_slots: 20,
quicksave_slot: "quick".to_string(),
};
let plugin = SaveLoadPlugin::default().with_config(config);
assert_eq!(plugin.config.save_directory, "./my_saves");
assert!(plugin.config.enable_auto_save);
assert_eq!(plugin.config.auto_save_period, 2);
}
#[test]
fn test_plugin_builder() {
let plugin = SaveLoadPlugin::default()
.with_save_directory("./test_saves")
.with_auto_save(3)
.with_max_slots(15);
assert_eq!(plugin.config.save_directory, "./test_saves");
assert!(plugin.config.enable_auto_save);
assert_eq!(plugin.config.auto_save_period, 3);
assert_eq!(plugin.config.max_save_slots, 15);
}
#[test]
fn test_plugin_builds() {
let mut app = App::new();
app.add_plugins(MinimalPlugins);
app.add_plugins(bevy::state::app::StatesPlugin);
app.add_plugins(crate::IssunCorePlugin);
app.add_plugins(SaveLoadPlugin::default());
assert!(app.world().contains_resource::<SaveLoadConfig>());
assert!(app.world().contains_resource::<SaveSlotRegistry>());
}
}