Skip to content

Commit 6fd23d3

Browse files
committed
support gettting addons by base type
1 parent 0779fbc commit 6fd23d3

4 files changed

Lines changed: 109 additions & 37 deletions

File tree

Sia.Examples/Example13_Addon.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
namespace Sia_Examples;
2+
3+
using Sia;
4+
5+
public static partial class Example13_Addon
6+
{
7+
public interface ITestAddon : IAddon {}
8+
public class Addon1 : ITestAddon {}
9+
public class Addon2 : ITestAddon {}
10+
11+
public static void Run(World world)
12+
{
13+
var a1 = world.AcquireAddon<Addon1>();
14+
var a2 = world.GetAddon<ITestAddon>();
15+
world.AddAddon<Addon2>();
16+
Console.WriteLine("Found addon by interface: " + (a1 == a2));
17+
18+
foreach (var addon in world.GetAddons<ITestAddon>()) {
19+
Console.WriteLine(addon.GetType());
20+
}
21+
}
22+
}

Sia.Examples/Program.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ void Invoke(Action<World> action)
2121
Invoke(Example8_SIMD.Run);
2222
Invoke(Example10_DuplicateSystem.Run);
2323
Invoke(Example11_RPG.Run);
24-
Invoke(Example12_DynEntityRef.Run);
24+
Invoke(Example12_DynEntityRef.Run);
25+
Invoke(Example13_Addon.Run);

Sia/Systems/AddonSystemBase.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ public AddonSystemBase(
1616
}
1717

1818
protected TAddon AddAddon<TAddon>(World world)
19-
where TAddon : IAddon, new()
19+
where TAddon : class, IAddon, new()
2020
{
21-
_addonRemovers.TryAdd(typeof(TAddon), static world => world.RemoveAddon<TAddon>());
22-
return world.AcquireAddon<TAddon>();
21+
_addonRemovers.TryAdd(typeof(TAddon),
22+
static world => world.RemoveAddon<TAddon>());
23+
return world.AddAddon<TAddon>();
2324
}
2425

2526
public override void Uninitialize(World world, Scheduler scheduler)

Sia/Worlds/World.cs

