From 2465ac84202b74bc879ce29f5c1bda2793cbcffc Mon Sep 17 00:00:00 2001 From: Ubpa <641614112@qq.com> Date: Mon, 10 Aug 2020 14:09:13 +0800 Subject: [PATCH] simplify CmptTypeSet, EntityMngr's h2a -> ts2a (avoid hash attack) --- CMakeLists.txt | 2 +- include/UECS/EntityMngr.h | 5 ++- include/UECS/detail/Archetype.h | 11 ++---- include/UECS/detail/Archetype.inl | 16 ++++++-- include/UECS/detail/CmptTypeSet.h | 43 +++------------------ include/UECS/detail/CmptTypeSet.inl | 60 ++++++----------------------- include/UECS/detail/EntityMngr.inl | 23 ++++++----- src/core/Archetype.cpp | 37 ++++++++++-------- src/core/ArchetypeFilter.cpp | 9 ++--- src/core/EntityMngr.cpp | 57 ++++++++++++--------------- 10 files changed, 99 insertions(+), 164 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d04d5b5..fd67141 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.14 FATAL_ERROR) -project(UECS VERSION 0.11.2) +project(UECS VERSION 0.11.3) message(STATUS "[Project] ${PROJECT_NAME}") include(cmake/InitUCMake.cmake) diff --git a/include/UECS/EntityMngr.h b/include/UECS/EntityMngr.h index b5b3b81..b39f05d 100644 --- a/include/UECS/EntityMngr.h +++ b/include/UECS/EntityMngr.h @@ -7,6 +7,8 @@ #include +#include + namespace Ubpa::UECS { class World; @@ -76,7 +78,6 @@ namespace Ubpa::UECS { private: friend class World; EntityMngr() = default; - ~EntityMngr(); static bool IsSet(const CmptType* types, size_t num); @@ -104,7 +105,7 @@ namespace Ubpa::UECS { size_t RequestEntityFreeEntry(); void RecycleEntityEntry(Entity e); - std::unordered_map h2a; // archetype's hashcode to archetype + std::unordered_map> ts2a; // archetype's CmptTypeSet to archetype mutable std::unordered_map> queryCache; }; diff --git a/include/UECS/detail/Archetype.h b/include/UECS/detail/Archetype.h index 946adfc..4fe5bd5 100644 --- a/include/UECS/detail/Archetype.h +++ b/include/UECS/detail/Archetype.h @@ -80,20 +80,17 @@ namespace Ubpa::UECS { const RTSCmptTraits& GetRTSCmptTraits() const noexcept { return cmptTraits; } // no Entity - size_t CmptNum() const noexcept { return types.size() - 1; } + size_t CmptNum() const noexcept { return types.data.size() - 1; } size_t EntityNum() const noexcept { return entityNum; } size_t EntityNumOfChunk(size_t chunkIdx) const noexcept; size_t ChunkNum() const noexcept { return chunks.size(); } size_t ChunkCapacity() const noexcept { return chunkCapacity; } + // add Entity + static CmptTypeSet GenCmptTypeSet(const CmptType* types, size_t num); template - static constexpr size_t HashCode() noexcept { return CmptTypeSet::HashCodeOf(); } - static size_t HashCode(const CmptType* types, size_t num) { - CmptTypeSet typeset{ types,num }; - typeset.Insert(CmptType::Of); - return typeset.HashCode(); - } + static CmptTypeSet GenCmptTypeSet(); private: Archetype() = default; diff --git a/include/UECS/detail/Archetype.inl b/include/UECS/detail/Archetype.inl index 8363c9f..e3d8b9f 100644 --- a/include/UECS/detail/Archetype.inl +++ b/include/UECS/detail/Archetype.inl @@ -5,7 +5,7 @@ namespace Ubpa::UECS { template Archetype::Archetype(TypeList) - : types(TypeList{}) + : types(GenCmptTypeSet()) { static_assert(IsSet_v>, "Archetype::Archetype: must be different"); @@ -21,7 +21,7 @@ namespace Ubpa::UECS { Archetype* rst = new Archetype; rst->types = from->types; - rst->types.Insert(CmptType::Of...); + rst->types.data.insert(CmptType::Of...); rst->cmptTraits = from->cmptTraits; (rst->cmptTraits.Register(), ...); @@ -37,7 +37,7 @@ namespace Ubpa::UECS { template std::tuple> Archetype::Create(Entity e) { - assert((types.Contains(CmptType::Of) &&...) && types.size() == 1 + sizeof...(Cmpts)); + assert((types.Contains(CmptType::Of) &&...) && types.data.size() == 1 + sizeof...(Cmpts)); static_assert((std::is_constructible_v &&...), "Archetype::Create: isn't constructible"); static_assert(IsSet_v>, @@ -53,4 +53,14 @@ namespace Ubpa::UECS { return { idx,cmpts }; } + + template + CmptTypeSet Archetype::GenCmptTypeSet() { + if constexpr(sizeof...(Cmpts) == 0) + return Archetype::GenCmptTypeSet(nullptr, 0); + else { + constexpr std::array types = { CmptType::Of... }; + return Archetype::GenCmptTypeSet(types.data(), types.size()); + } + } } diff --git a/include/UECS/detail/CmptTypeSet.h b/include/UECS/detail/CmptTypeSet.h index 8215cdc..c5f74a3 100644 --- a/include/UECS/detail/CmptTypeSet.h +++ b/include/UECS/detail/CmptTypeSet.h @@ -9,28 +9,13 @@ #include namespace Ubpa::UECS { - class CmptTypeSet : std::set { - public: - CmptTypeSet() : hashcode{ TypeID } {} - template - CmptTypeSet(TypeList); - template&&...)>> - CmptTypeSet(CmptTypes... types) : std::set{ types... }, hashcode{ HashCodeOf(*this) } {} - CmptTypeSet(const CmptType* types, size_t num); + struct CmptTypeSet { + std::set data; - template - static constexpr size_t HashCodeOf() noexcept; - - size_t HashCode() const noexcept { return hashcode; } - - template - void Insert(CmptTypes...); - - template - void Erase(CmptTypes...) noexcept; + size_t HashCode() const; + void Insert(const CmptType* types, size_t num); + void Erase(const CmptType* types, size_t num); bool Contains(CmptType type) const; template @@ -48,23 +33,7 @@ namespace Ubpa::UECS { bool IsMatch(const EntityQuery& query) const; - template - bool Is() const; - - using std::set::begin; - using std::set::end; - using std::set::size; - - bool operator==(const CmptTypeSet& rhs) const; - - private: - template - static constexpr size_t HashCodeOf(TypeList) noexcept; - - template - static constexpr size_t HashCodeOf(const Container& cmpts) noexcept; - - size_t hashcode; + bool operator==(const CmptTypeSet& rhs) const { return data == rhs.data; } }; } diff --git a/include/UECS/detail/CmptTypeSet.inl b/include/UECS/detail/CmptTypeSet.inl index 61addeb..b9f2881 100644 --- a/include/UECS/detail/CmptTypeSet.inl +++ b/include/UECS/detail/CmptTypeSet.inl @@ -1,43 +1,23 @@ #pragma once namespace Ubpa::UECS { - inline CmptTypeSet::CmptTypeSet(const CmptType* types, size_t num) { - assert(types != nullptr && num != 0); + inline void CmptTypeSet::Insert(const CmptType* types, size_t num) { for (size_t i = 0; i < num; i++) - insert(types[i]); - hashcode = HashCodeOf(*this); + data.insert(types[i]); } - template - CmptTypeSet::CmptTypeSet(TypeList) - : std::set{ CmptType::Of... }, hashcode{ HashCodeOf() } {} - - template - constexpr size_t CmptTypeSet::HashCodeOf() noexcept { - return HashCodeOf(QuickSort_t, TypeID_Less>{}); - } - - template - void CmptTypeSet::Insert(CmptTypes... types) { - static_assert((std::is_same_v &&...)); - (insert(types), ...); - hashcode = HashCodeOf(*this); - } - - template - void CmptTypeSet::Erase(CmptTypes... types) noexcept { - static_assert((std::is_same_v &&...)); - (erase(types), ...); - hashcode = HashCodeOf(*this); + inline void CmptTypeSet::Erase(const CmptType* types, size_t num) { + for (size_t i = 0; i < num; i++) + data.erase(types[i]); } inline bool CmptTypeSet::Contains(CmptType type) const { - return find(type) != cend(); + return data.find(type) != data.end(); } template bool CmptTypeSet::Contains(const CmptTypeContainer& types) const { - for (auto type : types) { + for (const auto& type : types) { if (!Contains(type)) return false; } @@ -49,7 +29,7 @@ namespace Ubpa::UECS { if (types.empty()) return true; - for (auto type : types) { + for (const auto& type : types) { if (Contains(type)) return true; } @@ -59,7 +39,7 @@ namespace Ubpa::UECS { template bool CmptTypeSet::NotContain(const CmptTypeContainer& types) const { - for (auto type : types) { + for (const auto& type : types) { if (Contains(type)) return false; } @@ -84,28 +64,12 @@ namespace Ubpa::UECS { return IsMatch(query.filter) && IsMatch(query.locator); } - template - bool CmptTypeSet::Is() const { - static_assert(IsSet_v); - return sizeof...(Cmpts) == size() && (Contains(CmptType::Of) &&...); - } - - template - static constexpr size_t CmptTypeSet::HashCodeOf(TypeList) noexcept { - return HashCodeOf(std::array{CmptType::Of...}); - } - - template - static constexpr size_t CmptTypeSet::HashCodeOf(const Container& cmpts) noexcept { + inline size_t CmptTypeSet::HashCode() const { size_t seed = TypeID; - for (const CmptType& cmpt : cmpts) - seed = hash_combine(seed, cmpt.HashCode()); + for (const auto& t : data) + seed = hash_combine(seed, t.HashCode()); return seed; } - - inline bool CmptTypeSet::operator==(const CmptTypeSet& rhs) const { - return static_cast&>(*this) == static_cast&>(rhs); - } } namespace std { diff --git a/include/UECS/detail/EntityMngr.inl b/include/UECS/detail/EntityMngr.inl index 57f4b21..3414072 100644 --- a/include/UECS/detail/EntityMngr.inl +++ b/include/UECS/detail/EntityMngr.inl @@ -11,13 +11,13 @@ namespace Ubpa::UECS { static_assert(IsSet_v>, "EntityMngr::GetOrCreateArchetypeOf: must be different"); - constexpr size_t hashcode = Archetype::HashCode(); - auto target = h2a.find(hashcode); - if(target != h2a.end()) - return target->second; + const auto typeset = Archetype::GenCmptTypeSet(); + auto target = ts2a.find(typeset); + if(target != ts2a.end()) + return target->second.get(); auto archetype = new Archetype(TypeList{}); - h2a[hashcode] = archetype; + ts2a.emplace(std::move(typeset), std::unique_ptr{ archetype }); for (auto& [query, archetypes] : queryCache) { if (archetype->GetCmptTypeSet().IsMatch(query)) archetypes.insert(archetype); @@ -50,23 +50,22 @@ namespace Ubpa::UECS { const auto& srcCmptTypeSet = srcArchetype->GetCmptTypeSet(); auto dstCmptTypeSet = srcCmptTypeSet; - dstCmptTypeSet.Insert(CmptType::Of...); - size_t dstCmptTypeSetHashCode = dstCmptTypeSet.HashCode(); + dstCmptTypeSet.data.insert(CmptType::Of...); // get dstArchetype Archetype* dstArchetype; - auto target = h2a.find(dstCmptTypeSetHashCode); - if (target == h2a.end()) { + auto target = ts2a.find(dstCmptTypeSet); + if (target == ts2a.end()) { dstArchetype = Archetype::Add(srcArchetype); assert(dstCmptTypeSet == dstArchetype->GetCmptTypeSet()); - h2a[dstCmptTypeSetHashCode] = dstArchetype; for (auto& [query, archetypes] : queryCache) { if (dstCmptTypeSet.IsMatch(query)) archetypes.insert(dstArchetype); } + ts2a.emplace(std::move(dstCmptTypeSet), std::unique_ptr{ dstArchetype }); } else - dstArchetype = target->second; + dstArchetype = target->second.get(); if (dstArchetype == srcArchetype) return; @@ -75,7 +74,7 @@ namespace Ubpa::UECS { size_t dstIdxInArchetype = dstArchetype->RequestBuffer(); auto srcCmptTraits = srcArchetype->GetRTSCmptTraits(); - for (auto type : srcCmptTypeSet) { + for (const auto& type : srcCmptTypeSet.data) { auto srcCmpt = srcArchetype->At(type, srcIdxInArchetype); auto dstCmpt = dstArchetype->At(type, dstIdxInArchetype); srcCmptTraits.MoveConstruct(type, dstCmpt, srcCmpt); diff --git a/src/core/Archetype.cpp b/src/core/Archetype.cpp index a637195..ea22450 100644 --- a/src/core/Archetype.cpp +++ b/src/core/Archetype.cpp @@ -7,7 +7,7 @@ void Archetype::SetLayout() { vector alignments; vector sizes; - for (const auto& type : types) { + for (const auto& type : types.data) { alignments.push_back(cmptTraits.Alignof(type)); sizes.push_back(cmptTraits.Sizeof(type)); } @@ -16,14 +16,14 @@ void Archetype::SetLayout() { chunkCapacity = layout.capacity; size_t i = 0; - for (const auto& type : types) + for (const auto& type : types.data) type2offset[type] = layout.offsets[i++]; } Archetype* Archetype::New(const CmptType* types, size_t num) { auto rst = new Archetype; - rst->types = CmptTypeSet{ types, num }; - rst->types.Insert(CmptType::Of); + rst->types.Insert(types, num); + rst->types.data.insert(CmptType::Of); rst->cmptTraits.Register(); for (size_t i = 0; i < num; i++) rst->cmptTraits.Register(types[i]); @@ -41,10 +41,9 @@ Archetype* Archetype::Add(const Archetype* from, const CmptType* types, size_t n rst->types = from->types; rst->cmptTraits = from->cmptTraits; - for (size_t i = 0; i < num; i++) { - rst->types.Insert(types[i]); + rst->types.Insert(types, num); + for (size_t i = 0; i < num; i++) rst->cmptTraits.Register(types[i]); - } rst->SetLayout(); @@ -59,10 +58,9 @@ Archetype* Archetype::Remove(const Archetype* from, const CmptType* types, size_ rst->types = from->types; rst->cmptTraits = from->cmptTraits; - for (size_t i = 0; i < num; i++) { - rst->types.Erase(types[i]); + rst->types.Erase(types, num); + for (size_t i = 0; i < num; i++) rst->cmptTraits.Deregister(types[i]); - } rst->SetLayout(); @@ -75,7 +73,7 @@ size_t Archetype::Create(Entity e) { byte* buffer = chunks[idx / chunkCapacity]->Data(); const auto& rtdct = RTDCmptTraits::Instance(); - for (auto type : types) { + for (const auto& type : types.data) { if (type.Is()) { constexpr size_t size = sizeof(Entity); size_t offset = Offsetof(type); @@ -96,7 +94,7 @@ size_t Archetype::Create(Entity e) { } Archetype::~Archetype() { - for (const auto& type : types) { + for (const auto& type : types.data) { size_t size = cmptTraits.Sizeof(type); size_t offset = Offsetof(type); for (size_t i = 0; i < entityNum; i++) { @@ -139,7 +137,7 @@ size_t Archetype::Instantiate(Entity e, size_t srcIdx) { size_t dstIdxInChunk = dstIdx % chunkCapacity; byte* dstBuffer = chunks[dstIdx / chunkCapacity]->Data(); - for (auto type : types) { + for (const auto& type : types.data) { size_t offset = Offsetof(type); if (type.Is()) { @@ -201,7 +199,7 @@ size_t Archetype::Erase(size_t idx) { size_t srcIdxInChunk = movedIdxInArchetype % chunkCapacity; byte* srcBuffer = chunks[movedIdxInArchetype / chunkCapacity]->Data(); - for (auto type : types) { + for (const auto& type : types.data) { auto size = cmptTraits.Sizeof(type); auto offset = Offsetof(type); byte* dst = dstBuffer + offset + dstIdxInChunk * size; @@ -217,7 +215,7 @@ size_t Archetype::Erase(size_t idx) { else { movedIdx = size_t_invalid; - for (auto type : types) { + for (const auto& type : types.data) { auto size = cmptTraits.Sizeof(type); auto offset = Offsetof(type); byte* dst = dstBuffer + offset + dstIdxInChunk * size; @@ -239,7 +237,7 @@ size_t Archetype::Erase(size_t idx) { vector Archetype::Components(size_t idx) const { vector rst; - for (const auto& type : types) { + for (const auto& type : types.data) { if (type.Is()) continue; rst.emplace_back(type, At(type, idx)); @@ -254,3 +252,10 @@ size_t Archetype::EntityNumOfChunk(size_t chunkIdx) const noexcept { else return chunkCapacity; } + +CmptTypeSet Archetype::GenCmptTypeSet(const CmptType* types, size_t num) { + CmptTypeSet typeset; + typeset.Insert(types, num); + typeset.data.insert(CmptType::Of); + return typeset; +} diff --git a/src/core/ArchetypeFilter.cpp b/src/core/ArchetypeFilter.cpp index 8580947..1809059 100644 --- a/src/core/ArchetypeFilter.cpp +++ b/src/core/ArchetypeFilter.cpp @@ -75,25 +75,22 @@ void ArchetypeFilter::EraseNone(const CmptType* types, size_t num) { size_t ArchetypeFilter::GenAllHashCode() const noexcept { size_t rst = TypeID; - for (auto type : allCmptTypes) { + for (const auto& type : allCmptTypes) rst = hash_combine(rst, type.HashCode()); - } return rst; } size_t ArchetypeFilter::GenAnyHashCode() const noexcept { size_t rst = TypeID; - for (auto type : anyCmptTypes) { + for (const auto& type : anyCmptTypes) rst = hash_combine(rst, type.HashCode()); - } return rst; } size_t ArchetypeFilter::GenNoneHashCode() const noexcept { size_t rst = TypeID; - for (auto type : noneCmptTypes) { + for (const auto& type : noneCmptTypes) rst = hash_combine(rst, type.HashCode()); - } return rst; } diff --git a/src/core/EntityMngr.cpp b/src/core/EntityMngr.cpp index 3027c78..623044d 100644 --- a/src/core/EntityMngr.cpp +++ b/src/core/EntityMngr.cpp @@ -5,11 +5,6 @@ using namespace Ubpa::UECS; using namespace std; -EntityMngr::~EntityMngr() { - for (auto [h, a] : h2a) - delete a; -} - size_t EntityMngr::RequestEntityFreeEntry() { if (entityTableFreeEntry.empty()) { size_t index = entityTable.size(); @@ -36,13 +31,14 @@ void EntityMngr::RecycleEntityEntry(Entity e) { Archetype* EntityMngr::GetOrCreateArchetypeOf(const CmptType* types, size_t num) { assert(IsSet(types, num)); - size_t hashcode = Archetype::HashCode(types, num); - auto target = h2a.find(hashcode); - if (target != h2a.end()) - return target->second; + auto typeset = Archetype::GenCmptTypeSet(types, num); + auto target = ts2a.find(typeset); + if (target != ts2a.end()) + return target->second.get(); auto archetype = Archetype::New(types, num); - h2a[hashcode] = archetype; + + ts2a.emplace(std::move(typeset), std::unique_ptr{ archetype }); for (auto& [query, archetypes] : queryCache) { if (archetype->GetCmptTypeSet().IsMatch(query)) archetypes.insert(archetype); @@ -64,6 +60,7 @@ Entity EntityMngr::Create(const CmptType* types, size_t num) { } void EntityMngr::AttachWithoutInit(Entity e, const CmptType* types, size_t num) { + assert(types != nullptr && num > 0); assert(IsSet(types, num)); if (!Exist(e)) throw std::invalid_argument("Entity is invalid"); @@ -73,24 +70,22 @@ void EntityMngr::AttachWithoutInit(Entity e, const CmptType* types, size_t num) const auto& srcCmptTypeSet = srcArchetype->GetCmptTypeSet(); auto dstCmptTypeSet = srcCmptTypeSet; - for (size_t i = 0; i < num; i++) - dstCmptTypeSet.Insert(types[i]); - size_t dstCmptTypeSetHashCode = dstCmptTypeSet.HashCode(); + dstCmptTypeSet.Insert(types, num); // get dstArchetype Archetype* dstArchetype; - auto target = h2a.find(dstCmptTypeSetHashCode); - if (target == h2a.end()) { + auto target = ts2a.find(dstCmptTypeSet); + if (target == ts2a.end()) { dstArchetype = Archetype::Add(srcArchetype, types, num); assert(dstCmptTypeSet == dstArchetype->GetCmptTypeSet()); - h2a[dstCmptTypeSetHashCode] = dstArchetype; for (auto& [query, archetypes] : queryCache) { if (dstCmptTypeSet.IsMatch(query)) archetypes.insert(dstArchetype); } + ts2a.emplace(std::move(dstCmptTypeSet), std::unique_ptr{dstArchetype}); } else - dstArchetype = target->second; + dstArchetype = target->second.get(); if (dstArchetype == srcArchetype) return; @@ -99,7 +94,7 @@ void EntityMngr::AttachWithoutInit(Entity e, const CmptType* types, size_t num) size_t dstIdxInArchetype = dstArchetype->RequestBuffer(); auto srcCmptTraits = srcArchetype->GetRTSCmptTraits(); - for (auto type : srcCmptTypeSet) { + for (const auto& type : srcCmptTypeSet.data) { auto srcCmpt = srcArchetype->At(type, srcIdxInArchetype); auto dstCmpt = dstArchetype->At(type, dstIdxInArchetype); srcCmptTraits.MoveConstruct(type, dstCmpt, srcCmpt); @@ -115,6 +110,7 @@ void EntityMngr::AttachWithoutInit(Entity e, const CmptType* types, size_t num) } void EntityMngr::Attach(Entity e, const CmptType* types, size_t num) { + assert(types != nullptr && num > 0); assert(IsSet(types, num)); if (!Exist(e)) throw std::invalid_argument("Entity is invalid"); @@ -123,7 +119,7 @@ void EntityMngr::Attach(Entity e, const CmptType* types, size_t num) { const auto& new_info = entityTable[e.Idx()]; const auto& rtdct = RTDCmptTraits::Instance(); for (size_t i = 0; i < num; i++) { - auto type = types[i]; + const auto& type = types[i]; if (srcArchetype->GetCmptTypeSet().Contains(type)) continue; auto target = rtdct.default_constructors.find(type); @@ -135,6 +131,7 @@ void EntityMngr::Attach(Entity e, const CmptType* types, size_t num) { } void EntityMngr::Detach(Entity e, const CmptType* types, size_t num) { + assert(types != nullptr && num > 0); assert(IsSet(types, num)); if (!Exist(e)) throw std::invalid_argument("EntityMngr::Detach: Entity is invalid"); @@ -144,24 +141,22 @@ void EntityMngr::Detach(Entity e, const CmptType* types, size_t num) { const auto& srcCmptTypeSet = srcArchetype->GetCmptTypeSet(); auto dstCmptTypeSet = srcCmptTypeSet; - for (size_t i = 0; i < num; i++) - dstCmptTypeSet.Erase(types[i]); - size_t dstCmptTypeSetHashCode = dstCmptTypeSet.HashCode(); + dstCmptTypeSet.Erase(types, num); // get dstArchetype Archetype* dstArchetype; - auto target = h2a.find(dstCmptTypeSetHashCode); - if (target == h2a.end()) { + auto target = ts2a.find(dstCmptTypeSet); + if (target == ts2a.end()) { dstArchetype = Archetype::Remove(srcArchetype, types, num); assert(dstCmptTypeSet == dstArchetype->GetCmptTypeSet()); - h2a[dstCmptTypeSetHashCode] = dstArchetype; for (auto& [query, archetypes] : queryCache) { if (dstCmptTypeSet.IsMatch(query)) archetypes.insert(dstArchetype); } + ts2a.emplace(std::move(dstCmptTypeSet), std::unique_ptr{dstArchetype}); } else - dstArchetype = target->second; + dstArchetype = target->second.get(); if (dstArchetype == srcArchetype) return; @@ -169,7 +164,7 @@ void EntityMngr::Detach(Entity e, const CmptType* types, size_t num) { // move src to dst size_t dstIdxInArchetype = dstArchetype->RequestBuffer(); auto srcCmptTraits = srcArchetype->GetRTSCmptTraits(); - for (auto type : srcCmptTypeSet) { + for (const auto& type : srcCmptTypeSet.data) { auto srcCmpt = srcArchetype->At(type, srcIdxInArchetype); if (dstCmptTypeSet.Contains(type)) { auto dstCmpt = dstArchetype->At(type, dstIdxInArchetype); @@ -210,8 +205,6 @@ Entity EntityMngr::Instantiate(Entity srcEntity) { } bool EntityMngr::IsSet(const CmptType* types, size_t num) { - assert(types != nullptr); - for (size_t i = 0; i < num; i++) { for (size_t j = 0; j < i; j++) if (types[i] == types[j]) @@ -228,9 +221,9 @@ const set& EntityMngr::QueryArchetypes(const EntityQuery& query) con // queryCache is **mutable** set& archetypes = queryCache[query]; - for (const auto& [h, a] : h2a) { + for (const auto& [ts, a] : ts2a) { if (a->GetCmptTypeSet().IsMatch(query)) - archetypes.insert(a); + archetypes.insert(a.get()); } return archetypes; @@ -349,7 +342,7 @@ void EntityMngr::GenJob(World* w, Job* job, SystemFunc* sys) const { void EntityMngr::Accept(IListener* listener) const { listener->EnterEntityMngr(this); - for (const auto& [h, a] : h2a) { + for (const auto& [ts, a] : ts2a) { for (size_t i = 0; i < a->EntityNum(); i++) { auto e = a->At(i); listener->EnterEntity(e);