1+ #include " engine/EntityRegistry.h"
2+
3+ #include < sstream>
4+ #include < stdexcept>
5+ #include < utility>
6+
7+ namespace safecrowd ::engine {
8+ namespace {
9+
10+ std::string describeEntity (Entity entity) {
11+ std::ostringstream stream;
12+ stream << entity;
13+ return stream.str ();
14+ }
15+
16+ } // namespace
17+
18+ EntityRegistry::EntityRegistry (std::size_t maxEntityCount)
19+ : entries_(maxEntityCount) {
20+ freeIndices_.resize (maxEntityCount);
21+
22+ for (std::size_t index = 0 ; index < maxEntityCount; ++index) {
23+ freeIndices_[index] = static_cast <EntityIndex>(index);
24+ }
25+ }
26+
27+ Entity EntityRegistry::allocate () {
28+ if (freeIndices_.empty ()) {
29+ throw std::overflow_error (" EntityRegistry capacity exhausted." );
30+ }
31+
32+ const EntityIndex index = freeIndices_.front ();
33+ freeIndices_.pop_front ();
34+
35+ Entry& entry = entries_[index];
36+ entry.alive = true ;
37+ entry.signature .reset ();
38+
39+ return Entity{index, entry.generation };
40+ }
41+
42+ void EntityRegistry::release (Entity entity) {
43+ Entry& entry = entryFor (entity);
44+ entry.alive = false ;
45+ entry.signature .reset ();
46+ ++entry.generation ;
47+ freeIndices_.push_back (entity.index );
48+ }
49+
50+ bool EntityRegistry::isAlive (Entity entity) const noexcept {
51+ if (!entity.isValid ()) {
52+ return false ;
53+ }
54+
55+ const auto index = static_cast <std::size_t >(entity.index );
56+ if (index >= entries_.size ()) {
57+ return false ;
58+ }
59+
60+ const Entry& entry = entries_[index];
61+ return entry.alive && entry.generation == entity.generation ;
62+ }
63+
64+ void EntityRegistry::setSignature (Entity entity, Signature signature) {
65+ Entry& entry = entryFor (entity);
66+ entry.signature = signature;
67+ }
68+
69+ Signature EntityRegistry::signatureOf (Entity entity) const {
70+ return entryFor (entity).signature ;
71+ }
72+
73+ const EntityRegistry::Entry& EntityRegistry::entryFor (Entity entity) const {
74+ if (!entity.isValid ()) {
75+ throw std::invalid_argument (" Invalid entity handle." );
76+ }
77+
78+ const auto index = static_cast <std::size_t >(entity.index );
79+ if (index >= entries_.size ()) {
80+ throw std::out_of_range (" Entity index is out of range." );
81+ }
82+
83+ const Entry& entry = entries_[index];
84+ if (!entry.alive || entry.generation != entity.generation ) {
85+ throw std::invalid_argument (" Stale or dead entity handle: " + describeEntity (entity));
86+ }
87+
88+ return entry;
89+ }
90+
91+ EntityRegistry::Entry& EntityRegistry::entryFor (Entity entity) {
92+ return const_cast <Entry&>(std::as_const (*this ).entryFor (entity));
93+ }
94+
95+ } // namespace safecrowd::engine
0 commit comments