Skip to content

Commit

Permalink
support gettting addons by base type
Browse files Browse the repository at this point in the history
  • Loading branch information
sicusa committed Feb 10, 2024
1 parent 0779fbc commit 6fd23d3
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 37 deletions.
22 changes: 22 additions & 0 deletions Sia.Examples/Example13_Addon.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace Sia_Examples;

using Sia;

public static partial class Example13_Addon
{
public interface ITestAddon : IAddon {}
public class Addon1 : ITestAddon {}
public class Addon2 : ITestAddon {}

public static void Run(World world)
{
var a1 = world.AcquireAddon<Addon1>();
var a2 = world.GetAddon<ITestAddon>();
world.AddAddon<Addon2>();
Console.WriteLine("Found addon by interface: " + (a1 == a2));

foreach (var addon in world.GetAddons<ITestAddon>()) {
Console.WriteLine(addon.GetType());
}
}
}
3 changes: 2 additions & 1 deletion Sia.Examples/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ void Invoke(Action<World> action)
Invoke(Example8_SIMD.Run);
Invoke(Example10_DuplicateSystem.Run);
Invoke(Example11_RPG.Run);
Invoke(Example12_DynEntityRef.Run);
Invoke(Example12_DynEntityRef.Run);
Invoke(Example13_Addon.Run);
7 changes: 4 additions & 3 deletions Sia/Systems/AddonSystemBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ public AddonSystemBase(
}

protected TAddon AddAddon<TAddon>(World world)
where TAddon : IAddon, new()
where TAddon : class, IAddon, new()
{
_addonRemovers.TryAdd(typeof(TAddon), static world => world.RemoveAddon<TAddon>());
return world.AcquireAddon<TAddon>();
_addonRemovers.TryAdd(typeof(TAddon),
static world => world.RemoveAddon<TAddon>());
return world.AddAddon<TAddon>();
}

public override void Uninitialize(World world, Scheduler scheduler)
Expand Down
114 changes: 81 additions & 33 deletions Sia/Worlds/World.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,17 @@ private readonly record struct SimpleIterationData<TData>(
public IReadOnlyDictionary<IEntityMatcher, EntityQuery> Queries => _queries;
public IEnumerable<IEntityHost> EntityHosts => _hosts.Values;

public IEnumerable<IAddon> Addons =>
_addons[.._addonCount].Where(addon => addon != null)!;
public IEnumerable<IAddon> Addons {
get {
for (int i = 0; i < _addonCount;) {
var addon = _addons[i];
if (addon != null) {
i++;
yield return addon;
}
}
}
}

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

public WorldCommandBuffer CreateCommandBuffer()
=> new(this);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private TAddon CreateAddon<TAddon>()
where TAddon : IAddon, new()
{
var addon = new TAddon();
addon.OnInitialize(this);
_addonCount++;
return addon;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TAddon AcquireAddon<TAddon>()
where TAddon : IAddon, new()
where TAddon : class, IAddon, new()
{
ref var addon = ref _addons[WorldAddonIndexer<TAddon>.Index];
if (addon != null) {
return (TAddon)addon!;
return Unsafe.As<TAddon>(addon);
}
var newAddon = CreateAddon<TAddon>();
addon = newAddon;
Expand All @@ -496,7 +495,7 @@ public TAddon AcquireAddon<TAddon>()

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TAddon AddAddon<TAddon>()
where TAddon : IAddon, new()
where TAddon : class, IAddon, new()
{
ref var addon = ref _addons[WorldAddonIndexer<TAddon>.Index];
if (addon != null) {
Expand All @@ -507,45 +506,94 @@ public TAddon AddAddon<TAddon>()
return newAddon;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private TAddon CreateAddon<TAddon>()
where TAddon : class, IAddon, new()
{
var addon = new TAddon();
addon.OnInitialize(this);
_addonCount++;
return addon;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool RemoveAddon<TAddon>()
where TAddon : IAddon
where TAddon : class, IAddon
{
ref var addon = ref _addons[WorldAddonIndexer<TAddon>.Index];
if (addon != null) {
addon.OnUninitialize(this);
addon = null;
_addonCount--;
return true;
if (addon == null) {
return false;
}
return false;
addon.OnUninitialize(this);
addon = null;
_addonCount--;
return true;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TAddon GetAddon<TAddon>()
where TAddon : IAddon
where TAddon : class, IAddon
{
ref var addon = ref _addons[WorldAddonIndexer<TAddon>.Index];
if (addon == null) {
throw new KeyNotFoundException("Addon not found: " + typeof(TAddon));
var addon = _addons[WorldAddonIndexer<TAddon>.Index];
if (addon != null) {
return Unsafe.As<TAddon>(addon);
}
return (TAddon)addon!;

for (int i = 0, found = 0; found < _addonCount; ++i) {
addon = _addons[i];
if (addon != null) {
if (addon is TAddon converted) {
return converted;
}
found++;
}
}

throw new KeyNotFoundException("Addon not found: " + typeof(TAddon));
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool ContainsAddon<TAddon>()
where TAddon : IAddon
=> _addons[WorldAddonIndexer<TAddon>.Index] != null;
public IEnumerable<TAddon> GetAddons<TAddon>()
where TAddon : class, IAddon
{
var addon = _addons[WorldAddonIndexer<TAddon>.Index];
if (addon != null) {
yield return Unsafe.As<TAddon>(addon);
}

for (int i = 0, found = 0; found < _addonCount; ++i) {
addon = _addons[i];
if (addon != null) {
if (addon is TAddon converted) {
yield return converted;
}
found++;
}
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryGetAddon<TAddon>([MaybeNullWhen(false)] out TAddon addon)
where TAddon : IAddon
where TAddon : class, IAddon
{
ref var rawAddon = ref _addons[WorldAddonIndexer<TAddon>.Index];
var rawAddon = _addons[WorldAddonIndexer<TAddon>.Index];

if (rawAddon != null) {
addon = (TAddon)rawAddon;
addon = Unsafe.As<TAddon>(rawAddon);
return true;
}

for (int i = 0, found = 0; found < _addonCount; ++i) {
rawAddon = _addons[i];
if (rawAddon != null) {
if (rawAddon is TAddon converted) {
addon = converted;
return true;
}
found++;
}
}

addon = default;
return false;
}
Expand Down

0 comments on commit 6fd23d3

Please sign in to comment.