saveload system
localstorage isn't supported by wasm, so playing online will probably just not have save games for a while
This commit is contained in:
parent
dd91a8cca7
commit
51060f1a85
11 changed files with 290 additions and 63 deletions
170
src/saveload_system.rs
Normal file
170
src/saveload_system.rs
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
use super::components::*;
|
||||
use specs::error::NoError;
|
||||
use specs::prelude::*;
|
||||
use specs::saveload::{DeserializeComponents, MarkedBuilder, SerializeComponents, SimpleMarker, SimpleMarkerAllocator};
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
|
||||
macro_rules! serialize_individually {
|
||||
($ecs:expr, $ser:expr, $data:expr, $( $type:ty),*) => {
|
||||
$(
|
||||
SerializeComponents::<NoError, SimpleMarker<SerializeMe>>::serialize(
|
||||
&( $ecs.read_storage::<$type>(), ),
|
||||
&$data.0,
|
||||
&$data.1,
|
||||
&mut $ser,
|
||||
)
|
||||
.unwrap();
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub fn save_game(_ecs: &mut World) {}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
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();
|
||||
|
||||
// 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,
|
||||
Destructible,
|
||||
Ranged,
|
||||
InflictsDamage,
|
||||
AOE,
|
||||
Confusion,
|
||||
ProvidesHealing,
|
||||
InBackpack,
|
||||
WantsToPickupItem,
|
||||
WantsToUseItem,
|
||||
WantsToDropItem,
|
||||
SerializationHelper
|
||||
);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
ecs.delete_entity(savehelper).expect("Crash on cleanup");
|
||||
}
|
||||
|
||||
pub fn does_save_exist() -> bool {
|
||||
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>(), ),
|
||||
&$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 ecs.write_resource::<SimpleMarkerAllocator<SerializeMe>>(),
|
||||
);
|
||||
|
||||
deserialize_individually!(
|
||||
ecs,
|
||||
de,
|
||||
d,
|
||||
Position,
|
||||
Renderable,
|
||||
Player,
|
||||
Viewshed,
|
||||
Monster,
|
||||
Name,
|
||||
BlocksTile,
|
||||
CombatStats,
|
||||
SufferDamage,
|
||||
WantsToMelee,
|
||||
Item,
|
||||
Consumable,
|
||||
Destructible,
|
||||
Ranged,
|
||||
InflictsDamage,
|
||||
AOE,
|
||||
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");
|
||||
}
|
||||
|
||||
pub fn delete_save() {
|
||||
if Path::new("./savegame.json").exists() {
|
||||
std::fs::remove_file("./savegame.json").expect("Unable to delete file");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue