using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using MiraAPI.Networking; using MiraAPI.Networking.Modifiers; using Reactor.Networking.Attributes; using Reactor.Networking.Rpc; namespace MiraAPI.Modifiers; /// /// Extensions for s. /// public static class ModifierExtensions { /// /// Gets the to cache s. /// public static Dictionary ModifierComponents { get; } = []; /// /// Remote Procedure Call to add a to a . /// /// The to add the to. /// The type ID. /// The arguments to initialize the with. public static void RpcAddModifier(this PlayerControl target, uint typeId, params object[] args) { _ = ModifierManager.GetModifierType(typeId) ?? throw new InvalidOperationException( $"Modifier with ID {typeId} is not registered."); Rpc.Instance.Send(target, new ModifierData(typeId, Guid.NewGuid(), args), true); } /// /// Remote Procedure Call to add a to a . /// /// The to add the to. /// The type of the . /// The arguments to initialize the with. public static void RpcAddModifier(this PlayerControl player, Type type, params object[] args) { var id = ModifierManager.GetModifierTypeId(type) ?? throw new InvalidOperationException( $"Modifier {type.Name} is not registered."); player.RpcAddModifier(id, args); } /// /// Remote Procedure Call to add a to a . /// /// The to add the to. /// The arguments to initialize the with. /// The Type. public static void RpcAddModifier(this PlayerControl player, params object[] args) where T : BaseModifier { player.RpcAddModifier(typeof(T), args); } /// /// Remote Procedure Call to remove a from a . /// /// The to remove the from. /// The unique ID of the . [MethodRpc((uint)MiraRpc.RemoveModifier)] public static void RpcRemoveModifier(this PlayerControl target, Guid uniqueId) { target.RemoveModifier(uniqueId); } /// /// Remote Procedure Call to remove a from a by type ID. /// /// The to remove the from. /// The type ID of the . /// Optional predicate to filter the s. public static void RpcRemoveModifier( this PlayerControl target, uint typeId, Func? predicate = null) { var modifier = target.GetModifier(typeId, predicate); if (modifier is null) { Error($"Player {target.PlayerId} does not have modifier with type ID {typeId}."); return; } target.RpcRemoveModifier(modifier.UniqueId); } /// /// Remote Procedure Call to remove a from a . /// /// The to remove the from. /// The type of the . /// Optional predicate to filter the s. public static void RpcRemoveModifier( this PlayerControl player, Type type, Func? predicate = null) { var id = ModifierManager.GetModifierTypeId(type) ?? throw new InvalidOperationException( $"Modifier {type.Name} is not registered."); player.RpcRemoveModifier(id, predicate); } /// /// Remote Procedure Call to remove a from a . /// /// The to remove the from. /// Optional predicate to filter the s. /// The Type of the . public static void RpcRemoveModifier(this PlayerControl player, Func? predicate = null) where T : BaseModifier { player.RpcRemoveModifier(typeof(T), predicate); } /// /// Gets the for a . /// /// The object. /// A if there is one, otherwise. public static ModifierComponent GetModifierComponent(this PlayerControl player) { if (ModifierComponents.TryGetValue(player, out var component)) { return component; } component = player.GetComponent(); if (!component) { throw new InvalidOperationException("ModifierComponent is not attached to the player."); } ModifierComponents[player] = component; return component; } /// /// Checks if the has a specific . /// /// The type of the . /// The instance. /// Optional predicate to filter the s. /// if the has the , otherwise. public static bool HasModifier(this PlayerControl player, Func? predicate = null) where T : BaseModifier { return player.GetModifierComponent().HasModifier(predicate); } /// /// Checks if the has a specific by type. /// /// The instance. /// The type of the modifier. /// Optional predicate to filter the s. /// if the has the , otherwise. public static bool HasModifier(this PlayerControl player, Type type, Func? predicate = null) { return player.GetModifierComponent().HasModifier(type, predicate); } /// /// Checks if the has a specific by type ID. /// /// The instance. /// The type ID of the . /// Optional predicate to filter the s. /// if the has the , otherwise. public static bool HasModifier( this PlayerControl player, uint typeId, Func? predicate = null) { return player.GetModifierComponent().HasModifier(typeId, predicate); } /// /// Checks if the has a specific modifier by its GUID. /// /// The instance. /// The unique ID of the . /// if the has the , otherwise. public static bool HasModifier(this PlayerControl player, Guid uniqueId) { return player.GetModifierComponent().HasModifier(uniqueId); } /// /// Clears all s from the . /// /// The player you want to clear s for. public static void ClearModifiers(this PlayerControl plr) { foreach (var mod in plr.GetModifierComponent().ActiveModifiers) { plr.RemoveModifier(mod); } } /// /// Clears all s from the . /// /// The player you want to clear s for. public static void RpcClearModifiers(this PlayerControl plr) { foreach (var mod in plr.GetModifierComponent().ActiveModifiers) { plr.RpcRemoveModifier(mod.UniqueId); } } /// /// Tries to get a . /// /// The instance. /// The or . /// The predicate to check the by. /// The Type of the . /// if the was found, otherwise. public static bool TryGetModifier(this PlayerControl player, [NotNullWhen(true)] out T? modifier, Func? predicate = null) where T : BaseModifier { return player.GetModifierComponent().TryGetModifier(out modifier, predicate); } /// /// Tries to get a by its type. /// /// The instance. /// The modifier type. /// The or . /// The predicate to check the by. /// if the was found, otherwise. public static bool TryGetModifier(this PlayerControl player, Type type, [NotNullWhen(true)] out BaseModifier? modifier, Func? predicate = null) { return player.GetModifierComponent().TryGetModifier(type, out modifier, predicate); } /// /// Tries to get a by its type ID. /// /// The instance. /// The type ID. /// The or . /// The predicate to check the by. /// if the was found, otherwise. public static bool TryGetModifier(this PlayerControl player, uint id, [NotNullWhen(true)] out BaseModifier? modifier, Func? predicate = null) { return player.GetModifierComponent().TryGetModifier(id, out modifier, predicate); } /// /// Tries to get a by its unique ID. /// /// The instance. /// The unique ID. /// The or . /// if the was found, otherwise. public static bool TryGetModifier(this PlayerControl player, Guid modifierGuid, [NotNullWhen(true)] out BaseModifier? modifier) { return player.GetModifierComponent().TryGetModifier(modifierGuid, out modifier); } /// /// Gets a specific from the . /// /// The type of the . /// The instance. /// Optional predicate to filter the s. /// The if found, otherwise. public static T? GetModifier(this PlayerControl player, Func? predicate = null) where T : BaseModifier { return player.GetModifierComponent().GetModifier(predicate); } /// /// Gets a specific from the by type. /// /// The instance. /// The type of the modifier. /// Optional predicate to filter the s. /// The if found, otherwise. public static BaseModifier? GetModifier( this PlayerControl player, Type type, Func? predicate = null) { return player.GetModifierComponent().GetModifier(type, predicate); } /// /// Gets a specific from the by its type ID. /// /// The instance. /// The type ID of the . /// Optional predicate to filter the s. /// The if found, otherwise. public static BaseModifier? GetModifier( this PlayerControl player, uint typeId, Func? predicate = null) { return player.GetModifierComponent().GetModifier(typeId, predicate); } /// /// Gets a specific from the by its GUID. /// /// The instance. /// The GUID of the . /// The if found, otherwise. public static BaseModifier? GetModifier( this PlayerControl player, Guid uniqueId) { return player.GetModifierComponent().GetModifier(uniqueId); } /// /// Gets all s from the . /// /// The type of the s. /// The instance. /// Optional predicate to filter the s. /// An of s. public static IEnumerable GetModifiers(this PlayerControl player, Func? predicate = null) where T : BaseModifier { return player.GetModifierComponent().GetModifiers(predicate); } /// /// Gets all s of a specific type from the . /// /// The instance. /// The type of the modifiers. /// Optional predicate to filter the s. /// An of s. public static IEnumerable GetModifiers( this PlayerControl player, Type type, Func? predicate = null) { return player.GetModifierComponent().GetModifiers(type, predicate); } /// /// Gets all s of a specific type from the by type ID. /// /// The instance. /// The type ID of the s. /// Optional predicate to filter the s. /// An of s. public static IEnumerable GetModifiers( this PlayerControl player, uint typeId, Func? predicate = null) { return player.GetModifierComponent().GetModifiers(typeId, predicate); } /// /// Removes a specific from the . /// /// The instance. /// The to remove. public static void RemoveModifier(this PlayerControl player, BaseModifier modifier) { player.GetModifierComponent().RemoveModifier(modifier); } /// /// Removes a specific from the . /// /// The type of the . /// The instance. /// Optional predicate to filter the s. public static void RemoveModifier(this PlayerControl player, Func? predicate = null) where T : BaseModifier { player.GetModifierComponent().RemoveModifier(predicate); } /// /// Removes a specific from the by type. /// /// The instance. /// The type of the modifier. /// Optional predicate to filter the s. public static void RemoveModifier(this PlayerControl player, Type type, Func? predicate = null) { player.GetModifierComponent().RemoveModifier(type, predicate); } /// /// Removes a specific from the by its type ID. /// /// The instance. /// The type ID of the . /// Optional predicate to filter the s. public static void RemoveModifier( this PlayerControl player, uint typeId, Func? predicate = null) { player.GetModifierComponent().RemoveModifier(typeId, predicate); } /// /// Removes a specific from the by its GUID. /// /// The instance. /// The GUID of the . public static void RemoveModifier( this PlayerControl player, Guid uniqueId) { player.GetModifierComponent().RemoveModifier(uniqueId); } /// /// Adds a specific to the . /// /// The type of the . /// The instance. /// The arguments to initialize the with. /// The added . public static T? AddModifier(this PlayerControl player, params object[] args) where T : BaseModifier { return player.GetModifierComponent().AddModifier(args); } /// /// Adds a specific to the . /// /// The instance. /// The to add. /// The added . public static BaseModifier? AddModifier(this PlayerControl player, BaseModifier modifier) { return player.GetModifierComponent().AddModifier(modifier); } /// /// Adds a specific to the by type. /// /// The instance. /// The type of the modifier. /// The arguments to initialize the with. /// The added . public static BaseModifier? AddModifier(this PlayerControl player, Type type, params object[] args) { return player.GetModifierComponent().AddModifier(type, args); } /// /// Adds a specific to the by type ID. /// /// The instance. /// The type ID of the . /// The arguments to initialize the with. /// The added . public static BaseModifier? AddModifier(this PlayerControl player, uint typeId, params object[] args) { return player.GetModifierComponent().AddModifier(typeId, args); } }