Skip to content

Commit

Permalink
UniqueEntity plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
andreakarasho committed Feb 27, 2024
1 parent cd1ebea commit 688b3e2
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 40 deletions.
7 changes: 2 additions & 5 deletions plugins/TinyEcs.Plugins/Relationship.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,10 @@ public static class RelationshipPlugin
{
[ModuleInitializer]

Check warning on line 48 in plugins/TinyEcs.Plugins/Relationship.cs

View workflow job for this annotation

GitHub Actions / build

The 'ModuleInitializer' attribute is only intended to be used in application code or advanced source generator scenarios (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2255)
internal static void ModuleInit()
{
// nop, this trigger the static ctor
}

static RelationshipPlugin()
{
World.OnPluginInitialization += world => {
world.Component<Parent>();
world.Component<Child>();
world.OnEntityDeleted += e => e.ClearChildren();
};
}
Expand Down
47 changes: 47 additions & 0 deletions plugins/TinyEcs.Plugins/UniqueEntity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.Runtime.CompilerServices;

namespace TinyEcs;

public readonly struct Identity
{
public readonly string Value;

internal Identity(string value) => Value = value;
}

public static class UniqueEntityPlugin
{
[ModuleInitializer]

Check warning on line 14 in plugins/TinyEcs.Plugins/UniqueEntity.cs

View workflow job for this annotation

GitHub Actions / build

The 'ModuleInitializer' attribute is only intended to be used in application code or advanced source generator scenarios (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2255)
internal static void ModuleInit()
{
World.OnPluginInitialization += world => {
// initialize the entity component
world.Component<Identity>();
};
}

public static EntityView Entity(this World world, string name)
{
if (string.IsNullOrWhiteSpace(name))
return world.Entity();

var found = EntityView.Invalid;
world.Query((EntityView entity, ref Identity identity) => {
if (identity.Value?.Equals(name) ?? false)
found = entity;
});

if (found.ID != 0)
return found;

return world.Entity().Set(new Identity(name));
}

public static string Name(this EntityView entity)
{
if (!entity.Has<Identity>())
return $"{entity.ID}";

return entity.Get<Identity>().Value ?? string.Empty;
}
}
28 changes: 14 additions & 14 deletions samples/MyBattleground/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

ecs.Filter<(Position, Velocity)>()
.Query((EntityView entity) => {
Console.WriteLine(entity);
Console.WriteLine(entity.Name());
});


Expand All @@ -38,39 +38,39 @@
}

ecs.Filter<(With<Child>, With<Parent>)>().Query((EntityView entity, ref Relationship relation) => {
Console.WriteLine("im [{0}] a child of {1}, but also having {2} children", entity, ecs.Entity(relation.Parent), relation.Count);
Console.WriteLine("im [{0}] a child of {1}, but also having {2} children", entity.Name(), ecs.Entity(relation.Parent).Name(), relation.Count);
});

Console.WriteLine();

ecs.Filter<With<Parent>>().Query((EntityView entity, ref Relationship relation) => {
Console.WriteLine("parent {0} has {1} children", entity, relation.Count);
Console.WriteLine("parent {0} has {1} children", entity.Name(), relation.Count);

foreach (var id in entity.Children())
{
Console.WriteLine("\tChild: {0}", ecs.Entity(id));
Console.WriteLine("\tChild: {0}", ecs.Entity(id).Name());
}
});

Console.WriteLine();

e.RemoveChild(child);
ecs.Filter<With<Parent>>().Query((EntityView entity, ref Relationship relation) => {
Console.WriteLine("parent {0} has {1} children", entity, relation.Count);
Console.WriteLine("parent {0} has {1} children", entity.Name(), relation.Count);
});

Console.WriteLine();

child2.RemoveChild(child3);
ecs.Filter<With<Parent>>().Query((EntityView entity, ref Relationship relation) => {
Console.WriteLine("parent {0} has {1} children", entity, relation.Count);
Console.WriteLine("parent {0} has {1} children", entity.Name(), relation.Count);
});

Console.WriteLine();

e.ClearChildren();
ecs.Filter<With<Parent>>().Query((EntityView entity, ref Relationship relation) => {
Console.WriteLine("parent {0} has {1} children", entity.ID, relation.Count);
Console.WriteLine("parent {0} has {1} children", entity.Name(), relation.Count);
});