Lines changed: 81 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,17 @@ private readonly record struct SimpleIterationData<TData>(
165165
public IReadOnlyDictionary<IEntityMatcher, EntityQuery> Queries => _queries;
166166
public IEnumerable<IEntityHost> EntityHosts => _hosts.Values;
167167

168-
public IEnumerable<IAddon> Addons =>
169-
_addons[.._addonCount].Where(addon => addon != null)!;
168+
public IEnumerable<IAddon> Addons {
169+
get {
170+
for (int i = 0; i < _addonCount;) {
171+
var addon = _addons[i];
172+
if (addon != null) {
173+
i++;
174+
yield return addon;
175+
}
176+
}
177+
}
178+
}
170179

171180
private readonly Dictionary<IEntityMatcher, EntityQuery> _queries = [];
172181
private readonly SparseSet<IReactiveEntityHost> _hosts = new(256, 256);
@@ -470,24 +479,14 @@ public void Modify<TEntity, TComponent, TCommand>(
470479

471480
public WorldCommandBuffer CreateCommandBuffer()
472481
=> new(this);
473-
474-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
475-
private TAddon CreateAddon<TAddon>()
476-
where TAddon : IAddon, new()
477-
{
478-
var addon = new TAddon();
479-
addon.OnInitialize(this);
480-
_addonCount++;
481-
return addon;
482-
}
483482

484483
[MethodImpl(MethodImplOptions.AggressiveInlining)]
485484
public TAddon AcquireAddon<TAddon>()
486-
where TAddon : IAddon, new()
485+
where TAddon : class, IAddon, new()
487486
{
488487
ref var addon = ref _addons[WorldAddonIndexer<TAddon>.Index];
489488
if (addon != null) {
490-
return (TAddon)addon!;
489+
return Unsafe.As<TAddon>(addon);
491490
}
492491
var newAddon = CreateAddon<TAddon>();
493492
addon = newAddon;
@@ -496,7 +495,7 @@ public TAddon AcquireAddon<TAddon>()
496495

497496
[MethodImpl(MethodImplOptions.AggressiveInlining)]
498497
public TAddon AddAddon<TAddon>()
499-
where TAddon : IAddon, new()
498+
where TAddon : class, IAddon, new()
500499
{
501500
ref var addon = ref _addons[WorldAddonIndexer<TAddon>.Index];
502501
if (addon != null) {
@@ -507,45 +506,94 @@ public TAddon AddAddon<TAddon>()
507506
return newAddon;
508507
}
509508

509+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
510+
private TAddon CreateAddon<TAddon>()
511+
where TAddon : class, IAddon, new()
512+
{
513+
var addon = new TAddon();
514+
addon.OnInitialize(this);
515+
_addonCount++;
516+
return addon;
517+
}
518+
510519
[MethodImpl(MethodImplOptions.AggressiveInlining)]
511520
public bool RemoveAddon<TAddon>()
512-
where TAddon : IAddon
521+
where TAddon : class, IAddon
513522
{
514523
ref var addon = ref _addons[WorldAddonIndexer<TAddon>.Index];
515-
if (addon != null) {
516-
addon.OnUninitialize(this);
517-
addon = null;
518-
_addonCount--;
519-
return true;
524+
if (addon == null) {
525+
return false;
520526
}
521-
return false;
527+
addon.OnUninitialize(this);
528+
addon = null;
529+
_addonCount--;
530+
return true;
522531
}
523532

524533
[MethodImpl(MethodImplOptions.AggressiveInlining)]
525534
public TAddon GetAddon<TAddon>()
526-
where TAddon : IAddon
535+
where TAddon : class, IAddon
527536
{
528-
ref var addon = ref _addons[WorldAddonIndexer<TAddon>.Index];
529-
if (addon == null) {
530-
throw new KeyNotFoundException("Addon not found: " + typeof(TAddon));
537+
var addon = _addons[WorldAddonIndexer<TAddon>.Index];
538+
if (addon != null) {
539+
return Unsafe.As<TAddon>(addon);
531540
}
532-
return (TAddon)addon!;
541+
542+
for (int i = 0, found = 0; found < _addonCount; ++i) {
543+
addon = _addons[i];
544+
if (addon != null) {
545+
if (addon is TAddon converted) {
546+
return converted;
547+
}
548+
found++;
549+
}
550+
}
551+
552+
throw new KeyNotFoundException("Addon not found: " + typeof(TAddon));
533553
}
534554

535555
[MethodImpl(MethodImplOptions.AggressiveInlining)]
536-
public bool ContainsAddon<TAddon>()
537-
where TAddon : IAddon
538-
=> _addons[WorldAddonIndexer<TAddon>.Index] != null;
556+
public IEnumerable<TAddon> GetAddons<TAddon>()
557+
where TAddon : class, IAddon
558+
{
559+
var addon = _addons[WorldAddonIndexer<TAddon>.Index];
560+
if (addon != null) {
561+
yield return Unsafe.As<TAddon>(addon);
562+
}
563+
564+
for (int i = 0, found = 0; found < _addonCount; ++i) {
565+
addon = _addons[i];
566+
if (addon != null) {
567+
if (addon is TAddon converted) {
568+
yield return converted;
569+
}
570+
found++;
571+
}
572+
}
573+
}
539574

540575
[MethodImpl(MethodImplOptions.AggressiveInlining)]
541576
public bool TryGetAddon<TAddon>([MaybeNullWhen(false)] out TAddon addon)
542-
where TAddon : IAddon
577+
where TAddon : class, IAddon
543578
{
544-
ref var rawAddon = ref _addons[WorldAddonIndexer<TAddon>.Index];
579+
var rawAddon = _addons[WorldAddonIndexer<TAddon>.Index];
580+
545581
if (rawAddon != null) {
546-
addon = (TAddon)rawAddon;
582+
addon = Unsafe.As<TAddon>(rawAddon);
547583
return true;
548584
}
585+
586+
for (int i = 0, found = 0; found < _addonCount; ++i) {
587+
rawAddon = _addons[i];
588+
if (rawAddon != null) {
589+
if (rawAddon is TAddon converted) {
590+
addon = converted;
591+
return true;
592+
}
593+
found++;
594+
}
595+
}
596+
549597
addon = default;
550598
return false;
551599
}

0 commit comments

Comments
 (0)