Skip to content

Instantly share code, notes, and snippets.

@chamons

chamons/test.rs Secret

Created January 15, 2023 04:48
Show Gist options
  • Save chamons/37e8c6f8753e63eaef08bef36686c2e2 to your computer and use it in GitHub Desktop.
Save chamons/37e8c6f8753e63eaef08bef36686c2e2 to your computer and use it in GitHub Desktop.
use bevy_ecs::{
archetype::{Archetype, ArchetypeId},
prelude::*,
};
use serde::{Deserialize, Serialize};
use crate::core::{Age, Buildings, BuildingsTimer, Demand, Inventory, Passives, Player, Research, ResearchTimer, Skills, Stability, StoreOffer};
use super::ChoosePlacementStoreItem;
#[derive(Debug, Serialize, Deserialize)]
struct SaveState {
stability: Stability,
demand: Demand,
age: Age,
buildings_timer: BuildingsTimer,
research_timer: ResearchTimer,
passives: Passives,
store_offer: StoreOffer,
placement_store_item: ChoosePlacementStoreItem,
entities: Vec<SaveEntity>,
}
#[derive(Debug, Serialize, Deserialize)]
struct SaveEntity {
entity: Entity,
inventory: Option<Inventory>,
player: bool, // Player has no state, so it serializes to null
skills: Option<Skills>,
buildings: Option<Buildings>,
research: Option<Research>,
}
impl SaveState {
pub fn create(world: &mut World) -> Self {
let stability = world.get_resource::<Stability>().unwrap().clone();
let demand = world.get_resource::<Demand>().unwrap().clone();
let age = world.get_resource::<Age>().unwrap().clone();
let buildings_timer = world.get_resource::<BuildingsTimer>().unwrap().clone();
let research_timer = world.get_resource::<ResearchTimer>().unwrap().clone();
let passives = world.get_resource::<Passives>().unwrap().clone();
let store_offer = world.get_resource::<StoreOffer>().unwrap().clone();
let placement_store_item = world.get_resource::<ChoosePlacementStoreItem>().unwrap().clone();
SaveState {
stability,
demand,
age,
buildings_timer,
research_timer,
passives,
store_offer,
placement_store_item,
entities: SaveState::snapshot_entities(world),
}
}
fn snapshot_entities(world: &World) -> Vec<SaveEntity> {
let archetypes = world.archetypes();
let all_archetypes: Vec<&Archetype> = archetypes
.iter()
.filter(|archetype| match archetype.id() {
ArchetypeId::EMPTY | ArchetypeId::RESOURCE | ArchetypeId::INVALID => false,
_ => true,
})
.collect();
let mut entities = Vec::with_capacity(all_archetypes.len());
for archetype in all_archetypes {
for entity in archetype.entities() {
entities.push(SaveEntity {
entity: *entity,
inventory: world.get::<Inventory>(*entity).cloned(),
player: world.get::<Player>(*entity).is_some(),
skills: world.get::<Skills>(*entity).cloned(),
buildings: world.get::<Buildings>(*entity).cloned(),
research: world.get::<Research>(*entity).cloned(),
});
}
}
entities
}
}
pub fn save_game(world: &mut World) -> String {
let state = SaveState::create(world);
serde_json::to_string(&state).unwrap()
}
pub fn load_game(state: &str) -> World {
let state: SaveState = serde_json::from_str(state).unwrap();
let mut world = World::new();
world.insert_resource(state.age);
world.insert_resource(state.buildings_timer);
world.insert_resource(state.demand);
world.insert_resource(state.passives);
world.insert_resource(state.research_timer);
world.insert_resource(state.stability);
world.insert_resource(state.store_offer);
world.insert_resource(state.placement_store_item);
for entity in state.entities {
let mut e = world.spawn();
if let Some(inventory) = entity.inventory {
e.insert(inventory);
}
if entity.player {
e.insert(Player {});
}
if let Some(skills) = entity.skills {
e.insert(skills);
}
if let Some(buildings) = entity.buildings {
e.insert(buildings);
}
if let Some(research) = entity.research {
e.insert(research);
}
}
world
}
#[cfg(test)]
mod tests {
use crate::{
core::{create_game_world, find_player, test_utils::test_root_dir, Data},
ui::{GameState, ImageCache, ScreenCoordinates},
};
use super::*;
#[test]
fn save_load_smoke() {
let image_cache = ImageCache::empty();
let data = Data::load_from_dir(&test_root_dir()).unwrap();
let screen_coordinates = ScreenCoordinates::new(ggez::graphics::Rect::new(0.0, 0.0, 800.0, 600.0));
let world = create_game_world(&data);
let mut world = GameState::instance_world(world, image_cache, data, screen_coordinates);
let save = save_game(&mut world);
let mut loaded_world = load_game(&save);
let _ = find_player(&mut loaded_world);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment