summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-03-18 16:44:39 +0100
committerStanislaw Halik <sthalik@misaki.pl>2023-03-18 16:44:39 +0100
commit27dd8b268fbe37fa6eed0c0fc0f013134e5e2dc9 (patch)
tree7f04c83b09aa1d0706e832d16fa19ee31cd12f31
parentf82e612070b3edc963e787f121a58a2821ffa2a5 (diff)
editor/app: don't duplicate characters on load
-rw-r--r--editor/app.cpp43
-rw-r--r--editor/app.hpp1
-rw-r--r--editor/update.cpp11
-rw-r--r--src/world.hpp20
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