e.Delete();
Expand All @@ -83,9 +83,9 @@
ecs.Entity()
.Set<Position>(new Position())
.Set<Velocity>(new Velocity())
.Set<PlayerTag>()
.Set<Dogs>()
.Set<Likes>()
// .Set<PlayerTag>()
// .Set<Dogs>()
// .Set<Likes>()
;

var sw = Stopwatch.StartNew();
Expand All @@ -108,19 +108,19 @@
// {
// var column0 = archetype.GetComponentIndex<Position>();
// var column1 = archetype.GetComponentIndex<Velocity>();

// foreach (ref readonly var chunk in archetype)
// {
// ref var pos = ref chunk.GetReference<Position>(column0);
// ref var vel = ref chunk.GetReference<Velocity>(column1);

// ref var last2 = ref Unsafe.Add(ref pos, chunk.Count);

// while (Unsafe.IsAddressLessThan(ref pos, ref last2))
// {
// pos.X *= vel.X;
// pos.Y *= vel.Y;

// pos = ref Unsafe.Add(ref pos, 1);
// vel = ref Unsafe.Add(ref vel, 1);
// }
Expand Down
3 changes: 0 additions & 3 deletions src/EntityView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ internal EntityView(World world, EcsID id)
ID = id;
}

public string Name => ToString();

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly bool Equals(EcsID other) => ID == other;
Expand Down Expand Up @@ -93,8 +92,6 @@ public readonly EntityView Disable()

public readonly bool IsEnabled() => !Has<EcsDisabled>();

public override string ToString() => World.GetRecord(ID).Name ?? $"{ID}";


public static implicit operator EcsID(EntityView d) => d.ID;

Expand Down
30 changes: 12 additions & 18 deletions src/World.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ public sealed partial class World : IDisposable
private readonly Archetype _archRoot;
private readonly EntitySparseSet<EcsRecord> _entities = new();
private readonly DictionarySlim<ulong, Archetype> _typeIndex = new();
private readonly Dictionary<string, EcsID> _entityNames = new();
private Archetype[] _archetypes = new Archetype[16];
private int _archetypeCount;
private readonly ComponentComparer _comparer;
Expand Down Expand Up @@ -54,7 +53,6 @@ public void Dispose()
_archRoot.Clear();
_typeIndex.Clear();
_commands.Clear();
_entityNames.Clear();

Array.Clear(_archetypes, 0, _archetypeCount);
_archetypeCount = 0;
Expand All @@ -75,7 +73,7 @@ static void InternalOptimize(Archetype root)
}
}

internal unsafe ref readonly EcsComponent Component<T>() where T : struct
public unsafe ref readonly EcsComponent Component<T>() where T : struct
{
ref readonly var lookup = ref Lookup.Component<T>.Value;

Expand Down Expand Up @@ -117,19 +115,19 @@ internal unsafe ref readonly EcsComponent Component<T>() where T : struct
return ref lookup;
}

public EntityView Entity(string name)
{
_entityNames.TryGetValue(name, out var id);
// public EntityView Entity(string name)
// {
// _entityNames.TryGetValue(name, out var id);

var entity = Entity(id);
if (id == 0)
{
_entityNames.Add(name, entity.ID);
GetRecord(entity.ID).Name = name;
}
// var entity = Entity(id);
// if (id == 0)
// {
// _entityNames.Add(name, entity.ID);
// GetRecord(entity.ID).Name = name;
// }

return entity;
}
// return entity;
// }

public EntityView Entity(EcsID id = default)
{
Expand Down Expand Up @@ -169,9 +167,6 @@ public void Delete(EcsID entity)
EcsAssert.Assert(removedId == entity);

_entities.Remove(removedId);

if (!string.IsNullOrEmpty(record.Name))
_entityNames.Remove(record.Name);
}

public bool Exists(EcsID entity)
Expand Down Expand Up @@ -679,7 +674,6 @@ struct EcsRecord
{
public Archetype Archetype;
public int Row;
public string? Name;

public readonly ref ArchetypeChunk GetChunk() => ref Archetype.GetChunk(Row);
}

0 comments on commit 688b3e2

Please sign in to comment.