From 7e4a71739c0ba89fdf2312e89c668d4751052619 Mon Sep 17 00:00:00 2001 From: XtraCube <72575280+XtraCube@users.noreply.github.com> Date: Tue, 25 Feb 2025 21:57:38 -0500 Subject: [PATCH] better modifier unique IDs --- MiraAPI/Modifiers/BaseModifier.cs | 2 +- MiraAPI/Modifiers/ModifierComponent.cs | 53 ++++++------ MiraAPI/Modifiers/ModifierData.cs | 19 ----- MiraAPI/Modifiers/ModifierExtensions.cs | 80 +++++++++---------- MiraAPI/Modifiers/ModifierManager.cs | 69 +--------------- MiraAPI/Networking/GuidConverter.cs | 32 ++++++++ .../Networking/Modifiers/AddModifierRpc.cs | 23 +++++- MiraAPI/Networking/Modifiers/ModifierData.cs | 11 +++ .../Networking/Modifiers/SyncModifiersRpc.cs | 52 ------------ MiraAPI/Patches/AmongUsClientSyncPatch.cs | 6 +- .../Patches/Freeplay/TaskAddButtonPatches.cs | 2 +- MiraAPI/Patches/Freeplay/TaskAdderPatches.cs | 4 +- 12 files changed, 134 insertions(+), 219 deletions(-) delete mode 100644 MiraAPI/Modifiers/ModifierData.cs create mode 100644 MiraAPI/Networking/GuidConverter.cs create mode 100644 MiraAPI/Networking/Modifiers/ModifierData.cs delete mode 100644 MiraAPI/Networking/Modifiers/SyncModifiersRpc.cs diff --git a/MiraAPI/Modifiers/BaseModifier.cs b/MiraAPI/Modifiers/BaseModifier.cs index 21ce064..52a2bb0 100644 --- a/MiraAPI/Modifiers/BaseModifier.cs +++ b/MiraAPI/Modifiers/BaseModifier.cs @@ -45,7 +45,7 @@ public abstract class BaseModifier /// /// Gets the unique ID of the modifier. /// - public uint UniqueId { get; internal set; } + public Guid UniqueId { get; internal set; } = Guid.Empty; /// /// Gets the type ID of the modifier. diff --git a/MiraAPI/Modifiers/ModifierComponent.cs b/MiraAPI/Modifiers/ModifierComponent.cs index 94ab3db..57abd8c 100644 --- a/MiraAPI/Modifiers/ModifierComponent.cs +++ b/MiraAPI/Modifiers/ModifierComponent.cs @@ -37,14 +37,6 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr) private readonly List _toAdd = []; - private uint _nextUniqueId; - - private uint GetNextUniqueId() - { - _nextUniqueId++; - return _nextUniqueId; - } - internal void ClearModifiers() { _toRemove.AddRange(Modifiers); @@ -204,22 +196,22 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr) /// The predicate to check the modifier by. /// True if the modifier was found, false otherwise. [HideFromIl2Cpp] - public bool TryGetModifierByTypeId(uint id, out BaseModifier? modifier, Func? predicate = null) + public bool TryGetModifier(uint id, out BaseModifier? modifier, Func? predicate = null) { - modifier = GetModifierByTypeId(id, predicate); + modifier = GetModifier(id, predicate); return modifier != null; } /// /// Tries to get a modifier by its unique ID. /// - /// The modifier unique ID. + /// The modifier unique ID. /// The modifier or null. /// True if the modifier was found, false otherwise. [HideFromIl2Cpp] - public bool TryGetModifierByUniqueId(uint id, out BaseModifier? modifier) + public bool TryGetModifier(Guid modifierGuid, out BaseModifier? modifier) { - modifier = GetModifierByUniqueId(id); + modifier = GetModifier(modifierGuid); return modifier != null; } @@ -254,7 +246,7 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr) /// The predicate to check the modifier by. /// The Modifier if it is found, null otherwise. [HideFromIl2Cpp] - public BaseModifier? GetModifierByTypeId(uint id, Func? predicate = null) + public BaseModifier? GetModifier(uint id, Func? predicate = null) { var type = ModifierManager.GetModifierType(id) ?? throw new InvalidOperationException( $"Cannot get modifier with id {id} because it is not registered."); @@ -265,12 +257,12 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr) /// /// Gets a modifier by unique ID. /// - /// The modifier's unique ID. + /// The modifier's unique ID. /// The modifier if it is found, or null. [HideFromIl2Cpp] - public BaseModifier? GetModifierByUniqueId(uint id) + public BaseModifier? GetModifier(Guid modifierGuid) { - return Modifiers.Find(x => x.UniqueId == id); + return Modifiers.Find(x => x.UniqueId == modifierGuid); } /// @@ -330,7 +322,7 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr) /// The modifier's type ID. /// The predicate to check the modifier by. [HideFromIl2Cpp] - public void RemoveModifierByTypeId(uint typeId, Func? predicate = null) + public void RemoveModifier(uint typeId, Func? predicate = null) { var type = ModifierManager.GetModifierType(typeId) ?? throw new InvalidOperationException( $"Cannot remove modifier with id {typeId} because it is not registered."); @@ -342,9 +334,9 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr) /// /// The modifier's unique ID. [HideFromIl2Cpp] - public void RemoveModifierByUniqueId(uint uniqueId) + public void RemoveModifier(Guid uniqueId) { - var modifier = GetModifierByUniqueId(uniqueId); + var modifier = GetModifier(uniqueId); if (modifier == null) { Logger.Error($"Cannot remove modifier with unique id {uniqueId} because it is not active."); @@ -390,7 +382,10 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr) _toAdd.Add(modifier); modifier.Player = _player; modifier.ModifierComponent = this; - modifier.UniqueId = GetNextUniqueId(); + if (modifier.UniqueId == Guid.Empty) + { + modifier.UniqueId = Guid.NewGuid(); + } return modifier; } @@ -460,13 +455,13 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr) } /// - /// Checks if a player has an active modifier by its type ID + /// Checks if a player has an active modifier by its type ID. /// - /// The Modifier type ID. + /// The modifier's type ID. /// The predicate to check the modifier. - /// True if the Modifier is present, false otherwise. + /// True if the modifier is present, false otherwise. [HideFromIl2Cpp] - public bool HasModifierByTypeId(uint id, Func? predicate=null) + public bool HasModifier(uint id, Func? predicate=null) { var type = ModifierManager.GetModifierType(id) ?? throw new InvalidOperationException( $"Cannot get modifier with id {id} because it is not registered."); @@ -475,12 +470,12 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr) } /// - /// Checks if a player has an active modifier by its unique ID + /// Checks if a player has an active modifier by its unique ID. /// - /// The Modifier type ID. - /// True if the Modifier is present, false otherwise. + /// The modifier's guid. + /// True if the modifier is present, false otherwise. [HideFromIl2Cpp] - public bool HasModifierByUniqueId(uint id) + public bool HasModifier(Guid id) { return Modifiers.Exists(x => x.UniqueId == id); } diff --git a/MiraAPI/Modifiers/ModifierData.cs b/MiraAPI/Modifiers/ModifierData.cs deleted file mode 100644 index 7260834..0000000 --- a/MiraAPI/Modifiers/ModifierData.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace MiraAPI.Modifiers; - -/// -/// Modifier data for networking. -/// -/// The ID of the modifier. -/// Parameters for constructor. -public readonly struct ModifierData(uint id, object[] args) -{ - /// - /// Gets the type of the modifier. - /// - public uint Id { get; } = id; - - /// - /// Gets the parameters for the constructor. - /// - public object[] Args { get; } = args; -} diff --git a/MiraAPI/Modifiers/ModifierExtensions.cs b/MiraAPI/Modifiers/ModifierExtensions.cs index 5b42c6b..5d05d69 100644 --- a/MiraAPI/Modifiers/ModifierExtensions.cs +++ b/MiraAPI/Modifiers/ModifierExtensions.cs @@ -29,7 +29,7 @@ public static class ModifierExtensions _ = ModifierManager.GetModifierType(typeId) ?? throw new InvalidOperationException( $"Modifier with ID {typeId} is not registered."); - Rpc.Instance.Send(target, new ModifierData(typeId, args)); + Rpc.Instance.Send(target, new ModifierData(typeId, Guid.NewGuid(), args)); } /// @@ -63,9 +63,9 @@ public static class ModifierExtensions /// The player to remove the modifier from. /// The unique ID of the modifier. [MethodRpc((uint)MiraRpc.RemoveModifier)] - public static void RpcRemoveModifierByUniqueId(this PlayerControl target, uint uniqueId) + public static void RpcRemoveModifier(this PlayerControl target, Guid uniqueId) { - target.RemoveModifierByUniqueId(uniqueId); + target.RemoveModifier(uniqueId); } /// @@ -74,19 +74,19 @@ public static class ModifierExtensions /// The player to remove the modifier from. /// The type ID of the modifier. /// Optional predicate to filter the modifiers. - public static void RpcRemoveModifierByTypeId( + public static void RpcRemoveModifier( this PlayerControl target, uint typeId, Func? predicate = null) { - var modifier = target.GetModifierByTypeId(typeId, predicate); + var modifier = target.GetModifier(typeId, predicate); if (modifier is null) { Logger.Error($"Player {target.PlayerId} does not have modifier with type ID {typeId}."); return; } - target.RpcRemoveModifierByUniqueId(modifier.UniqueId); + target.RpcRemoveModifier(modifier.UniqueId); } /// @@ -103,7 +103,7 @@ public static class ModifierExtensions var id = ModifierManager.GetModifierTypeId(type) ?? throw new InvalidOperationException( $"Modifier {type.Name} is not registered."); - player.RpcRemoveModifierByTypeId(id, predicate); + player.RpcRemoveModifier(id, predicate); } /// @@ -168,26 +168,26 @@ public static class ModifierExtensions /// Checks if the player has a specific modifier by type ID. /// /// The PlayerControl instance. - /// The type ID of the modifier. + /// The type ID of the modifier. /// Optional predicate to filter the modifiers. /// True if the player has the modifier, false otherwise. - public static bool HasModifierByTypeId( + public static bool HasModifier( this PlayerControl player, - uint id, + uint typeId, Func? predicate = null) { - return player.GetModifierComponent().HasModifierByTypeId(id, predicate); + return player.GetModifierComponent().HasModifier(typeId, predicate); } /// - /// Checks if the player has a specific modifier by unique ID. + /// Checks if the player has a specific modifier by its GUID. /// /// The PlayerControl instance. - /// The unique ID of the modifier. + /// The unique ID of the modifier. /// True if the player has the modifier, false otherwise. - public static bool HasModifierByUniqueId(this PlayerControl player, uint id) + public static bool HasModifier(this PlayerControl player, Guid uniqueId) { - return player.GetModifierComponent().HasModifierByUniqueId(id); + return player.GetModifierComponent().HasModifier(uniqueId); } /// @@ -218,31 +218,31 @@ public static class ModifierExtensions } /// - /// Gets a specific modifier from the player by type ID. + /// Gets a specific modifier from the player by its type ID. /// /// The PlayerControl instance. - /// The type ID of the modifier. + /// The type ID of the modifier. /// Optional predicate to filter the modifiers. /// The modifier if found, null otherwise. - public static BaseModifier? GetModifierByTypeId( + public static BaseModifier? GetModifier( this PlayerControl player, - uint id, + uint typeId, Func? predicate = null) { - return player.GetModifierComponent().GetModifierByTypeId(id, predicate); + return player.GetModifierComponent().GetModifier(typeId, predicate); } /// - /// Gets a specific modifier from the player by ID. + /// Gets a specific modifier from the player by its GUID. /// /// The PlayerControl instance. - /// The ID of the modifier. + /// The GUID of the modifier. /// The modifier if found, null otherwise. - public static BaseModifier? GetModifierByUniqueId( + public static BaseModifier? GetModifier( this PlayerControl player, - uint id) + Guid uniqueId) { - return player.GetModifierComponent().GetModifierByUniqueId(id); + return player.GetModifierComponent().GetModifier(uniqueId); } /// @@ -251,7 +251,7 @@ public static class ModifierExtensions /// The type of the modifiers. /// The PlayerControl instance. /// Optional predicate to filter the modifiers. - /// An enumerable of modifiers. + /// A collection of modifiers. public static IEnumerable GetModifiers(this PlayerControl player, Func? predicate = null) where T : BaseModifier { @@ -264,7 +264,7 @@ public static class ModifierExtensions /// The PlayerControl instance. /// The type of the modifiers. /// Optional predicate to filter the modifiers. - /// An enumerable of modifiers. + /// A collection of modifiers. public static IEnumerable GetModifiers( this PlayerControl player, Type type, @@ -277,15 +277,15 @@ public static class ModifierExtensions /// Gets all modifiers of a specific type from the player by type ID. /// /// The PlayerControl instance. - /// The type ID of the modifiers. + /// The type ID of the modifiers. /// Optional predicate to filter the modifiers. - /// An enumerable of modifiers. + /// A collection of modifiers. public static IEnumerable GetModifiers( this PlayerControl player, - uint id, + uint typeId, Func? predicate = null) { - return player.GetModifierComponent().GetModifiers(id, predicate); + return player.GetModifierComponent().GetModifiers(typeId, predicate); } /// @@ -322,29 +322,29 @@ public static class ModifierExtensions } /// - /// Removes a specific modifier from the player by ID. + /// Removes a specific modifier from the player by its type ID. /// /// The PlayerControl instance. - /// The ID of the modifier. + /// The type ID of the modifier. /// Optional predicate to filter the modifiers. - public static void RemoveModifierByTypeId( + public static void RemoveModifier( this PlayerControl player, uint typeId, Func? predicate = null) { - player.GetModifierComponent().RemoveModifierByTypeId(typeId, predicate); + player.GetModifierComponent().RemoveModifier(typeId, predicate); } /// - /// Removes a specific modifier from the player by ID. + /// Removes a specific modifier from the player by its GUID. /// /// The PlayerControl instance. - /// The ID of the modifier. - public static void RemoveModifierByUniqueId( + /// The GUID of the modifier. + public static void RemoveModifier( this PlayerControl player, - uint uniqueId) + Guid uniqueId) { - player.GetModifierComponent().RemoveModifierByUniqueId(uniqueId); + player.GetModifierComponent().RemoveModifier(uniqueId); } /// diff --git a/MiraAPI/Modifiers/ModifierManager.cs b/MiraAPI/Modifiers/ModifierManager.cs index 209423e..4285a73 100644 --- a/MiraAPI/Modifiers/ModifierManager.cs +++ b/MiraAPI/Modifiers/ModifierManager.cs @@ -3,12 +3,9 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using MiraAPI.Modifiers.Types; -using MiraAPI.Networking; -using MiraAPI.Networking.Modifiers; using MiraAPI.PluginLoading; using MiraAPI.Roles; using MiraAPI.Utilities; -using Reactor.Networking.Rpc; using Reactor.Utilities; using Reactor.Utilities.Extensions; using Random = System.Random; @@ -159,70 +156,6 @@ public static class ModifierManager private static bool IsGameModifierValid(PlayerControl player, GameModifier modifier, uint modifierId) { return (player.Data.Role is not ICustomRole role || role.IsModifierApplicable(modifier)) && - modifier.IsModifierValidOn(player.Data.Role) && !player.HasModifierByTypeId(modifierId); - } - - internal static void SyncAllModifiers(int targetId = -1) - { - var data = new List(); - - foreach (var player in PlayerControl.AllPlayerControls) - { - data.Add(GetPlayerModifiers(player)); - } - - Rpc.Instance.SendTo(PlayerControl.LocalPlayer, targetId, [.. data]); - } - - internal static void HandleSyncModifiers(NetData[] data) - { - foreach (var netData in data) - { - var ids = new uint[netData.Data.Length / 4]; - Buffer.BlockCopy(netData.Data, 0, ids, 0, netData.Data.Length); - - var plr = GameData.Instance.GetPlayerById((byte)netData.Id).Object; - var modifierComponent = plr.GetComponent(); - - if (!modifierComponent) - { - continue; - } - - modifierComponent.ClearModifiers(); - - foreach (var id in ids) - { - if (!IdToTypeModifierMap.TryGetValue(id, out var type)) - { - Logger.Error($"Cannot add modifier with id {id} because it is not registered."); - continue; - } - - modifierComponent.AddModifier(type); - } - } - } - - private static NetData GetPlayerModifiers(PlayerControl? player) - { - if (player == null || !player) - { - return new NetData(0, []); - } - - List bytes = []; - var modifierComponent = player.GetComponent(); - if (modifierComponent == null || !modifierComponent) - { - return new NetData(player.PlayerId, []); - } - - foreach (var modifier in modifierComponent.ActiveModifiers) - { - bytes.AddRange(BitConverter.GetBytes(TypeToIdModifierMap[modifier.GetType()])); - } - - return new NetData(player.PlayerId, [.. bytes]); + modifier.IsModifierValidOn(player.Data.Role) && !player.HasModifier(modifierId); } } diff --git a/MiraAPI/Networking/GuidConverter.cs b/MiraAPI/Networking/GuidConverter.cs new file mode 100644 index 0000000..c00d759 --- /dev/null +++ b/MiraAPI/Networking/GuidConverter.cs @@ -0,0 +1,32 @@ +using System; +using Hazel; +using Reactor.Networking.Attributes; +using Reactor.Networking.Serialization; + +namespace MiraAPI.Networking; + +/// +/// Converter for . +/// +[MessageConverter] +public class GuidConverter : MessageConverter +{ + /// + /// Writes a to the writer. + /// + /// + public override void Write(MessageWriter writer, Guid value) + { + writer.WriteBytesAndSize(value.ToByteArray()); + } + + /// + /// Reads a from the reader. + /// + /// + /// A GUID object. + public override Guid Read(MessageReader reader, Type objectType) + { + return new Guid(reader.ReadBytesAndSize()); + } +} diff --git a/MiraAPI/Networking/Modifiers/AddModifierRpc.cs b/MiraAPI/Networking/Modifiers/AddModifierRpc.cs index 5727ba5..2e7b19e 100644 --- a/MiraAPI/Networking/Modifiers/AddModifierRpc.cs +++ b/MiraAPI/Networking/Modifiers/AddModifierRpc.cs @@ -21,7 +21,8 @@ public class AddModifierRpc(MiraApiPlugin plugin, uint id) : PlayerCustomRpc public override void Write(MessageWriter writer, ModifierData data) { - writer.WritePacked(data.Id); + writer.WritePacked(data.TypeId); + writer.WriteBytesAndSize(data.UniqueId.ToByteArray()); writer.WritePacked(data.Args.Length); foreach (var arg in data.Args) { @@ -34,6 +35,7 @@ public class AddModifierRpc(MiraApiPlugin plugin, uint id) : PlayerCustomRpc public override void Handle(PlayerControl player, ModifierData data) { - player.AddModifier(data.Id, data.Args); + var type = ModifierManager.GetModifierType(data.TypeId) ?? throw new InvalidOperationException($"Modifier type not found for ID {data.TypeId}."); + BaseModifier? modifier; + if (data.Args.Length > 0) + { + modifier = ModifierFactory.CreateInstance(type, data.Args); + } + else + { + modifier = Activator.CreateInstance(type) as BaseModifier; + if (modifier == null) + { + throw new InvalidOperationException($"Cannot add modifier {type.Name} because it is not a valid modifier."); + } + } + modifier.UniqueId = data.UniqueId; + player.AddModifier(modifier); } } diff --git a/MiraAPI/Networking/Modifiers/ModifierData.cs b/MiraAPI/Networking/Modifiers/ModifierData.cs new file mode 100644 index 0000000..3d3f158 --- /dev/null +++ b/MiraAPI/Networking/Modifiers/ModifierData.cs @@ -0,0 +1,11 @@ +using System; + +namespace MiraAPI.Networking.Modifiers; + +/// +/// Modifier data for networking. +/// +/// The ID of the modifier. +/// The unique ID of the modifier. +/// Parameters for constructor. +public record struct ModifierData(uint TypeId, Guid UniqueId, object[] Args); diff --git a/MiraAPI/Networking/Modifiers/SyncModifiersRpc.cs b/MiraAPI/Networking/Modifiers/SyncModifiersRpc.cs deleted file mode 100644 index 0571198..0000000 --- a/MiraAPI/Networking/Modifiers/SyncModifiersRpc.cs +++ /dev/null @@ -1,52 +0,0 @@ -using Hazel; -using MiraAPI.Modifiers; -using Reactor.Networking.Attributes; -using Reactor.Networking.Rpc; - -namespace MiraAPI.Networking.Modifiers; - -[RegisterCustomRpc((uint)MiraRpc.SyncModifiers)] -internal sealed class SyncModifiersRpc(MiraApiPlugin plugin, uint id) : PlayerCustomRpc(plugin, id) -{ - public override RpcLocalHandling LocalHandling => RpcLocalHandling.None; - - public override void Write(MessageWriter writer, NetData[]? data) - { - if (data == null) - { - writer.WritePacked(0U); - return; - } - - writer.WritePacked((uint)data.Length); - foreach (var netData in data) - { - writer.WritePacked(netData.Id); - writer.WriteBytesAndSize(netData.Data); - } - } - - public override NetData[] Read(MessageReader reader) - { - var length = reader.ReadPackedUInt32(); - var data = new NetData[length]; - for (var i = 0; i < length; i++) - { - var dataId = reader.ReadPackedUInt32(); - var bytes = reader.ReadBytesAndSize(); - data[i] = new NetData(dataId, bytes); - } - - return data; - } - - public override void Handle(PlayerControl playerControl, NetData[]? data) - { - if (AmongUsClient.Instance.HostId != playerControl.OwnerId) - { - return; - } - - ModifierManager.HandleSyncModifiers(data ?? []); - } -} diff --git a/MiraAPI/Patches/AmongUsClientSyncPatch.cs b/MiraAPI/Patches/AmongUsClientSyncPatch.cs index 4a76283..6af91c1 100644 --- a/MiraAPI/Patches/AmongUsClientSyncPatch.cs +++ b/MiraAPI/Patches/AmongUsClientSyncPatch.cs @@ -3,16 +3,15 @@ using InnerNet; using MiraAPI.Events; using MiraAPI.Events.Vanilla.Player; using MiraAPI.GameOptions; -using MiraAPI.Modifiers; using MiraAPI.Roles; namespace MiraAPI.Patches; /// -/// Sync all options, role settings, and modifiers to the player when they join the game. +/// Sync all settings to the player when they join the game. /// [HarmonyPatch(typeof(AmongUsClient))] -public static class AmongUsClientSyncPatch +internal static class AmongUsClientSyncPatch { [HarmonyPostfix] [HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.CreatePlayer))] @@ -33,7 +32,6 @@ public static class AmongUsClientSyncPatch ModdedOptionsManager.SyncAllOptions(clientData.Id); CustomRoleManager.SyncAllRoleSettings(clientData.Id); - ModifierManager.SyncAllModifiers(clientData.Id); } [HarmonyPostfix] diff --git a/MiraAPI/Patches/Freeplay/TaskAddButtonPatches.cs b/MiraAPI/Patches/Freeplay/TaskAddButtonPatches.cs index 0ee6da4..184bafb 100644 --- a/MiraAPI/Patches/Freeplay/TaskAddButtonPatches.cs +++ b/MiraAPI/Patches/Freeplay/TaskAddButtonPatches.cs @@ -16,7 +16,7 @@ internal static class TaskAddButtonPatches if (uint.TryParse(__instance.name, out var result)) { __instance.Overlay.sprite = __instance.CheckImage; - __instance.Overlay.enabled = PlayerControl.LocalPlayer.HasModifierByTypeId(result); + __instance.Overlay.enabled = PlayerControl.LocalPlayer.HasModifier(result); return false; } diff --git a/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs b/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs index 0c35670..666a1ea 100644 --- a/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs +++ b/MiraAPI/Patches/Freeplay/TaskAdderPatches.cs @@ -337,9 +337,9 @@ internal static class TaskAdderPatches taskAddButton.Button.OnClick.AddListener((UnityEngine.Events.UnityAction)(() => { var id = modifier.TypeId; - if (PlayerControl.LocalPlayer.HasModifierByTypeId(id)) + if (PlayerControl.LocalPlayer.HasModifier(id)) { - PlayerControl.LocalPlayer.RemoveModifierByTypeId(id); + PlayerControl.LocalPlayer.RemoveModifier(id); taskAddButton.Overlay.enabled = false; } else