mirror of
https://github.com/All-Of-Us-Mods/MiraAPI.git
synced 2026-10-20 01:46:15 +00:00
major modifier overhaul
This commit is contained in:
1 parent
0ebec6d0f1
commit
1c6fa9a84d
13 files changed
+531
-447
No files matched your search
@@ -1,4 +1,6 @@
|
||||
namespace MiraAPI.Modifiers;
|
||||
using System;
|
||||
|
||||
namespace MiraAPI.Modifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for all modifiers.
|
||||
@@ -15,11 +17,6 @@ public abstract class BaseModifier
|
||||
/// </summary>
|
||||
public ModifierComponent? ModifierComponent { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the modifier id.
|
||||
/// </summary>
|
||||
public uint ModifierId { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the modifier name.
|
||||
/// </summary>
|
||||
@@ -40,6 +37,20 @@ public abstract class BaseModifier
|
||||
/// </summary>
|
||||
public virtual bool Unique => true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the modifier has been initialized.
|
||||
/// </summary>
|
||||
public bool Initialized { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the ID of the modifier.
|
||||
/// </summary>
|
||||
/// <returns>The ID of the modifier.</returns>
|
||||
public uint GetId()
|
||||
{
|
||||
return ModifierManager.GetModifierId(GetType()) ?? throw new InvalidOperationException("Modifier is not registered.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the HUD information for this modifier. Defaults to the modifier name. Does nothing if <see cref="HideOnUi"/> is true.
|
||||
/// </summary>
|
||||
|
||||
@@ -67,6 +67,7 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
|
||||
foreach (var modifier in _toAdd)
|
||||
{
|
||||
Modifiers.Add(modifier);
|
||||
modifier.Initialized = true;
|
||||
modifier.OnActivate();
|
||||
|
||||
if (modifier is TimedModifier { AutoStart: true } timer)
|
||||
@@ -123,46 +124,153 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of modifiers by their type, or null if the player doesn't have one.
|
||||
/// Gets a collection of modifiers by type.
|
||||
/// </summary>
|
||||
/// <param name="predicate">The predicate to check the modifier by.</param>
|
||||
/// <typeparam name="T">The Type of the Modifier.</typeparam>
|
||||
/// <returns>The Modifier if it is found, null otherwise.</returns>
|
||||
public IEnumerable<T> GetModifiersByType<T>() where T : BaseModifier
|
||||
[HideFromIl2Cpp]
|
||||
public IEnumerable<T> GetModifiersByType<T>(Func<T, bool>? predicate=null) where T : BaseModifier
|
||||
{
|
||||
return ActiveModifiers.OfType<T>();
|
||||
return ActiveModifiers.OfType<T>().Where(x => predicate == null || predicate(x));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a modifier by its type, or null if the player doesn't have it.
|
||||
/// Gets a collection of modifiers by type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The Type of the Modifier.</typeparam>
|
||||
/// <param name="type">The modifier type.</param>
|
||||
/// <param name="predicate">The predicate to check the modifier by.</param>
|
||||
/// <returns>The Modifier if it is found, null otherwise.</returns>
|
||||
public T? GetModifier<T>() where T : BaseModifier
|
||||
[HideFromIl2Cpp]
|
||||
public IEnumerable<BaseModifier> GetModifiersByType(Type type, Func<BaseModifier, bool>? predicate=null)
|
||||
{
|
||||
return GetModifiersByType<T>().FirstOrDefault();
|
||||
return ActiveModifiers.Where(x => x.GetType() == type && (predicate == null || predicate(x)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of modifiers by ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The Modifier ID.</param>
|
||||
/// <param name="predicate">The predicate to check the modifier by.</param>
|
||||
/// <returns>The Modifier if it is found, null otherwise.</returns>
|
||||
[HideFromIl2Cpp]
|
||||
public IEnumerable<BaseModifier> GetModifiersByType(uint id, Func<BaseModifier, bool>? predicate=null)
|
||||
{
|
||||
var type = ModifierManager.GetModifierType(id) ?? throw new InvalidOperationException(
|
||||
$"Cannot get modifier with id {id} because it is not registered.");
|
||||
|
||||
return GetModifiersByType(type, predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get a modifier by its type.
|
||||
/// </summary>
|
||||
/// <param name="modifier">The modifier or null.</param>
|
||||
/// <param name="predicate">The predicate to check the modifier by.</param>
|
||||
/// <typeparam name="T">The Type of the Modifier.</typeparam>
|
||||
/// <returns>True if the modifier was found, false otherwise.</returns>
|
||||
public bool TryGetModifier<T>(out T? modifier) where T : BaseModifier
|
||||
[HideFromIl2Cpp]
|
||||
public bool TryGetModifier<T>(out T? modifier, Func<T, bool>? predicate = null) where T : BaseModifier
|
||||
{
|
||||
modifier = GetModifier<T>();
|
||||
modifier = GetModifier(predicate);
|
||||
return modifier != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get a modifier by its type.
|
||||
/// </summary>
|
||||
/// <param name="type">The modifier type.</param>
|
||||
/// <param name="modifier">The modifier or null.</param>
|
||||
/// <param name="predicate">The predicate to check the modifier by.</param>
|
||||
/// <returns>True if the modifier was found, false otherwise.</returns>
|
||||
[HideFromIl2Cpp]
|
||||
public bool TryGetModifier(Type type, out BaseModifier? modifier, Func<BaseModifier, bool>? predicate = null)
|
||||
{
|
||||
modifier = GetModifier(type, predicate);
|
||||
return modifier != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get a modifier by its ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The modifier ID.</param>
|
||||
/// <param name="modifier">The modifier or null.</param>
|
||||
/// <param name="predicate">The predicate to check the modifier by.</param>
|
||||
/// <returns>True if the modifier was found, false otherwise.</returns>
|
||||
[HideFromIl2Cpp]
|
||||
public bool TryGetModifier(uint id, out BaseModifier? modifier, Func<BaseModifier, bool>? predicate = null)
|
||||
{
|
||||
var type = ModifierManager.GetModifierType(id) ?? throw new InvalidOperationException(
|
||||
$"Cannot get modifier with id {id} because it is not registered.");
|
||||
|
||||
return TryGetModifier(type, out modifier, predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a modifier by its type, or null if the player doesn't have it.
|
||||
/// </summary>
|
||||
/// <param name="predicate">The predicate to check the modifier by.</param>
|
||||
/// <typeparam name="T">The Type of the Modifier.</typeparam>
|
||||
/// <returns>The Modifier if it is found, null otherwise.</returns>
|
||||
[HideFromIl2Cpp]
|
||||
public T? GetModifier<T>(Func<T, bool>? predicate = null) where T : BaseModifier
|
||||
{
|
||||
return GetModifiersByType(predicate).FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a modifier by its type, or null if the player doesn't have it.
|
||||
/// </summary>
|
||||
/// <param name="type">The modifier type.</param>
|
||||
/// <param name="predicate">The predicate to check the modifier by.</param>
|
||||
/// <returns>The Modifier if it is found, null otherwise.</returns>
|
||||
[HideFromIl2Cpp]
|
||||
public BaseModifier? GetModifier(Type type, Func<BaseModifier, bool>? predicate = null)
|
||||
{
|
||||
return GetModifiersByType(type).FirstOrDefault(predicate ?? (_ => true));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a modifier by its type, or null if the player doesn't have it.
|
||||
/// </summary>
|
||||
/// <param name="id">The modifier ID.</param>
|
||||
/// <param name="predicate">The predicate to check the modifier by.</param>
|
||||
/// <returns>The Modifier if it is found, null otherwise.</returns>
|
||||
[HideFromIl2Cpp]
|
||||
public BaseModifier? GetModifier(uint id, Func<BaseModifier, bool>? predicate = null)
|
||||
{
|
||||
var type = ModifierManager.GetModifierType(id) ?? throw new InvalidOperationException(
|
||||
$"Cannot get modifier with id {id} because it is not registered.");
|
||||
|
||||
return GetModifier(type, predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a modifier from the player.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The modifier type.</typeparam>
|
||||
/// <param name="predicate">The predicate to check the modifier by.</param>
|
||||
[HideFromIl2Cpp]
|
||||
public void RemoveModifier<T>(Func<T, bool>? predicate = null) where T : BaseModifier
|
||||
{
|
||||
RemoveModifier(typeof(T), x => predicate == null || predicate((T)x));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a modifier from the player.
|
||||
/// </summary>
|
||||
/// <param name="type">The modifier type.</param>
|
||||
/// <param name="predicate">The predicate to check the modifier by.</param>
|
||||
[HideFromIl2Cpp]
|
||||
public void RemoveModifier(Type type)
|
||||
public void RemoveModifier(Type type, Func<BaseModifier, bool>? predicate = null)
|
||||
{
|
||||
var modifier = Modifiers.Find(x => x.GetType() == type);
|
||||
var modifiers = Modifiers.Where(x => x.GetType() == type && (predicate == null || predicate(x))).ToList();
|
||||
if (modifiers.Count > 1)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot remove modifier {type.Name} because there are multiple instances of that modifier.");
|
||||
}
|
||||
|
||||
var modifier = modifiers.FirstOrDefault();
|
||||
if (modifier is null)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Cannot remove modifier {type.Name} because it is not active.");
|
||||
@@ -172,32 +280,17 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
|
||||
RemoveModifier(modifier);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a modifier from the player.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The modifier type.</typeparam>
|
||||
[HideFromIl2Cpp]
|
||||
public void RemoveModifier<T>() where T : BaseModifier
|
||||
{
|
||||
RemoveModifier(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a modifier from the player.
|
||||
/// </summary>
|
||||
/// <param name="modifierId">The modifier ID.</param>
|
||||
/// <param name="predicate">The predicate to check the modifier by.</param>
|
||||
[HideFromIl2Cpp]
|
||||
public void RemoveModifier(uint modifierId)
|
||||
public void RemoveModifier(uint modifierId, Func<BaseModifier, bool>? predicate = null)
|
||||
{
|
||||
var modifier = Modifiers.Find(x => x.ModifierId == modifierId);
|
||||
|
||||
if (modifier is null)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Cannot remove modifier with id {modifierId} because it is not active.");
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveModifier(modifier);
|
||||
var type = ModifierManager.GetModifierType(modifierId) ?? throw new InvalidOperationException(
|
||||
$"Cannot remove modifier with id {modifierId} because it is not registered.");
|
||||
RemoveModifier(type, predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -216,6 +309,18 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
|
||||
_toRemove.Add(modifier);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a modifier to the player.
|
||||
/// </summary>
|
||||
/// <param name="args">The arguments to initialize the modifier constructor with.</param>
|
||||
/// <typeparam name="T">The Type of the modifier.</typeparam>
|
||||
/// <returns>The new modifier.</returns>
|
||||
[HideFromIl2Cpp]
|
||||
public T? AddModifier<T>(params object[] args) where T : BaseModifier
|
||||
{
|
||||
return AddModifier(typeof(T), args) as T;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a modifier to the player.
|
||||
/// </summary>
|
||||
@@ -224,24 +329,22 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
|
||||
[HideFromIl2Cpp]
|
||||
public BaseModifier? AddModifier(BaseModifier modifier)
|
||||
{
|
||||
if (Modifiers.Contains(modifier))
|
||||
var id = modifier.GetId();
|
||||
if (modifier.Unique && Modifiers.Find(x => x.GetId() == id) != null)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Player already has modifier with id {modifier.ModifierId}!");
|
||||
Logger<MiraApiPlugin>.Error($"Player already has modifier with id {id}!");
|
||||
return null;
|
||||
}
|
||||
|
||||
var modifierId = ModifierManager.GetModifierId(modifier.GetType());
|
||||
|
||||
if (modifierId == null)
|
||||
if (Modifiers.Contains(modifier))
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Cannot add modifier {modifier.GetType().Name} because it has no ID!");
|
||||
Logger<MiraApiPlugin>.Error($"Player already has this modifier!");
|
||||
return null;
|
||||
}
|
||||
|
||||
_toAdd.Add(modifier);
|
||||
modifier.Player = _player;
|
||||
modifier.ModifierComponent = this;
|
||||
modifier.ModifierId = modifierId.Value;
|
||||
return modifier;
|
||||
}
|
||||
|
||||
@@ -249,66 +352,79 @@ public class ModifierComponent(IntPtr cppPtr) : MonoBehaviour(cppPtr)
|
||||
/// Adds a modifier to the player.
|
||||
/// </summary>
|
||||
/// <param name="type">The modifier type.</param>
|
||||
/// <param name="args">The arguments to initialize the modifier constructor with.</param>
|
||||
/// <returns>The modifier that was added.</returns>
|
||||
[HideFromIl2Cpp]
|
||||
public BaseModifier? AddModifier(Type type)
|
||||
public BaseModifier? AddModifier(Type type, params object[] args)
|
||||
{
|
||||
var modifierId = ModifierManager.GetModifierId(type);
|
||||
if (modifierId == null)
|
||||
BaseModifier? modifier;
|
||||
if (args.Length > 0)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Cannot add modifier {type.Name} because it is not registered.");
|
||||
return null;
|
||||
modifier = ModifierFactory.CreateInstance(type, 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.");
|
||||
}
|
||||
}
|
||||
|
||||
if (Modifiers.Find(x => x.ModifierId == modifierId && x.Unique) != null)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Player already has modifier with id {modifierId}!");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Activator.CreateInstance(type) is not BaseModifier modifier)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Cannot add modifier {type.Name} because it is null.");
|
||||
return null;
|
||||
}
|
||||
|
||||
AddModifier(modifier);
|
||||
|
||||
return modifier;
|
||||
return AddModifier(modifier);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a modifier to the player.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The Type of the modifier.</typeparam>
|
||||
/// <returns>The new modifier.</returns>
|
||||
/// <param name="id">The ID of the modifier.</param>
|
||||
/// <param name="args">The arguments to initialize the modifier constructor with.</param>
|
||||
/// <returns>The modifier if it was created, or null if it failed.</returns>
|
||||
[HideFromIl2Cpp]
|
||||
public T? AddModifier<T>() where T : BaseModifier
|
||||
public BaseModifier? AddModifier(uint id, params object[] args)
|
||||
{
|
||||
return AddModifier(typeof(T)) as T;
|
||||
var type = ModifierManager.GetModifierType(id) ?? throw new InvalidOperationException(
|
||||
$"Cannot add modifier with id {id} because it is not registered.");
|
||||
|
||||
return AddModifier(type, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a player has an active or queued modifier by its ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The Modifier ID.</param>
|
||||
/// <param name="predicate">The predicate to check the modifier.</param>
|
||||
/// <returns>True if the Modifier is present, false otherwise.</returns>
|
||||
public bool HasModifier(uint id, Func<BaseModifier, bool>? predicate=null)
|
||||
{
|
||||
return ActiveModifiers.Exists(x => x.ModifierId == id && (predicate == null || predicate(x))) ||
|
||||
_toAdd.Exists(x => x.ModifierId == id && (predicate == null || predicate(x)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a player has an active or queued modifier by its type.
|
||||
/// Checks if a player has an active modifier by its type.
|
||||
/// </summary>
|
||||
/// <param name="predicate">The predicate to check the modifier.</param>
|
||||
/// <typeparam name="T">The Type of the Modifier.</typeparam>
|
||||
/// <returns>True if the Modifier is present, false otherwise.</returns>
|
||||
[HideFromIl2Cpp]
|
||||
public bool HasModifier<T>(Func<T, bool>? predicate=null) where T : BaseModifier
|
||||
{
|
||||
return ModifierManager.GetModifierId(typeof(T)) is { } id &&
|
||||
HasModifier(id, (Func<BaseModifier, bool>?)predicate);
|
||||
return ActiveModifiers.Exists(x => x is T modifier && (predicate == null || predicate(modifier)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a player has an active modifier by its type.
|
||||
/// </summary>
|
||||
/// <param name="type">The modifier type.</param>
|
||||
/// <param name="predicate">The predicate to check the modifier.</param>
|
||||
/// <returns>True if the Modifier is present, false otherwise.</returns>
|
||||
[HideFromIl2Cpp]
|
||||
public bool HasModifier(Type type, Func<BaseModifier, bool>? predicate=null)
|
||||
{
|
||||
return ActiveModifiers.Exists(x => x.GetType() == type && (predicate == null || predicate(x)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a player has an active modifier by its ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The Modifier ID.</param>
|
||||
/// <param name="predicate">The predicate to check the modifier.</param>
|
||||
/// <returns>True if the Modifier is present, false otherwise.</returns>
|
||||
[HideFromIl2Cpp]
|
||||
public bool HasModifier(uint id, Func<BaseModifier, bool>? predicate=null)
|
||||
{
|
||||
var type = ModifierManager.GetModifierType(id) ?? throw new InvalidOperationException(
|
||||
$"Cannot get modifier with id {id} because it is not registered.");
|
||||
|
||||
return HasModifier(type, predicate);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace MiraAPI.Modifiers;
|
||||
namespace MiraAPI.Modifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Modifier data for networking.
|
||||
/// </summary>
|
||||
/// <param name="type">The Type of the modifier.</param>
|
||||
/// <param name="id">The ID of the modifier.</param>
|
||||
/// <param name="args">Parameters for constructor.</param>
|
||||
public readonly struct ModifierData(Type type, object[] args)
|
||||
public readonly struct ModifierData(uint id, object[] args)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the type of the modifier.
|
||||
/// </summary>
|
||||
public Type Type { get; } = type;
|
||||
public uint Id { get; } = id;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parameters for the constructor.
|
||||
|
||||
@@ -8,11 +8,81 @@ using Reactor.Utilities;
|
||||
namespace MiraAPI.Modifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for modifiers.
|
||||
/// Extensions for modifiers.
|
||||
/// </summary>
|
||||
public static class ModifierExtensions
|
||||
{
|
||||
internal static Dictionary<PlayerControl, ModifierComponent> ModifierComponents { get; } = [];
|
||||
/// <summary>
|
||||
/// Gets the dictionary to cache ModifierComponents.
|
||||
/// </summary>
|
||||
public static Dictionary<PlayerControl, ModifierComponent> ModifierComponents { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Remote Procedure Call to add a modifier to a player.
|
||||
/// </summary>
|
||||
/// <param name="target">The player to add the modifier to.</param>
|
||||
/// <param name="modifierId">The modifier ID.</param>
|
||||
/// <param name="args">The arguments to initialize the modifier constructor with.</param>
|
||||
public static void RpcAddModifier(this PlayerControl target, uint modifierId, params object[] args)
|
||||
{
|
||||
_ = ModifierManager.GetModifierType(modifierId) ?? throw new InvalidOperationException(
|
||||
$"Modifier with ID {modifierId} is not registered.");
|
||||
|
||||
Rpc<AddModifierRpc>.Instance.Send(target, new ModifierData(modifierId, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remote Procedure Call to add a modifier to a player.
|
||||
/// </summary>
|
||||
/// <param name="player">The player to add the modifier to.</param>
|
||||
/// <param name="type">The type of the modifier.</param>
|
||||
/// <param name="args">The arguments to initialize the modifier constructor with.</param>
|
||||
public static void RpcAddModifier(this PlayerControl player, Type type, params object[] args)
|
||||
{
|
||||
var id = ModifierManager.GetModifierId(type) ?? throw new InvalidOperationException(
|
||||
$"Modifier {type.Name} is not registered.");
|
||||
|
||||
player.RpcAddModifier(id, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remote Procedure Call to add a modifier to a player.
|
||||
/// </summary>
|
||||
/// <param name="player">The player to add the modifier to.</param>
|
||||
/// <param name="args">The arguments to initialize the modifier constructor with.</param>
|
||||
/// <typeparam name="T">The modifier Type.</typeparam>
|
||||
public static void RpcAddModifier<T>(this PlayerControl player, params object[] args) where T : BaseModifier
|
||||
{
|
||||
player.RpcAddModifier(typeof(T), args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remote Procedure Call to remove a modifier from a player.
|
||||
/// </summary>
|
||||
/// <param name="target">The player to remove the modifier from.</param>
|
||||
/// <param name="modifierId">The ID of the modifier.</param>
|
||||
[MethodRpc((uint)MiraRpc.RemoveModifier)]
|
||||
public static void RpcRemoveModifier(this PlayerControl target, uint modifierId)
|
||||
{
|
||||
target.RemoveModifier(modifierId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remote Procedure Call to remove a modifier from a player.
|
||||
/// </summary>
|
||||
/// <param name="player">The player to remove the modifier from.</param>
|
||||
/// <typeparam name="T">The Type of the Modifier.</typeparam>
|
||||
public static void RpcRemoveModifier<T>(this PlayerControl player) where T : BaseModifier
|
||||
{
|
||||
var id = ModifierManager.GetModifierId(typeof(T));
|
||||
if (id == null)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Cannot add modifier {typeof(T).Name} because it is not registered.");
|
||||
return;
|
||||
}
|
||||
|
||||
player.RpcRemoveModifier(id.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ModifierComponent for a player.
|
||||
@@ -37,102 +107,217 @@ public static class ModifierExtensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a modifier by its type, or null if the player doesn't have it.
|
||||
/// Checks if the player has a specific modifier.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <typeparam name="T">The Type of the Modifier.</typeparam>
|
||||
/// <returns>The Modifier if it is found, null otherwise.</returns>
|
||||
public static T? GetModifier<T>(this PlayerControl? player) where T : BaseModifier
|
||||
/// <typeparam name="T">The type of the modifier.</typeparam>
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="predicate">Optional predicate to filter the modifiers.</param>
|
||||
/// <returns>True if the player has the modifier, false otherwise.</returns>
|
||||
public static bool HasModifier<T>(this PlayerControl player, Func<T, bool>? predicate = null) where T : BaseModifier
|
||||
{
|
||||
return player?.GetModifierComponent()?.ActiveModifiers.Find(x => x is T) as T;
|
||||
return player.GetModifierComponent()!.HasModifier(predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a player has a modifier.
|
||||
/// Checks if the player has a specific modifier by type.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <typeparam name="T">The Type of the Modifier.</typeparam>
|
||||
/// <returns>True if the Modifier is present, false otherwise.</returns>
|
||||
public static bool HasModifier<T>(this PlayerControl? player) where T : BaseModifier
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="type">The type of the modifier.</param>
|
||||
/// <param name="predicate">Optional predicate to filter the modifiers.</param>
|
||||
/// <returns>True if the player has the modifier, false otherwise.</returns>
|
||||
public static bool HasModifier(this PlayerControl player, Type type, Func<BaseModifier, bool>? predicate = null)
|
||||
{
|
||||
return player?.GetModifierComponent() != null &&
|
||||
player.GetModifierComponent()!.HasModifier<T>();
|
||||
return player.GetModifierComponent()!.HasModifier(type, predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a player has a modifier by its ID.
|
||||
/// Checks if the player has a specific modifier by ID.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <param name="id">The Modifier ID.</param>
|
||||
/// <returns>True if the Modifier is present, false otherwise.</returns>
|
||||
public static bool HasModifier(this PlayerControl? player, uint id)
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="id">The ID of the modifier.</param>
|
||||
/// <param name="predicate">Optional predicate to filter the modifiers.</param>
|
||||
/// <returns>True if the player has the modifier, false otherwise.</returns>
|
||||
public static bool HasModifier(this PlayerControl player, uint id, Func<BaseModifier, bool>? predicate = null)
|
||||
{
|
||||
return player?.GetModifierComponent() != null &&
|
||||
player.GetModifierComponent()!.HasModifier(id);
|
||||
return player.GetModifierComponent()!.HasModifier(id, predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remote Procedure Call to remove a modifier from a player.
|
||||
/// Gets a specific modifier from the player.
|
||||
/// </summary>
|
||||
/// <param name="target">The player to remove the modifier from.</param>
|
||||
/// <typeparam name="T">The type of the modifier.</typeparam>
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="predicate">Optional predicate to filter the modifiers.</param>
|
||||
/// <returns>The modifier if found, null otherwise.</returns>
|
||||
public static T? GetModifier<T>(this PlayerControl player, Func<T, bool>? predicate = null) where T : BaseModifier
|
||||
{
|
||||
return player.GetModifierComponent()!.GetModifier(predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific modifier from the player by type.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="type">The type of the modifier.</param>
|
||||
/// <param name="predicate">Optional predicate to filter the modifiers.</param>
|
||||
/// <returns>The modifier if found, null otherwise.</returns>
|
||||
public static BaseModifier? GetModifier(
|
||||
this PlayerControl player,
|
||||
Type type,
|
||||
Func<BaseModifier, bool>? predicate = null)
|
||||
{
|
||||
return player.GetModifierComponent()!.GetModifier(type, predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific modifier from the player by ID.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="id">The ID of the modifier.</param>
|
||||
/// <param name="predicate">Optional predicate to filter the modifiers.</param>
|
||||
/// <returns>The modifier if found, null otherwise.</returns>
|
||||
public static BaseModifier? GetModifier(
|
||||
this PlayerControl player,
|
||||
uint id,
|
||||
Func<BaseModifier, bool>? predicate = null)
|
||||
{
|
||||
return player.GetModifierComponent()!.GetModifier(id, predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all modifiers of a specific type from the player.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the modifiers.</typeparam>
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="predicate">Optional predicate to filter the modifiers.</param>
|
||||
/// <returns>An enumerable of modifiers.</returns>
|
||||
public static IEnumerable<T> GetModifiersByType<T>(this PlayerControl player, Func<T, bool>? predicate = null)
|
||||
where T : BaseModifier
|
||||
{
|
||||
return player.GetModifierComponent()!.GetModifiersByType(predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all modifiers of a specific type from the player.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="type">The type of the modifiers.</param>
|
||||
/// <param name="predicate">Optional predicate to filter the modifiers.</param>
|
||||
/// <returns>An enumerable of modifiers.</returns>
|
||||
public static IEnumerable<BaseModifier> GetModifiersByType(
|
||||
this PlayerControl player,
|
||||
Type type,
|
||||
Func<BaseModifier, bool>? predicate = null)
|
||||
{
|
||||
return player.GetModifierComponent()!.GetModifiersByType(type, predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all modifiers of a specific type from the player by ID.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="id">The ID of the modifiers.</param>
|
||||
/// <param name="predicate">Optional predicate to filter the modifiers.</param>
|
||||
/// <returns>An enumerable of modifiers.</returns>
|
||||
public static IEnumerable<BaseModifier> GetModifiersByType(
|
||||
this PlayerControl player,
|
||||
uint id,
|
||||
Func<BaseModifier, bool>? predicate = null)
|
||||
{
|
||||
return player.GetModifierComponent()!.GetModifiersByType(id, predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a specific modifier from the player.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the modifier.</typeparam>
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="predicate">Optional predicate to filter the modifiers.</param>
|
||||
public static void RemoveModifier<T>(this PlayerControl player, Func<T, bool>? predicate = null)
|
||||
where T : BaseModifier
|
||||
{
|
||||
player.GetModifierComponent()!.RemoveModifier(predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a specific modifier from the player by type.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="type">The type of the modifier.</param>
|
||||
/// <param name="predicate">Optional predicate to filter the modifiers.</param>
|
||||
public static void RemoveModifier(this PlayerControl player, Type type, Func<BaseModifier, bool>? predicate = null)
|
||||
{
|
||||
player.GetModifierComponent()!.RemoveModifier(type, predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a specific modifier from the player by ID.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="modifierId">The ID of the modifier.</param>
|
||||
[MethodRpc((uint)MiraRpc.RemoveModifier)]
|
||||
public static void RpcRemoveModifier(this PlayerControl target, uint modifierId)
|
||||
/// <param name="predicate">Optional predicate to filter the modifiers.</param>
|
||||
public static void RemoveModifier(
|
||||
this PlayerControl player,
|
||||
uint modifierId,
|
||||
Func<BaseModifier, bool>? predicate = null)
|
||||
{
|
||||
target.GetModifierComponent()?.RemoveModifier(modifierId);
|
||||
player.GetModifierComponent()!.RemoveModifier(modifierId, predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remote Procedure Call to remove a modifier from a player.
|
||||
/// Removes a specific modifier from the player.
|
||||
/// </summary>
|
||||
/// <param name="player">The player to remove the modifier from.</param>
|
||||
/// <typeparam name="T">The Type of the Modifier.</typeparam>
|
||||
public static void RpcRemoveModifier<T>(this PlayerControl player) where T : BaseModifier
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="modifier">The modifier to remove.</param>
|
||||
public static void RemoveModifier(this PlayerControl player, BaseModifier modifier)
|
||||
{
|
||||
var id = ModifierManager.GetModifierId(typeof(T));
|
||||
|
||||
if (id == null)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Cannot add modifier {typeof(T).Name} because it is not registered.");
|
||||
return;
|
||||
}
|
||||
|
||||
player.RpcRemoveModifier(id.Value);
|
||||
player.GetModifierComponent()!.RemoveModifier(modifier);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remote Procedure Call to add a modifier to a player.
|
||||
/// Adds a specific modifier to the player.
|
||||
/// </summary>
|
||||
/// <param name="target">The player to add the modifier to.</param>
|
||||
/// <param name="modifierId">The modifier ID.</param>
|
||||
/// <typeparam name="T">The type of the modifier.</typeparam>
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="args">The arguments to initialize the modifier constructor with.</param>
|
||||
public static void RpcAddModifier(this PlayerControl target, uint modifierId, params object[] args)
|
||||
/// <returns>The added modifier.</returns>
|
||||
public static T? AddModifier<T>(this PlayerControl player, params object[] args) where T : BaseModifier
|
||||
{
|
||||
var type = ModifierManager.GetModifierType(modifierId);
|
||||
if (type == null)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Cannot add modifier with id {modifierId} because it is not registered.");
|
||||
return;
|
||||
}
|
||||
|
||||
Rpc<AddModifierRpc>.Instance.Send(target, new ModifierData(type, args));
|
||||
return player.GetModifierComponent()!.AddModifier<T>(args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remote Procedure Call to add a modifier to a player.
|
||||
/// Adds a specific modifier to the player.
|
||||
/// </summary>
|
||||
/// <param name="player">The player to add the modifier to.</param>
|
||||
/// <param name="args">The arguments to initialize the modifier constructor with.</param>
|
||||
/// <typeparam name="T">The modifier Type.</typeparam>
|
||||
public static void RpcAddModifier<T>(this PlayerControl player, params object[] args) where T : BaseModifier
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="modifier">The modifier to add.</param>
|
||||
/// <returns>The added modifier.</returns>
|
||||
public static BaseModifier? AddModifier(this PlayerControl player, BaseModifier modifier)
|
||||
{
|
||||
var id = ModifierManager.GetModifierId(typeof(T));
|
||||
if (id == null)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Cannot add modifier {typeof(T).Name} because it is not registered.");
|
||||
return;
|
||||
}
|
||||
return player.GetModifierComponent()!.AddModifier(modifier);
|
||||
}
|
||||
|
||||
player.RpcAddModifier(id.Value, args);
|
||||
/// <summary>
|
||||
/// Adds a specific modifier to the player by type.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="type">The type of the modifier.</param>
|
||||
/// <param name="args">The arguments to initialize the modifier constructor with.</param>
|
||||
/// <returns>The added modifier.</returns>
|
||||
public static BaseModifier? AddModifier(this PlayerControl player, Type type, params object[] args)
|
||||
{
|
||||
return player.GetModifierComponent()!.AddModifier(type, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a specific modifier to the player by ID.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl instance.</param>
|
||||
/// <param name="id">The ID of the modifier.</param>
|
||||
/// <param name="args">The arguments to initialize the modifier constructor with.</param>
|
||||
/// <returns>The added modifier.</returns>
|
||||
public static BaseModifier? AddModifier(this PlayerControl player, uint id, params object[] args)
|
||||
{
|
||||
return player.GetModifierComponent()!.AddModifier(id, args);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,28 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace MiraAPI.Modifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Factory for creating instances of a modifier. More efficient than using reflection.
|
||||
/// </summary>
|
||||
public static class ModifierFactory
|
||||
{
|
||||
private static Func<object[], BaseModifier>? _constructor;
|
||||
|
||||
private static Func<object[], BaseModifier> CreateConstructor(Type type)
|
||||
private static Func<object[], BaseModifier> CreateConstructor(Type type, params object[] args)
|
||||
{
|
||||
var constructorInfo = type.GetConstructors()
|
||||
.OrderByDescending(c => c.GetParameters().Length)
|
||||
.FirstOrDefault() ?? throw new InvalidOperationException($"Type {type} does not have a public constructor.");
|
||||
var constructorInfo = Array.Find(
|
||||
type.GetConstructors(),
|
||||
x =>
|
||||
{
|
||||
var parameters = x.GetParameters();
|
||||
return parameters.Length == args.Length && Array.TrueForAll(
|
||||
parameters,
|
||||
t => t.ParameterType.IsInstanceOfType(args[t.Position]));
|
||||
}) ?? throw new InvalidOperationException(
|
||||
$"Could not find a constructor for type {type} with the specified arguments.");
|
||||
|
||||
var parameters = constructorInfo.GetParameters();
|
||||
|
||||
var argsParam = Expression.Parameter(typeof(object[]), "args");
|
||||
@@ -32,9 +42,15 @@ public static class ModifierFactory
|
||||
return lambda.Compile();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a modifier with the specified type and arguments.
|
||||
/// </summary>
|
||||
/// <param name="type">Modifier type.</param>
|
||||
/// <param name="args">Arguments.</param>
|
||||
/// <returns>An instance of the modifier.</returns>
|
||||
public static BaseModifier CreateInstance(Type type, params object[] args)
|
||||
{
|
||||
_constructor ??= CreateConstructor(type);
|
||||
_constructor ??= CreateConstructor(type, args);
|
||||
return _constructor(args);
|
||||
}
|
||||
}
|
||||
@@ -47,11 +63,18 @@ public static class ModifierFactory<T> where T : BaseModifier
|
||||
{
|
||||
private static readonly Func<object[], T> Constructor = CreateConstructor();
|
||||
|
||||
private static Func<object[], T> CreateConstructor()
|
||||
private static Func<object[], T> CreateConstructor(params object[] args)
|
||||
{
|
||||
var constructorInfo = typeof(T).GetConstructors()
|
||||
.OrderByDescending(c => c.GetParameters().Length)
|
||||
.FirstOrDefault() ?? throw new InvalidOperationException($"Type {typeof(T)} does not have a public constructor.");
|
||||
var constructorInfo = Array.Find(
|
||||
typeof(T).GetConstructors(),
|
||||
x =>
|
||||
{
|
||||
var parameters = x.GetParameters();
|
||||
return parameters.Length == args.Length && Array.TrueForAll(
|
||||
parameters,
|
||||
t => t.ParameterType.IsInstanceOfType(args[t.Position]));
|
||||
}) ?? throw new InvalidOperationException($"Could not find a constructor for type {typeof(T)} with the specified arguments.");
|
||||
|
||||
var parameters = constructorInfo.GetParameters();
|
||||
|
||||
var argsParam = Expression.Parameter(typeof(object[]), "args");
|
||||
|
||||
@@ -48,7 +48,12 @@ public static class ModifierManager
|
||||
/// <returns>The ID of the modifier.</returns>
|
||||
public static uint? GetModifierId(Type type)
|
||||
{
|
||||
return TypeToIdModifierMap.GetValueOrDefault(type);
|
||||
if (!TypeToIdModifierMap.TryGetValue(type, out var id))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
internal static bool RegisterModifier(Type modifierType, MiraPluginInfo info)
|
||||
@@ -61,7 +66,6 @@ public static class ModifierManager
|
||||
IdToTypeModifierMap.Add(GetNextId(), modifierType);
|
||||
TypeToIdModifierMap.Add(modifierType, _nextId);
|
||||
var bm = (BaseModifier)FormatterServices.GetUninitializedObject(modifierType); // this probably isn't a great idea
|
||||
bm.ModifierId = _nextId;
|
||||
info.Modifiers.Add(bm);
|
||||
|
||||
if (!typeof(GameModifier).IsAssignableFrom(modifierType))
|
||||
|
||||
@@ -102,7 +102,7 @@ public abstract class TimedModifier : BaseModifier
|
||||
|
||||
if (RemoveOnComplete)
|
||||
{
|
||||
ModifierComponent?.RemoveModifier(ModifierId);
|
||||
ModifierComponent?.RemoveModifier(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Hazel;
|
||||
using MiraAPI.Modifiers;
|
||||
using Reactor.Networking.Attributes;
|
||||
@@ -18,44 +15,45 @@ namespace MiraAPI.Networking;
|
||||
[RegisterCustomRpc((uint)MiraRpc.AddModifier)]
|
||||
public class AddModifierRpc(MiraApiPlugin plugin, uint id) : PlayerCustomRpc<MiraApiPlugin, ModifierData>(plugin, id)
|
||||
{
|
||||
private static readonly Dictionary<Type, ParameterInfo[]> ParameterCache = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public override RpcLocalHandling LocalHandling => RpcLocalHandling.Before;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Write(MessageWriter writer, ModifierData data)
|
||||
{
|
||||
var modId = ModifierManager.GetModifierId(data.Type);
|
||||
writer.WritePacked((uint)modId!);
|
||||
MessageSerializer.Serialize(writer, data.Args);
|
||||
writer.WritePacked(data.Id);
|
||||
writer.WritePacked(data.Args.Length);
|
||||
foreach (var arg in data.Args)
|
||||
{
|
||||
writer.Write(arg.GetType().AssemblyQualifiedName);
|
||||
writer.Serialize(arg);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ModifierData Read(MessageReader reader)
|
||||
{
|
||||
var modId = reader.ReadPackedUInt32();
|
||||
var modifier = ModifierManager.GetModifierType(modId)!;
|
||||
var argCount = reader.ReadPackedUInt32();
|
||||
var objects = new object[argCount];
|
||||
|
||||
if (!ParameterCache.TryGetValue(modifier, out var paramTypes))
|
||||
if (argCount > 0)
|
||||
{
|
||||
paramTypes = modifier.GetConstructors().OrderBy(x => x.GetParameters().Length).First().GetParameters();
|
||||
ParameterCache[modifier] = paramTypes;
|
||||
var types = new Type[argCount];
|
||||
for (var i = 0; i < argCount; i++)
|
||||
{
|
||||
var name = reader.ReadString();
|
||||
types[i] = Type.GetType(name) ?? throw new InvalidOperationException($"Type not found: {name}");
|
||||
objects[i] = reader.Deserialize(types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var objects = new object[paramTypes.Length];
|
||||
foreach (var paramType in paramTypes)
|
||||
{
|
||||
objects[paramType.Position] = reader.Deserialize(paramType.ParameterType);
|
||||
}
|
||||
|
||||
return new ModifierData(modifier, objects);
|
||||
return new ModifierData(modId, objects);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Handle(PlayerControl innerNetObject, ModifierData data)
|
||||
public override void Handle(PlayerControl player, ModifierData data)
|
||||
{
|
||||
var modifier = ModifierFactory.CreateInstance(data.Type, data.Args);
|
||||
innerNetObject.GetModifierComponent()?.AddModifier(modifier);
|
||||
player.AddModifier(data.Id, data.Args);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using HarmonyLib;
|
||||
using MiraAPI.Modifiers;
|
||||
using MiraAPI.Roles;
|
||||
using MiraAPI.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MiraAPI.Patches.Freeplay;
|
||||
|
||||
@@ -326,7 +326,7 @@ internal static class TaskAdderPatches
|
||||
}
|
||||
|
||||
var taskAddButton = Object.Instantiate(instance.RoleButton);
|
||||
taskAddButton.name = modifier.ModifierId.ToString(CultureInfo.InvariantCulture);
|
||||
taskAddButton.name = modifier.GetId().ToString(NumberFormatInfo.InvariantInfo);
|
||||
taskAddButton.role = null;
|
||||
taskAddButton.MyTask = null;
|
||||
taskAddButton.SafePositionWorld = instance.SafePositionWorld;
|
||||
@@ -336,14 +336,15 @@ internal static class TaskAdderPatches
|
||||
taskAddButton.Button.OnClick = new Button.ButtonClickedEvent();
|
||||
taskAddButton.Button.OnClick.AddListener((UnityEngine.Events.UnityAction)(() =>
|
||||
{
|
||||
if (PlayerControl.LocalPlayer.HasModifier(modifier.ModifierId))
|
||||
var id = modifier.GetId();
|
||||
if (PlayerControl.LocalPlayer.HasModifier(id))
|
||||
{
|
||||
PlayerControl.LocalPlayer.RemoveModifier(modifier.ModifierId);
|
||||
PlayerControl.LocalPlayer.RemoveModifier(id);
|
||||
taskAddButton.Overlay.enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayerControl.LocalPlayer.AddModifier(ModifierManager.GetModifierType(modifier.ModifierId)!);
|
||||
PlayerControl.LocalPlayer.AddModifier(id);
|
||||
taskAddButton.Overlay.enabled = true;
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -126,6 +126,6 @@ public static class PlayerControlPatches
|
||||
[HarmonyPatch(nameof(PlayerControl.OnDestroy))]
|
||||
public static void PlayerControlOnDestroyPrefix(PlayerControl __instance)
|
||||
{
|
||||
Utilities.ModifierExtensions.ModifierComponents.Remove(__instance);
|
||||
ModifierExtensions.ModifierComponents.Remove(__instance);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using UnityEngine;
|
||||
namespace MiraAPI.Patches.Roles;
|
||||
|
||||
[HarmonyPatch(typeof(TaskPanelBehaviour))]
|
||||
public static class TaskPanelPatch
|
||||
internal static class TaskPanelPatch
|
||||
{
|
||||
/// <summary>
|
||||
/// This patch is to override the automatic updating of the y position on the tab (which is in base game)
|
||||
|
||||
@@ -1,252 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MiraAPI.Modifiers;
|
||||
using MiraAPI.Networking;
|
||||
using Reactor.Networking.Attributes;
|
||||
using Reactor.Utilities;
|
||||
|
||||
namespace MiraAPI.Utilities;
|
||||
|
||||
/// <summary>
|
||||
/// Extensions for modifiers.
|
||||
/// </summary>
|
||||
public static class ModifierExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the dictionary to cache ModifierComponents.
|
||||
/// </summary>
|
||||
public static Dictionary<PlayerControl, ModifierComponent> ModifierComponents { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Remote Procedure Call to add a modifier to a player.
|
||||
/// </summary>
|
||||
/// <param name="target">The player to add the modifier to.</param>
|
||||
/// <param name="modifierId">The modifier ID.</param>
|
||||
[MethodRpc((uint)MiraRpc.AddModifier)]
|
||||
public static void RpcAddModifier(this PlayerControl target, uint modifierId)
|
||||
{
|
||||
var type = ModifierManager.GetModifierType(modifierId);
|
||||
if (type == null)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Cannot add modifier with id {modifierId} because it is not registered.");
|
||||
return;
|
||||
}
|
||||
|
||||
target.AddModifier(type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remote Procedure Call to add a modifier to a player.
|
||||
/// </summary>
|
||||
/// <param name="player">The player to add the modifier to.</param>
|
||||
/// <typeparam name="T">The modifier Type.</typeparam>
|
||||
public static void RpcAddModifier<T>(this PlayerControl player) where T : BaseModifier
|
||||
{
|
||||
var id = ModifierManager.GetModifierId(typeof(T));
|
||||
if (id == null)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Cannot add modifier {typeof(T).Name} because it is not registered.");
|
||||
return;
|
||||
}
|
||||
|
||||
player.RpcAddModifier(id.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remote Procedure Call to remove a modifier from a player.
|
||||
/// </summary>
|
||||
/// <param name="target">The player to remove the modifier from.</param>
|
||||
/// <param name="modifierId">The ID of the modifier.</param>
|
||||
[MethodRpc((uint)MiraRpc.RemoveModifier)]
|
||||
public static void RpcRemoveModifier(this PlayerControl target, uint modifierId)
|
||||
{
|
||||
target.RemoveModifier(modifierId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remote Procedure Call to remove a modifier from a player.
|
||||
/// </summary>
|
||||
/// <param name="player">The player to remove the modifier from.</param>
|
||||
/// <typeparam name="T">The Type of the Modifier.</typeparam>
|
||||
public static void RpcRemoveModifier<T>(this PlayerControl player) where T : BaseModifier
|
||||
{
|
||||
var id = ModifierManager.GetModifierId(typeof(T));
|
||||
if (id == null)
|
||||
{
|
||||
Logger<MiraApiPlugin>.Error($"Cannot add modifier {typeof(T).Name} because it is not registered.");
|
||||
return;
|
||||
}
|
||||
|
||||
player.RpcRemoveModifier(id.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ModifierComponent for a player.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <returns>A ModifierComponent if there is one, null otherwise.</returns>
|
||||
public static ModifierComponent? GetModifierComponent(this PlayerControl player)
|
||||
{
|
||||
if (ModifierComponents.TryGetValue(player, out var component))
|
||||
{
|
||||
return component;
|
||||
}
|
||||
|
||||
component = player.GetComponent<ModifierComponent>();
|
||||
if (!component)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ModifierComponents[player] = component;
|
||||
return component;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ModifierComponent for a player.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <param name="component">The ModifierComponent if it is found.</param>
|
||||
/// <returns>A ModifierComponent if there is one, null otherwise.</returns>
|
||||
public static bool TryGetModifierComponent(this PlayerControl player, out ModifierComponent? component)
|
||||
{
|
||||
if (ModifierComponents.TryGetValue(player, out component))
|
||||
{
|
||||
return component;
|
||||
}
|
||||
|
||||
component = player.GetComponent<ModifierComponent>();
|
||||
return component;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of modifiers by their type, or null if the player doesn't have one.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <typeparam name="T">The Type of the Modifier.</typeparam>
|
||||
/// <returns>The Modifier if it is found, null otherwise.</returns>
|
||||
public static IEnumerable<T> GetModifiersByType<T>(this PlayerControl player) where T : BaseModifier
|
||||
{
|
||||
return player.GetModifierComponent()!.GetModifiersByType<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a modifier by its type, or null if the player doesn't have it.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <typeparam name="T">The Type of the Modifier.</typeparam>
|
||||
/// <returns>The Modifier if it is found, null otherwise.</returns>
|
||||
public static T? GetModifier<T>(this PlayerControl player) where T : BaseModifier
|
||||
{
|
||||
return player.GetModifierComponent()!.GetModifier<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get a modifier by its type.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <param name="modifier">The modifier or null.</param>
|
||||
/// <typeparam name="T">The Type of the Modifier.</typeparam>
|
||||
/// <returns>True if the modifier was found, false otherwise.</returns>
|
||||
public static bool TryGetModifier<T>(this PlayerControl player, out T? modifier) where T : BaseModifier
|
||||
{
|
||||
return player.GetModifierComponent()!.TryGetModifier(out modifier);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a modifier from the player.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <param name="type">The modifier type.</param>
|
||||
public static void RemoveModifier(this PlayerControl player, Type type)
|
||||
{
|
||||
player.GetModifierComponent()!.RemoveModifier(type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a modifier from the player.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <typeparam name="T">The modifier type.</typeparam>
|
||||
public static void RemoveModifier<T>(this PlayerControl player) where T : BaseModifier
|
||||
{
|
||||
player.GetModifierComponent()!.RemoveModifier<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a modifier from the player.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <param name="modifierId">The modifier ID.</param>
|
||||
public static void RemoveModifier(this PlayerControl player, uint modifierId)
|
||||
{
|
||||
player.GetModifierComponent()!.RemoveModifier(modifierId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a modifier from the player.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <param name="modifier">The modifier object.</param>
|
||||
public static void RemoveModifier(this PlayerControl player, BaseModifier modifier)
|
||||
{
|
||||
player.GetModifierComponent()!.RemoveModifier(modifier);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a modifier to the player.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <param name="modifier">The modifier to add.</param>
|
||||
/// <returns>The modifier that was added.</returns>
|
||||
public static BaseModifier? AddModifier(this PlayerControl player, BaseModifier modifier)
|
||||
{
|
||||
return player.GetModifierComponent()!.AddModifier(modifier);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a modifier to the player.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <param name="type">The modifier type.</param>
|
||||
/// <returns>The modifier that was added.</returns>
|
||||
public static BaseModifier? AddModifier(this PlayerControl player, Type type)
|
||||
{
|
||||
return player.GetModifierComponent()!.AddModifier(type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a modifier to the player.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <typeparam name="T">The Type of the modifier.</typeparam>
|
||||
/// <returns>The new modifier.</returns>
|
||||
public static T? AddModifier<T>(this PlayerControl player) where T : BaseModifier
|
||||
{
|
||||
return player.GetModifierComponent()!.AddModifier<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a player has an active or queued modifier by its ID.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <param name="id">The Modifier ID.</param>
|
||||
/// <param name="predicate">The predicate to check the modifier.</param>
|
||||
/// <returns>True if the Modifier is present, false otherwise.</returns>
|
||||
public static bool HasModifier(this PlayerControl player, uint id, Func<BaseModifier, bool>? predicate=null)
|
||||
{
|
||||
return player.GetModifierComponent()!.HasModifier(id, predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a player has an active or queued modifier by its type.
|
||||
/// </summary>
|
||||
/// <param name="player">The PlayerControl object.</param>
|
||||
/// <param name="predicate">The predicate to check the modifier.</param>
|
||||
/// <typeparam name="T">The Type of the Modifier.</typeparam>
|
||||
/// <returns>True if the Modifier is present, false otherwise.</returns>
|
||||
public static bool HasModifier<T>(this PlayerControl player, Func<T, bool>? predicate=null) where T : BaseModifier
|
||||
{
|
||||
return player.GetModifierComponent()!.HasModifier(predicate);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user