summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/scenery-proto.hpp3
-rw-r--r--src/scenery-type.hpp2
-rw-r--r--src/scenery.hpp3
-rw-r--r--src/world.cpp27
-rw-r--r--src/world.hpp4
5 files changed, 34 insertions, 5 deletions
diff --git a/src/scenery-proto.hpp b/src/scenery-proto.hpp
index c5889b04..44c8fe6f 100644
--- a/src/scenery-proto.hpp
+++ b/src/scenery-proto.hpp
@@ -41,4 +41,7 @@ struct scenery_proto : object_proto
scenery_proto& operator=(scenery_proto&&) noexcept;
};
+template<> struct scenery_type_<generic_scenery_proto> : std::integral_constant<scenery_type, scenery_type::generic> {};
+template<> struct scenery_type_<door_scenery_proto> : std::integral_constant<scenery_type, scenery_type::door> {};
+
} // namespace floormat
diff --git a/src/scenery-type.hpp b/src/scenery-type.hpp
index 3879e225..98cb9b10 100644
--- a/src/scenery-type.hpp
+++ b/src/scenery-type.hpp
@@ -6,4 +6,6 @@ enum class scenery_type : unsigned char {
none, generic, door, COUNT,
};
+template<typename T> struct scenery_type_;
+
} // namespace floormat
diff --git a/src/scenery.hpp b/src/scenery.hpp
index 6699fe2f..beb06db5 100644
--- a/src/scenery.hpp
+++ b/src/scenery.hpp
@@ -66,4 +66,7 @@ template<> struct object_type_<generic_scenery> : std::integral_constant<object_
template<> struct object_type_<door_scenery> : std::integral_constant<object_type, object_type::scenery> {};
template<> struct object_type_<scenery_proto> : std::integral_constant<object_type, object_type::scenery> {};
+template<> struct scenery_type_<generic_scenery> : std::integral_constant<scenery_type, scenery_type::generic> {};
+template<> struct scenery_type_<door_scenery> : std::integral_constant<scenery_type, scenery_type::door> {};
+
} // namespace floormat
diff --git a/src/world.cpp b/src/world.cpp
index 9f7c0cc3..dd6f2ca7 100644
--- a/src/world.cpp
+++ b/src/world.cpp
@@ -196,7 +196,12 @@ void world::set_object_counter(object_id value)
void world::throw_on_wrong_object_type(object_id id, object_type actual, object_type expected)
{
- fm_throw("object '{}' has wrong object type '{}', should be '{}'"_cf, id, (size_t)actual, (size_t)expected);
+ fm_throw("object {} has wrong object type {}, should be {}"_cf, id, (size_t)actual, (size_t)expected);
+}
+
+void world::throw_on_wrong_scenery_type(object_id id, scenery_type actual, scenery_type expected)
+{
+ fm_throw("object {} has wrong scenery 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)
@@ -285,18 +290,30 @@ std::shared_ptr<T> world::find_object(object_id id)
return {};
else if constexpr(std::is_same_v<T, object>)
return ptr;
+ else if (ptr->type() != object_type_<T>::value) [[unlikely]]
+ throw_on_wrong_object_type(id, ptr->type(), object_type_<T>::value);
+ else
+ return static_pointer_cast<T>(move(ptr));
+}
+
+template<typename T>
+requires is_strict_base_of<scenery, T>
+std::shared_ptr<T> world::find_object(object_id id)
+{
+ if (auto ptr = find_object<scenery>(id); !ptr)
+ return {};
+ else if (ptr->scenery_type() != scenery_type_<T>::value) [[unlikely]]
+ throw_on_wrong_scenery_type(id, ptr->scenery_type(), scenery_type_<T>::value);
else
- {
- if (!(ptr->type() == object_type_<T>::value)) [[unlikely]]
- throw_on_wrong_object_type(id, ptr->type(), object_type_<T>::value);
return static_pointer_cast<T>(move(ptr));
- }
}
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 std::shared_ptr<generic_scenery> world::find_object<generic_scenery>(object_id id);
+template std::shared_ptr<door_scenery> world::find_object<door_scenery>(object_id id);
template<bool sorted>
std::shared_ptr<scenery> world::make_scenery(object_id id, global_coords pos, scenery_proto&& proto)
diff --git a/src/world.hpp b/src/world.hpp
index e92979db..52cb1f64 100644
--- a/src/world.hpp
+++ b/src/world.hpp
@@ -1,8 +1,10 @@
#pragma once
#include "compat/safe-ptr.hpp"
+#include "compat/base-of.hpp"
#include "chunk.hpp"
#include "global-coords.hpp"
#include "object-type.hpp"
+#include "scenery-type.hpp"
#include "loader/policy.hpp"
#include <memory>
#include <unordered_map>
@@ -50,6 +52,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_wrong_scenery_type(object_id id, scenery_type actual, scenery_type expected);
[[noreturn]] static void throw_on_empty_scenery_proto(object_id id, global_coords pos, Vector2b offset);
friend struct object;
@@ -91,6 +94,7 @@ public:
}
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);
+ template<typename T> requires is_strict_base_of<scenery, T> std::shared_ptr<T> find_object(object_id id);
shared_ptr_wrapper<critter> ensure_player_character(object_id& id, critter_proto p);
shared_ptr_wrapper<critter> ensure_player_character(object_id& id);