96 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "save.hpp"
 | |
| #include <fstream>
 | |
| #include "dbc.hpp"
 | |
| #include <fmt/core.h>
 | |
| #include "config.hpp"
 | |
| #include <filesystem>
 | |
| 
 | |
| using namespace components;
 | |
| using namespace fmt;
 | |
| 
 | |
| template<typename CompT>
 | |
| inline void extract(DinkyECS::World &world, std::map<DinkyECS::Entity, CompT> &into) {
 | |
|   auto from_world = world.entity_map_for<CompT>();
 | |
|   for(auto [entity, value] : from_world) {
 | |
|     into[entity] = std::any_cast<CompT>(value);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void save::to_file(fs::path path, DinkyECS::World &world, Map &map) {
 | |
|   SaveData save_data;
 | |
|   tser::BinaryArchive archive;
 | |
| 
 | |
|   save_data.facts.player = world.get_the<Player>();
 | |
|   save_data.map = MapData{
 | |
|     map.$width, map.$height,
 | |
|     map.$rooms, map.$walls};
 | |
| 
 | |
|   // BUG: lights aren't saved/restored
 | |
|   extract<Position>(world, save_data.position);
 | |
|   extract<Combat>(world, save_data.combat);
 | |
|   extract<Motion>(world, save_data.motion);
 | |
|   extract<Tile>(world, save_data.tile);
 | |
|   // extract<Inventory>(world, save_data.inventory);
 | |
| 
 | |
|   archive.save(save_data);
 | |
|   std::string_view archive_view = archive.get_buffer();
 | |
| 
 | |
|   std::ofstream out(path, std::ios::binary);
 | |
|   out << archive_view;
 | |
|   out.flush();
 | |
| }
 | |
| 
 | |
| template<typename CompT>
 | |
| inline void inject(DinkyECS::World &world, std::map<DinkyECS::Entity, CompT> &outof) {
 | |
|   for(auto [entity, value] : outof) {
 | |
|     world.set<CompT>(entity, value);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void save::from_file(fs::path path, DinkyECS::World &world_out, Map &map_out) {
 | |
|   tser::BinaryArchive archive(0);
 | |
|   dbc::check(fs::exists(path), format("save file does not exist {}", path.string()));
 | |
|   auto size = fs::file_size(path);
 | |
| 
 | |
|   if(std::ifstream in_file{path, std::ios::binary}) {
 | |
|     std::string in_data(size, '\0');
 | |
| 
 | |
|     if(in_file.read(&in_data[0], size)) {
 | |
|       std::string_view in_view(in_data);
 | |
|       archive.initialize(in_view);
 | |
|     } else {
 | |
|       dbc::sentinel(format("wrong size or error reading {}", path.string()));
 | |
|     }
 | |
|   } else {
 | |
|     dbc::sentinel(format("failed to load file {}", path.string()));
 | |
|   }
 | |
| 
 | |
|   auto save_data = archive.load<SaveData>();
 | |
| 
 | |
|   world_out.set_the<Player>(save_data.facts.player);
 | |
|   inject<Position>(world_out, save_data.position);
 | |
|   inject<Combat>(world_out, save_data.combat);
 | |
|   inject<Motion>(world_out, save_data.motion);
 | |
|   inject<Tile>(world_out, save_data.tile);
 | |
|   // inject<Inventory>(world_out, save_data.inventory);
 | |
| 
 | |
|   size_t width = save_data.map.width;
 | |
|   size_t height = save_data.map.height;
 | |
| 
 | |
|   Pathing paths(width, height);
 | |
|   map_out = Map(save_data.map.walls, paths);
 | |
| 
 | |
|   save::load_configs(world_out);
 | |
| }
 | |
| 
 | |
| void save::load_configs(DinkyECS::World &world) {
 | |
|   Config game("./assets/config.json");
 | |
|   Config enemies("./assets/enemies.json");
 | |
|   Config items("./assets/items.json");
 | |
|   Config tiles("./assets/tiles.json");
 | |
|   Config devices("./assets/devices.json");
 | |
| 
 | |
|   world.set_the<GameConfig>({
 | |
|     game, enemies, items, tiles, devices
 | |
|   });
 | |
| }
 | 
