Skip to content

Commit 46d9d1e

Browse files
authored
Merge pull request #61 from Strife-AI/entity-groups
Store entities in groups for efficient querying/updating
2 parents f2702c9 + 640e55e commit 46d9d1e

File tree

8 files changed

+185
-182
lines changed

8 files changed

+185
-182
lines changed

src/Memory/DLinkNode.hpp

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,15 @@ struct DLinkedNode
1111

1212
void Unlink()
1313
{
14-
if (owner != nullptr)
15-
{
16-
prev->next = next;
17-
next->prev = prev;
18-
19-
next = nullptr;
20-
prev = nullptr;
21-
}
14+
prev->next = next;
15+
next->prev = prev;
16+
17+
next = nullptr;
18+
prev = nullptr;
2219
}
2320

24-
TElement* next;
25-
TElement* prev;
26-
DLinkedList<TElement>* owner;
21+
DLinkedNode<TElement>* next = nullptr;
22+
DLinkedNode<TElement>* prev = nullptr;
2723
};
2824

2925
template<typename T>
@@ -45,7 +41,7 @@ struct DLinkedListIterator
4541
return !(*this == rhs);
4642
}
4743

48-
T& operator*()
44+
T* operator*()
4945
{
5046
return current->GetElement();
5147
}
@@ -73,6 +69,7 @@ struct DLinkedList
7369
using Node = DLinkedNode<T>;
7470

7571
DLinkedList();
72+
DLinkedList(const DLinkedList& rhs) = delete;
7673

7774
DLinkedListIterator<T> begin()
7875
{
@@ -85,7 +82,6 @@ struct DLinkedList
8582
}
8683

8784
void Append(Node* node);
88-
void Remove(Node* node);
8985
void InsertBefore(Node* node, Node* before);
9086

9187
Node head;
@@ -95,21 +91,12 @@ struct DLinkedList
9591
template<typename T>
9692
void DLinkedList<T>::Append(DLinkedList::Node* node)
9793
{
98-
node->owner = this;
99-
InsertBefore(&tail);
100-
}
101-
102-
template<typename T>
103-
void DLinkedList<T>::Remove(DLinkedList::Node* node)
104-
{
105-
assert(node->owner == this);
94+
InsertBefore(node, &tail);
10695
}
10796

10897
template<typename T>
10998
void DLinkedList<T>::InsertBefore(Node* node, Node* before)
11099
{
111-
assert(node->owner == nullptr);
112-
113100
before->prev->next = node;
114101
node->prev = before->prev;
115102

src/Scene/Entity.cpp

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -194,57 +194,41 @@ void Entity::NotifyMovement()
194194
}
195195

196196
Entity::Entity()
197-
: flags{
198-
EntityFlags::EnableUpdate,
199-
EntityFlags::EnableFixedUpdate,
200-
EntityFlags::EnableServerUpdate,
201-
EntityFlags::EnableServerFixedUpdate,
202-
EntityFlags::EnableRender,
203-
EntityFlags::EnableRenderHud
204-
}
205197
{
206198

207199
}
208200

201+
template<typename THookSelector>
202+
static void DisableHook(Entity* entity, THookSelector selector)
203+
{
204+
auto& entityManager = entity->scene->GetEntityManager();
205+
auto set = selector(entityManager);
206+
entityManager.scheduledHookRemovals.emplace_back(set, entity->entityGroup);
207+
}
208+
209209
void Entity::Update(float deltaTime)
210210
{
211-
flags.ResetFlag(EntityFlags::EnableUpdate);
212-
FlagsChanged();
211+
DisableHook(this, [](auto& em) { return &em.updatables; });
213212
}
214213

215214
void Entity::ServerUpdate(float deltaTime)
216215
{
217-
flags.ResetFlag(EntityFlags::EnableServerUpdate);
218-
FlagsChanged();
216+
DisableHook(this, [](auto& em) { return &em.serverUpdatables; });
219217
}
220218

221219
void Entity::FixedUpdate(float deltaTime)
222220
{
223-
flags.ResetFlag(EntityFlags::EnableFixedUpdate);
224-
FlagsChanged();
221+
DisableHook(this, [](auto& em) { return &em.fixedUpdatables; });
225222
}
226223

227224
void Entity::ServerFixedUpdate(float deltaTime)
228225
{
229-
flags.ResetFlag(EntityFlags::EnableServerUpdate);
230-
FlagsChanged();
226+
DisableHook(this, [](auto& em) { return &em.serverFixedUpdatables; });
231227
}
232228

233229
void Entity::Render(Renderer* renderer)
234230
{
235-
flags.ResetFlag(EntityFlags::EnableRender);
236-
FlagsChanged();
237-
}
238-
239-
void Entity::RenderHud(Renderer* renderer)
240-
{
241-
flags.ResetFlag(EntityFlags::EnableRenderHud);
242-
FlagsChanged();
243-
}
244-
245-
void Entity::FlagsChanged()
246-
{
247-
scene->GetEntityManager().ScheduleUpdateInterfaces(this);
231+
DisableHook(this, [](auto& em) { return &em.renderables; });
248232
}
249233

250234
Vector2 Entity::ScreenCenter() const

