diff --git a/MiraAPI/GameOptions/ModdedOptionsManager.cs b/MiraAPI/GameOptions/ModdedOptionsManager.cs index 0d8e15f..0ca20c3 100644 --- a/MiraAPI/GameOptions/ModdedOptionsManager.cs +++ b/MiraAPI/GameOptions/ModdedOptionsManager.cs @@ -10,7 +10,7 @@ using Reactor.Networking.Rpc; namespace MiraAPI.GameOptions; -public class ModdedOptionsManager +public static class ModdedOptionsManager { public static readonly Dictionary ModdedOptions = new(); public static readonly List Options = []; diff --git a/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs b/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs index 386cc7c..712955a 100644 --- a/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs +++ b/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs @@ -4,7 +4,6 @@ using Reactor.Localization.Utilities; using System; using MiraAPI.Networking; using Reactor.Networking.Rpc; -using Reactor.Utilities; using UnityEngine; namespace MiraAPI.GameOptions.OptionTypes; diff --git a/MiraAPI/Modifiers/BaseModifier.cs b/MiraAPI/Modifiers/BaseModifier.cs index 284f989..2e6812b 100644 --- a/MiraAPI/Modifiers/BaseModifier.cs +++ b/MiraAPI/Modifiers/BaseModifier.cs @@ -2,7 +2,9 @@ public abstract class BaseModifier { public abstract string ModifierName { get; } - public uint ModifierId { get; set; } + + public PlayerControl Player { get; internal set; } + public virtual void OnActivate() { } public virtual void OnDeactivate() { } public virtual void Update() { } diff --git a/MiraAPI/Modifiers/ModifierComponent.cs b/MiraAPI/Modifiers/ModifierComponent.cs new file mode 100644 index 0000000..5dc1acc --- /dev/null +++ b/MiraAPI/Modifiers/ModifierComponent.cs @@ -0,0 +1,97 @@ +using Reactor.Utilities.Attributes; +using System; +using System.Collections.Generic; +using MiraAPI.Networking; +using MiraAPI.Utilities; +using Reactor.Networking.Attributes; +using Reactor.Utilities; +using UnityEngine; + +namespace MiraAPI.Modifiers; + +[RegisterInIl2Cpp] +public class ModifierComponent(IntPtr ptr) : MonoBehaviour(ptr) +{ + public List activeModifiers = []; + + public PlayerControl player; + + public void Start() + { + player = GetComponent(); + } + + public bool HasModifier() where T : BaseModifier + { + return activeModifiers.Exists(x=>x is T); + } + + public void AddModifier() where T : BaseModifier + { + if (!ModifierManager.TypeToIdModifiers.TryGetValue(typeof(T), out var id)) + { + Logger.Error($"Cannot add modifier {typeof(T).Name} because it is not registered."); + return; + } + + RpcAddModifier(player, id); + } + + public void RemoveModifier() where T : BaseModifier + { + if (!ModifierManager.TypeToIdModifiers.TryGetValue(typeof(T), out var id)) + { + Logger.Error($"Cannot add modifier {typeof(T).Name} because it is not registered."); + return; + } + + RpcRemoveModifier(player, id); + } + + [MethodRpc((uint)MiraRpc.RemoveModifier)] + private static void RpcRemoveModifier(PlayerControl target, uint modifierId) + { + if (!ModifierManager.IdToTypeModifiers.TryGetValue(modifierId, out var type)) + { + Logger.Error($"Cannot remove modifier with id {modifierId} because it is not registered."); + return; + } + + var modifierComponent = target.GetModifierComponent(); + + var modifier = modifierComponent.activeModifiers.Find(x => x.GetType() == type); + + if (modifier is null) + { + Logger.Error($"Cannot remove modifier {type.Name} because it is not active."); + return; + } + + modifier.OnDeactivate(); + modifierComponent.activeModifiers.Remove(modifier); + } + + [MethodRpc((uint)MiraRpc.AddModifier)] + private static void RpcAddModifier(PlayerControl target, uint modifierId) + { + if (!ModifierManager.IdToTypeModifiers.TryGetValue(modifierId, out var type)) + { + Logger.Error($"Cannot add modifier with id {modifierId} because it is not registered."); + return; + } + + var modifier = (BaseModifier)Activator.CreateInstance(type); + + var modifierComponent = target.GetModifierComponent(); + + if (modifier is null) + { + Logger.Error($"Cannot add modifier {type.Name} because it is null."); + return; + } + + modifierComponent.activeModifiers.Add(modifier); + modifier.Player = modifierComponent.player; + modifier.OnActivate(); + } +} \ No newline at end of file diff --git a/MiraAPI/Modifiers/ModifierManager.cs b/MiraAPI/Modifiers/ModifierManager.cs index fc07183..8093e09 100644 --- a/MiraAPI/Modifiers/ModifierManager.cs +++ b/MiraAPI/Modifiers/ModifierManager.cs @@ -1,74 +1,28 @@ -using MiraAPI.Networking; -using MiraAPI.Utilities; -using Reactor.Networking.Attributes; -using Reactor.Utilities; -using Reactor.Utilities.Attributes; -using System; +using System; using System.Collections.Generic; -using UnityEngine; namespace MiraAPI.Modifiers; -[RegisterInIl2Cpp] -public class ModifierManager(IntPtr ptr) : MonoBehaviour(ptr) +public static class ModifierManager { - public List activeModifiersIds = new(); - public static List registeredModifiers = new(); - + public static readonly Dictionary IdToTypeModifiers = []; + public static readonly Dictionary TypeToIdModifiers = []; + + private static uint _nextId; + + private static uint GetNextId() + { + return _nextId++; + } + public static void RegisterModifier(Type modifierType) { if (!typeof(BaseModifier).IsAssignableFrom(modifierType)) { return; } - - BaseModifier newMod = (BaseModifier)Activator.CreateInstance(modifierType); - newMod.ModifierId = (uint)registeredModifiers.Count; - registeredModifiers.Add(newMod); - } - - - public bool HasModifier(PlayerControl target) where T : BaseModifier - { - uint id = registeredModifiers.Find(mod => mod.GetType() == typeof(T)).ModifierId; - return target.GetModifierManager().activeModifiersIds.Contains(id); - } - - public void AddModifier(PlayerControl target) where T : BaseModifier - { - uint id = registeredModifiers.Find(mod => mod.GetType() == typeof(T)).ModifierId; - RpcAddModifier(target, id); - } - - public void RemoveModifier(PlayerControl target) where T : BaseModifier - { - uint id = registeredModifiers.Find(mod => mod.GetType() == typeof(T)).ModifierId; - if (!activeModifiersIds.Contains(id)) - { - Logger.Error($"Cannot remove modifier {typeof(T).Name} because it is not active."); - return; - } - - RpcRemoveModifier(target, id); - } - - [MethodRpc((uint)MiraRpc.AddModifier)] - private static void RpcRemoveModifier(PlayerControl target, uint modifierId) - { - BaseModifier modifier = registeredModifiers.Find(mod => mod.ModifierId == modifierId); - if (modifier is null) return; - - modifier.OnDeactivate(); - target.GetModifierManager().activeModifiersIds.Remove(modifierId); - } - - [MethodRpc((uint)MiraRpc.AddModifier)] - private static void RpcAddModifier(PlayerControl target, uint modifierId) - { - BaseModifier modifier = registeredModifiers.Find(mod => mod.ModifierId == modifierId); - if (modifier is null) return; - - target.GetModifierManager().activeModifiersIds.Add(modifierId); - modifier.OnActivate(); + + IdToTypeModifiers.Add(GetNextId(), modifierType); + TypeToIdModifiers.Add(modifierType, _nextId); } } \ No newline at end of file diff --git a/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs b/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs index 2350801..bcdecbe 100644 --- a/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs +++ b/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs @@ -162,7 +162,7 @@ public static class RoleSettingMenuPatches { ICustomRole customRole = role as ICustomRole; __instance.roleDescriptionText.text = customRole.RoleLongDescription; - __instance.roleTitleText.text = DestroyableSingleton.Instance.GetString(role.StringName, Array.Empty()); + __instance.roleTitleText.text = DestroyableSingleton.Instance.GetString(role.StringName, []); __instance.roleScreenshot.sprite = Sprite.Create(role.RoleScreenshot.texture, new Rect(0, 0, 370, 230), Vector2.one / 2, 100); __instance.roleScreenshot.drawMode = SpriteDrawMode.Sliced; __instance.roleHeaderSprite.color = customRole.RoleColor; diff --git a/MiraAPI/Patches/PlayerControlPatches.cs b/MiraAPI/Patches/PlayerControlPatches.cs index 99b6efb..55fd72e 100644 --- a/MiraAPI/Patches/PlayerControlPatches.cs +++ b/MiraAPI/Patches/PlayerControlPatches.cs @@ -12,7 +12,7 @@ public static class PlayerControlPatches [HarmonyPatch(nameof(PlayerControl.Start))] public static void PlayerControlStartPostfix(PlayerControl __instance) { - __instance.gameObject.AddComponent(); + __instance.gameObject.AddComponent(); } [HarmonyPostfix] diff --git a/MiraAPI/Patches/Roles/NameTagPatch.cs b/MiraAPI/Patches/Roles/NameTagPatch.cs index 3566416..929ccaf 100644 --- a/MiraAPI/Patches/Roles/NameTagPatch.cs +++ b/MiraAPI/Patches/Roles/NameTagPatch.cs @@ -1,6 +1,4 @@ using HarmonyLib; -using MiraAPI.GameModes; -using MiraAPI.GameOptions; using UnityEngine; namespace MiraAPI.Patches.Roles; diff --git a/MiraAPI/Utilities/Extensions.cs b/MiraAPI/Utilities/Extensions.cs index 2cc615c..2291243 100644 --- a/MiraAPI/Utilities/Extensions.cs +++ b/MiraAPI/Utilities/Extensions.cs @@ -14,14 +14,14 @@ public static class Extensions return ModdedOptionsManager.Options.Any(opt => opt.OptionBehaviour && opt.OptionBehaviour.Equals(optionBehaviour)); } - public static ModifierManager GetModifierManager(this PlayerControl player) + public static ModifierComponent GetModifierComponent(this PlayerControl player) { - return player.gameObject.GetComponent(); + return player.gameObject.GetComponent(); } public static void AddModifier(this PlayerControl player) where T : BaseModifier { - player.GetModifierManager().AddModifier(); + player.GetModifierComponent().AddModifier(); } public static void RemoveModifier(this PlayerControl player) where T : BaseModifier