use crate::prelude::*; use std::fs; use std::path::PathBuf; #[derive(Resource, Clone, Debug)] pub struct SavegamePath(pub PathBuf); #[derive(Debug)] pub struct SavegameInfo { pub path: SavegamePath, pub index: u32, pub total_berries: u32, pub completed_focus: u32, } #[derive(Deserialize)] struct PartialSaveData { session_tracker: PartialSessionTracker, } #[derive(Deserialize)] struct PartialSessionTracker { completed_focus_phases: u32, } impl SavegamePath { pub fn new(index: u32) -> Self { let base_path = get_internal_path().unwrap_or_else(|| { println!( "Could not determine platform-specific save directory. Falling back to `./saves/" ); PathBuf::from("./saves/") }); if let Err(e) = std::fs::create_dir_all(&base_path) { panic!("Failed to create save directory at {:?}: {}", base_path, e); } Self(base_path.join(format!("savegame-{}.json", index))) } pub fn list() -> Vec { let mut savegames = Vec::new(); let Some(base_path) = get_internal_path() else { return Vec::new(); }; if !base_path.exists() { return Vec::new(); } let Ok(entries) = fs::read_dir(base_path) else { return Vec::new(); }; for entry in entries.flatten() { let path = entry.path(); if path.extension().and_then(|s| s.to_str()) != Some("json") { continue; } let Some(file_name) = path.file_stem().and_then(|s| s.to_str()) else { continue; }; if !file_name.starts_with("savegame-") { continue; } let Ok(index) = file_name.trim_start_matches("savegame-").parse::() else { continue; }; let Ok(content) = fs::read_to_string(&path) else { continue; }; let Ok(data) = serde_json::from_str::(&content) else { continue; }; savegames.push(SavegameInfo { path: SavegamePath(path), index, total_berries: 0, // TODO: add total_berries completed_focus: data.session_tracker.completed_focus_phases, }); } savegames.sort_by_key(|s| s.index); savegames } pub fn next() -> Self { let savegames = Self::list(); let next_index = savegames.last().map(|s| s.index + 1).unwrap_or(0); Self::new(next_index) } }