diff --git a/src/gaemstone/ECS/Attributes.cs b/src/gaemstone/ECS/Attributes.cs
index f2fa1f1..c043ece 100644
--- a/src/gaemstone/ECS/Attributes.cs
+++ b/src/gaemstone/ECS/Attributes.cs
@@ -19,6 +19,18 @@ public interface ICreateEntityAttribute { }
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
public class PrivateAttribute : Attribute { }
+///
+/// A singleton is a single instance of a tag or component that can be retrieved
+/// without explicitly specifying an entity in a query, where it is equivalent
+/// to with itself as the generic type parameter.
+///
+[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
+public class SingletonAttribute : Attribute
+{
+ /// Whether to add the entity to itself on registration.
+ public bool AutoAdd { get; init; } = false;
+}
+
///
/// Register the proxied type instead of the one marked with this attribute.
/// This can be used to make types not registered in a module available,
diff --git a/src/gaemstone/ECS/Entity.cs b/src/gaemstone/ECS/Entity.cs
index 63b2abc..1eb9de8 100644
--- a/src/gaemstone/ECS/Entity.cs
+++ b/src/gaemstone/ECS/Entity.cs
@@ -21,18 +21,6 @@ public class EntityAttribute : Attribute, ICreateEntityAttribute
}
}
-///
-/// A singleton is a single instance of a tag or component that can be retrieved
-/// without explicitly specifying an entity in a query, where it is equivalent
-/// to with itself as the generic type parameter.
-///
-[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
-public class SingletonAttribute : EntityAttribute
-{
- public SingletonAttribute() { }
- public SingletonAttribute(params string[] path) : base(path) { }
-}
-
public readonly struct Entity
: IEquatable
{
diff --git a/src/gaemstone/ECS/Universe+Modules.cs b/src/gaemstone/ECS/Universe+Modules.cs
index b6cd235..e59b86e 100644
--- a/src/gaemstone/ECS/Universe+Modules.cs
+++ b/src/gaemstone/ECS/Universe+Modules.cs
@@ -198,7 +198,7 @@ internal class ModuleInfo
foreach (var attr in type.GetMultiple())
entity.Add(Lookup(attr.Relation), Lookup(attr.Target));
- if (type.Has()) entity.Add(entity);
+ if (type.Get()?.AutoAdd == true) entity.Add(entity);
if (type.Has()) entity.CreateComponent(proxyType);
else entity.CreateLookup(proxyType);
}
diff --git a/src/gaemstone/Utility/IL/IterActionGenerator.cs b/src/gaemstone/Utility/IL/IterActionGenerator.cs
index 599a758..7de3703 100644
--- a/src/gaemstone/Utility/IL/IterActionGenerator.cs
+++ b/src/gaemstone/Utility/IL/IterActionGenerator.cs
@@ -271,8 +271,8 @@ public unsafe class IterActionGenerator
// Reference types have a backing type of nint - they're pointers.
FieldType = underlyingType.IsValueType ? underlyingType : typeof(nint);
- Source = Info.Get()?.Type
- ?? (UnderlyingType.Has() ? UnderlyingType : null);
+ if (UnderlyingType.Has()) Source = UnderlyingType;
+ if (Info.Get()?.Type is Type type) Source = type;
}
public static ParamInfo Build(ParameterInfo info)