diff --git a/MiraAPI.Example/Buttons/Freezer/FreezeButton.cs b/MiraAPI.Example/Buttons/Freezer/FreezeButton.cs index c04d4a4..3926316 100644 --- a/MiraAPI.Example/Buttons/Freezer/FreezeButton.cs +++ b/MiraAPI.Example/Buttons/Freezer/FreezeButton.cs @@ -18,7 +18,7 @@ public class FreezeButton : CustomActionButton protected override void OnClick() { - Target.AddModifier(); + Target?.RpcAddModifier(); } public override PlayerControl GetTarget() diff --git a/MiraAPI.Example/Buttons/MeetingButton.cs b/MiraAPI.Example/Buttons/MeetingButton.cs index c7f202d..639e663 100644 --- a/MiraAPI.Example/Buttons/MeetingButton.cs +++ b/MiraAPI.Example/Buttons/MeetingButton.cs @@ -41,7 +41,7 @@ public class MeetingButton : CustomActionButton if (UsesLeft == 0 && PlayerControl.LocalPlayer.HasModifier()) { - PlayerControl.LocalPlayer.RemoveModifier(); + PlayerControl.LocalPlayer.RpcRemoveModifier(); } } } diff --git a/MiraAPI/Modifiers/ModifierComponent.cs b/MiraAPI/Modifiers/ModifierComponent.cs index 55c3f30..6da6580 100644 --- a/MiraAPI/Modifiers/ModifierComponent.cs +++ b/MiraAPI/Modifiers/ModifierComponent.cs @@ -1,7 +1,5 @@ using MiraAPI.Modifiers.Types; -using MiraAPI.Networking; using MiraAPI.Utilities; -using Reactor.Networking.Attributes; using Reactor.Utilities; using Reactor.Utilities.Attributes; using System; @@ -54,7 +52,7 @@ public class ModifierComponent(IntPtr ptr) : MonoBehaviour(ptr) var filteredModifiers = ActiveModifiers.Where(mod => !mod.HideOnUi); var baseModifiers = filteredModifiers as BaseModifier[] ?? filteredModifiers.ToArray(); - + if (player.AmOwner && baseModifiers.Any()) { var stringBuild = new StringBuilder(); @@ -74,76 +72,111 @@ public class ModifierComponent(IntPtr ptr) : MonoBehaviour(ptr) } } - public static void RemoveModifier(PlayerControl target, uint modifierId) + public void RemoveModifier(Type type) { - 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); + var modifier = ActiveModifiers.Find(x => x.GetType() == type); if (modifier is null) { Logger.Error($"Cannot remove modifier {type.Name} because it is not active."); return; } + + RemoveModifier(modifier); + } + public void RemoveModifier() where T : BaseModifier + { + RemoveModifier(typeof(T)); + } + + public void RemoveModifier(uint modifierId) + { + var modifier = ActiveModifiers.Find(x => x.ModifierId == modifierId); + + if (modifier is null) + { + Logger.Error($"Cannot remove modifier with id {modifierId} because it is not active."); + return; + } + + RemoveModifier(modifier); + } + + public void RemoveModifier(BaseModifier modifier) + { + if (!ActiveModifiers.Contains(modifier)) + { + Logger.Error($"Cannot remove modifier {modifier.ModifierName} because it is not active on this player."); + return; + } + modifier.OnDeactivate(); - modifierComponent.ActiveModifiers.Remove(modifier); + ActiveModifiers.Remove(modifier); - if (target.AmOwner) + if (player.AmOwner) { HudManager.Instance.SetHudActive(true); } } - public static void AddModifier(PlayerControl target, uint modifierId) + public BaseModifier AddModifier(BaseModifier modifier) { - if (!ModifierManager.IdToTypeModifiers.TryGetValue(modifierId, out var type)) + if (ActiveModifiers.Contains(modifier)) { - Logger.Error($"Cannot add modifier with id {modifierId} because it is not registered."); - return; + Logger.Error($"Player already has modifier with id {modifier.ModifierId}!"); + return null; + } + + ActiveModifiers.Add(modifier); + modifier.Player = player; + modifier.ModifierId = ModifierManager.TypeToIdModifiers[modifier.GetType()]; + modifier.OnActivate(); + + if (!player.AmOwner) + { + return modifier; } - if (target.HasModifier(modifierId)) + if (modifier is TimedModifier { AutoStart: true } timer) + { + timer.StartTimer(); + } + + HudManager.Instance.SetHudActive(true); + + return modifier; + } + + public BaseModifier AddModifier(Type type) + { + if (!ModifierManager.TypeToIdModifiers.TryGetValue(type, out var modifierId)) + { + Logger.Error($"Cannot add modifier {type.Name} because it is not registered."); + return null; + } + + if (ActiveModifiers.Find(x=>x.ModifierId == modifierId) != null) { Logger.Error($"Player already has modifier with id {modifierId}!"); - return; + return null; } 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; + return null; } - modifierComponent.ActiveModifiers.Add(modifier); - modifier.Player = modifierComponent.player; - modifier.ModifierId = modifierId; - modifier.OnActivate(); - - if (target.AmOwner) - { - if (modifier is TimedModifier { AutoStart: true } timer) - { - timer.StartTimer(); - } - - HudManager.Instance.SetHudActive(true); - } + AddModifier(modifier); + + return modifier; } - [MethodRpc((uint)MiraRpc.RemoveModifier)] - public static void RpcRemoveModifier(PlayerControl target, uint modifierId) => RemoveModifier(target, modifierId); - - [MethodRpc((uint)MiraRpc.AddModifier)] - public static void RpcAddModifier(PlayerControl target, uint modifierId) => AddModifier(target, modifierId); + public T AddModifier() where T : BaseModifier + { + return AddModifier(typeof(T)) as T; + } } \ No newline at end of file diff --git a/MiraAPI/Modifiers/ModifierManager.cs b/MiraAPI/Modifiers/ModifierManager.cs index c45cc01..ad0d71d 100644 --- a/MiraAPI/Modifiers/ModifierManager.cs +++ b/MiraAPI/Modifiers/ModifierManager.cs @@ -106,7 +106,7 @@ public static class ModifierManager } shuffledModifiers.RemoveAt(0); - ModifierComponent.RpcAddModifier(plr, id); + plr.RpcAddModifier(id); } } @@ -152,7 +152,13 @@ public static class ModifierManager foreach (var id in ids) { - ModifierComponent.AddModifier(plr, id); + if (!IdToTypeModifiers.TryGetValue(id, out var type)) + { + Logger.Error($"Cannot add modifier with id {id} because it is not registered."); + continue; + } + + modifierComponent.AddModifier(type); } } } diff --git a/MiraAPI/Modifiers/Types/TimedModifier.cs b/MiraAPI/Modifiers/Types/TimedModifier.cs index b37c80e..44e73f7 100644 --- a/MiraAPI/Modifiers/Types/TimedModifier.cs +++ b/MiraAPI/Modifiers/Types/TimedModifier.cs @@ -1,4 +1,5 @@ -using Reactor.Utilities; +using MiraAPI.Utilities; +using Reactor.Utilities; using UnityEngine; namespace MiraAPI.Modifiers.Types; @@ -32,7 +33,7 @@ public abstract class TimedModifier : BaseModifier if (RemoveOnComplete) { - ModifierComponent.RpcRemoveModifier(Player, ModifierId); + Player.RpcRemoveModifier(ModifierId); } } } diff --git a/MiraAPI/Utilities/Extensions.cs b/MiraAPI/Utilities/Extensions.cs index f075ce0..157fcd7 100644 --- a/MiraAPI/Utilities/Extensions.cs +++ b/MiraAPI/Utilities/Extensions.cs @@ -6,6 +6,7 @@ using MiraAPI.Modifiers; using Reactor.Utilities; using System.Linq; using MiraAPI.Networking; +using Reactor.Networking.Attributes; using UnityEngine; namespace MiraAPI.Utilities; @@ -71,9 +72,22 @@ public static class Extensions return ModdedOptionsManager.ModdedOptions.Values.Any(opt => opt.OptionBehaviour && opt.OptionBehaviour.Equals(optionBehaviour)); } + public static readonly Dictionary ModifierComponents = new(); + public static ModifierComponent? GetModifierComponent(this PlayerControl player) { - return player.GetComponent(); + if (ModifierComponents.TryGetValue(player, out var component)) + { + return component; + } + + component = player.GetComponent(); + if (component) + { + ModifierComponents[player] = component; + } + + return component; } public static List Randomize(this List list) @@ -88,28 +102,52 @@ public static class Extensions } return randomizedList; } - + + public static T? GetModifier(this PlayerControl? player) where T : BaseModifier + { + return player?.GetModifierComponent()?.ActiveModifiers.Find(x => x is T) as T; + } + public static bool HasModifier(this PlayerControl? player) where T : BaseModifier { return player?.GetModifierComponent() != null && player.GetModifierComponent()!.ActiveModifiers.Exists(x => x is T); } + public static bool HasModifier(this PlayerControl? player, uint id) { return player?.GetModifierComponent() != null && player.GetModifierComponent()!.ActiveModifiers.Exists(x => x.ModifierId == id); } - public static void AddModifier(this PlayerControl player) where T : BaseModifier + [MethodRpc((uint)MiraRpc.RemoveModifier)] + public static void RpcRemoveModifier(this PlayerControl target, uint modifierId) { - if (!ModifierManager.TypeToIdModifiers.TryGetValue(typeof(T), out var id)) - { - Logger.Error($"Cannot add modifier {typeof(T).Name} because it is not registered."); - return; - } - - ModifierComponent.RpcAddModifier(player, id); + target.GetModifierComponent()?.RemoveModifier(modifierId); } - public static void RemoveModifier(this PlayerControl player) where T : BaseModifier + [MethodRpc((uint)MiraRpc.AddModifier)] + public static BaseModifier? RpcAddModifier(this PlayerControl target, uint modifierId) + { + if (ModifierManager.IdToTypeModifiers.TryGetValue(modifierId, out var type)) + { + return target.GetModifierComponent()?.AddModifier(type); + } + + Logger.Error($"Cannot add modifier with id {modifierId} because it is not registered."); + return null; + } + + public static void RpcAddModifier(this PlayerControl player) 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; + } + + player.RpcAddModifier(id); + } + + public static void RpcRemoveModifier(this PlayerControl player) where T : BaseModifier { if (!ModifierManager.TypeToIdModifiers.TryGetValue(typeof(T), out var id)) { @@ -117,7 +155,7 @@ public static class Extensions return; } - ModifierComponent.RpcRemoveModifier(player, id); + player.RpcAddModifier(id); } public static Color DarkenColor(this Color color)