diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-04-13 12:26:26 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-04-13 12:26:26 +0200 |
commit | cb13eb86db3593e723ce06c48a5cb2c94505d6ae (patch) | |
tree | 9b56825b1debc908dc999feace69645eb56eb2f8 /serialize | |
parent | 2c042d30d96827941e5052d4eca0cc03965cacc8 (diff) |
use inheritance for scenery, not std::variant
It's still WIP because creating scenery has to branch on all subtypes.
This needs to be taken care of generically in `world::make_object()`.
Diffstat (limited to 'serialize')
-rw-r--r-- | serialize/old-savegame.cpp | 29 | ||||
-rw-r--r-- | serialize/savegame.cpp | 56 |
2 files changed, 55 insertions, 30 deletions
diff --git a/serialize/old-savegame.cpp b/serialize/old-savegame.cpp index 46b83590..31136798 100644 --- a/serialize/old-savegame.cpp +++ b/serialize/old-savegame.cpp @@ -186,7 +186,7 @@ bool read_object_flags(binary_reader<T>& s, U& e) } else if constexpr(tag == object_type::critter) { - e.playable = !!(flags & 1 << 2); + e.playable = !!(flags & 1 << 2); } else { @@ -355,7 +355,7 @@ void reader_state::read_chunks(reader_t& s) } uint32_t object_count = 0; if (PROTO >= 8) [[likely]] - object_count << s; + object_count << s; SET_CHUNK_SIZE(); @@ -482,6 +482,7 @@ void reader_state::read_chunks(reader_t& s) uint16_t delta_; delta_ << s; sc.delta = uint32_t(sc.delta) * 65536u; } + _world->make_object<generic_scenery, false>(oid, {ch, local}, *val, sc); } else if (const auto* val = std::get_if<door_scenery_proto>(&sc.subtype)) { @@ -490,10 +491,11 @@ void reader_state::read_chunks(reader_t& s) uint16_t delta_; delta_ << s; sc.delta = uint32_t(sc.delta) * 65536u; } + _world->make_object<door_scenery, false>(oid, {ch, local}, *val, sc); } + else + fm_soft_assert(false); } - auto e = _world->make_object<scenery, false>(oid, {ch, local}, sc); - (void)e; break; } case object_type::light: { @@ -564,10 +566,12 @@ void reader_state::read_old_scenery(reader_t& s, chunk_coords_ ch, size_t i) atlasid id; id << s; const bool exact = id & meta_short_scenery_bit_; const auto r = rotation(id >> sizeof(id)*8-1-rotation_BITS & rotation_MASK); + const global_coords coord{ch, local_coords{i}}; id &= ~scenery_id_flag_mask_; auto sc = lookup_scenery(id); - (void)sc.atlas->group(r); sc.r = r; + (void)sc.atlas->group(r); + if (!exact) { if (read_object_flags(s, sc)) @@ -589,6 +593,7 @@ void reader_state::read_old_scenery(reader_t& s, chunk_coords_ ch, size_t i) sc.bbox_offset[0] << s; sc.bbox_offset[1] << s; } + if (auto* val = std::get_if<generic_scenery_proto>(&sc.subtype)) { if (val->active) @@ -625,10 +630,18 @@ void reader_state::read_old_scenery(reader_t& s, chunk_coords_ ch, size_t i) } } } + else + fm_soft_assert(false); + } + else + { + if (auto* val = std::get_if<generic_scenery_proto>(&sc.subtype)) + auto e = _world->make_object<generic_scenery, false>(_world->make_id(), coord, *val, sc); + else if (auto* val = std::get_if<door_scenery_proto>(&sc.subtype)) + auto e = _world->make_object<door_scenery, false>(_world->make_id(), coord, *val, sc); + else + fm_soft_assert(false); } - global_coords coord{ch, local_coords{i}}; - auto e = _world->make_object<scenery, false>(_world->make_id(), coord, sc); - (void)e; } void reader_state::deserialize_world(ArrayView<const char> buf, proto_t proto) diff --git a/serialize/savegame.cpp b/serialize/savegame.cpp index b152fb31..4bc1c7ad 100644 --- a/serialize/savegame.cpp +++ b/serialize/savegame.cpp @@ -412,12 +412,16 @@ struct writer final : visitor_<writer, true> template<typename F> void write_scenery_proto(const scenery& obj, F&& f) // todo! replace scenery::subtype with inheritance! { auto sc_type = obj.scenery_type(); - fm_debug_assert(sc_type != scenery_type::none); + fm_debug_assert(sc_type != scenery_type::none && sc_type < scenery_type::COUNT); visit(sc_type, f); - std::visit( - [&](auto& subtype) { visit_scenery_proto(subtype, f); }, - obj.subtype - ); + switch (sc_type) + { + case scenery_type::generic: visit_scenery_proto(static_cast<const generic_scenery&>(obj), f); break; + case scenery_type::door: visit_scenery_proto(static_cast<const door_scenery&>(obj), f); break; + case scenery_type::none: + case scenery_type::COUNT: + std::unreachable(); + } } template<typename F> void write_object(o_object& obj, chunk* c, F&& f) @@ -815,10 +819,16 @@ struct reader final : visitor_<reader, false> } } - template<typename F> void visit_object_proto(o_scenery& obj, std::nullptr_t, F&& f) + template<typename F> + void read_scenery(std::shared_ptr<scenery>& ret, const object_proto& pʹ, const object_header_s& h, F&& f) { + const auto coord = global_coords{h.ch->coord(), h.tile}; auto sc_type = scenery_type::none; visit(sc_type, f); + + scenery_proto sc; + static_cast<object_proto&>(sc) = pʹ; + switch (sc_type) { case scenery_type::none: @@ -827,19 +837,20 @@ struct reader final : visitor_<reader, false> case scenery_type::generic: { generic_scenery_proto p; visit_scenery_proto(p, f); - obj.subtype = move(p); - goto ok; + sc.subtype = move(p); // todo! extract into make_scenery() + ret = w.make_object<generic_scenery>(h.id, coord, move(p), move(sc)); + return; } case scenery_type::door: { door_scenery_proto p; visit_scenery_proto(p, f); - obj.subtype = move(p); - goto ok; + sc.subtype = move(p); + ret = w.make_object<door_scenery>(h.id, coord, move(p), move(sc)); + return; } } + fm_throw("invalid sc_type {}"_cf, (int)sc_type); -ok: - void(); } template<typename Obj, typename Proto, typename Header> @@ -856,7 +867,7 @@ ok: return w.make_object<Obj>(h0.id, coord, move(p)); } - template<typename F> [[nodiscard]] std::shared_ptr<object> read_object(chunk* ch, F&& f) + template<typename F> void read_object(chunk* ch, F&& f) { std::shared_ptr<object> obj; object_id id = 0; @@ -870,8 +881,8 @@ ok: .tile = tile, }; - object_proto pʹ; - visit_object_header(pʹ, s, f); + object_proto p; + visit_object_header(p, s, f); switch (type) { @@ -883,17 +894,20 @@ ok: critter_header_s h{ .offset_frac = offset_frac, }; - obj = make_object<critter, critter_proto, critter_header_s>(s, move(pʹ), move(h), f); + obj = make_object<critter, critter_proto, critter_header_s>(s, move(p), move(h), f); goto ok; } case object_type::light: - obj = make_object<light, light_proto, std::nullptr_t>(s, move(pʹ), {}, f); + obj = make_object<light, light_proto, std::nullptr_t>(s, move(p), {}, f); goto ok; - case object_type::scenery: - obj = make_object<scenery, scenery_proto, std::nullptr_t>(s, move(pʹ), {}, f); + case object_type::scenery: { + std::shared_ptr<scenery> objʹ; + read_scenery(objʹ, move(p), s, f); + obj = move(objʹ); goto ok; } - fm_throw("invalid sc_type {}"_cf, (int)type); + } + fm_throw("invalid object_type {}"_cf, (int)type); ok: fm_assert(obj); fm_debug_assert(obj->c == ch); @@ -905,8 +919,6 @@ ok: fm_soft_assert(object_counter >= id); else if (PROTO == 20) [[unlikely]] object_counter = Math::max(object_counter, id); - - return obj; } bool deserialize_header_(binary_reader<const char*>& s, ArrayView<const char> buf) |