From 9485099ab94510e66b6051a7cb6537d874a964f1 Mon Sep 17 00:00:00 2001
From: XtraCube <72575280+XtraCube@users.noreply.github.com>
Date: Sun, 2 Feb 2025 16:09:06 -0500
Subject: [PATCH 1/3] RPC add modifier with arguments
---
.../Buttons/Freezer/FreezeButton.cs | 1 +
MiraAPI.Example/Buttons/MeetingButton.cs | 2 +-
.../OptionTypes/ModdedEnumOption.cs | 1 -
MiraAPI/Modifiers/ModifierExtensions.cs | 139 ++++++++++++++++++
MiraAPI/Modifiers/ModifierFactory.cs | 83 +++++++++++
.../Patches/Modifiers/EndGameDidWinPatch.cs | 2 +-
MiraAPI/Patches/PlayerControlPatches.cs | 2 +-
MiraAPI/Patches/VentPatches.cs | 2 +-
MiraAPI/Utilities/Extensions.cs | 125 ----------------
9 files changed, 227 insertions(+), 130 deletions(-)
create mode 100644 MiraAPI/Modifiers/ModifierExtensions.cs
create mode 100644 MiraAPI/Modifiers/ModifierFactory.cs
diff --git a/MiraAPI.Example/Buttons/Freezer/FreezeButton.cs b/MiraAPI.Example/Buttons/Freezer/FreezeButton.cs
index 8db98c7..86feece 100644
--- a/MiraAPI.Example/Buttons/Freezer/FreezeButton.cs
+++ b/MiraAPI.Example/Buttons/Freezer/FreezeButton.cs
@@ -3,6 +3,7 @@
using MiraAPI.Example.Roles;
using MiraAPI.GameOptions;
using MiraAPI.Hud;
+using MiraAPI.Modifiers;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using UnityEngine;
diff --git a/MiraAPI.Example/Buttons/MeetingButton.cs b/MiraAPI.Example/Buttons/MeetingButton.cs
index 85b8ff1..742c7e0 100644
--- a/MiraAPI.Example/Buttons/MeetingButton.cs
+++ b/MiraAPI.Example/Buttons/MeetingButton.cs
@@ -1,6 +1,6 @@
using MiraAPI.Example.Modifiers;
using MiraAPI.Hud;
-using MiraAPI.Utilities;
+using MiraAPI.Modifiers;
using MiraAPI.Utilities.Assets;
using UnityEngine;
diff --git a/MiraAPI/GameOptions/OptionTypes/ModdedEnumOption.cs b/MiraAPI/GameOptions/OptionTypes/ModdedEnumOption.cs
index e917cdc..80bd497 100644
--- a/MiraAPI/GameOptions/OptionTypes/ModdedEnumOption.cs
+++ b/MiraAPI/GameOptions/OptionTypes/ModdedEnumOption.cs
@@ -1,5 +1,4 @@
using System;
-using System.Globalization;
using System.Linq;
using System.Text;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
diff --git a/MiraAPI/Modifiers/ModifierExtensions.cs b/MiraAPI/Modifiers/ModifierExtensions.cs
new file mode 100644
index 0000000..83dfd4c
--- /dev/null
+++ b/MiraAPI/Modifiers/ModifierExtensions.cs
@@ -0,0 +1,139 @@
+using System;
+using System.Collections.Generic;
+using MiraAPI.Networking;
+using Reactor.Networking.Attributes;
+using Reactor.Utilities;
+
+namespace MiraAPI.Modifiers;
+
+///
+/// Extension methods for modifiers.
+///
+public static class ModifierExtensions
+{
+ internal static Dictionary ModifierComponents { get; } = [];
+
+ ///
+ /// Gets the ModifierComponent for a player.
+ ///
+ /// The PlayerControl object.
+ /// A ModifierComponent if there is one, null otherwise.
+ public static ModifierComponent? GetModifierComponent(this PlayerControl player)
+ {
+ if (ModifierComponents.TryGetValue(player, out var component))
+ {
+ return component;
+ }
+
+ component = player.GetComponent();
+ if (component == null)
+ {
+ return null;
+ }
+
+ ModifierComponents[player] = component;
+ return component;
+ }
+
+ ///
+ /// Gets a modifier by its type, or null if the player doesn't have it.
+ ///
+ /// The PlayerControl object.
+ /// The Type of the Modifier.
+ /// The Modifier if it is found, null otherwise.
+ public static T? GetModifier(this PlayerControl? player) where T : BaseModifier
+ {
+ return player?.GetModifierComponent()?.ActiveModifiers.Find(x => x is T) as T;
+ }
+
+ ///
+ /// Checks if a player has a modifier.
+ ///
+ /// The PlayerControl object.
+ /// The Type of the Modifier.
+ /// True if the Modifier is present, false otherwise.
+ public static bool HasModifier(this PlayerControl? player) where T : BaseModifier
+ {
+ return player?.GetModifierComponent() != null &&
+ player.GetModifierComponent()!.HasModifier();
+ }
+
+ ///
+ /// Checks if a player has a modifier by its ID.
+ ///
+ /// The PlayerControl object.
+ /// The Modifier ID.
+ /// True if the Modifier is present, false otherwise.
+ public static bool HasModifier(this PlayerControl? player, uint id)
+ {
+ return player?.GetModifierComponent() != null &&
+ player.GetModifierComponent()!.HasModifier(id);
+ }
+
+ ///
+ /// Remote Procedure Call to remove a modifier from a player.
+ ///
+ /// The player to remove the modifier from.
+ /// The ID of the modifier.
+ [MethodRpc((uint)MiraRpc.RemoveModifier)]
+ public static void RpcRemoveModifier(this PlayerControl target, uint modifierId)
+ {
+ target.GetModifierComponent()?.RemoveModifier(modifierId);
+ }
+
+ ///
+ /// Remote Procedure Call to remove a modifier from a player.
+ ///
+ /// The player to remove the modifier from.
+ /// The Type of the Modifier.
+ public static void RpcRemoveModifier(this PlayerControl player) where T : BaseModifier
+ {
+ var id = ModifierManager.GetModifierId(typeof(T));
+
+ if (id == null)
+ {
+ Logger.Error($"Cannot add modifier {typeof(T).Name} because it is not registered.");
+ return;
+ }
+
+ player.RpcRemoveModifier(id.Value);
+ }
+
+ ///
+ /// Remote Procedure Call to add a modifier to a player.
+ ///
+ /// The player to add the modifier to.
+ /// The modifier ID.
+ [MethodRpc((uint)MiraRpc.AddModifier)]
+ public static void RpcAddModifier(this PlayerControl target, uint modifierId, params object[] args)
+ {
+ var type = ModifierManager.GetModifierType(modifierId);
+ if (type == null)
+ {
+ Logger.Error($"Cannot add modifier with id {modifierId} because it is not registered.");
+ return;
+ }
+
+ var modifier = ModifierFactory.CreateInstance(type, args);
+ target.GetModifierComponent()?.AddModifier(modifier);
+ }
+
+ ///
+ /// Remote Procedure Call to add a modifier to a player.
+ ///
+ /// The player to add the modifier to.
+ /// The arguments to initialize the modifier constructor with.
+ /// The modifier Type.
+ public static void RpcAddModifier(this PlayerControl player, params object[] args) where T : BaseModifier
+ {
+ var id = ModifierManager.GetModifierId(typeof(T));
+ if (id == null)
+ {
+ Logger.Error($"Cannot add modifier {typeof(T).Name} because it is not registered.");
+ return;
+ }
+
+ var modifier = ModifierFactory.CreateInstance(args);
+ player.GetModifierComponent()!.AddModifier(modifier);
+ }
+}
diff --git a/MiraAPI/Modifiers/ModifierFactory.cs b/MiraAPI/Modifiers/ModifierFactory.cs
new file mode 100644
index 0000000..e1b018c
--- /dev/null
+++ b/MiraAPI/Modifiers/ModifierFactory.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Linq;
+using System.Linq.Expressions;
+
+namespace MiraAPI.Modifiers;
+
+public static class ModifierFactory
+{
+ private static Func