diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2023-03-18 02:02:49 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2023-03-18 02:02:49 +0100 |
commit | 87b07a5c872ba37676ea02e6f9961307839137b2 (patch) | |
tree | 5e8d02a9658ead0779fd012f6faf426fd0e72b8b | |
parent | 142adf90cdc69bbd608ff03354b54db053540bb7 (diff) |
a
-rw-r--r-- | editor/app.cpp | 2 | ||||
-rw-r--r-- | editor/scenery-editor.cpp | 2 | ||||
-rw-r--r-- | serialize/world-reader.cpp | 17 | ||||
-rw-r--r-- | serialize/world-writer.cpp | 15 | ||||
-rw-r--r-- | src/chunk.cpp | 5 | ||||
-rw-r--r-- | src/chunk.hpp | 3 | ||||
-rw-r--r-- | src/world.cpp | 10 | ||||
-rw-r--r-- | src/world.hpp | 14 | ||||
-rw-r--r-- | test/serializer.cpp | 27 |
9 files changed, 50 insertions, 45 deletions
diff --git a/editor/app.cpp b/editor/app.cpp index 49d8e96c..5820c165 100644 --- a/editor/app.cpp +++ b/editor/app.cpp @@ -55,7 +55,7 @@ void app::reset_world(struct world&& w) character_proto cproto; cproto.name = "Player"_s; cproto.playable = true; - _character_id = w2.make_entity<character>(global_coords{}, cproto)->id; + _character_id = w2.make_entity<character>(w2.make_id(), global_coords{}, cproto)->id; } } diff --git a/editor/scenery-editor.cpp b/editor/scenery-editor.cpp index 1165219d..22a7fd16 100644 --- a/editor/scenery-editor.cpp +++ b/editor/scenery-editor.cpp @@ -98,7 +98,7 @@ void scenery_editor::place_tile(world& w, global_coords pos, const scenery_& s) else { // todo check collision at pos - w.make_entity<scenery>(pos, s.proto); + w.make_entity<scenery>(w.make_id(), pos, s.proto); } c.mark_scenery_modified(); } diff --git a/serialize/world-reader.cpp b/serialize/world-reader.cpp index 78e7e539..e9d4bc96 100644 --- a/serialize/world-reader.cpp +++ b/serialize/world-reader.cpp @@ -214,14 +214,13 @@ void reader_state::read_chunks(reader_t& s) } } global_coords coord{ch, local_coords{i}}; - auto e = _world->make_entity<scenery>(coord, sc); - c.add_entity_unsorted(e); + auto e = _world->make_entity<scenery, false>(_world->make_id(), coord, sc); } } - if (PROTO < 8) [[unlikely]] - c.sort_entities(); + std::uint32_t entity_count = 0; + if (PROTO >= 8) [[likely]] + entity_count << s; - std::uint32_t entity_count; entity_count << s; for (auto i = 0_uz; i < entity_count; i++) { std::uint64_t _id; _id << s; @@ -252,8 +251,8 @@ void reader_state::read_chunks(reader_t& s) proto.name = StringView{name.buf, name.len, StringViewFlag::Global|StringViewFlag::NullTerminated}; if (id & meta_long_scenery_bit) read_offsets(s, proto); - auto C = _world->make_entity<character>(oid, {ch, local}, proto); - c.add_entity_unsorted(C); + auto e = _world->make_entity<character>(oid, {ch, local}, proto); + (void)e; break; } case entity_type::scenery: { @@ -274,8 +273,8 @@ void reader_state::read_chunks(reader_t& s) if (sc.active) sc.delta << s; } - auto e = _world->make_entity<scenery>(oid, {ch, local}, sc); - c.add_entity_unsorted(e); + auto e = _world->make_entity<scenery, false>(oid, {ch, local}, sc); + (void)e; break; } default: diff --git a/serialize/world-writer.cpp b/serialize/world-writer.cpp index 9f724ef1..461f6dd6 100644 --- a/serialize/world-writer.cpp +++ b/serialize/world-writer.cpp @@ -335,11 +335,20 @@ void writer_state::serialize_chunk(const chunk& c, chunk_coords coord) check_atlas(wall_west); if (img_g != null_atlas) - s << img_g, s << ground.variant; + { + s << img_g; + s << ground.variant; + } if (img_n != null_atlas) - s << img_n, s << wall_north.variant; + { + s << img_n; + s << wall_north.variant; + } if (img_w != null_atlas) - s << img_w, s << wall_west.variant; + { + s << img_w; + s << wall_west.variant; + } } s << (std::uint32_t)c.entities().size(); diff --git a/src/chunk.cpp b/src/chunk.cpp index a99facf6..e0a09012 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -108,6 +108,7 @@ bool chunk::bbox::operator==(const bbox& other) const noexcept = default; void chunk::add_entity_unsorted(const std::shared_ptr<entity>& e) { + _entities_sorted = false; if (!e->is_dynamic()) mark_scenery_modified(false); if (bbox bb; _bbox_for_scenery(*e, bb)) @@ -117,6 +118,7 @@ void chunk::add_entity_unsorted(const std::shared_ptr<entity>& e) void chunk::sort_entities() { + _entities_sorted = true; mark_scenery_modified(false); std::sort(_entities.begin(), _entities.end(), [](const auto& a, const auto& b) { @@ -126,6 +128,7 @@ void chunk::sort_entities() void chunk::add_entity(const std::shared_ptr<entity>& e) { + fm_assert(_entities_sorted); if (e->atlas->info().fps == 0) mark_scenery_modified(false); if (bbox bb; _bbox_for_scenery(*e, bb)) @@ -140,6 +143,7 @@ void chunk::add_entity(const std::shared_ptr<entity>& e) void chunk::remove_entity(std::size_t i) { + fm_assert(_entities_sorted); fm_debug_assert(i < _entities.size()); const auto& e = _entities[i]; if (!e->is_dynamic()) @@ -152,6 +156,7 @@ void chunk::remove_entity(std::size_t i) const std::vector<std::shared_ptr<entity>>& chunk::entities() const { + fm_assert(_entities_sorted); return _entities; } diff --git a/src/chunk.hpp b/src/chunk.hpp index e825ce33..e51c55ac 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -129,7 +129,8 @@ private: _walls_modified : 1 = true, _scenery_modified : 1 = true, _pass_modified : 1 = true, - _teardown : 1 = false; + _teardown : 1 = false, + _entities_sorted : 1 = true; struct bbox final // NOLINT(cppcoreguidelines-pro-type-member-init) { diff --git a/src/world.cpp b/src/world.cpp index ee1ef459..8743981f 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -106,15 +106,19 @@ void world::collect(bool force) fm_debug("world: collected %zu/%zu chunks", len, len0); } -void world::do_make_entity(const std::shared_ptr<entity>& e, global_coords pos) +void world::do_make_entity(const std::shared_ptr<entity>& e, global_coords pos, bool sorted) { - fm_debug_assert(e->id > 0); + fm_assert(e->id > 0); fm_debug_assert(e->c->world()._unique_id == _unique_id); + fm_assert(!_entities.contains(e->id)); fm_assert(Vector2ui(e->bbox_size).product() > 0); fm_assert(e->type != entity_type::none); e->coord = pos; _entities[e->id] = e; - e->c->add_entity(e); + if (sorted) + e->c->add_entity(e); + else + e->c->add_entity_unsorted(e); } void world::do_kill_entity(std::uint64_t id) diff --git a/src/world.hpp b/src/world.hpp index 08e4d384..0b7b87a5 100644 --- a/src/world.hpp +++ b/src/world.hpp @@ -37,7 +37,7 @@ private: explicit world(std::size_t capacity); - void do_make_entity(const std::shared_ptr<entity>& e, global_coords pos); + void do_make_entity(const std::shared_ptr<entity>& e, global_coords pos, bool sorted); void do_kill_entity(std::uint64_t id); std::shared_ptr<entity> find_entity_(std::uint64_t id); @@ -67,27 +67,21 @@ public: void set_collect_threshold(std::size_t value) { _collect_every = value; } std::size_t collect_threshold() const noexcept { return _collect_every; } - template<typename T, typename... Xs> + template<typename T, bool sorted = true, typename... Xs> requires requires(chunk& c) { T{std::uint64_t(), c, entity_type(), std::declval<Xs>()...}; } std::shared_ptr<T> make_entity(std::uint64_t id, global_coords pos, Xs&&... xs) { static_assert(std::is_base_of_v<entity, T>); auto ret = std::shared_ptr<T>(new T{id, operator[](pos.chunk()), entity_type_<T>::value, std::forward<Xs>(xs)...}); - do_make_entity(std::static_pointer_cast<entity>(ret), pos); + do_make_entity(std::static_pointer_cast<entity>(ret), pos, sorted); return ret; } - template<typename T, typename... Xs> - requires requires(chunk& c) { T{std::uint64_t(), c, entity_type(), std::declval<Xs>()...}; } - inline std::shared_ptr<T> make_entity(global_coords pos, Xs&&... xs) - { - return make_entity<T, Xs...>(++_entity_counter, pos, std::forward<Xs>(xs)...); - } - template<typename T = entity, typename U = 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; } + [[nodiscard]] std::uint64_t make_id() { return ++_entity_counter; } void set_entity_counter(std::uint64_t value); world& operator=(world&& w) noexcept; diff --git a/test/serializer.cpp b/test/serializer.cpp index f71ad078..928fb25b 100644 --- a/test/serializer.cpp +++ b/test/serializer.cpp @@ -30,10 +30,10 @@ chunk& test_app::make_test_chunk(chunk_coords ch) c[{K, K }].wall_west() = { metal2, 0 }; c[{K, K+1}].wall_north() = { metal1, 0 }; c[{K+1, K }].wall_west() = { metal2, 0 }; - w.make_entity<scenery>({ch, {3, 4}}, table); - w.make_entity<scenery>({ch, {K, K+1}}, control_panel); + w.make_entity<scenery>(w.make_id(), {ch, {3, 4}}, table); + w.make_entity<scenery>(w.make_id(), {ch, {K, K+1}}, control_panel); { - auto& e = *w.make_entity<scenery>({ch, {K+3, K+1}}, door); + auto& e = *w.make_entity<scenery>(w.make_id(), {ch, {K+3, K+1}}, door); auto i = e.index(); e.activate(i); e.update(i, 1.f/60); @@ -43,48 +43,41 @@ chunk& test_app::make_test_chunk(chunk_coords ch) return c; } -static bool chunks_equal(const chunk& a, const chunk& b) +static void assert_chunks_equal(const chunk& a, const chunk& b) { - if (a.entities().size() != b.entities().size()) - return false; + fm_assert(a.entities().size() == b.entities().size()); for (auto i = 0_uz; i < TILE_COUNT; i++) { const auto &a1 = a[i], &b1 = b[i]; - if (a1 != b1) - return false; + fm_assert(a1 == b1); } for (auto i = 0_uz; i < a.entities().size(); i++) { const auto& ae = *a.entities()[i]; const auto& be = *b.entities()[i]; - if (ae.type != be.type) - return false; + fm_assert(ae.type == be.type); switch (ae.type) { case entity_type::character: { const auto& e1 = static_cast<const character&>(ae); const auto& e2 = static_cast<const character&>(be); const auto p1 = character_proto(e1), p2 = character_proto(e2); - if (p1 != p2) - return false; + fm_assert(p1 == p2); break; } case entity_type::scenery: { const auto& e1 = static_cast<const scenery&>(ae); const auto& e2 = static_cast<const scenery&>(be); const auto p1 = scenery_proto(e1), p2 = scenery_proto(e2); - if (p1 != p2) - return false; + fm_assert(p1 == p2); break; } default: fm_abort("invalid entity type '%d'", (int)ae.type); } } - - return true; } void test_app::test_serializer() @@ -97,7 +90,7 @@ void test_app::test_serializer() w.serialize(filename); auto w2 = world::deserialize(filename); auto& c2 = w2[coord]; - fm_assert(chunks_equal(c, c2)); + assert_chunks_equal(c, c2); } } // namespace floormat |