From b6e64d28713bc93c51a0b408d7ae6f31a5d4234c Mon Sep 17 00:00:00 2001 From: hypercross Date: Sat, 18 Jul 2026 22:05:29 +0800 Subject: [PATCH] refactor: add struct constraint to Relationship Add `where TSelf : struct where TTarget : struct` constraints to the `Relationship` struct to ensure type safety and consistency with the ECS architecture. Also remove unused `IterateThree` method in `QueryExecutor`. --- src/OECS/QueryExecutor.cs | 42 --------------------------- src/OECS/Relationship.cs | 1 + tests/OECS.Tests/RelationshipTests.cs | 11 +++---- 3 files changed, 7 insertions(+), 47 deletions(-) diff --git a/src/OECS/QueryExecutor.cs b/src/OECS/QueryExecutor.cs index e8cb3a4..c20f69c 100644 --- a/src/OECS/QueryExecutor.cs +++ b/src/OECS/QueryExecutor.cs @@ -179,48 +179,6 @@ internal static class QueryExecutor } } - private static void IterateThree( - SparseSet driveSet, - SparseSet setA, - SparseSet setB, - ComponentStore store, - IReadOnlySet withoutTypes, - ForEachAction actionWhenDriverIsT2, - ForEachAction actionWhenDriverIsT1, - ForEachAction actionWhenDriverIsT3) - where TDriver : struct where TA : struct where TB : struct - { - var dense = driveSet.Dense; - var denseEntities = driveSet.DenseEntities; - var count = driveSet.Count; - - for (int i = 0; i < count; i++) - { - var entity = denseEntities[i]; - if (entity.Id == SingletonId) continue; - if (!setA.Contains(entity)) continue; - if (!setB.Contains(entity)) continue; - if (!PassesWithoutFilter(store, entity, withoutTypes)) - continue; - - if (actionWhenDriverIsT2 != null!) - { - // Driver is T2, so order is: T1=setA, T2=driveSet, T3=setB - actionWhenDriverIsT2(entity, ref setA.Get(entity), ref dense[i], ref setB.Get(entity)); - } - else if (actionWhenDriverIsT3 != null!) - { - // Driver is T3, so order is: T1=setA, T2=setB, T3=driveSet - actionWhenDriverIsT3(entity, ref setA.Get(entity), ref setB.Get(entity), ref dense[i]); - } - else - { - // Driver is T1, so order is: T1=driveSet, T2=setA, T3=setB - actionWhenDriverIsT1(entity, ref dense[i], ref setA.Get(entity), ref setB.Get(entity)); - } - } - } - public static void ForEach( ComponentStore store, QueryDescriptor query, diff --git a/src/OECS/Relationship.cs b/src/OECS/Relationship.cs index 95b308c..008d2e2 100644 --- a/src/OECS/Relationship.cs +++ b/src/OECS/Relationship.cs @@ -25,6 +25,7 @@ namespace OECS; /// [MessagePackObject] public struct Relationship : IRelationship + where TSelf : struct where TTarget : struct { /// /// The entity that owns this relationship component. diff --git a/tests/OECS.Tests/RelationshipTests.cs b/tests/OECS.Tests/RelationshipTests.cs index 33ac59e..31764c7 100644 --- a/tests/OECS.Tests/RelationshipTests.cs +++ b/tests/OECS.Tests/RelationshipTests.cs @@ -9,6 +9,7 @@ public struct ChildOf { } public struct ParentOf { } public struct OwnedBy { } public struct MemberOf { } +public struct Thing { } // ── Tests ──────────────────────────────────────────────────────────── @@ -153,20 +154,20 @@ public class RelationshipTests var owner = world.CreateEntity(); var group = world.CreateEntity(); - world.AddComponent(entity, new Relationship + world.AddComponent(entity, new Relationship { Source = entity, Target = owner }); - world.AddComponent(entity, new Relationship + world.AddComponent(entity, new Relationship { Source = entity, Target = group }); - world.GetSources>(owner).Should().BeEquivalentTo([entity]); - world.GetSources>(group).Should().BeEquivalentTo([entity]); + world.GetSources>(owner).Should().BeEquivalentTo([entity]); + world.GetSources>(group).Should().BeEquivalentTo([entity]); // Cross-check: OwnedBy sources should not appear in MemberOf lookups. - world.GetSources>(owner).Should().BeEmpty(); + world.GetSources>(owner).Should().BeEmpty(); } [Fact]