diff --git a/src/gui.rs b/src/gui.rs index c098dd6..b2e0263 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -409,6 +409,7 @@ pub fn ranged_target( } pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult { + let save_exists = crate::saveload_system::does_save_exist(); let runstate = gs.ecs.fetch::(); ctx.print_color_centered( @@ -438,20 +439,22 @@ pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult { ); } - if selection == MainMenuSelection::LoadGame { - ctx.print_color_centered( - 25, - RGB::named(rltk::MAGENTA), - RGB::named(rltk::BLACK), - "Load Game", - ); - } else { - ctx.print_color_centered( - 25, - RGB::named(rltk::WHITE), - RGB::named(rltk::BLACK), - "Load Game", - ); + if save_exists { + if selection == MainMenuSelection::LoadGame { + ctx.print_color_centered( + 25, + RGB::named(rltk::MAGENTA), + RGB::named(rltk::BLACK), + "Load Game", + ); + } else { + ctx.print_color_centered( + 25, + RGB::named(rltk::WHITE), + RGB::named(rltk::BLACK), + "Load Game", + ); + } } if selection == MainMenuSelection::Quit { diff --git a/src/main.rs b/src/main.rs index 2251538..b9251f8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -110,7 +110,24 @@ impl GameState for State { ctx.cls(); match newrunstate { - RunState::MainMenu { .. } => {} + RunState::MainMenu { .. } => match gui::main_menu(self, ctx) { + gui::MainMenuResult::NoSelection { selected } => { + newrunstate = RunState::MainMenu { + menu_selection: selected, + } + } + gui::MainMenuResult::Selected { selected } => match selected { + gui::MainMenuSelection::NewGame => newrunstate = RunState::PreRun, + gui::MainMenuSelection::LoadGame => { + saveload_system::load_game(&mut self.ecs); + newrunstate = RunState::AwaitingInput; + saveload_system::delete_save(); + } + gui::MainMenuSelection::Quit => { + ::std::process::exit(0); + } + }, + }, _ => { // Draw the UI draw_map(&self.ecs, ctx); diff --git a/src/saveload_system.rs b/src/saveload_system.rs index b73dfee..beffbc2 100644 --- a/src/saveload_system.rs +++ b/src/saveload_system.rs @@ -22,6 +22,21 @@ macro_rules! serialize_individually { }; } +macro_rules! deserialize_individually { + ($ecs:expr, $de:expr, $data:expr, $( $type:ty),*) => { + $( + DeserializeComponents::::deserialize( + &mut ( &mut $ecs.write_storage::<$type>(), ), + &mut $data.0, // entities + &mut $data.1, // marker + &mut $data.2, // allocater + &mut $de, + ) + .unwrap(); + )* + }; +} + pub fn save_game(ecs: &mut World) { // Create helper let mapcopy = ecs.get_mut::().unwrap().clone(); @@ -77,3 +92,88 @@ pub fn save_game(ecs: &mut World) { pub fn does_save_exist() -> bool { Path::new("./savegame.json").exists() } + +pub fn load_game(ecs: &mut World) { + { + // Delete everything + let mut to_delete = Vec::new(); + for e in ecs.entities().join() { + to_delete.push(e); + } + + for del in to_delete.iter() { + ecs.delete_entity(*del).expect("Failed to delete entity"); + } + } + + let data = fs::read_to_string("./savegame.json").unwrap(); + let mut de = serde_json::Deserializer::from_str(&data); + + { + let mut d = ( + &mut ecs.entities(), + &mut ecs.write_storage::>(), + &mut ecs.write_resource::>(), + ); + + deserialize_individually!( + ecs, + de, + d, + Position, + Renderable, + Player, + Viewshed, + Monster, + Name, + BlocksTile, + CombatStats, + SufferDamage, + WantsToMelee, + Item, + Consumable, + Ranged, + InflictsDamage, + AreaOfEffect, + Confusion, + ProvidesHealing, + InBackpack, + WantsToPickupItem, + WantsToUseItem, + WantsToDropItem, + SerializationHelper + ); + } + + let mut deleteme: Option = None; + { + let entities = ecs.entities(); + let helper = ecs.read_storage::(); + let player = ecs.read_storage::(); + let position = ecs.read_storage::(); + + for (e, h) in (&entities, &helper).join() { + let mut worldmap = ecs.write_resource::(); + *worldmap = h.map.clone(); + worldmap.tile_content = vec![Vec::new(); crate::map::MAP_COUNT]; + deleteme = Some(e); + } + + for (e, _p, pos) in (&entities, &player, &position).join() { + let mut ppos = ecs.write_resource::(); + *ppos = rltk::Point::new(pos.x, pos.y); + + let mut player_resource = ecs.write_resource::(); + *player_resource = e; + } + } + + ecs.delete_entity(deleteme.unwrap()) + .expect("Unable to delete helper entitiy"); +} + +pub fn delete_save() { + if Path::new("./savegame.json").exists() { + std::fs::remove_file("./savegame.json").expect("Failed to delete save file."); + } +}