src/Scene/Entity.hpp

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,14 @@
1919
#include "Memory/DLinkNode.hpp"
2020

2121
class b2Body;
22-
2322
struct IEntityEvent;
2423
struct MoveResult;
25-
2624
class Renderer;
27-
2825
class Scene;
29-
3026
struct Entity;
31-
3227
class Engine;
33-
3428
struct EntityInstance;
29+
struct EntityGroup;
3530

3631
struct EntityHeader
3732
{
@@ -49,13 +44,6 @@ enum class EntityFlags
4944
EnableBuoyancy = 1,
5045
WasTeleported = 2,
5146
CastsShadows = 4,
52-
53-
EnableUpdate = 8,
54-
EnableServerUpdate = 16,
55-
EnableFixedUpdate = 32,
56-
EnableServerFixedUpdate = 64,
57-
EnableRender = 128,
58-
EnableRenderHud = 256
5947
};
6048

6149
struct Entity;
@@ -131,7 +119,6 @@ struct Entity : DLinkedNode<Entity>
131119
virtual void ServerFixedUpdate(float deltaTime);
132120

133121
virtual void Render(Renderer* renderer);
134-
virtual void RenderHud(Renderer* renderer);
135122

136123
/// <summary>
137124
/// Called when an entity has been added to the scene.
@@ -208,6 +195,7 @@ struct Entity : DLinkedNode<Entity>
208195
Entity* parent = nullptr;
209196
Entity* nextSibling = nullptr;
210197
Entity* children = nullptr;
198+
EntityGroup* entityGroup = nullptr;
211199

212200
ISyncVar* syncVarHead = nullptr;
213201

src/Scene/EntityManager.cpp

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -20,51 +20,50 @@ void EntityManager::RegisterEntity(Entity* entity)
2020

2121
entity->id = header->id;
2222
entity->header = header;
23+
24+
// Put into entity group
25+
{
26+
auto groupIt = entitiesByType.find(entity->type.key);
27+
28+
if (groupIt == entitiesByType.end())
29+
{
30+
// We don't know whether the entity is updatable, renderable, etc since there's no way to introspect the vtable
31+
// to see if the methods are overridden. So, assume it implements those things and let the base class implementation
32+
// turn them off for the group.
33+
auto[it, inserted] = entitiesByType.try_emplace(entity->type.key);
34+
groupIt = it;
35+
36+
EntityGroup* group = &it->second;
37+
38+
updatables.insert(group);
39+
fixedUpdatables.insert(group);
40+
renderables.insert(group);
41+
42+
serverUpdatables.insert(group);
43+
serverFixedUpdatables.insert(group);
44+
}
45+
46+
groupIt->second.entities.Append(entity);
47+
entity->entityGroup = &groupIt->second;
48+
}
2349
}
2450

2551
void EntityManager::UnregisterEntity(Entity* entity)
2652
{
2753
entities.erase(entity);
28-
29-
updatables.erase(entity);
30-
fixedUpdatables.erase(entity);
31-
serverUpdatables.erase(entity);
32-
serverFixedUpdatables.erase(entity);
33-
renderables.erase(entity);
34-
hudRenderables.erase(entity);
54+
entity->Unlink();
3555

3656
EntityHeader* header = entity->header;
3757
header->id = InvalidEntityHeaderId;
3858
freeEntityHeaders.Return(header);
3959
}
4060

41-
static void SetOwnershipBasedOnFlag(std::unordered_set<Entity*>& set, Entity* entity, EntityFlags flag)
42-
{
43-
if(entity->flags.HasFlag(flag)) set.insert(entity);
44-
else set.erase(entity);
45-
}
46-
47-
void EntityManager::AddInterfaces(Entity* entity)
48-
{
49-
SetOwnershipBasedOnFlag(updatables, entity, EntityFlags::EnableUpdate);
50-
SetOwnershipBasedOnFlag(fixedUpdatables, entity, EntityFlags::EnableFixedUpdate);
51-
SetOwnershipBasedOnFlag(serverUpdatables, entity, EntityFlags::EnableServerUpdate);
52-
SetOwnershipBasedOnFlag(serverFixedUpdatables, entity, EntityFlags::EnableServerFixedUpdate);
53-
SetOwnershipBasedOnFlag(renderables, entity, EntityFlags::EnableRender);
54-
SetOwnershipBasedOnFlag(hudRenderables, entity, EntityFlags::EnableRenderHud);
55-
}
56-
57-
void EntityManager::ScheduleUpdateInterfaces(Entity* entity)
61+
void EntityManager::RunHookRemovals()
5862
{
59-
needsUpdatedInterfaces.insert(entity);
60-
}
61-
62-
void EntityManager::UpdateInterfaces()
63-
{
64-
for (auto entity : needsUpdatedInterfaces)
65-
{
66-
AddInterfaces(entity);
67-
}
63+
for (auto& removal : scheduledHookRemovals)
64+
{
65+
removal.hookSet->erase(removal.entityGroup);
66+
}
6867

69-
needsUpdatedInterfaces.clear();
68+
scheduledHookRemovals.clear();
7069
}

0 commit comments

Comments
 (0)