priority system

This commit is contained in:
XtraCube committed 2024-11-26 16:27:36 -05:00
1 parent 8884996c06
commit 707b5629b4
8 files changed
+148 -19

No files matched your search

+27
View File
@@ -0,0 +1,27 @@
using MiraAPI.Events;
using MiraAPI.Events.Mira;
using MiraAPI.Example.Buttons.Freezer;
using Reactor.Utilities;
namespace MiraAPI.Example;
public static class ExampleEventHandlers
{
public static void Initialize()
{
// Register event handlers here
MiraEventManager.RegisterEventHandler<MiraButtonClickEvent<FreezeButton>>(FreezeButtonClickHandler, 1);
}
// Example event handler
public static void FreezeButtonClickHandler(MiraButtonClickEvent<FreezeButton> @event)
{
Logger<ExamplePlugin>.Warning("Freeze button clicked!");
if (PlayerControl.LocalPlayer.Data.PlayerName == "stupid")
{
@event.Cancel();
@event.Button.SetTimer(15f);
}
}
}
+7 -3
View File
@@ -25,11 +25,15 @@ public partial class ExamplePlugin : BasePlugin, IMiraPlugin
public ConfigFile GetConfigFile() => Config;
public override void Load()
{
MiraEventManager.RegisterEventHandler<MiraButtonClickEvent<FreezeButton>>(e=>
MiraEventManager.RegisterEventHandler<MiraButtonClickEvent<FreezeButton>>(e=>
{
Logger<ExamplePlugin>.Warning("Freeze button clicked!");
e.Cancel();
e.Button.SetTimer(15f);
if (PlayerControl.LocalPlayer.Data.PlayerName == "stupid")
{
e.Cancel();
e.Button.SetTimer(15f);
}
});
MiraEventManager.RegisterEventHandler<MiraButtonCancelledEvent<FreezeButton>>(e=>
@@ -22,3 +22,23 @@ public sealed class MiraButtonCancelledEvent<T> : MiraEvent where T : CustomActi
Button = button;
}
}
/// <summary>
/// Invoked when a Mira Button click is cancelled. Do not use for vanilla buttons.
/// </summary>
public sealed class MiraButtonCancelledEvent : MiraEvent
{
/// <summary>
/// Gets Mira Button whose click was cancelled.
/// </summary>
public CustomActionButton Button { get; }
/// <summary>
/// Initializes a new instance of the <see cref="MiraButtonCancelledEvent"/> class.
/// </summary>
/// <param name="button">The Mira Button whose click was cancelled.</param>
public MiraButtonCancelledEvent(CustomActionButton button)
{
Button = button;
}
}
+8 -1
View File
@@ -13,12 +13,19 @@ public sealed class MiraButtonClickEvent<T> : MiraCancelableEvent where T : Cust
/// </summary>
public T Button { get; }
/// <summary>
/// Gets the generic click event that is invoked before this button-specific event.
/// </summary>
public MiraButtonClickEvent GenericClickEvent { get; }
/// <summary>
/// Initializes a new instance of the <see cref="MiraButtonClickEvent{T}"/> class.
/// </summary>
/// <param name="button">The Mira Button that was clicked.</param>
public MiraButtonClickEvent(T button)
/// <param name="genericClickEvent">The generic click event invoked before button-specific events.</param>
public MiraButtonClickEvent(T button, MiraButtonClickEvent genericClickEvent)
{
GenericClickEvent = genericClickEvent;
Button = button;
}
}
+32 -13
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using BepInEx.Unity.IL2CPP;
using Reactor.Utilities;
namespace MiraAPI.Events;
@@ -9,26 +10,29 @@ namespace MiraAPI.Events;
/// </summary>
public static class MiraEventManager
{
private static readonly Dictionary<Type, List<Delegate>> EventHandlers = [];
private static readonly Dictionary<Type, List<MiraEventWrapper>> EventWrappers = [];
/// <summary>
/// Invoke an event.
/// </summary>
/// <param name="eventInstance">The event instance.</param>
/// <typeparam name="T">Type of Event.</typeparam>
public static void InvokeEvent<T>(T eventInstance) where T : MiraEvent
/// <returns>If there was an event handler invoked for this event, return true. Otherwise, return false.</returns>
public static bool InvokeEvent<T>(T eventInstance) where T : MiraEvent
{
EventHandlers.TryGetValue(typeof(T), out var handlers);
EventWrappers.TryGetValue(typeof(T), out var handlers);
if (handlers == null)
{
Logger<MiraApiPlugin>.Warning("No handlers for event " + typeof(T).Name);
return;
return false;
}
foreach (var handler in handlers)
{
((Action<T>)handler).Invoke(eventInstance);
((Action<T>)handler.EventHandler).Invoke(eventInstance);
}
return true;
}
/// <summary>
@@ -36,33 +40,48 @@ public static class MiraEventManager
/// </summary>
/// <param name="eventInstance">The event instance.</param>
/// <param name="type">The type to use for handler lookup.</param>
public static void InvokeEvent(MiraEvent eventInstance, Type type)
/// <returns>If there was an event handler invoked for this event, return true. Otherwise, return false.</returns>
public static bool InvokeEvent(MiraEvent eventInstance, Type type)
{
EventHandlers.TryGetValue(type, out var handlers);
EventWrappers.TryGetValue(type, out var handlers);
if (handlers == null)
{
Logger<MiraApiPlugin>.Warning("No handlers for event " + type.Name);
return;
return false;
}
foreach (var handler in handlers)
{
handler.DynamicInvoke(eventInstance);
handler.EventHandler.DynamicInvoke(eventInstance);
}
return true;
}
/// <summary>
/// Register an event.
/// </summary>
/// <param name="handler">The callback method/handler for the event.</param>
/// <param name="priority">The priority of the event handler. Higher values are called first.</param>
/// <typeparam name="T">Type of event.</typeparam>
public static void RegisterEventHandler<T>(Action<T> handler) where T : MiraEvent
public static void RegisterEventHandler<T>(Action<T> handler, int priority = 0) where T : MiraEvent
{
if (!EventHandlers.ContainsKey(typeof(T)))
if (!EventWrappers.ContainsKey(typeof(T)))
{
EventHandlers.Add(typeof(T), []);
EventWrappers.Add(typeof(T), []);
}
EventHandlers[typeof(T)].Add(handler);
var handlers = EventWrappers[typeof(T)];
handlers.Add(new MiraEventWrapper(handler, priority));
Logger<MiraApiPlugin>.Info("Registered event handler for " + typeof(T).Name);
}
internal static void SortAllHandlers()
{
foreach (var handlers in EventWrappers.Values)
{
handlers.Sort((a, b) => a.Priority.CompareTo(b.Priority));
}
}
}
+30
View File
@@ -0,0 +1,30 @@
using System;
namespace MiraAPI.Events;
/// <summary>
/// Wrapper for event handlers.
/// </summary>
public class MiraEventWrapper
{
/// <summary>
/// Gets the event handler delegate.
/// </summary>
public Delegate EventHandler { get; }
/// <summary>
/// Gets the priority of the handler. Higher values are called first.
/// </summary>
public int Priority { get; }
/// <summary>
/// Initializes a new instance of the <see cref="MiraEventWrapper"/> class.
/// </summary>
/// <param name="eventHandler">The action for the event handler.</param>
/// <param name="priority">The priority of the handler.</param>
public MiraEventWrapper(Delegate eventHandler, int priority)
{
EventHandler = eventHandler;
Priority = priority;
}
}
+22 -2
View File
@@ -101,18 +101,38 @@ public abstract class CustomActionButton
pb.OnClick = new Button.ButtonClickedEvent();
pb.OnClick.AddListener((UnityAction)(() =>
{
// Invoke the generic button click event.
var genericEvent = new MiraButtonClickEvent(this);
MiraEventManager.InvokeEvent(genericEvent);
if (genericEvent.IsCancelled)
{
MiraEventManager.InvokeEvent(new MiraButtonCancelledEvent(this));
}
// Invoke the button click event for specific button.
var eventType = CustomButtonManager.ButtonEventTypes[GetType()];
var @event = (MiraCancelableEvent)Activator.CreateInstance(eventType, this)!;
MiraEventManager.InvokeEvent(@event, eventType);
var specificInvoked = MiraEventManager.InvokeEvent(@event, eventType);
if (@event.IsCancelled)
{
var cancelEventType = CustomButtonManager.ButtonCancelledEventTypes[GetType()];
var cancelEvent = (MiraEvent)Activator.CreateInstance(cancelEventType, this)!;
MiraEventManager.InvokeEvent(cancelEvent, cancelEventType);
}
if (specificInvoked)
{
if (!@event.IsCancelled)
{
ClickHandler();
}
}
else
{
ClickHandler();
if (!genericEvent.IsCancelled)
{
ClickHandler();
}
}
}));
}
@@ -4,6 +4,7 @@ using System.Linq;
using System.Reflection;
using BepInEx.Unity.IL2CPP;
using MiraAPI.Colors;
using MiraAPI.Events;
using MiraAPI.GameOptions;
using MiraAPI.GameOptions.Attributes;
using MiraAPI.Hud;
@@ -51,6 +52,7 @@ public sealed class MiraPluginManager
Logger<MiraApiPlugin>.Info($"Registering mod {pluginInfo.Metadata.GUID} with Mira API.");
};
IL2CPPChainloader.Instance.Finished += PaletteManager.RegisterAllColors;
IL2CPPChainloader.Instance.Finished += MiraEventManager.SortAllHandlers;
}
/// <summary>