summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--editor/scenery-editor.cpp18
-rw-r--r--serialize/old-savegame.cpp30
-rw-r--r--serialize/savegame.cpp11
-rw-r--r--serialize/scenery.cpp1
-rw-r--r--src/object-type.hpp1
-rw-r--r--src/object.cpp9
-rw-r--r--src/object.hpp16
-rw-r--r--src/scenery.cpp6
-rw-r--r--src/scenery.hpp4
-rw-r--r--src/world.cpp44
-rw-r--r--src/world.hpp8
-rw-r--r--test/critter.cpp14
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)