diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2023-03-18 16:44:39 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2023-03-18 16:44:39 +0100 |
commit | 27dd8b268fbe37fa6eed0c0fc0f013134e5e2dc9 (patch) | |
tree | 7f04c83b09aa1d0706e832d16fa19ee31cd12f31 | |
parent | f82e612070b3edc963e787f121a58a2821ffa2a5 (diff) |
editor/app: don't duplicate characters on load
-rw-r--r-- | editor/app.cpp | 43 | ||||
-rw-r--r-- | editor/app.hpp | 1 | ||||
-rw-r--r-- | editor/update.cpp | 11 | ||||
-rw-r--r-- | src/world.hpp | 20 |
4 files changed, 57 insertions, 18 deletions
diff --git a/editor/app.cpp b/editor/app.cpp index 5820c165..c795d403 100644 --- a/editor/app.cpp +++ b/editor/app.cpp @@ -6,7 +6,7 @@ #include "loader/loader.hpp" #include "world.hpp" #include "src/anim-atlas.hpp" -#include "character.hpp" +#include "src/character.hpp" #include <cerrno> #include <cstdlib> #include <cstring> @@ -43,6 +43,40 @@ void app::reset_world() reset_world(floormat::world{}); } +void app::ensure_player_character(world& w) +{ + if (_character_id) + if (auto C = w.find_entity(_character_id); C && C->type == entity_type::character) + return; + _character_id = 0; + + auto id = (std::uint64_t)-1; + + for (const auto& [coord, c] : w.chunks()) + { + for (const auto& e_ : c.entities()) + { + const auto& e = *e_; + if (e.type == entity_type::character) + { + const auto& C = static_cast<const character&>(e); + if (C.playable) + id = std::min(id, C.id); + } + } + } + + if (id != (std::uint64_t)-1) + _character_id = id; + else + { + character_proto cproto; + cproto.name = "Player"_s; + cproto.playable = true; + _character_id = w.make_entity<character>(w.make_id(), global_coords{}, cproto)->id; + } +} + void app::reset_world(struct world&& w) { _popup_target = {}; @@ -51,12 +85,7 @@ void app::reset_world(struct world&& w) return; auto& w2 = M->reset_world(std::move(w)); w2.collect(true); - { - character_proto cproto; - cproto.name = "Player"_s; - cproto.playable = true; - _character_id = w2.make_entity<character>(w2.make_id(), global_coords{}, cproto)->id; - } + ensure_player_character(w2); } int app::exec() diff --git a/editor/app.hpp b/editor/app.hpp index 2407f7cb..dc8fed2c 100644 --- a/editor/app.hpp +++ b/editor/app.hpp @@ -77,6 +77,7 @@ private: void update_character(float dt); void reset_world(); void reset_world(struct world&& w); + void ensure_player_character(world& w); void draw() override; diff --git a/editor/update.cpp b/editor/update.cpp index cbe08c05..7c084a85 100644 --- a/editor/update.cpp +++ b/editor/update.cpp @@ -198,10 +198,13 @@ void app::update_world(float dt) void app::update_character([[maybe_unused]] float dt) { - auto& w = M->world(); - auto c = w.find_entity<character>(_character_id); - if (c) - c->set_keys(keys[key_left], keys[key_right], keys[key_up], keys[key_down]); + if (_character_id) + { + auto& w = M->world(); + auto c = w.find_entity<character>(_character_id); + if (c) + c->set_keys(keys[key_left], keys[key_right], keys[key_up], keys[key_down]); + } } void app::set_cursor() diff --git a/src/world.hpp b/src/world.hpp index f29a83e2..29d5a8dd 100644 --- a/src/world.hpp +++ b/src/world.hpp @@ -77,7 +77,7 @@ public: return ret; } - template<typename T = entity, typename U = entity> std::shared_ptr<T> find_entity(std::uint64_t id); + template<typename T = entity> std::shared_ptr<T> find_entity(std::uint64_t id); bool is_teardown() const { return _teardown; } std::uint64_t entity_counter() const { return _entity_counter; } @@ -98,15 +98,21 @@ world::world(std::unordered_map<chunk_coords, chunk, Hash, Alloc, Pred>&& chunks operator[](coord) = std::move(c); } -template<typename T, typename U> +template<typename T> std::shared_ptr<T> world::find_entity(std::uint64_t id) { static_assert(std::is_base_of_v<entity, T>); - std::shared_ptr<U> ptr = find_entity_(id); - if (!ptr) - return nullptr; - fm_assert(ptr->type == entity_type_<T>::value); - return std::static_pointer_cast<T>(ptr); + // make it a dependent name so that including "src/entity.hpp" isn't needed + using U = std::conditional_t<std::is_same_v<T, entity>, T, entity>; + if (std::shared_ptr<U> ptr = find_entity_(id); !ptr) + return {}; + else if constexpr(std::is_same_v<T, entity>) + return ptr; + else + { + fm_assert(ptr->type == entity_type_<T>::value); + return std::static_pointer_cast<T>(std::move(ptr)); + } } } // namespace floormat |