diff --git a/tests/zecsy.cpp b/tests/zecsy.cpp index ad7042a..0174c37 100644 --- a/tests/zecsy.cpp +++ b/tests/zecsy.cpp @@ -1,6 +1,8 @@ #include #define CATCH_CONFIG_MAIN #include + +#define MAX_ZECSY_ENTITIES 4 #include "../zecsy.hpp" using namespace zecsy; @@ -12,6 +14,7 @@ TEST_CASE("Create a single entity and verify its existence") auto e = w.make_entity(); REQUIRE(w.is_alive(e)); + REQUIRE(e.is_alive()); } TEST_CASE("Destroy an entity and ensure it no longer exists in the world") @@ -22,6 +25,7 @@ TEST_CASE("Destroy an entity and ensure it no longer exists in the world") w.destroy_entity(e); REQUIRE_FALSE(w.is_alive(e)); + REQUIRE_FALSE(e.is_alive()); } TEST_CASE("Entity #0 should be reserved and never used") @@ -31,4 +35,18 @@ TEST_CASE("Entity #0 should be reserved and never used") auto e = w.make_entity(); REQUIRE(e != 0); + REQUIRE(entity() == 0); + REQUIRE_FALSE(entity().is_alive()); +} + +TEST_CASE("World should throw on id overflow") +{ + world w; + + for(int i = 0; i < MAX_ZECSY_ENTITIES; ++i) + { + REQUIRE_NOTHROW(w.make_entity()); + } + + REQUIRE_THROWS(w.make_entity()); } diff --git a/zecsy.hpp b/zecsy.hpp index d9d0b4a..612a389 100644 --- a/zecsy.hpp +++ b/zecsy.hpp @@ -1,7 +1,8 @@ #pragma once #include #include -#include +#include +#include #ifndef MAX_ZECSY_ENTITIES #define MAX_ZECSY_ENTITIES 65536 @@ -12,6 +13,24 @@ namespace zecsy { using entity_id = uint64_t; + class entity final + { + public: + entity(class world* w, entity_id id); + + entity() = default; + entity(const entity &) = default; + entity(entity &&) = default; + entity &operator=(const entity &) = default; + entity &operator=(entity &&) = default; + operator entity_id() const; + + bool is_alive() const; + private: + entity_id id = 0; + class world* w = nullptr; + }; + class world final { public: @@ -21,7 +40,7 @@ namespace zecsy world &operator=(const world &) = default; world &operator=(world &&) = default; - entity_id make_entity(); + entity make_entity(); void destroy_entity(entity_id e); bool is_alive(entity_id e) const; private: @@ -29,13 +48,34 @@ namespace zecsy entity_id entity_counter = 0; }; - inline entity_id world::make_entity() + inline entity::entity(class world* w, entity_id id): w(w), id(id) + { + + } + + inline entity::operator entity_id() const { - auto id = ++entity_counter; - entities_bitset.set(id); return id; } + inline bool entity::is_alive() const + { + return w && w->is_alive(id); + } + + inline entity world::make_entity() + { + auto id = (++entity_counter)%MAX_ZECSY_ENTITIES; + if(is_alive(id)) + { + throw std::runtime_error(std::format("entity_id #{} already in use," + " can't make a new entity", id)); + } + + entities_bitset.set(id); + return entity(this, id); + } + inline void world::destroy_entity(entity_id e) { entities_bitset.reset(e);