|
@@ -1,10 +1,10 @@
|
|
use specs::prelude::*;
|
|
use specs::prelude::*;
|
|
-use specs::saveload::{SimpleMarker, SerializeComponents};
|
|
|
|
|
|
+use specs::saveload::{SimpleMarker, SimpleMarkerAllocator, SerializeComponents, DeserializeComponents, MarkedBuilder};
|
|
use specs::error::NoError;
|
|
use specs::error::NoError;
|
|
use super::components::*;
|
|
use super::components::*;
|
|
use std::fs::File;
|
|
use std::fs::File;
|
|
-use std::io::Write;
|
|
|
|
use std::path::Path;
|
|
use std::path::Path;
|
|
|
|
+use std::fs;
|
|
|
|
|
|
macro_rules! serialize_individually {
|
|
macro_rules! serialize_individually {
|
|
($ecs:expr, $ser:expr, $data:expr, $( $type:ty),*) => {
|
|
($ecs:expr, $ser:expr, $data:expr, $( $type:ty),*) => {
|
|
@@ -20,18 +20,96 @@ macro_rules! serialize_individually {
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
-pub fn save_game(ecs : &World) {
|
|
|
|
- let data = ( ecs.entities(), ecs.read_storage::<SimpleMarker<SerializeMe>>() );
|
|
|
|
|
|
+pub fn save_game(ecs : &mut World) {
|
|
|
|
+ // Create helper
|
|
|
|
+ let mapcopy = ecs.get_mut::<super::map::Map>().unwrap().clone();
|
|
|
|
+ let savehelper = ecs
|
|
|
|
+ .create_entity()
|
|
|
|
+ .with(SerializationHelper{ map : mapcopy })
|
|
|
|
+ .marked::<SimpleMarker<SerializeMe>>()
|
|
|
|
+ .build();
|
|
|
|
|
|
- let writer = File::create("./savegame.json").unwrap();
|
|
|
|
- let mut serializer = serde_json::Serializer::new(writer);
|
|
|
|
- serialize_individually!(ecs, serializer, data, Position, Renderable, Player, Viewshed, Monster,
|
|
|
|
- Name, BlocksTile, CombatStats, SufferDamage, WantsToMelee, Item, Consumable, Ranged, InflictsDamage,
|
|
|
|
- AreaOfEffect, Confusion, ProvidesHealing, InBackpack, WantsToPickupItem, WantsToUseItem,
|
|
|
|
- WantsToDropItem
|
|
|
|
- );
|
|
|
|
|
|
+ // Actually serialize
|
|
|
|
+ {
|
|
|
|
+ let data = ( ecs.entities(), ecs.read_storage::<SimpleMarker<SerializeMe>>() );
|
|
|
|
+
|
|
|
|
+ let writer = File::create("./savegame.json").unwrap();
|
|
|
|
+ let mut serializer = serde_json::Serializer::new(writer);
|
|
|
|
+ serialize_individually!(ecs, serializer, data, Position, Renderable, Player, Viewshed, Monster,
|
|
|
|
+ Name, BlocksTile, CombatStats, SufferDamage, WantsToMelee, Item, Consumable, Ranged, InflictsDamage,
|
|
|
|
+ AreaOfEffect, Confusion, ProvidesHealing, InBackpack, WantsToPickupItem, WantsToUseItem,
|
|
|
|
+ WantsToDropItem, SerializationHelper
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Clean up
|
|
|
|
+ ecs.delete_entity(savehelper).expect("Crash on cleanup");
|
|
}
|
|
}
|
|
|
|
|
|
pub fn does_save_exist() -> bool {
|
|
pub fn does_save_exist() -> bool {
|
|
Path::new("./savegame.json").exists()
|
|
Path::new("./savegame.json").exists()
|
|
-}
|
|
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+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 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("Deletion failed");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 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 SimpleMarkerAllocator::<SerializeMe>::new());
|
|
|
|
+
|
|
|
|
+ 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::<super::map::Map>();
|
|
|
|
+ *worldmap = h.map.clone();
|
|
|
|
+ worldmap.tile_content = vec![Vec::new(); super::map::MAPCOUNT];
|
|
|
|
+ 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");
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+}
|