Skip to content

Commit 1a04407

Browse files
committed
ECS - add runtime assertion for missing indexed component values
1 parent 6c28e45 commit 1a04407

File tree

6 files changed

+36
-1
lines changed

6 files changed

+36
-1
lines changed

src/ECS/Index/Indexes/EntityIndex.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ internal override void RemoveEntityFromIndex(int id, Archetype archetype, int co
8585
map.TryGetValue(linkedEntity, out var idArray);
8686
var idSpan = idArray.GetSpan(heap, store);
8787
int index = idSpan.IndexOf(id);
88+
if (index == -1) {
89+
StoreIndex.ThrowIndexedComponentValueNotFound();
90+
}
8891
idArray.RemoveAt(index, heap);
8992
if (idArray.Count == 0) {
9093
map.Remove(linkedEntity);

src/ECS/Index/Indexes/RangeIndex.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ internal override void RemoveEntityFromIndex(int id, Archetype archetype, int co
6565
map.TryGetValue(value, out var idArray);
6666
var idSpan = idArray.GetSpan(heap, store);
6767
var index = idSpan.IndexOf(id);
68+
if (index == -1) {
69+
StoreIndex.ThrowIndexedComponentValueNotFound();
70+
}
6871
idArray.RemoveAt(index, heap);
6972
if (idArray.Count == 0) {
7073
map.Remove(value);

src/ECS/Index/Indexes/ValueClassIndex.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ internal override void RemoveEntityFromIndex(int id, Archetype archetype, int co
5858
map.TryGetValue(value, out var idArray);
5959
var idSpan = idArray.GetSpan(heap, store);
6060
var index = idSpan.IndexOf(id);
61+
if (index == -1) {
62+
StoreIndex.ThrowIndexedComponentValueNotFound();
63+
}
6164
idArray.RemoveAt(index, heap);
6265
if (idArray.Count == 0) {
6366
map.Remove(value);

src/ECS/Index/Indexes/ValueStructIndex.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ internal override void RemoveEntityFromIndex(int id, Archetype archetype, int co
5656
map.TryGetValue(value, out var idArray);
5757
var idSpan = idArray.GetSpan(heap, store);
5858
var index = idSpan.IndexOf(id);
59+
if (index == -1) {
60+
StoreIndex.ThrowIndexedComponentValueNotFound();
61+
}
5962
idArray.RemoveAt(index, heap);
6063
if (idArray.Count == 0) {
6164
map.Remove(value);

src/ECS/Index/Internal/StoreIndex.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
// See LICENSE file in the project root for full license information.
33

44
// ReSharper disable once CheckNamespace
5+
6+
using System;
7+
58
namespace Friflo.Engine.ECS.Index;
69

710
internal static class StoreIndex
@@ -52,4 +55,8 @@ private static AbstractComponentIndex[] CreateStoreIndexMap()
5255
var schema = EntityStoreBase.Static.EntitySchema;
5356
return new AbstractComponentIndex[schema.maxIndexedStructIndex];
5457
}
58+
59+
internal static void ThrowIndexedComponentValueNotFound() {
60+
throw new InvalidOperationException("Indexed component value not found. Reason: indexed values mus not be changed. See: https://friflo.gitbook.io/friflo.engine.ecs/documentation/component-index#indexed-components");
61+
}
5562
}

src/Tests/ECS/Index/Test_Index_Delete.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Friflo.Engine.ECS;
1+
using System;
2+
using Friflo.Engine.ECS;
23
using NUnit.Framework;
34
using static NUnit.Framework.Assert;
45

@@ -177,6 +178,21 @@ public static void Test_Index_Delete_Range()
177178
entity3.DeleteEntity();
178179
AreEqual("{ }", values.Debug());
179180
}
181+
182+
[Test]
183+
public static void TestDeleteEntity() {
184+
var store = new EntityStore();
185+
var root = store.CreateEntity(1);
186+
var entity2 = store.CreateEntity(2);
187+
var entity3 = store.CreateEntity(3);
188+
var child = store.CreateEntity(new AttackComponent { target = entity2 });
189+
child.GetComponent<AttackComponent>().target = entity3; // causes subsequent exception. The indexed value MUST never be changed
190+
root.AddChild(child);
191+
var e = Throws<InvalidOperationException>(() => {
192+
child.DeleteEntity();
193+
});
194+
AreEqual("Indexed component value not found. Reason: indexed values mus not be changed. See: https://friflo.gitbook.io/friflo.engine.ecs/documentation/component-index#indexed-components", e!.Message);
195+
}
180196
}
181197

182198
}

0 commit comments

Comments
 (0)