diff options
-rw-r--r-- | editor/scenery-editor.cpp | 18 | ||||
-rw-r--r-- | serialize/old-savegame.cpp | 30 | ||||
-rw-r--r-- | serialize/savegame.cpp | 11 | ||||
-rw-r--r-- | serialize/scenery.cpp | 1 | ||||
-rw-r--r-- | src/object-type.hpp | 1 | ||||
-rw-r--r-- | src/object.cpp | 9 | ||||
-rw-r--r-- | src/object.hpp | 16 | ||||
-rw-r--r-- | src/scenery.cpp | 6 | ||||
-rw-r--r-- | src/scenery.hpp | 4 | ||||
-rw-r--r-- | src/world.cpp | 44 | ||||
-rw-r--r-- | src/world.hpp | 8 | ||||
-rw-r--r-- | test/critter.cpp | 14 |
12 files changed, 81 insertions, 81 deletions
diff --git a/editor/scenery-editor.cpp b/editor/scenery-editor.cpp index 28d94263..55e194bf 100644 --- a/editor/scenery-editor.cpp +++ b/editor/scenery-editor.cpp @@ -103,25 +103,9 @@ start: } else { - const auto sc_type = s.proto.scenery_type(); // todo check collision at pos - switch (sc_type) - { - case scenery_type::none: - case scenery_type::COUNT: - break; - case scenery_type::generic: - w.make_object<generic_scenery>(w.make_id(), pos, std::get<generic_scenery_proto>(s.proto.subtype), s.proto); - goto ok; - case scenery_type::door: - w.make_object<door_scenery>(w.make_id(), pos, std::get<door_scenery_proto>(s.proto.subtype), s.proto); - goto ok; - } - fm_abort("place_tile: wrong scenery type %d", (int)sc_type); -ok: - void(); + w.make_scenery(w.make_id(), pos, scenery_proto(s.proto)); } - } } // namespace floormat diff --git a/serialize/old-savegame.cpp b/serialize/old-savegame.cpp index 31136798..fe56be32 100644 --- a/serialize/old-savegame.cpp +++ b/serialize/old-savegame.cpp @@ -183,6 +183,8 @@ bool read_object_flags(binary_reader<T>& s, U& e) val->closing = !!(flags & 1 << 3); val->interactive = !!(flags & 1 << 4); } + else + fm_soft_assert(false); } else if constexpr(tag == object_type::critter) { @@ -475,26 +477,7 @@ void reader_state::read_chunks(reader_t& s) s >> sc.offset[1]; } read_bbox(s, sc); - if (const auto* val = std::get_if<generic_scenery_proto>(&sc.subtype)) - { - if (val->active) - { - 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)) - { - if (val->active) - { - 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); + _world->make_scenery(oid, {ch, local}, move(sc)); } break; } @@ -635,12 +618,7 @@ void reader_state::read_old_scenery(reader_t& s, chunk_coords_ ch, size_t i) } 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); + _world->make_scenery(_world->make_id(), coord, move(sc)); } } diff --git a/serialize/savegame.cpp b/serialize/savegame.cpp index 4bc1c7ad..04f9c599 100644 --- a/serialize/savegame.cpp +++ b/serialize/savegame.cpp @@ -837,20 +837,19 @@ struct reader final : visitor_<reader, false> case scenery_type::generic: { generic_scenery_proto p; visit_scenery_proto(p, f); - sc.subtype = move(p); // todo! extract into make_scenery() - ret = w.make_object<generic_scenery>(h.id, coord, move(p), move(sc)); - return; + sc.subtype = move(p); + goto ok; } case scenery_type::door: { door_scenery_proto p; visit_scenery_proto(p, f); sc.subtype = move(p); - ret = w.make_object<door_scenery>(h.id, coord, move(p), move(sc)); - return; + goto ok; } } - fm_throw("invalid sc_type {}"_cf, (int)sc_type); +ok: + ret = w.make_scenery(h.id, coord, move(sc)); } template<typename Obj, typename Proto, typename Header> diff --git a/serialize/scenery.cpp b/serialize/scenery.cpp index 5950ddf3..edcd57c7 100644 --- a/serialize/scenery.cpp +++ b/serialize/scenery.cpp @@ -104,6 +104,7 @@ void adl_serializer<scenery_proto>::to_json(json& j, const scenery_proto& f) if (f.pass != default_scenery.pass) j["pass-mode"] = f.pass; std::visit(overloaded { + [](std::monostate) { fm_soft_assert(false); }, [&](const generic_scenery_proto& x) { if (x.active != default_generic_scenery.active) j["active"] = x.active; diff --git a/src/object-type.hpp b/src/object-type.hpp index 8c84c31a..35b25ccf 100644 --- a/src/object-type.hpp +++ b/src/object-type.hpp @@ -5,5 +5,6 @@ namespace floormat { enum class object_type : unsigned char { none, critter, scenery, light, COUNT, }; +template<typename T> struct object_type_; } // namespace floormat diff --git a/src/object.cpp b/src/object.cpp index 03491de3..cd883795 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -43,10 +43,12 @@ constexpr inline Pair<int, int8_t> normalize_coord(const int8_t cur, const int n } // namespace bool object_proto::operator==(const object_proto&) const = default; -object_proto& object_proto::operator=(const object_proto&) = default; +object_proto::object_proto(const object_proto&) noexcept = default; +object_proto& object_proto::operator=(const object_proto&) noexcept = default; +object_proto::object_proto(object_proto&&) noexcept = default; +object_proto& object_proto::operator=(object_proto&&) noexcept = default; object_proto::~object_proto() noexcept = default; -object_proto::object_proto() = default; -object_proto::object_proto(const object_proto&) = default; +object_proto::object_proto() noexcept = default; object_type object_proto::type_of() const noexcept { return type; } object::object(object_id id, class chunk& c, const object_proto& proto) : @@ -90,6 +92,7 @@ float object::ordinal(local_coords xy, Vector2b offset, Vector2s z_offset) const size_t object::index() const { auto& c = chunk(); + fm_assert(c._objects_sorted); const auto fn = [id = id](const auto& a, const auto&) { return a->id < id; }; auto& es = c._objects; auto it = std::lower_bound(es.cbegin(), es.cend(), nullptr, fn); diff --git a/src/object.hpp b/src/object.hpp index ce793fe8..e1582419 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -11,7 +11,6 @@ namespace floormat { -template<typename T> struct object_type_; class anim_atlas; class world; class chunk; @@ -28,15 +27,16 @@ struct object_proto rotation r = rotation::N; pass_mode pass = pass_mode::see_through; // todo move to struct scenery, add inherit bit - object_proto& operator=(const object_proto&); - object_proto(); - object_proto(const object_proto&); - - virtual bool operator==(const object_proto&) const; - bool operator!=(const object_proto& o) const { return !operator==(o); } + object_proto() noexcept; virtual ~object_proto() noexcept; - + virtual bool operator==(const object_proto&) const; + bool operator!=(const object_proto& o) const noexcept { return !operator==(o); } object_type type_of() const noexcept; + + object_proto& operator=(const object_proto&) noexcept; + object_proto(const object_proto&) noexcept; + object_proto& operator=(object_proto&&) noexcept; + object_proto(object_proto&&) noexcept; }; struct object diff --git a/src/scenery.cpp b/src/scenery.cpp index 4d47da5a..26213757 100644 --- a/src/scenery.cpp +++ b/src/scenery.cpp @@ -1,6 +1,7 @@ #include "scenery.hpp" #include "compat/assert.hpp" #include "compat/exception.hpp" +#include "compat/overloaded.hpp" #include "tile-constants.hpp" #include "anim-atlas.hpp" #include "rotation.inl" @@ -32,9 +33,10 @@ scenery_proto::operator bool() const { return atlas != nullptr; } enum scenery_type scenery_proto::scenery_type() const { - return std::visit( + return std::visit(overloaded { + [](std::monostate) { return scenery_type::none; }, []<typename T>(const T&) { return T::scenery_type(); }, - subtype + }, subtype ); } diff --git a/src/scenery.hpp b/src/scenery.hpp index be57296d..6ae7a10a 100644 --- a/src/scenery.hpp +++ b/src/scenery.hpp @@ -33,7 +33,7 @@ struct door_scenery_proto static enum scenery_type scenery_type(); }; -using scenery_proto_variants = std::variant<generic_scenery_proto, door_scenery_proto>; +using scenery_proto_variants = std::variant<std::monostate, generic_scenery_proto, door_scenery_proto>; struct scenery_proto : object_proto { @@ -55,7 +55,7 @@ struct scenery : object float depth_offset() const override; enum object_type type() const noexcept override; virtual enum scenery_type scenery_type() const = 0; - virtual explicit operator scenery_proto() const; + virtual explicit operator scenery_proto() const; // todo make protected? protected: scenery(object_id id, class chunk& c, const scenery_proto& proto); diff --git a/src/world.cpp b/src/world.cpp index edab80b6..821e4c65 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -7,6 +7,7 @@ #include "compat/shared-ptr-wrapper.hpp" #include "compat/int-hash.hpp" #include "compat/exception.hpp" +#include "compat/overloaded.hpp" #include <cr/GrowableArray.h> #include <tsl/robin_map.h> @@ -118,7 +119,7 @@ chunk* world::at(chunk_coords_ c) noexcept bool world::contains(chunk_coords_ c) const noexcept { - return _chunks.find(c) != _chunks.cend(); + return _chunks.contains(c); } void world::clear() @@ -197,6 +198,16 @@ void world::throw_on_wrong_object_type(object_id id, object_type actual, object_ fm_throw("object '{}' has wrong object type '{}', should be '{}'"_cf, id, (size_t)actual, (size_t)expected); } +void world::throw_on_empty_scenery_proto(object_id id, global_coords pos, Vector2b offset) +{ + ERR_nospace << "scenery_proto subtype not set" + << " id:" << id + << " pos:" << point{pos, offset}; + auto ch = Vector3i(pos.chunk3()); + auto t = Vector2i(pos.local()); + fm_throw("scenery_proto subtype not set! id:{} chunk:{}x{}x{} tile:{}x{}"_cf, id, ch.x(), ch.y(), ch.z(), t.x(), t.y()); +} + auto world::neighbors(chunk_coords_ coord) -> std::array<chunk*, 8> { std::array<chunk*, 8> ret; @@ -283,9 +294,32 @@ std::shared_ptr<T> world::find_object(object_id id) } } -template std::shared_ptr<object> world::find_object(object_id id); -template std::shared_ptr<critter> world::find_object(object_id id); -template std::shared_ptr<scenery> world::find_object(object_id id); -template std::shared_ptr<light> world::find_object(object_id id); +template std::shared_ptr<object> world::find_object<object>(object_id id); +template std::shared_ptr<critter> world::find_object<critter>(object_id id); +template std::shared_ptr<scenery> world::find_object<scenery>(object_id id); +template std::shared_ptr<light> world::find_object<light>(object_id id); + +template<bool sorted> +std::shared_ptr<scenery> world::make_scenery(object_id id, global_coords pos, scenery_proto&& proto) +{ + using type = std::shared_ptr<scenery>; + + return std::visit(overloaded { + [&](std::monostate) -> type { + throw_on_empty_scenery_proto(id, pos, proto.offset); + }, + [&](generic_scenery_proto&& p) -> type { + fm_debug_assert(p.scenery_type() == scenery_type::generic); + return make_object<generic_scenery, sorted>(id, pos, move(p), move(proto)); + }, + [&](door_scenery_proto&& p) -> type { + fm_debug_assert(p.scenery_type() == scenery_type::door); + return make_object<door_scenery, sorted>(id, pos, move(p), move(proto)); + }, + }, move(proto.subtype)); +} + +template std::shared_ptr<scenery> world::make_scenery<false>(object_id id, global_coords pos, scenery_proto&& proto); +template std::shared_ptr<scenery> world::make_scenery<true>(object_id id, global_coords pos, scenery_proto&& proto); } // namespace floormat diff --git a/src/world.hpp b/src/world.hpp index e805ae1f..e92979db 100644 --- a/src/world.hpp +++ b/src/world.hpp @@ -9,11 +9,12 @@ namespace floormat { +template<typename T> struct shared_ptr_wrapper; struct object; struct critter; struct critter_proto; -template<typename T> struct object_type_; -template<typename T> struct shared_ptr_wrapper; +struct scenery; +struct scenery_proto; class world final { @@ -49,6 +50,7 @@ private: std::shared_ptr<object> find_object_(object_id id); [[noreturn]] static void throw_on_wrong_object_type(object_id id, object_type actual, object_type expected); + [[noreturn]] static void throw_on_empty_scenery_proto(object_id id, global_coords pos, Vector2b offset); friend struct object; @@ -87,7 +89,7 @@ public: do_make_object(std::static_pointer_cast<object>(ret), pos, sorted); return ret; } - + template<bool sorted = true> std::shared_ptr<scenery> make_scenery(object_id id, global_coords pos, scenery_proto&& proto); template<typename T = object> std::shared_ptr<T> find_object(object_id id); shared_ptr_wrapper<critter> ensure_player_character(object_id& id, critter_proto p); diff --git a/test/critter.cpp b/test/critter.cpp index f7ce3b35..72bb58cc 100644 --- a/test/critter.cpp +++ b/test/critter.cpp @@ -302,21 +302,17 @@ void test2(StringView instance_name, const Function& make_dt, double accel, uint void test3(StringView instance_name, const Function& make_dt, double accel, rotation r, bool no_unroll) { const auto W = wall_image_proto{ loader.wall_atlas("empty"), 0 }; - const auto S = scenery_proto{loader.scenery("table0")}; + auto S = loader.scenery("table0"); auto w = world(); w[{{-1,-1,0}, {13,13}}].t.wall_north() = W; w[{{-1,-1,0}, {13,13}}].t.wall_west() = W; w[{{1,1,0}, {4,5}}].t.wall_north() = W; w[{{1,1,0}, {5,4}}].t.wall_west() = W; - (void)w.make_object<generic_scenery, false>(w.make_id(), {{}, {0, 0}}, - std::get<generic_scenery_proto>(S.subtype), S); // todo! - (void)w.make_object<generic_scenery, false>(w.make_id(), {{}, {1, 1}}, - std::get<generic_scenery_proto>(S.subtype), S); - (void)w.make_object<generic_scenery, false>(w.make_id(), {{}, {14, 14}}, - std::get<generic_scenery_proto>(S.subtype), S); - (void)w.make_object<generic_scenery, false>(w.make_id(), {{}, {15, 15}}, - std::get<generic_scenery_proto>(S.subtype), S); + w.make_scenery(w.make_id(), {{}, {0, 0}}, scenery_proto(S)); + w.make_scenery(w.make_id(), {{}, {1, 1}}, scenery_proto(S)); + w.make_scenery(w.make_id(), {{}, {14, 14}}, scenery_proto(S)); + w.make_scenery(w.make_id(), {{}, {15, 15}}, scenery_proto(S)); w[chunk_coords_{}].sort_objects(); if (no_unroll) |