Implement game loading

This commit is contained in:
Timothy Warren 2021-11-09 10:29:23 -05:00
parent 48609aee1f
commit a307521d64
3 changed files with 135 additions and 15 deletions

View File

@ -409,6 +409,7 @@ pub fn ranged_target(
} }
pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult { 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::<RunState>(); let runstate = gs.ecs.fetch::<RunState>();
ctx.print_color_centered( ctx.print_color_centered(
@ -438,20 +439,22 @@ pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
); );
} }
if selection == MainMenuSelection::LoadGame { if save_exists {
ctx.print_color_centered( if selection == MainMenuSelection::LoadGame {
25, ctx.print_color_centered(
RGB::named(rltk::MAGENTA), 25,
RGB::named(rltk::BLACK), RGB::named(rltk::MAGENTA),
"Load Game", RGB::named(rltk::BLACK),
); "Load Game",
} else { );
ctx.print_color_centered( } else {
25, ctx.print_color_centered(
RGB::named(rltk::WHITE), 25,
RGB::named(rltk::BLACK), RGB::named(rltk::WHITE),
"Load Game", RGB::named(rltk::BLACK),
); "Load Game",
);
}
} }
if selection == MainMenuSelection::Quit { if selection == MainMenuSelection::Quit {

View File

@ -110,7 +110,24 @@ impl GameState for State {
ctx.cls(); ctx.cls();
match newrunstate { 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 the UI
draw_map(&self.ecs, ctx); draw_map(&self.ecs, ctx);

View File

@ -22,6 +22,21 @@ macro_rules! serialize_individually {
}; };
} }
macro_rules! deserialize_individually {
($ecs:expr, $de:expr, $data:expr, $( $type:ty),*) => {
$(
DeserializeComponents::<NoError, _>::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) { pub fn save_game(ecs: &mut World) {
// Create helper // Create helper
let mapcopy = ecs.get_mut::<crate::map::Map>().unwrap().clone(); let mapcopy = ecs.get_mut::<crate::map::Map>().unwrap().clone();
@ -77,3 +92,88 @@ pub fn save_game(ecs: &mut World) {
pub fn does_save_exist() -> bool { pub fn does_save_exist() -> bool {
Path::new("./savegame.json").exists() 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::<SimpleMarker<SerializeMe>>(),
&mut ecs.write_resource::<SimpleMarkerAllocator<SerializeMe>>(),
);
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<Entity> = None;
{
let entities = ecs.entities();
let helper = ecs.read_storage::<SerializationHelper>();
let player = ecs.read_storage::<Player>();
let position = ecs.read_storage::<Position>();
for (e, h) in (&entities, &helper).join() {
let mut worldmap = ecs.write_resource::<crate::map::Map>();
*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::<rltk::Point>();
*ppos = rltk::Point::new(pos.x, pos.y);
let mut player_resource = ecs.write_resource::<Entity>();
*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.");
}
}