2022-01-20 16:31:03 -05:00
|
|
|
use std::fs::{self, File};
|
2021-12-10 20:16:48 -05:00
|
|
|
use std::path::Path;
|
|
|
|
|
2021-12-24 10:38:44 -05:00
|
|
|
use ::rltk::Point;
|
|
|
|
use ::specs::error::NoError;
|
|
|
|
use ::specs::prelude::*;
|
|
|
|
use ::specs::saveload::{
|
2021-11-08 13:58:40 -05:00
|
|
|
DeserializeComponents, MarkedBuilder, SerializeComponents, SimpleMarker, SimpleMarkerAllocator,
|
|
|
|
};
|
2021-12-10 20:16:48 -05:00
|
|
|
|
|
|
|
use crate::components::*;
|
2022-01-06 10:00:42 -05:00
|
|
|
use crate::map::{Map, MasterDungeonMap};
|
2022-01-12 10:45:13 -05:00
|
|
|
use crate::spatial;
|
2021-11-08 13:58:40 -05:00
|
|
|
|
|
|
|
macro_rules! serialize_individually {
|
2021-11-18 15:25:29 -05:00
|
|
|
($ecs:expr, $ser:expr, $data:expr, $( $type:ty),*,) => {
|
2021-11-08 13:58:40 -05:00
|
|
|
$(
|
2022-01-20 16:31:03 -05:00
|
|
|
SerializeComponents::<NoError, SimpleMarker<SerializeMe>>::serialize(
|
|
|
|
&( $ecs.read_storage::<$type>(), ),
|
|
|
|
&$data.0,
|
|
|
|
&$data.1,
|
|
|
|
&mut $ser,
|
|
|
|
)
|
|
|
|
.unwrap();
|
2021-11-08 13:58:40 -05:00
|
|
|
)*
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-11-09 10:49:39 -05:00
|
|
|
#[cfg(target_arch = "wasm32")]
|
|
|
|
pub fn save_game(_ecs: &mut World) {}
|
|
|
|
|
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2021-11-08 13:58:40 -05:00
|
|
|
pub fn save_game(ecs: &mut World) {
|
|
|
|
// Create helper
|
2021-12-24 10:38:44 -05:00
|
|
|
let mapcopy = ecs.get_mut::<Map>().unwrap().clone();
|
2022-01-06 10:00:42 -05:00
|
|
|
let dungeon_master = ecs.get_mut::<MasterDungeonMap>().unwrap().clone();
|
2021-11-08 13:58:40 -05:00
|
|
|
let savehelper = ecs
|
|
|
|
.create_entity()
|
|
|
|
.with(SerializationHelper { map: mapcopy })
|
|
|
|
.marked::<SimpleMarker<SerializeMe>>()
|
|
|
|
.build();
|
2022-01-06 10:00:42 -05:00
|
|
|
let savehelper2 = ecs
|
|
|
|
.create_entity()
|
|
|
|
.with(DMSerializationHelper {
|
|
|
|
map: dungeon_master,
|
|
|
|
})
|
|
|
|
.marked::<SimpleMarker<SerializeMe>>()
|
|
|
|
.build();
|
2021-11-08 13:58:40 -05:00
|
|
|
|
|
|
|
// Actually serialize
|
|
|
|
{
|
|
|
|
let data = (
|
|
|
|
ecs.entities(),
|
|
|
|
ecs.read_storage::<SimpleMarker<SerializeMe>>(),
|
|
|
|
);
|
|
|
|
|
|
|
|
let writer = File::create("./savegame.json").unwrap();
|
2021-12-24 10:38:44 -05:00
|
|
|
let mut serializer = ::serde_json::Serializer::new(writer);
|
2021-11-08 13:58:40 -05:00
|
|
|
serialize_individually!(
|
|
|
|
ecs,
|
|
|
|
serializer,
|
|
|
|
data,
|
2022-01-18 11:00:13 -05:00
|
|
|
ApplyMove,
|
|
|
|
ApplyTeleport,
|
2021-11-08 13:58:40 -05:00
|
|
|
AreaOfEffect,
|
2022-01-24 09:56:42 -05:00
|
|
|
AttributeBonus,
|
2022-01-05 11:46:39 -05:00
|
|
|
Attributes,
|
|
|
|
BlocksTile,
|
|
|
|
BlocksVisibility,
|
2022-01-11 15:35:59 -05:00
|
|
|
Chasing,
|
2021-11-08 13:58:40 -05:00
|
|
|
Confusion,
|
2022-01-05 11:46:39 -05:00
|
|
|
Consumable,
|
2022-01-21 11:18:53 -05:00
|
|
|
CursedItem,
|
2022-01-25 13:45:44 -05:00
|
|
|
DamageOverTime,
|
2022-01-05 11:46:39 -05:00
|
|
|
Door,
|
2022-01-06 10:00:42 -05:00
|
|
|
DMSerializationHelper,
|
2022-01-24 10:58:37 -05:00
|
|
|
Duration,
|
2022-01-05 11:46:39 -05:00
|
|
|
EntityMoved,
|
|
|
|
EntryTrigger,
|
2021-11-15 11:32:09 -05:00
|
|
|
Equippable,
|
|
|
|
Equipped,
|
2022-01-13 10:14:13 -05:00
|
|
|
EquipmentChanged,
|
2022-01-11 14:16:23 -05:00
|
|
|
Faction,
|
2022-01-05 11:46:39 -05:00
|
|
|
Hidden,
|
|
|
|
HungerClock,
|
2022-01-19 11:04:10 -05:00
|
|
|
IdentifiedItem,
|
2022-01-05 11:46:39 -05:00
|
|
|
InBackpack,
|
|
|
|
InflictsDamage,
|
2022-01-11 09:28:45 -05:00
|
|
|
Initiative,
|
2022-01-05 11:46:39 -05:00
|
|
|
Item,
|
2022-01-25 09:58:30 -05:00
|
|
|
KnownSpells,
|
2022-01-10 10:21:19 -05:00
|
|
|
LightSource,
|
2022-01-05 11:46:39 -05:00
|
|
|
LootTable,
|
2022-01-19 09:38:41 -05:00
|
|
|
MagicItem,
|
2022-01-05 11:46:39 -05:00
|
|
|
MagicMapper,
|
2022-01-04 10:08:06 -05:00
|
|
|
MeleeWeapon,
|
2022-01-11 14:16:23 -05:00
|
|
|
MoveMode,
|
2022-01-11 09:33:21 -05:00
|
|
|
MyTurn,
|
2022-01-05 11:46:39 -05:00
|
|
|
Name,
|
|
|
|
NaturalAttackDefense,
|
2022-01-19 10:15:51 -05:00
|
|
|
ObfuscatedName,
|
2022-01-06 09:34:17 -05:00
|
|
|
OtherLevelPosition,
|
2021-11-17 16:23:01 -05:00
|
|
|
ParticleLifetime,
|
2022-01-05 11:46:39 -05:00
|
|
|
Player,
|
|
|
|
Pools,
|
|
|
|
Position,
|
2021-11-18 15:25:29 -05:00
|
|
|
ProvidesFood,
|
2022-01-05 11:46:39 -05:00
|
|
|
ProvidesHealing,
|
2022-01-21 15:13:31 -05:00
|
|
|
ProvidesIdentification,
|
2022-01-25 11:42:02 -05:00
|
|
|
ProvidesMana,
|
2022-01-21 11:57:36 -05:00
|
|
|
ProvidesRemoveCurse,
|
2022-01-03 10:49:12 -05:00
|
|
|
Quips,
|
2022-01-05 11:46:39 -05:00
|
|
|
Ranged,
|
|
|
|
Renderable,
|
|
|
|
SerializationHelper,
|
|
|
|
SingleActivation,
|
2022-01-03 15:24:38 -05:00
|
|
|
Skills,
|
2022-01-25 13:45:44 -05:00
|
|
|
Slow,
|
2022-01-20 16:31:03 -05:00
|
|
|
SpawnParticleBurst,
|
|
|
|
SpawnParticleLine,
|
2022-01-25 09:58:30 -05:00
|
|
|
SpellTemplate,
|
2022-01-24 10:58:37 -05:00
|
|
|
StatusEffect,
|
2022-01-25 13:39:43 -05:00
|
|
|
TeachesSpell,
|
2022-01-18 11:00:13 -05:00
|
|
|
TeleportTo,
|
|
|
|
TownPortal,
|
2022-01-13 11:29:20 -05:00
|
|
|
Vendor,
|
2022-01-05 11:46:39 -05:00
|
|
|
Viewshed,
|
2022-01-11 14:16:23 -05:00
|
|
|
WantsToApproach,
|
2022-01-25 09:58:30 -05:00
|
|
|
WantsToCastSpell,
|
2022-01-05 11:46:39 -05:00
|
|
|
WantsToDropItem,
|
2022-01-11 14:16:23 -05:00
|
|
|
WantsToFlee,
|
2022-01-05 11:46:39 -05:00
|
|
|
WantsToMelee,
|
|
|
|
WantsToPickupItem,
|
|
|
|
WantsToRemoveItem,
|
|
|
|
WantsToUseItem,
|
|
|
|
Wearable,
|
2021-11-08 13:58:40 -05:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clean up
|
|
|
|
ecs.delete_entity(savehelper)
|
|
|
|
.expect("Failed to clean up savehelper component");
|
2022-01-06 10:00:42 -05:00
|
|
|
ecs.delete_entity(savehelper2)
|
|
|
|
.expect("Failed to clean up savehelper2 component");
|
2021-11-08 13:58:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn does_save_exist() -> bool {
|
|
|
|
Path::new("./savegame.json").exists()
|
|
|
|
}
|
2021-11-09 10:29:23 -05:00
|
|
|
|
2021-11-15 13:55:31 -05:00
|
|
|
macro_rules! deserialize_individually {
|
2021-11-18 15:25:29 -05:00
|
|
|
($ecs:expr, $de:expr, $data:expr, $( $type:ty),*,) => {
|
2021-11-15 13:55:31 -05:00
|
|
|
$(
|
2022-01-20 16:31:03 -05:00
|
|
|
DeserializeComponents::<NoError, _>::deserialize(
|
|
|
|
&mut ( &mut $ecs.write_storage::<$type>(), ),
|
|
|
|
&$data.0, // entities
|
|
|
|
&mut $data.1, // marker
|
|
|
|
&mut $data.2, // allocater
|
|
|
|
&mut $de,
|
|
|
|
)
|
|
|
|
.unwrap();
|
2021-11-15 13:55:31 -05:00
|
|
|
)*
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-11-09 10:29:23 -05:00
|
|
|
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();
|
2021-12-24 10:38:44 -05:00
|
|
|
let mut de = ::serde_json::Deserializer::from_str(&data);
|
2021-11-09 10:29:23 -05:00
|
|
|
|
|
|
|
{
|
|
|
|
let mut d = (
|
|
|
|
&mut ecs.entities(),
|
|
|
|
&mut ecs.write_storage::<SimpleMarker<SerializeMe>>(),
|
|
|
|
&mut ecs.write_resource::<SimpleMarkerAllocator<SerializeMe>>(),
|
|
|
|
);
|
|
|
|
|
|
|
|
deserialize_individually!(
|
|
|
|
ecs,
|
|
|
|
de,
|
|
|
|
d,
|
2022-01-18 11:00:13 -05:00
|
|
|
ApplyMove,
|
|
|
|
ApplyTeleport,
|
2021-11-09 10:29:23 -05:00
|
|
|
AreaOfEffect,
|
2022-01-24 09:56:42 -05:00
|
|
|
AttributeBonus,
|
2022-01-05 11:46:39 -05:00
|
|
|
Attributes,
|
|
|
|
BlocksTile,
|
|
|
|
BlocksVisibility,
|
2022-01-11 15:35:59 -05:00
|
|
|
Chasing,
|
2021-11-09 10:29:23 -05:00
|
|
|
Confusion,
|
2022-01-05 11:46:39 -05:00
|
|
|
Consumable,
|
2022-01-21 11:18:53 -05:00
|
|
|
CursedItem,
|
2022-01-25 13:45:44 -05:00
|
|
|
DamageOverTime,
|
2022-01-05 11:46:39 -05:00
|
|
|
Door,
|
2022-01-06 10:00:42 -05:00
|
|
|
DMSerializationHelper,
|
2022-01-24 10:58:37 -05:00
|
|
|
Duration,
|
2022-01-05 11:46:39 -05:00
|
|
|
EntityMoved,
|
|
|
|
EntryTrigger,
|
2021-11-15 11:32:09 -05:00
|
|
|
Equippable,
|
|
|
|
Equipped,
|
2022-01-13 10:14:13 -05:00
|
|
|
EquipmentChanged,
|
2022-01-11 14:16:23 -05:00
|
|
|
Faction,
|
2022-01-05 11:46:39 -05:00
|
|
|
Hidden,
|
|
|
|
HungerClock,
|
2022-01-19 11:04:10 -05:00
|
|
|
IdentifiedItem,
|
2022-01-05 11:46:39 -05:00
|
|
|
InBackpack,
|
|
|
|
InflictsDamage,
|
2022-01-11 09:28:45 -05:00
|
|
|
Initiative,
|
2022-01-05 11:46:39 -05:00
|
|
|
Item,
|
2022-01-25 09:58:30 -05:00
|
|
|
KnownSpells,
|
2022-01-10 10:21:19 -05:00
|
|
|
LightSource,
|
2022-01-05 11:46:39 -05:00
|
|
|
LootTable,
|
2022-01-19 09:38:41 -05:00
|
|
|
MagicItem,
|
2022-01-05 11:46:39 -05:00
|
|
|
MagicMapper,
|
2022-01-04 10:08:06 -05:00
|
|
|
MeleeWeapon,
|
2022-01-11 14:16:23 -05:00
|
|
|
MoveMode,
|
2022-01-11 09:33:21 -05:00
|
|
|
MyTurn,
|
2022-01-05 11:46:39 -05:00
|
|
|
Name,
|
|
|
|
NaturalAttackDefense,
|
2022-01-19 10:15:51 -05:00
|
|
|
ObfuscatedName,
|
2022-01-06 09:34:17 -05:00
|
|
|
OtherLevelPosition,
|
2021-11-17 16:23:01 -05:00
|
|
|
ParticleLifetime,
|
2022-01-05 11:46:39 -05:00
|
|
|
Player,
|
|
|
|
Pools,
|
|
|
|
Position,
|
2021-11-18 15:25:29 -05:00
|
|
|
ProvidesFood,
|
2022-01-05 11:46:39 -05:00
|
|
|
ProvidesHealing,
|
2022-01-21 15:13:31 -05:00
|
|
|
ProvidesIdentification,
|
2022-01-25 11:42:02 -05:00
|
|
|
ProvidesMana,
|
2022-01-21 11:57:36 -05:00
|
|
|
ProvidesRemoveCurse,
|
2022-01-03 10:49:12 -05:00
|
|
|
Quips,
|
2022-01-05 11:46:39 -05:00
|
|
|
Ranged,
|
|
|
|
Renderable,
|
|
|
|
SerializationHelper,
|
|
|
|
SingleActivation,
|
2022-01-25 13:45:44 -05:00
|
|
|
Slow,
|
2022-01-03 15:24:38 -05:00
|
|
|
Skills,
|
2022-01-20 16:31:03 -05:00
|
|
|
SpawnParticleBurst,
|
|
|
|
SpawnParticleLine,
|
2022-01-25 09:58:30 -05:00
|
|
|
SpellTemplate,
|
2022-01-24 10:58:37 -05:00
|
|
|
StatusEffect,
|
2022-01-25 13:39:43 -05:00
|
|
|
TeachesSpell,
|
2022-01-18 11:00:13 -05:00
|
|
|
TeleportTo,
|
|
|
|
TownPortal,
|
2022-01-13 11:29:20 -05:00
|
|
|
Vendor,
|
2022-01-05 11:46:39 -05:00
|
|
|
Viewshed,
|
2022-01-11 14:16:23 -05:00
|
|
|
WantsToApproach,
|
2022-01-25 09:58:30 -05:00
|
|
|
WantsToCastSpell,
|
2022-01-05 11:46:39 -05:00
|
|
|
WantsToDropItem,
|
2022-01-11 14:16:23 -05:00
|
|
|
WantsToFlee,
|
2022-01-05 11:46:39 -05:00
|
|
|
WantsToMelee,
|
|
|
|
WantsToPickupItem,
|
|
|
|
WantsToRemoveItem,
|
|
|
|
WantsToUseItem,
|
|
|
|
Wearable,
|
2021-11-09 10:29:23 -05:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut deleteme: Option<Entity> = None;
|
2022-01-06 10:00:42 -05:00
|
|
|
let mut deleteme2: Option<Entity> = None;
|
2021-11-09 10:29:23 -05:00
|
|
|
{
|
|
|
|
let entities = ecs.entities();
|
|
|
|
let helper = ecs.read_storage::<SerializationHelper>();
|
2022-01-06 10:00:42 -05:00
|
|
|
let helper2 = ecs.read_storage::<DMSerializationHelper>();
|
2021-11-09 10:29:23 -05:00
|
|
|
let player = ecs.read_storage::<Player>();
|
|
|
|
let position = ecs.read_storage::<Position>();
|
|
|
|
|
|
|
|
for (e, h) in (&entities, &helper).join() {
|
2021-12-24 10:38:44 -05:00
|
|
|
let mut worldmap = ecs.write_resource::<Map>();
|
2021-11-09 10:29:23 -05:00
|
|
|
*worldmap = h.map.clone();
|
2022-01-12 10:45:13 -05:00
|
|
|
spatial::set_size((worldmap.height * worldmap.width) as usize);
|
2021-11-09 10:29:23 -05:00
|
|
|
deleteme = Some(e);
|
|
|
|
}
|
2022-01-06 10:00:42 -05:00
|
|
|
for (e, h) in (&entities, &helper2).join() {
|
|
|
|
let mut dungeon_master = ecs.write_resource::<MasterDungeonMap>();
|
|
|
|
*dungeon_master = h.map.clone();
|
|
|
|
deleteme2 = Some(e);
|
|
|
|
}
|
2021-11-09 10:29:23 -05:00
|
|
|
|
|
|
|
for (e, _p, pos) in (&entities, &player, &position).join() {
|
2021-12-24 10:38:44 -05:00
|
|
|
let mut ppos = ecs.write_resource::<Point>();
|
2022-01-06 10:00:42 -05:00
|
|
|
*ppos = Point::from(*pos);
|
2021-11-09 10:29:23 -05:00
|
|
|
|
|
|
|
let mut player_resource = ecs.write_resource::<Entity>();
|
|
|
|
*player_resource = e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ecs.delete_entity(deleteme.unwrap())
|
2021-11-15 13:55:31 -05:00
|
|
|
.expect("Unable to delete helper entity");
|
2022-01-06 10:00:42 -05:00
|
|
|
ecs.delete_entity(deleteme2.unwrap())
|
|
|
|
.expect("Unable to delete helper2 entity");
|
2021-11-09 10:29:23 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn delete_save() {
|
|
|
|
if Path::new("./savegame.json").exists() {
|
|
|
|
std::fs::remove_file("./savegame.json").expect("Failed to delete save file.");
|
|
|
|
}
|
|
|
|
}
|