using System;
using System.Collections.Generic;
namespace Syntriax.Engine.Core;
///
/// Represents a simple event with no parameters.
/// Example usage:
///
/// public class MyBehaviour : Behaviour, IUpdate
/// {
/// public readonly Event MyEvent = new();
///
/// public MyBehaviour()
/// {
/// MyEvent.AddListener(OnEventTriggered);
/// MyEvent.AddOneTimeListener(OnEventTriggeredOneTime);
/// }
///
/// public void Update()
/// {
/// MyEvent.Invoke();
/// }
///
/// private void OnEventTriggered()
/// {
/// Console.WriteLine($"Event occurred!");
/// }
///
/// private static void OnEventTriggeredOneTime()
/// {
/// Console.WriteLine($"Event called once!");
/// }
/// }
///
/// The output of the example code above would be:
///
/// Event occurred!
/// Event called once!
/// Event occurred!
/// Event occurred!
/// Event occurred!
/// ...
///
///
public class Event
{
private readonly List listeners = null!;
private readonly List onceListeners = null!;
///
/// Subscribes the callback to be invoked whenever the event is triggered.
///
/// The callback to be called when the event is triggered.
public void AddListener(EventHandler listener) => listeners.Add(listener);
///
/// Subscribes the callback to be invoked the next time the event is triggered. The callback will be called only once.
///
/// The callback to be called the next time the event is triggered.
public void AddOneTimeListener(EventHandler listener) => onceListeners.Add(listener);
///
/// Unsubscribes the callback that was previously registered by .
///
/// The callback that was previously registered by
public void RemoveListener(EventHandler listener) => listeners.Remove(listener);
///
/// Unsubscribes the callback that was previously registered by .
///
/// The callback that was previously registered by
public void RemoveOneTimeListener(EventHandler listener) => onceListeners.Remove(listener);
///
/// Unsubscribes all listeners that was previously registered by either or .
///
public void Clear() { listeners.Clear(); onceListeners.Clear(); }
///
/// Triggers the event.
///
public void Invoke()
{
for (int i = listeners.Count - 1; i >= 0; i--)
try { listeners[i].Invoke(); }
catch (Exception exception)
{
string methodCallRepresentation = $"{listeners[i].Method.DeclaringType?.FullName}.{listeners[i].Method.Name}()";
Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
}
for (int i = onceListeners.Count - 1; i >= 0; i--)
{
try { onceListeners[i].Invoke(); }
catch (Exception exception)
{
string methodCallRepresentation = $"{onceListeners[i].Method.DeclaringType?.FullName}.{onceListeners[i].Method.Name}()";
Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
}
onceListeners.RemoveAt(i);
}
}
public Event(int initialListenerCount = 4, int initialOnceListenerCount = 2)
{
listeners = new(initialListenerCount);
onceListeners = new(initialOnceListenerCount);
}
public Event()
{
listeners = new(4);
onceListeners = new(2);
}
public delegate void EventHandler();
}
///
/// Represents an event with only sender parameters.
/// Example usage:
///
/// public class MyBehaviour : Behaviour, IUpdate
/// {
/// public readonly Event<MyBehaviour> MyEvent = new();
///
/// public MyBehaviour()
/// {
/// MyEvent.AddListener(OnEventTriggered);
/// MyEvent.AddOneTimeListener(OnEventTriggeredOneTime);
/// }
///
/// public void Update()
/// {
/// MyEvent.Invoke(this);
/// }
///
/// private void OnEventTriggered(MyBehaviour sender)
/// {
/// Console.WriteLine($"{sender.Id}'s event occurred!");
/// }
///
/// private static void OnEventTriggeredOneTime(MyBehaviour sender)
/// {
/// Console.WriteLine($"{sender.Id}'s event called once!");
/// }
/// }
///
/// The output of the example code above would be:
///
/// [Id]'s event occurred!
/// [Id]'s event called once!
/// [Id]'s event occurred!
/// [Id]'s event occurred!
/// [Id]'s event occurred!
/// ...
///
///
///
/// Sender type
public class Event
{
private readonly List listeners = null!;
private readonly List onceListeners = null!;
///
/// Subscribes the callback to be invoked whenever the event is triggered.
///
/// The callback to be called when the event is triggered.
public void AddListener(EventHandler listener) => listeners.Add(listener);
///
/// Subscribes the callback to be invoked the next time the event is triggered. The callback will be called only once.
///
/// The callback to be called the next time the event is triggered.
public void AddOneTimeListener(EventHandler listener) => onceListeners.Add(listener);
///
/// Unsubscribes the callback that was previously registered by .
///
/// The callback that was previously registered by
public void RemoveListener(EventHandler listener) => listeners.Remove(listener);
///
/// Unsubscribes the callback that was previously registered by .
///
/// The callback that was previously registered by
public void RemoveOneTimeListener(EventHandler listener) => onceListeners.Remove(listener);
///
/// Unsubscribes all listeners that was previously registered by either or .
///
public void Clear() { listeners.Clear(); onceListeners.Clear(); }
///
/// Triggers the event.
///
/// The caller that's triggering this event.
public void Invoke(TSender sender)
{
for (int i = listeners.Count - 1; i >= 0; i--)
try { listeners[i].Invoke(sender); }
catch (Exception exception)
{
string methodCallRepresentation = $"{listeners[i].Method.DeclaringType?.FullName}.{listeners[i].Method.Name}({sender})";
Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
}
for (int i = onceListeners.Count - 1; i >= 0; i--)
{
try { onceListeners[i].Invoke(sender); }
catch (Exception exception)
{
string methodCallRepresentation = $"{onceListeners[i].Method.DeclaringType?.FullName}.{onceListeners[i].Method.Name}({sender})";
Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
}
onceListeners.RemoveAt(i);
}
}
public Event(int initialListenerCount = 4, int initialOnceListenerCount = 2)
{
listeners = new(initialListenerCount);
onceListeners = new(initialOnceListenerCount);
}
public Event()
{
listeners = new(4);
onceListeners = new(2);
}
public delegate void EventHandler(TSender sender);
}
///
/// Represents an event with sender and argument parameters.
/// Example usage:
///
/// public class MyBehaviour : Behaviour, IUpdate
/// {
/// public readonly Event<MyBehaviour, MyArguments> MyEvent = new();
///
/// private int myInt = 0;
/// private bool myBool = false;
///
/// public MyBehaviour()
/// {
/// MyEvent.AddOneTimeListener(OnEventTriggeredOneTime);
/// MyEvent.AddListener(OnEventTriggered);
/// }
///
/// public void Update()
/// {
/// MyEvent.Invoke(this, new MyArguments(myInt, myBool));
/// myInt++;
/// myBool = !myBool;
/// }
///
/// private void OnEventTriggered(MyBehaviour sender, MyArguments args)
/// {
/// Console.WriteLine($"{sender.Id}'s event occurred with MyInt: {args.MyInt} and MyBool {args.MyBool}!");
/// }
///
/// private static void OnEventTriggeredOneTime(MyBehaviour sender, MyArguments args)
/// {
/// Console.WriteLine($"{sender.Id}'s event called once with MyInt: {args.MyInt} and MyBool {args.MyBool}!");
/// }
///
/// public readonly record struct MyArguments(int MyInt, bool MyBool);
/// }
///
/// The output of the example code above would be:
///
/// [Id]'s event occurred with MyInt: 0 and MyBool False!
/// [Id]'s event called once with MyInt: 0 and MyBool False!
/// [Id]'s event occurred with MyInt: 1 and MyBool True!
/// [Id]'s event occurred with MyInt: 2 and MyBool False!
/// [Id]'s event occurred with MyInt: 3 and MyBool True!
/// ...
///
///
///
/// Sender type
public class Event
{
private readonly List listeners = null!;
private readonly List onceListeners = null!;
///
/// Subscribes the callback to be invoked whenever the event is triggered.
///
/// The callback to be called when the event is triggered.
public void AddListener(EventHandler listener) => listeners.Add(listener);
///
/// Subscribes the callback to be invoked the next time the event is triggered. The callback will be called only once.
///
/// The callback to be called the next time the event is triggered.
public void AddOneTimeListener(EventHandler listener) => onceListeners.Add(listener);
///
/// Unsubscribes the callback that was previously registered by .
///
/// The callback that was previously registered by
public void RemoveListener(EventHandler listener) => listeners.Remove(listener);
///
/// Unsubscribes the callback that was previously registered by .
///
/// The callback that was previously registered by
public void RemoveOneTimeListener(EventHandler listener) => onceListeners.Remove(listener);
///
/// Unsubscribes all listeners that was previously registered by either or .
///
public void Clear() { listeners.Clear(); onceListeners.Clear(); }
///
/// Triggers the event.
///
/// The caller that's triggering this event.
/// The arguments provided for this event.
public void Invoke(TSender sender, TArguments args)
{
for (int i = listeners.Count - 1; i >= 0; i--)
try { listeners[i].Invoke(sender, args); }
catch (Exception exception)
{
string methodCallRepresentation = $"{listeners[i].Method.DeclaringType?.FullName}.{listeners[i].Method.Name}({string.Join(", ", sender, args)})";
Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
}
for (int i = onceListeners.Count - 1; i >= 0; i--)
{
try { onceListeners[i].Invoke(sender, args); }
catch (Exception exception)
{
string methodCallRepresentation = $"{onceListeners[i].Method.DeclaringType?.FullName}.{onceListeners[i].Method.Name}({string.Join(", ", sender, args)})";
Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
}
onceListeners.RemoveAt(i);
}
}
public Event(int initialListenerCount = 4, int initialOnceListenerCount = 2)
{
listeners = new(initialListenerCount);
onceListeners = new(initialOnceListenerCount);
}
public Event()
{
listeners = new(4);
onceListeners = new(2);
}
public delegate void EventHandler(TSender sender, TArguments args);
}