mirror of
https://github.com/All-Of-Us-Mods/MiraAPI.git
synced 2026-10-19 15:51:48 +00:00
Merge pull request #15 from All-Of-Us-Mods/events-system
initial event draft
This commit is contained in:
31 files changed
+820
-33
No files matched your search
@@ -0,0 +1,42 @@
|
||||
using MiraAPI.Events;
|
||||
using MiraAPI.Events.Mira;
|
||||
using MiraAPI.Events.Vanilla;
|
||||
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);
|
||||
MiraEventManager.RegisterEventHandler<MiraButtonCancelledEvent<FreezeButton>>(FreezeButtonCancelledHandler);
|
||||
MiraEventManager.RegisterEventHandler<UpdateSystemEvent>(UpdateSystemEventHandler);
|
||||
}
|
||||
|
||||
public static void UpdateSystemEventHandler(UpdateSystemEvent @event)
|
||||
{
|
||||
Logger<ExamplePlugin>.Error(@event.SystemType.ToString());
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
// Example event handler
|
||||
public static void FreezeButtonCancelledHandler(MiraButtonCancelledEvent<FreezeButton> @event)
|
||||
{
|
||||
Logger<ExamplePlugin>.Warning("Freeze button cancelled!");
|
||||
@event.Button.OverrideName("Freeze Canceled");
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,14 @@
|
||||
using BepInEx.Configuration;
|
||||
using BepInEx.Unity.IL2CPP;
|
||||
using HarmonyLib;
|
||||
using MiraAPI.Events;
|
||||
using MiraAPI.Events.Mira;
|
||||
using MiraAPI.Example.Buttons.Freezer;
|
||||
using MiraAPI.PluginLoading;
|
||||
using Reactor;
|
||||
using Reactor.Networking;
|
||||
using Reactor.Networking.Attributes;
|
||||
using Reactor.Utilities;
|
||||
|
||||
namespace MiraAPI.Example;
|
||||
|
||||
@@ -21,6 +25,7 @@ public partial class ExamplePlugin : BasePlugin, IMiraPlugin
|
||||
public ConfigFile GetConfigFile() => Config;
|
||||
public override void Load()
|
||||
{
|
||||
ExampleEventHandlers.Initialize();
|
||||
Harmony.PatchAll();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using MiraAPI.Hud;
|
||||
|
||||
namespace MiraAPI.Events.Mira;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when a Mira Button click is cancelled. Do not use for vanilla buttons.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The Mira Button type.</typeparam>
|
||||
public sealed class MiraButtonCancelledEvent<T> : MiraEvent where T : CustomActionButton
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets Mira Button whose click was cancelled.
|
||||
/// </summary>
|
||||
public T Button { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MiraButtonCancelledEvent{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="button">The Mira Button whose click was cancelled.</param>
|
||||
public MiraButtonCancelledEvent(T button)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using MiraAPI.Hud;
|
||||
|
||||
namespace MiraAPI.Events.Mira;
|
||||
|
||||
/// <summary>
|
||||
/// Button click event for Mira Buttons only. Do not use for vanilla buttons.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The Mira Button type.</typeparam>
|
||||
public sealed class MiraButtonClickEvent<T> : MiraCancelableEvent where T : CustomActionButton
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets Mira Button that was clicked.
|
||||
/// </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>
|
||||
/// <param name="genericClickEvent">The generic click event invoked before button-specific events.</param>
|
||||
public MiraButtonClickEvent(T button, MiraButtonClickEvent genericClickEvent)
|
||||
{
|
||||
GenericClickEvent = genericClickEvent;
|
||||
Button = button;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Button click event for Mira Buttons only. Do not use for vanilla buttons.
|
||||
/// </summary>
|
||||
public sealed class MiraButtonClickEvent : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets Mira Button that was clicked.
|
||||
/// </summary>
|
||||
public CustomActionButton Button { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MiraButtonClickEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="button">The Mira Button that was clicked.</param>
|
||||
public MiraButtonClickEvent(CustomActionButton button)
|
||||
{
|
||||
Button = button;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace MiraAPI.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Abstract class for Mira Events that can be cancelled.
|
||||
/// </summary>
|
||||
public abstract class MiraCancelableEvent : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the event is cancelled.
|
||||
/// </summary>
|
||||
public bool IsCancelled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cancels the event.
|
||||
/// </summary>
|
||||
public void Cancel()
|
||||
{
|
||||
IsCancelled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uncancels the event.
|
||||
/// </summary>
|
||||
public void UnCancel()
|
||||
{
|
||||
IsCancelled = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace MiraAPI.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Abstract class for Mira Events.
|
||||
/// </summary>
|
||||
public abstract class MiraEvent;
|
||||
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BepInEx.Unity.IL2CPP;
|
||||
using Reactor.Utilities;
|
||||
|
||||
namespace MiraAPI.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Mira Event manager.
|
||||
/// </summary>
|
||||
public static class MiraEventManager
|
||||
{
|
||||
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>
|
||||
/// <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
|
||||
{
|
||||
EventWrappers.TryGetValue(typeof(T), out var handlers);
|
||||
if (handlers == null)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Warning("No handlers for event " + typeof(T).Name);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var handler in handlers)
|
||||
{
|
||||
((Action<T>)handler.EventHandler).Invoke(eventInstance);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoke an event and use a specific type to find the handlers.
|
||||
/// </summary>
|
||||
/// <param name="eventInstance">The event instance.</param>
|
||||
/// <param name="type">The type to use for handler lookup.</param>
|
||||
/// <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)
|
||||
{
|
||||
EventWrappers.TryGetValue(type, out var handlers);
|
||||
if (handlers == null)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Warning("No handlers for event " + type.Name);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var handler in handlers)
|
||||
{
|
||||
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, int priority = 0) where T : MiraEvent
|
||||
{
|
||||
if (!EventWrappers.ContainsKey(typeof(T)))
|
||||
{
|
||||
EventWrappers.Add(typeof(T), []);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace MiraAPI.Events.Vanilla;
|
||||
|
||||
/// <summary>
|
||||
/// Button click event for <see cref="AdminButton"/> from Vanilla Among Us.
|
||||
/// </summary>
|
||||
public class AdminButtonClickEvent : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the instance of <see cref="AdminButton"/> that was clicked.
|
||||
/// </summary>
|
||||
public AdminButton Button { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AdminButtonClickEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="button">The AdminButton.</param>
|
||||
public AdminButtonClickEvent(AdminButton button)
|
||||
{
|
||||
Button = button;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace MiraAPI.Events.Vanilla;
|
||||
|
||||
/// <summary>
|
||||
/// Event that is invoked after a player is murdered. Only called after a successful murder. This event is not cancelable.
|
||||
/// </summary>
|
||||
public class AfterMurderEvent : MiraEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the player that killed the target.
|
||||
/// </summary>
|
||||
public PlayerControl Source { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the player that was killed.
|
||||
/// </summary>
|
||||
public PlayerControl Target { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AfterMurderEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="source">The killer.</param>
|
||||
/// <param name="target">The killed player.</param>
|
||||
public AfterMurderEvent(PlayerControl source, PlayerControl target)
|
||||
{
|
||||
Source = source;
|
||||
Target = target;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace MiraAPI.Events.Vanilla;
|
||||
|
||||
/// <summary>
|
||||
/// Event that is invoked before a player is murdered. This event is cancelable.
|
||||
/// </summary>
|
||||
public sealed class BeforeMurderEvent : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the player that is killing the target.
|
||||
/// </summary>
|
||||
public PlayerControl Source { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the player that is being killed.
|
||||
/// </summary>
|
||||
public PlayerControl Target { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BeforeMurderEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="source">The player that is killing the target.</param>
|
||||
/// <param name="target">The player that is being killed.</param>
|
||||
public BeforeMurderEvent(PlayerControl source, PlayerControl target)
|
||||
{
|
||||
Source = source;
|
||||
Target = target;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace MiraAPI.Events.Vanilla;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when a player closes the doors in a room.
|
||||
/// </summary>
|
||||
public class CloseDoorsEvent : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the room that the doors were closed in.
|
||||
/// </summary>
|
||||
public SystemTypes Room { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CloseDoorsEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="room">The room that was closed.</param>
|
||||
public CloseDoorsEvent(SystemTypes room)
|
||||
{
|
||||
Room = room;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace MiraAPI.Events.Vanilla;
|
||||
|
||||
/// <summary>
|
||||
/// Event that is invoked when a player enters a vent. This event is cancelable.
|
||||
/// </summary>
|
||||
public class EnterVentEvent : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the player that is entering the vent.
|
||||
/// </summary>
|
||||
public PlayerControl Player { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the vent that the player is entering.
|
||||
/// </summary>
|
||||
public Vent? Vent { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EnterVentEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="player">The player that is entering the vent.</param>
|
||||
/// <param name="vent">The vent being entered.</param>
|
||||
public EnterVentEvent(PlayerControl player, Vent? vent)
|
||||
{
|
||||
Player = player;
|
||||
Vent = vent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace MiraAPI.Events.Vanilla;
|
||||
|
||||
/// <summary>
|
||||
/// Event that is invoked when a player exits a vent. This event is cancelable.
|
||||
/// </summary>
|
||||
public class ExitVentEvent : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the player that is exiting the vent.
|
||||
/// </summary>
|
||||
public PlayerControl Player { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the vent that the player is exiting.
|
||||
/// </summary>
|
||||
public Vent? Vent { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExitVentEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="player">The player who is exiting the vent.</param>
|
||||
/// <param name="vent">The vent being exited from.</param>
|
||||
public ExitVentEvent(PlayerControl player, Vent? vent)
|
||||
{
|
||||
Player = player;
|
||||
Vent = vent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace MiraAPI.Events.Vanilla;
|
||||
|
||||
/// <summary>
|
||||
/// Button click event for <see cref="SabotageButton"/> from Vanilla Among Us.
|
||||
/// </summary>
|
||||
public class SabotageButtonClickEvent : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the instance of <see cref="SabotageButton"/> that was clicked.
|
||||
/// </summary>
|
||||
public SabotageButton Button { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SabotageButtonClickEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="button">The SabotageButton.</param>
|
||||
public SabotageButtonClickEvent(SabotageButton button)
|
||||
{
|
||||
Button = button;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
namespace MiraAPI.Events.Vanilla;
|
||||
|
||||
/// <summary>
|
||||
/// The event that is invoked when a meeting is called
|
||||
/// </summary>
|
||||
public class StartMeetingEvent : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the player that is calling the meeting.
|
||||
/// </summary>
|
||||
public PlayerControl Reporter { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the player that is being reported. Will be null for emergency meeting.
|
||||
/// </summary>
|
||||
public NetworkedPlayerInfo? Target { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the body that is being reported. Will be null for emergency meeting.
|
||||
/// </summary>
|
||||
public DeadBody? Body { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StartMeetingEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="reporter">The player who reported the body.</param>
|
||||
/// <param name="target">The player being reported.</param>
|
||||
/// <param name="body">The body being reported.</param>
|
||||
public StartMeetingEvent(PlayerControl reporter, NetworkedPlayerInfo? target, DeadBody? body)
|
||||
{
|
||||
Reporter = reporter;
|
||||
Target = target;
|
||||
Body = body;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
namespace MiraAPI.Events.Vanilla;
|
||||
|
||||
/// <summary>
|
||||
/// Cancelable event that is invoked before a system is updated. Usually used for sabotage events.
|
||||
/// </summary>
|
||||
public class UpdateSystemEvent : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the type of system that will be updated.
|
||||
/// </summary>
|
||||
public SystemTypes SystemType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the player that is updating the system.
|
||||
/// </summary>
|
||||
public PlayerControl Player { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte amount the system is being updated by.
|
||||
/// </summary>
|
||||
public byte Amount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UpdateSystemEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="systemType">The SystemType being updated.</param>
|
||||
/// <param name="amount">Amount to update System to.</param>
|
||||
public UpdateSystemEvent(SystemTypes systemType, PlayerControl player, byte amount)
|
||||
{
|
||||
SystemType = systemType;
|
||||
Player = player;
|
||||
Amount = amount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace MiraAPI.Events.Vanilla;
|
||||
|
||||
/// <summary>
|
||||
/// Button click event for <see cref="UseButton"/> from Vanilla Among Us.
|
||||
/// </summary>
|
||||
public class UseButtonClickEvent : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the instance of <see cref="UseButton"/> that was clicked.
|
||||
/// </summary>
|
||||
public UseButton Button { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UseButtonClickEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="button">The UseButton.</param>
|
||||
public UseButtonClickEvent(UseButton button)
|
||||
{
|
||||
Button = button;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace MiraAPI.Events.Vanilla;
|
||||
|
||||
/// <summary>
|
||||
/// Button click event for <see cref="VentButton"/> from Vanilla Among Us.
|
||||
/// </summary>
|
||||
public class VentButtonClickEvent : MiraCancelableEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the instance of <see cref="VentButton"/> that was clicked.
|
||||
/// </summary>
|
||||
public VentButton Button { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="VentButtonClickEvent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="button">The VentButton.</param>
|
||||
public VentButtonClickEvent(VentButton button)
|
||||
{
|
||||
Button = button;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using System;
|
||||
using MiraAPI.Events;
|
||||
using MiraAPI.Events.Mira;
|
||||
using MiraAPI.Utilities.Assets;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.UI;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace MiraAPI.Hud;
|
||||
|
||||
@@ -95,7 +99,42 @@ public abstract class CustomActionButton
|
||||
|
||||
var pb = Button.GetComponent<PassiveButton>();
|
||||
pb.OnClick = new Button.ButtonClickedEvent();
|
||||
pb.OnClick.AddListener((UnityAction)ClickHandler);
|
||||
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)!;
|
||||
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
|
||||
{
|
||||
if (!genericEvent.IsCancelled)
|
||||
{
|
||||
ClickHandler();
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using MiraAPI.Events.Mira;
|
||||
using MiraAPI.PluginLoading;
|
||||
using Reactor.Utilities;
|
||||
|
||||
@@ -9,6 +10,8 @@ namespace MiraAPI.Hud;
|
||||
internal static class CustomButtonManager
|
||||
{
|
||||
internal static readonly List<CustomActionButton> CustomButtons = [];
|
||||
internal static readonly Dictionary<Type, Type> ButtonEventTypes = [];
|
||||
internal static readonly Dictionary<Type, Type> ButtonCancelledEventTypes = [];
|
||||
|
||||
internal static void RegisterButton(Type buttonType, MiraPluginInfo pluginInfo)
|
||||
{
|
||||
@@ -29,5 +32,8 @@ internal static class CustomButtonManager
|
||||
typeof(CustomButtonSingleton<>).MakeGenericType(buttonType)
|
||||
.GetField("_instance", BindingFlags.Static | BindingFlags.NonPublic)!
|
||||
.SetValue(null, button);
|
||||
|
||||
ButtonEventTypes.Add(buttonType, typeof(MiraButtonClickEvent<>).MakeGenericType(buttonType));
|
||||
ButtonCancelledEventTypes.Add(buttonType, typeof(MiraButtonCancelledEvent<>).MakeGenericType(buttonType));
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,9 @@ using System.Linq;
|
||||
using AmongUs.GameOptions;
|
||||
using Assets.CoreScripts;
|
||||
using BepInEx.Unity.IL2CPP.Utils;
|
||||
using Discord;
|
||||
using MiraAPI.Events;
|
||||
using MiraAPI.Events.Vanilla;
|
||||
using Reactor.Networking.Attributes;
|
||||
using Reactor.Networking.Rpc;
|
||||
using Reactor.Utilities;
|
||||
@@ -39,6 +42,15 @@ public static class CustomMurderRpc
|
||||
bool playKillSound = true)
|
||||
{
|
||||
var murderResultFlags = didSucceed ? MurderResultFlags.Succeeded : MurderResultFlags.FailedError;
|
||||
|
||||
var beforeMurderEvent = new BeforeMurderEvent(source, target);
|
||||
MiraEventManager.InvokeEvent(beforeMurderEvent);
|
||||
|
||||
if (beforeMurderEvent.IsCancelled)
|
||||
{
|
||||
murderResultFlags = MurderResultFlags.FailedError;
|
||||
}
|
||||
|
||||
var murderResultFlags2 = MurderResultFlags.DecisionByHost | murderResultFlags;
|
||||
|
||||
source.CustomMurder(
|
||||
@@ -268,5 +280,8 @@ public static class CustomMurderRpc
|
||||
|
||||
PlayerControl.LocalPlayer.isKilling = false;
|
||||
source.isKilling = false;
|
||||
|
||||
var afterMurderEvent = new AfterMurderEvent(source, target);
|
||||
MiraEventManager.InvokeEvent(afterMurderEvent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using HarmonyLib;
|
||||
using MiraAPI.Events;
|
||||
using MiraAPI.Events.Vanilla;
|
||||
using Reactor.Utilities;
|
||||
|
||||
namespace MiraAPI.Patches.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Patch for button related MiraEvents.
|
||||
/// </summary>
|
||||
[HarmonyPatch]
|
||||
public static class HudButtonEventPatches
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(AdminButton), nameof(AdminButton.DoClick))]
|
||||
public static bool AdminButtonDoClickPrefix(AdminButton __instance)
|
||||
{
|
||||
var @event = new AdminButtonClickEvent(__instance);
|
||||
MiraEventManager.InvokeEvent(@event);
|
||||
return !@event.IsCancelled;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(SabotageButton), nameof(SabotageButton.DoClick))]
|
||||
public static bool SabotageButtonDoClickPrefix(SabotageButton __instance)
|
||||
{
|
||||
var @event = new SabotageButtonClickEvent(__instance);
|
||||
MiraEventManager.InvokeEvent(@event);
|
||||
return !@event.IsCancelled;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(UseButton), nameof(UseButton.DoClick))]
|
||||
public static bool UseButtonDoClickPrefix(UseButton __instance)
|
||||
{
|
||||
var @event = new UseButtonClickEvent(__instance);
|
||||
MiraEventManager.InvokeEvent(@event);
|
||||
return !@event.IsCancelled;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(VentButton), nameof(VentButton.DoClick))]
|
||||
public static bool VentButtonDoClickPrefix(VentButton __instance)
|
||||
{
|
||||
var @event = new VentButtonClickEvent(__instance);
|
||||
MiraEventManager.InvokeEvent(@event);
|
||||
return !@event.IsCancelled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using HarmonyLib;
|
||||
using MiraAPI.Events;
|
||||
using MiraAPI.Events.Vanilla;
|
||||
|
||||
namespace MiraAPI.Patches.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Used for patching sabotage/system related MiraEvents.
|
||||
/// </summary>
|
||||
[HarmonyPatch]
|
||||
public static class SabotageEventPatches
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.RpcUpdateSystem), typeof(SystemTypes), typeof(byte))]
|
||||
public static bool ShipStatusUpdateSystemPrefix(ShipStatus __instance, SystemTypes systemType, byte amount)
|
||||
{
|
||||
var @event = new UpdateSystemEvent(systemType, PlayerControl.LocalPlayer, amount);
|
||||
MiraEventManager.InvokeEvent(@event);
|
||||
return !@event.IsCancelled;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.RpcCloseDoorsOfType))]
|
||||
public static bool ShipStatusCloseDoorsOfTypePrefix(ShipStatus __instance, SystemTypes type)
|
||||
{
|
||||
var @event = new CloseDoorsEvent(type);
|
||||
MiraEventManager.InvokeEvent(@event);
|
||||
return !@event.IsCancelled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using HarmonyLib;
|
||||
using MiraAPI.Events;
|
||||
using MiraAPI.Events.Vanilla;
|
||||
using MiraAPI.Utilities;
|
||||
|
||||
namespace MiraAPI.Patches.Events;
|
||||
|
||||
[HarmonyPatch]
|
||||
public static class StartMeetingEventPatch
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.CmdReportDeadBody))]
|
||||
public static bool PlayerControlCmdReportDeadBodyPrefix(PlayerControl __instance, NetworkedPlayerInfo? target)
|
||||
{
|
||||
var body = target != null ? Helpers.GetBodyById(target.PlayerId) : null;
|
||||
|
||||
var @event = new StartMeetingEvent(__instance, target, body);
|
||||
MiraEventManager.InvokeEvent(@event);
|
||||
return !@event.IsCancelled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using System.Linq;
|
||||
using BepInEx.Unity.IL2CPP.Utils.Collections;
|
||||
using HarmonyLib;
|
||||
using MiraAPI.Events;
|
||||
using MiraAPI.Events.Vanilla;
|
||||
using MiraAPI.Utilities;
|
||||
using Reactor.Utilities;
|
||||
|
||||
namespace MiraAPI.Patches.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Patches to invoke vent related MiraEvents.
|
||||
/// </summary>
|
||||
[HarmonyPatch]
|
||||
public static class VentEventPatches
|
||||
{
|
||||
// necessary because Vent.Use is inlined in il2cpp.
|
||||
private static bool _showButtons;
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(VentButton), nameof(VentButton.DoClick))]
|
||||
public static void VentUsePostfix(VentButton __instance)
|
||||
{
|
||||
__instance.currentTarget?.SetButtons(_showButtons);
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(PlayerPhysics), nameof(PlayerPhysics.RpcEnterVent))]
|
||||
public static bool PlayerPhysicsRpcEnterVentPrefix(PlayerPhysics __instance, int id)
|
||||
{
|
||||
var pc = __instance.myPlayer;
|
||||
var vent = ShipStatus.Instance.AllVents.FirstOrDefault(v => v.Id == id);
|
||||
|
||||
var @event = new EnterVentEvent(pc, vent);
|
||||
MiraEventManager.InvokeEvent(@event);
|
||||
|
||||
if (pc.AmOwner)
|
||||
{
|
||||
_showButtons = !@event.IsCancelled;
|
||||
}
|
||||
return !@event.IsCancelled;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(PlayerPhysics), nameof(PlayerPhysics.RpcExitVent))]
|
||||
public static bool PlayerPhysicsRpcExitVentPrefix(PlayerPhysics __instance, int id)
|
||||
{
|
||||
var pc = __instance.myPlayer;
|
||||
var vent = ShipStatus.Instance.AllVents.First(v => v.Id == id);
|
||||
|
||||
var @event = new ExitVentEvent(pc, vent);
|
||||
MiraEventManager.InvokeEvent(@event);
|
||||
|
||||
if (pc.AmOwner)
|
||||
{
|
||||
_showButtons = @event.IsCancelled;
|
||||
}
|
||||
return !@event.IsCancelled;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -15,6 +15,8 @@ public struct CustomRoleConfiguration
|
||||
/// <param name="role">The role in which you are configuring.</param>
|
||||
public CustomRoleConfiguration(ICustomRole role)
|
||||
{
|
||||
var roleBehaviour = role as RoleBehaviour;
|
||||
|
||||
MaxRoleCount = 15;
|
||||
DefaultRoleCount = 0;
|
||||
DefaultChance = 0;
|
||||
@@ -29,13 +31,12 @@ public struct CustomRoleConfiguration
|
||||
};
|
||||
RoleHintType = RoleHintType.RoleTab;
|
||||
GhostRole = role.Team is ModdedRoleTeams.Impostor ? RoleTypes.ImpostorGhost : RoleTypes.CrewmateGhost;
|
||||
CanGetKilled = !IsGhostRole && role.Team is not ModdedRoleTeams.Impostor;
|
||||
CanGetKilled = roleBehaviour?.IsDead == false && role.Team is not ModdedRoleTeams.Impostor;
|
||||
UseVanillaKillButton = role.Team is ModdedRoleTeams.Impostor;
|
||||
CanUseVent = role.Team is ModdedRoleTeams.Impostor;
|
||||
CanUseSabotage = role.Team is ModdedRoleTeams.Impostor;
|
||||
TasksCountForProgress = role.Team is ModdedRoleTeams.Crewmate;
|
||||
IsGhostRole = false;
|
||||
HideSettings = IsGhostRole;
|
||||
HideSettings = roleBehaviour?.IsDead == true;
|
||||
CanModifyChance = true;
|
||||
}
|
||||
|
||||
@@ -99,11 +100,6 @@ public struct CustomRoleConfiguration
|
||||
/// </summary>
|
||||
public bool TasksCountForProgress;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the role is a Ghost.
|
||||
/// </summary>
|
||||
public bool IsGhostRole;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the role should show up in the Role Options menu.
|
||||
/// </summary>
|
||||
|
||||
@@ -93,7 +93,7 @@ public static class CustomRoleManager
|
||||
roleBehaviour.MaxCount = customRole.Configuration.MaxRoleCount;
|
||||
roleBehaviour.RoleScreenshot = customRole.Configuration.OptionsScreenshot.LoadAsset();
|
||||
|
||||
if (customRole.Configuration.IsGhostRole)
|
||||
if (roleBehaviour.IsDead)
|
||||
{
|
||||
RoleManager.GhostRoles.Add(roleBehaviour.Role);
|
||||
}
|
||||
|
||||
@@ -13,26 +13,6 @@ namespace MiraAPI.Utilities.Assets;
|
||||
/// </summary>
|
||||
public static class SpriteTools
|
||||
{
|
||||
private delegate bool DLoadImage(IntPtr tex, IntPtr data, bool markNonReadable);
|
||||
|
||||
private static DLoadImage? _iCallLoadImage;
|
||||
|
||||
/// <summary>
|
||||
/// Load an image into a texture.
|
||||
/// </summary>
|
||||
/// <param name="tex">The texture.</param>
|
||||
/// <param name="data">Byte data of image.</param>
|
||||
/// <param name="markNonReadable">Mark nonreadable.</param>
|
||||
/// <returns>True if succeeded.</returns>
|
||||
public static bool LoadImage(Texture2D tex, byte[] data, bool markNonReadable)
|
||||
{
|
||||
_iCallLoadImage ??= IL2CPP.ResolveICall<DLoadImage>("UnityEngine.ImageConversion::LoadImage");
|
||||
|
||||
var il2CPPArray = (Il2CppStructArray<byte>)data;
|
||||
|
||||
return _iCallLoadImage.Invoke(tex.Pointer, il2CPPArray.Pointer, markNonReadable);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load a sprite from a resource path.
|
||||
/// </summary>
|
||||
@@ -46,7 +26,7 @@ public static class SpriteTools
|
||||
if (myStream != null)
|
||||
{
|
||||
var buttonTexture = myStream.ReadFully();
|
||||
LoadImage(tex, buttonTexture, false);
|
||||
tex.LoadImage(buttonTexture, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using MiraAPI.Roles;
|
||||
using System.Collections;
|
||||
using MiraAPI.Roles;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
@@ -14,6 +15,15 @@ namespace MiraAPI.Utilities;
|
||||
/// </summary>
|
||||
public static class Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns an empty coroutine.
|
||||
/// </summary>
|
||||
/// <returns>Empty coroutine.</returns>
|
||||
public static IEnumerator EmptyCoroutine()
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a ContactFilter2D from a layer mask.
|
||||
/// </summary>
|
||||
|
||||
Reference in new issue
Block a user