diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/chunk.cpp | 1 | ||||
-rw-r--r-- | src/critter-script.cpp | 12 | ||||
-rw-r--r-- | src/critter-script.hpp | 2 | ||||
-rw-r--r-- | src/critter.cpp | 15 | ||||
-rw-r--r-- | src/critter.hpp | 4 | ||||
-rw-r--r-- | src/object.cpp | 4 | ||||
-rw-r--r-- | src/object.hpp | 4 | ||||
-rw-r--r-- | src/script.hpp | 4 | ||||
-rw-r--r-- | src/script.inl | 34 | ||||
-rw-r--r-- | src/world.cpp | 31 | ||||
-rw-r--r-- | src/world.hpp | 7 |
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); |