summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/chunk.cpp1
-rw-r--r--src/critter-script.cpp12
-rw-r--r--src/critter-script.hpp2
-rw-r--r--src/critter.cpp15
-rw-r--r--src/critter.hpp4
-rw-r--r--src/object.cpp4
-rw-r--r--src/object.hpp4
-rw-r--r--src/script.hpp4
-rw-r--r--src/script.inl34
-rw-r--r--src/world.cpp31
-rw-r--r--src/world.hpp7
11 files changed, 91 insertions, 27 deletions
diff --git a/src/chunk.cpp b/src/chunk.cpp
index e2b26e72..9f6fe993 100644
--- a/src/chunk.cpp
+++ b/src/chunk.cpp
@@ -173,7 +173,6 @@ void chunk::add_object(const std::shared_ptr<object>& e)
void chunk::on_teardown()
{
fm_assert(!_teardown); // too late, some chunks were already erased
- //for (const auto& eʹ : _objects) eʹ->on_destroy(eʹ, true); // todo!
}
void chunk::remove_object(size_t i)
diff --git a/src/critter-script.cpp b/src/critter-script.cpp
index 7b80234f..b222f628 100644
--- a/src/critter-script.cpp
+++ b/src/critter-script.cpp
@@ -34,24 +34,28 @@ void empty_critter_script::on_init(const std::shared_ptr<critter>& p)
}
void empty_critter_script::on_update(const std::shared_ptr<critter>& p, size_t&, const Ns&)
{
- DBG_nospace << "> update critter:" << (void*)&*p << " id:" << p->id << (p->name ? " name:" : "") << p->name;
+ DBG_nospace << " update critter:" << (void*)&*p << " id:" << p->id << (p->name ? " name:" : "") << p->name;
touch_ptr(p);
}
void empty_critter_script::on_destroy(const std::shared_ptr<critter>& p, script_destroy_reason r)
{
- DBG_nospace << "> destroy critter:" << (void*)&*p << " id:" << p->id << " reason:" << (int)r << (p->name ? " name:" : "") << p->name;
+ DBG_nospace << " destroy critter:" << (void*)&*p << " id:" << p->id << " reason:" << (int)r << (p->name ? " name:" : "") << p->name;
touch_ptr(p);
}
void empty_critter_script::delete_self() noexcept
{
- DBG_nospace << "> delete critter";
+ DBG_nospace << "< delete critter";
}
empty_critter_script empty_script_ = {};
} // namespace
-critter_script* const critter_script::empty_script = &empty_script_;
+template <>
+critter_script* Script<critter_script, critter>::make_empty()
+{
+ return &empty_script_;
+}
critter_script::critter_script(const std::shared_ptr<critter>&) {}
critter_script::~critter_script() noexcept {}
diff --git a/src/critter-script.hpp b/src/critter-script.hpp
index 75f8156d..629d9d1b 100644
--- a/src/critter-script.hpp
+++ b/src/critter-script.hpp
@@ -17,8 +17,6 @@ struct critter_script : base_script
virtual void on_destroy(const std::shared_ptr<critter>& c, script_destroy_reason reason) = 0;
virtual void delete_self() = 0;
// todo can_activate, activate
-
- static critter_script* const empty_script;
};
} // namespace floormat
diff --git a/src/critter.cpp b/src/critter.cpp
index ece278b2..f743f614 100644
--- a/src/critter.cpp
+++ b/src/critter.cpp
@@ -549,4 +549,19 @@ critter::~critter() noexcept
//fm_assert(!script);
}
+void critter::init_script(const std::shared_ptr<object>& ptrʹ)
+{
+ script.do_initialize(std::static_pointer_cast<critter>(ptrʹ));
+}
+
+void critter::destroy_script_pre(const std::shared_ptr<object>& ptrʹ, script_destroy_reason r)
+{
+ script.do_destroy_pre(std::static_pointer_cast<critter>(ptrʹ), r);
+}
+
+void critter::destroy_script_post()
+{
+ script.do_finish_destroy();
+}
+
} // namespace floormat
diff --git a/src/critter.hpp b/src/critter.hpp
index 0ac56578..954499c3 100644
--- a/src/critter.hpp
+++ b/src/critter.hpp
@@ -44,6 +44,10 @@ struct critter final : object
Vector2 ordinal_offset(Vector2b offset) const override;
float depth_offset() const override;
+ void init_script(const std::shared_ptr<object>& ptr) override;
+ void destroy_script_pre(const std::shared_ptr<object>& ptr, script_destroy_reason r) override;
+ void destroy_script_post() override;
+
Script<critter_script, critter> script;
String name;
float speed = 1;
diff --git a/src/object.cpp b/src/object.cpp
index cd883795..f4c803b7 100644
--- a/src/object.cpp
+++ b/src/object.cpp
@@ -361,4 +361,8 @@ bool object::is_dynamic() const
return atlas->info().fps > 0;
}
+void object::init_script(const std::shared_ptr<object>&) {}
+void object::destroy_script_pre(const std::shared_ptr<object>&, script_destroy_reason) {}
+void object::destroy_script_post() {}
+
} // namespace floormat
diff --git a/src/object.hpp b/src/object.hpp
index 9d842572..d2607626 100644
--- a/src/object.hpp
+++ b/src/object.hpp
@@ -97,6 +97,10 @@ struct object
requires std::is_unsigned_v<T>
static uint32_t alloc_frame_time(const Ns& dt, T& accum, uint32_t hz, float speed);
+ virtual void init_script(const std::shared_ptr<object>& ptr);
+ virtual void destroy_script_pre(const std::shared_ptr<object>& ptr, script_destroy_reason r);
+ virtual void destroy_script_post();
+
protected:
object(object_id id, class chunk& c, const object_proto& proto);
void set_bbox_(Vector2b offset, Vector2b bbox_offset, Vector2ub bbox_size, pass_mode pass);
diff --git a/src/script.hpp b/src/script.hpp
index c37cf448..5f657e28 100644
--- a/src/script.hpp
+++ b/src/script.hpp
@@ -37,6 +37,7 @@ class Script final
S* ptr;
script_lifecycle state;
void _assert_state(script_lifecycle s, const char* file, int line);
+ static S* make_empty();
public:
fm_DECLARE_DELETED_COPY_ASSIGNMENT(Script);
@@ -60,8 +61,7 @@ public:
void do_create(S* ptr);
void do_initialize(const std::shared_ptr<Obj>& obj);
void do_reassign(S* ptr, const std::shared_ptr<Obj>& obj);
- void do_destroy_1(const std::shared_ptr<Obj>& obj);
- void do_destroy_pre(const std::shared_ptr<Obj>& obj);
+ void do_destroy_pre(const std::shared_ptr<Obj>& obj, script_destroy_reason r);
void do_finish_destroy();
void do_ensure_torn_down();
void do_error_unwind();
diff --git a/src/script.inl b/src/script.inl
index d2e0bcd4..a756bb08 100644
--- a/src/script.inl
+++ b/src/script.inl
@@ -35,8 +35,7 @@ namespace floormat {
#define FM_ASSERT_SCRIPT_STATE(new_state) (Script<S, Obj>::_assert_state((new_state), __FILE__, __LINE__))
-template <typename S, typename Obj>
-Script<S, Obj>::~Script() noexcept
+template <typename S, typename Obj> Script<S, Obj>::~Script() noexcept
{
fm_assert(state < script_lifecycle::COUNT);
switch (state)
@@ -96,9 +95,20 @@ void Script<S, Obj>::do_create(S* p)
template <typename S, typename Obj>
void Script<S, Obj>::do_initialize(const std::shared_ptr<Obj>& obj)
{
- FM_ASSERT_SCRIPT_STATE(script_lifecycle::initializing);
- state = script_lifecycle::created;
- ptr->on_init(obj);
+ switch (state)
+ {
+ default:
+ FM_ASSERT_SCRIPT_STATE(script_lifecycle::initializing);
+ std::unreachable();
+ case script_lifecycle::no_init:
+ ptr = make_empty();
+ [[fallthrough]];
+ case script_lifecycle::initializing:
+ state = script_lifecycle::created;
+ ptr->on_init(obj);
+ return;
+ }
+ std::unreachable();
}
template <typename S, typename Obj>
@@ -114,21 +124,11 @@ void Script<S, Obj>::do_reassign(S* p, const std::shared_ptr<Obj>& obj)
}
template <typename S, typename Obj>
-void Script<S, Obj>::do_destroy_1(const std::shared_ptr<Obj>& obj)
-{
- FM_ASSERT_SCRIPT_STATE(script_lifecycle::created);
- state = script_lifecycle::torn_down;
- ptr->on_destroy(obj, script_destroy_reason::kill);
- ptr->delete_self();
- ptr = nullptr;
-}
-
-template <typename S, typename Obj>
-void Script<S, Obj>::do_destroy_pre(const std::shared_ptr<Obj>& obj)
+void Script<S, Obj>::do_destroy_pre(const std::shared_ptr<Obj>& obj, script_destroy_reason r)
{
FM_ASSERT_SCRIPT_STATE(script_lifecycle::created);
state = script_lifecycle::destroying;
- ptr->on_destroy(obj, script_destroy_reason::quit);
+ ptr->on_destroy(obj, r);
}
template <typename S, typename Obj>
diff --git a/src/world.cpp b/src/world.cpp
index e3fae3c3..975181c0 100644
--- a/src/world.cpp
+++ b/src/world.cpp
@@ -44,6 +44,11 @@ world::world(std::unordered_map<chunk_coords_, chunk>&& chunks) :
world& world::operator=(world&& w) noexcept
{
fm_debug_assert(&w != this);
+ fm_assert(!w._script_initialized);
+ fm_assert(!w._script_finalized);
+ fm_assert(!_script_initialized || _script_finalized);
+ _script_initialized = false;
+ _script_finalized = false;
fm_assert(!w._teardown);
fm_assert(!_teardown);
fm_assert(w._unique_id);
@@ -69,6 +74,7 @@ world::world() : world{initial_capacity}
world::~world() noexcept
{
+ fm_assert(_script_finalized || !_script_initialized);
for (auto& [k, c] : _chunks)
c.on_teardown();
_teardown = true;
@@ -231,6 +237,31 @@ critter_proto world::make_player_proto()
return cproto;
}
+bool world::is_teardown() const { return _teardown; }
+
+void world::init_scripts()
+{
+ fm_assert(!_script_initialized);
+ _script_initialized = true;
+ for (auto& [k, c] : _chunks)
+ for (const auto& obj : c.objects())
+ obj->init_script(obj);
+}
+
+void world::finish_scripts()
+{
+ fm_assert(_script_initialized);
+ fm_assert(!_script_finalized);
+ _script_finalized = true;
+
+ for (auto& [k, c] : _chunks)
+ for (const auto& obj : c.objects())
+ obj->destroy_script_pre(obj, script_destroy_reason::quit);
+ for (auto& [k, c] : _chunks)
+ for (const auto& obj : c.objects())
+ obj->destroy_script_post();
+}
+
shared_ptr_wrapper<critter> world::ensure_player_character(object_id& id)
{
return ensure_player_character(id, make_player_proto());
diff --git a/src/world.hpp b/src/world.hpp
index 78fdd690..2a3a26f1 100644
--- a/src/world.hpp
+++ b/src/world.hpp
@@ -44,6 +44,8 @@ private:
object_id _object_counter = object_counter_init;
uint64_t _current_frame = 1; // zero is special for struct object
bool _teardown : 1 = false;
+ bool _script_initialized : 1 = false;
+ bool _script_finalized : 1 = false;
explicit world(size_t capacity);
@@ -92,6 +94,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);
template<typename T> requires is_strict_base_of<scenery, T> std::shared_ptr<T> find_object(object_id id);
@@ -100,7 +103,9 @@ public:
shared_ptr_wrapper<critter> ensure_player_character(object_id& id);
static critter_proto make_player_proto();
- bool is_teardown() const { return _teardown; }
+ void init_scripts();
+ void finish_scripts();
+ bool is_teardown() const;
object_id object_counter() const { return _object_counter; }
[[nodiscard]] object_id make_id() { return ++_object_counter; }
void set_object_counter(object_id value);