From 280b4c235fe11dd629f882f0fb5054384fcee1d7 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 28 Oct 2022 22:10:27 +0200 Subject: more work --- serialize/world-reader.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 6 deletions(-) (limited to 'serialize/world-reader.cpp') diff --git a/serialize/world-reader.cpp b/serialize/world-reader.cpp index 86b07834..299386de 100644 --- a/serialize/world-reader.cpp +++ b/serialize/world-reader.cpp @@ -2,6 +2,8 @@ #include "world-impl.hpp" #include "binary-reader.inl" #include "src/world.hpp" +#include "src/loader.hpp" +#include "src/tile-atlas.hpp" namespace floormat::Serialize { @@ -12,9 +14,11 @@ struct reader_state final { void deserialize_world(ArrayView buf); private: + using reader_t = binary_reader{}.cbegin())>; + std::shared_ptr lookup_atlas(atlasid id); - void read_atlases(); - void read_chunks(); + void read_atlases(reader_t& reader); + void read_chunks(reader_t& reader); std::unordered_map> atlases; struct world* world; @@ -22,11 +26,84 @@ private: reader_state::reader_state(struct world& world) noexcept : world{&world} {} +void reader_state::read_atlases(reader_t& s) +{ + const auto N = s.read(); + atlases.reserve(N * 2); + for (atlasid i = 0; i < N; i++) + { + Vector2ub size; + s >> size[0]; + s >> size[1]; + atlases[i] = loader.tile_atlas(s.read_asciiz_string(), size); + } +} + +std::shared_ptr reader_state::lookup_atlas(atlasid id) +{ + if (auto it = atlases.find(id); it != atlases.end()) + return it->second; + else + fm_abort("not such atlas: '%zu'", (std::size_t)id); +} + +void reader_state::read_chunks(reader_t& s) +{ + const auto N = s.read(); + + for (std::size_t i = 0; i < N; i++) + { + std::decay_t magic; + s >> magic; + if (magic != chunk_magic) + fm_abort("bad chunk magic"); + chunk_coords coord; + s >> coord.x; + s >> coord.y; + auto& chunk = (*world)[coord]; + for (std::size_t i = 0; i < TILE_COUNT; i++) + { + const tilemeta flags = s.read(); + const auto make_atlas = [&] -> tile_image { + auto atlas = lookup_atlas(s.read()); + auto id = s.read(); + return { atlas, id }; + }; + tile t; + if (flags & meta_ground) + t.ground_image = make_atlas(); + if (flags & meta_wall_n) + t.wall_north = make_atlas(); + if (flags & meta_wall_w) + t.wall_west = make_atlas(); + switch (auto x = flags & pass_mask) + { + case tile::pass_shoot_through: + case tile::pass_blocked: + case tile::pass_ok: + t.passability = (tile::pass_mode)x; + break; + default: + fm_abort("bad pass mode '%zu' for tile %zu", i, (std::size_t)x); + } + chunk[i] = std::move(t); + } + } +} + void reader_state::deserialize_world(ArrayView buf) { auto s = binary_reader{buf}; if (!!::memcmp(s.read().data(), file_magic, std::size(file_magic)-1)) fm_abort("bad magic"); + std::decay_t proto; + s >> proto; + if (proto != proto_version) + fm_abort("bad proto version '%zu' (should be '%zu')", + (std::size_t)proto, (std::size_t)proto_version); + read_atlases(s); + read_chunks(s); + s.assert_end(); } } // namespace @@ -47,17 +124,17 @@ world world::deserialize(StringView filename) if (!f) fm_abort("fopen(\"%s\", \"r\"): %s", filename.data(), strerror(errbuf)); if (int ret = ::fseek(f, 0, SEEK_END); ret != 0) - fm_abort("fseek(\"%s\", 0, SEEK_END): %s", filename.data(), strerror(errbuf)); + fm_abort("fseek(SEEK_END): %s", strerror(errbuf)); std::size_t len; if (auto len_ = ::ftell(f); len_ >= 0) len = (std::size_t)len_; else - fm_abort("ftell(\"%s\"): %s", filename.data(), strerror(errbuf)); + fm_abort("ftell: %s", strerror(errbuf)); if (int ret = ::fseek(f, 0, SEEK_SET); ret != 0) - fm_abort("fseek(\"%s\", 0, SEEK_SET): %s", filename.data(), strerror(errbuf)); + fm_abort("fseek(SEEK_SET): %s", strerror(errbuf)); auto buf_ = std::make_unique(len); if (auto ret = ::fread(&buf_[0], len, 1, f); ret != 1) - fm_abort("fread(\"%s\", %zu): %s", filename.data(), len, strerror(errbuf)); + fm_abort("fread %zu: %s", len, strerror(errbuf)); world w; Serialize::reader_state s{w}; -- cgit v1.2.3