feat: add initial architecture

This commit is contained in:
2026-08-20 19:46:07 +02:00
parent 6fbdc578a2
commit 51ac7aee8c
32 changed files with 1264 additions and 41 deletions
+87
View File
@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
namespace Game.Shared.Events;
public sealed class InMemoryEventBus : IEventBus
{
private readonly Dictionary<Type, List<Delegate>> _handlers = [];
private readonly object _lock = new();
public IDisposable Subscribe<TEvent>(Action<TEvent> handler) where TEvent : IEvent
{
ArgumentNullException.ThrowIfNull(handler);
var eventType = typeof(TEvent);
lock (_lock)
{
if (!_handlers.TryGetValue(eventType, out var list))
{
list = [];
_handlers[eventType] = list;
}
list.Add(handler);
}
return new EventSubscription(() => Unsubscribe(eventType, handler));
}
public void Publish<TEvent>(TEvent gameEvent) where TEvent : IEvent
{
ArgumentNullException.ThrowIfNull(gameEvent);
List<Delegate> snapshot = null;
var eventType = typeof(TEvent);
lock (_lock)
{
if (_handlers.TryGetValue(eventType, out var list))
{
snapshot = new List<Delegate>(list);
}
}
if (snapshot == null) return;
foreach (var subscriber in snapshot)
{
((Action<TEvent>)subscriber)(gameEvent);
}
}
private void Unsubscribe(Type eventType, Delegate handler)
{
lock (_lock)
{
if (!_handlers.TryGetValue(eventType, out var list)) return;
list.Remove(handler);
if (list.Count == 0)
{
_handlers.Remove(eventType);
}
}
}
public void Clear()
{
lock (_lock)
{
_handlers.Clear();
}
}
private sealed class EventSubscription(Action unsubscribeAction) : IDisposable
{
private Action _unsubscribeAction = unsubscribeAction;
public void Dispose()
{
_unsubscribeAction?.Invoke();
_unsubscribeAction = null;
}
}
}