saveload_system.rs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. use specs::prelude::*;
  2. use specs::saveload::{SimpleMarker, SimpleMarkerAllocator, SerializeComponents, DeserializeComponents, MarkedBuilder};
  3. use specs::error::NoError;
  4. use super::components::*;
  5. use std::fs::File;
  6. use std::path::Path;
  7. use std::fs;
  8. macro_rules! serialize_individually {
  9. ($ecs:expr, $ser:expr, $data:expr, $( $type:ty),*) => {
  10. $(
  11. SerializeComponents::<NoError, SimpleMarker<SerializeMe>>::serialize(
  12. &( $ecs.read_storage::<$type>(), ),
  13. &$data.0,
  14. &$data.1,
  15. &mut $ser,
  16. )
  17. .unwrap();
  18. )*
  19. };
  20. }
  21. #[cfg(target_arch = "wasm32")]
  22. pub fn save_game(_ecs : &mut World) {
  23. }
  24. #[cfg(not(target_arch = "wasm32"))]
  25. pub fn save_game(ecs : &mut World) {
  26. // Create helper
  27. let mapcopy = ecs.get_mut::<super::map::Map>().unwrap().clone();
  28. let savehelper = ecs
  29. .create_entity()
  30. .with(SerializationHelper{ map : mapcopy })
  31. .marked::<SimpleMarker<SerializeMe>>()
  32. .build();
  33. // Actually serialize
  34. {
  35. let data = ( ecs.entities(), ecs.read_storage::<SimpleMarker<SerializeMe>>() );
  36. let writer = File::create("./savegame.json").unwrap();
  37. let mut serializer = serde_json::Serializer::new(writer);
  38. serialize_individually!(ecs, serializer, data, Position, Renderable, Player, Viewshed, Monster,
  39. Name, BlocksTile, CombatStats, SufferDamage, WantsToMelee, Item, Consumable, Ranged, InflictsDamage,
  40. AreaOfEffect, Confusion, ProvidesHealing, InBackpack, WantsToPickupItem, WantsToUseItem,
  41. WantsToDropItem, SerializationHelper, Equippable, Equipped, MeleePowerBonus, DefenseBonus,
  42. WantsToRemoveItem, ParticleLifetime, HungerClock, ProvidesFood, MagicMapper, Hidden,
  43. EntryTrigger, EntityMoved, SingleActivation
  44. );
  45. }
  46. // Clean up
  47. ecs.delete_entity(savehelper).expect("Crash on cleanup");
  48. }
  49. pub fn does_save_exist() -> bool {
  50. Path::new("./savegame.json").exists()
  51. }
  52. macro_rules! deserialize_individually {
  53. ($ecs:expr, $de:expr, $data:expr, $( $type:ty),*) => {
  54. $(
  55. DeserializeComponents::<NoError, _>::deserialize(
  56. &mut ( &mut $ecs.write_storage::<$type>(), ),
  57. &$data.0, // entities
  58. &mut $data.1, // marker
  59. &mut $data.2, // allocater
  60. &mut $de,
  61. )
  62. .unwrap();
  63. )*
  64. };
  65. }
  66. pub fn load_game(ecs: &mut World) {
  67. {
  68. // Delete everything
  69. let mut to_delete = Vec::new();
  70. for e in ecs.entities().join() {
  71. to_delete.push(e);
  72. }
  73. for del in to_delete.iter() {
  74. ecs.delete_entity(*del).expect("Deletion failed");
  75. }
  76. }
  77. let data = fs::read_to_string("./savegame.json").unwrap();
  78. let mut de = serde_json::Deserializer::from_str(&data);
  79. {
  80. let mut d = (&mut ecs.entities(), &mut ecs.write_storage::<SimpleMarker<SerializeMe>>(), &mut SimpleMarkerAllocator::<SerializeMe>::new());
  81. deserialize_individually!(ecs, de, d, Position, Renderable, Player, Viewshed, Monster,
  82. Name, BlocksTile, CombatStats, SufferDamage, WantsToMelee, Item, Consumable, Ranged, InflictsDamage,
  83. AreaOfEffect, Confusion, ProvidesHealing, InBackpack, WantsToPickupItem, WantsToUseItem,
  84. WantsToDropItem, SerializationHelper, Equippable, Equipped, MeleePowerBonus, DefenseBonus,
  85. WantsToRemoveItem, ParticleLifetime, HungerClock, ProvidesFood, MagicMapper, Hidden,
  86. EntryTrigger, EntityMoved, SingleActivation
  87. );
  88. }
  89. let mut deleteme : Option<Entity> = None;
  90. {
  91. let entities = ecs.entities();
  92. let helper = ecs.read_storage::<SerializationHelper>();
  93. let player = ecs.read_storage::<Player>();
  94. let position = ecs.read_storage::<Position>();
  95. for (e,h) in (&entities, &helper).join() {
  96. let mut worldmap = ecs.write_resource::<super::map::Map>();
  97. *worldmap = h.map.clone();
  98. worldmap.tile_content = vec![Vec::new(); super::map::MAPCOUNT];
  99. deleteme = Some(e);
  100. }
  101. for (e,_p,pos) in (&entities, &player, &position).join() {
  102. let mut ppos = ecs.write_resource::<rltk::Point>();
  103. *ppos = rltk::Point::new(pos.x, pos.y);
  104. let mut player_resource = ecs.write_resource::<Entity>();
  105. *player_resource = e;
  106. }
  107. }
  108. ecs.delete_entity(deleteme.unwrap()).expect("Unable to delete helper");
  109. }
  110. pub fn delete_save() {
  111. if Path::new("./savegame.json").exists() { std::fs::remove_file("./savegame.json").expect("Unable to delete file"); }
  112. }