|
|
|
#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.$rooms, map.$input_map, map.$walls, map.$limit};
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
map_out = Map(save_data.map.input_map,
|
|
|
|
save_data.map.walls, save_data.map.limit);
|
|
|
|
|
|
|
|
save::load_configs(world_out);
|
|
|
|
}
|
|
|
|
|
|
|
|
void save::load_configs(DinkyECS::World &world) {
|
|
|
|
Config config("./assets/config.json");
|
|
|
|
world.set_the<Config>(config);
|
|
|
|
|
|
|
|
auto map = config["map"];
|
|
|
|
world.set_the<MapConfig>({
|
|
|
|
map["WALL_TILE"],
|
|
|
|
map["FLOOR_TILE"],
|
|
|
|
map["PLAYER_TILE"],
|
|
|
|
map["ENEMY_TILE"],
|
|
|
|
map["BG_TILE"]
|
|
|
|
});
|
|
|
|
|
|
|
|
auto enemy = config["enemy"];
|
|
|
|
world.set_the<EnemyConfig>({
|
|
|
|
enemy["HEARING_DISTANCE"]
|
|
|
|
});
|
|
|
|
}
|