diff --git a/AmongUs.props b/AmongUs.props
index b7a170a..ff68350 100644
--- a/AmongUs.props
+++ b/AmongUs.props
@@ -9,7 +9,7 @@
-
+
diff --git a/Reactor.Benchmarks/SingleThreadedInProcessEmitToolchain.cs b/Reactor.Benchmarks/SingleThreadedInProcessEmitToolchain.cs
index 2772892..9f4e4b2 100644
--- a/Reactor.Benchmarks/SingleThreadedInProcessEmitToolchain.cs
+++ b/Reactor.Benchmarks/SingleThreadedInProcessEmitToolchain.cs
@@ -1,3 +1,5 @@
+#pragma warning disable SA1611, SA1615
+
using BenchmarkDotNet.Engines;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Toolchains;
diff --git a/Reactor.Benchmarks/packages.lock.json b/Reactor.Benchmarks/packages.lock.json
index e03c8cb..8007400 100644
--- a/Reactor.Benchmarks/packages.lock.json
+++ b/Reactor.Benchmarks/packages.lock.json
@@ -30,9 +30,9 @@
},
"BepInEx.AutoPlugin": {
"type": "Direct",
- "requested": "[1.0.1, )",
- "resolved": "1.0.1",
- "contentHash": "G4YpTHG9rtkDJof+ld7Er4E+sCOlgsjG4bJ1itx1ub7dgff6qqHLy9ksX1ehgO0AdBOPVyVl/GKJg9o7iNl8HA=="
+ "requested": "[1.1.0, )",
+ "resolved": "1.1.0",
+ "contentHash": "/7Nmc1EA9lYlGBiyz6qPAaHvlcJHEjFZ1RFpGX+8EBj3GrgoX5kbpnZusuSHoOlLx0l+CnzKuQNE54B8UaGPyw=="
},
"BepInEx.IL2CPP.MSBuild": {
"type": "Direct",
@@ -57,6 +57,15 @@
"Samboy063.Cpp2IL.Core": "2022.0.7.2"
}
},
+ "StyleCop.Analyzers": {
+ "type": "Direct",
+ "requested": "[1.2.0-beta.435, )",
+ "resolved": "1.2.0-beta.435",
+ "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
+ "dependencies": {
+ "StyleCop.Analyzers.Unstable": "1.2.0.435"
+ }
+ },
"AssetRipper.VersionUtilities": {
"type": "Transitive",
"resolved": "1.2.1",
@@ -463,6 +472,11 @@
"resolved": "2.0.2",
"contentHash": "4EQgYdNZ92SyaO7YFk6olVnebF5V+jrHyMUjvPq89tLeMo8NSfgDF+6Zwq/lgh9j/0yfQp9Lkm0ZA0rUATCZFA=="
},
+ "StyleCop.Analyzers.Unstable": {
+ "type": "Transitive",
+ "resolved": "1.2.0.435",
+ "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
+ },
"System.CodeDom": {
"type": "Transitive",
"resolved": "6.0.0",
diff --git a/Reactor.Debugger/packages.lock.json b/Reactor.Debugger/packages.lock.json
index d94a3f8..5e55856 100644
--- a/Reactor.Debugger/packages.lock.json
+++ b/Reactor.Debugger/packages.lock.json
@@ -10,9 +10,9 @@
},
"BepInEx.AutoPlugin": {
"type": "Direct",
- "requested": "[1.0.1, )",
- "resolved": "1.0.1",
- "contentHash": "G4YpTHG9rtkDJof+ld7Er4E+sCOlgsjG4bJ1itx1ub7dgff6qqHLy9ksX1ehgO0AdBOPVyVl/GKJg9o7iNl8HA=="
+ "requested": "[1.1.0, )",
+ "resolved": "1.1.0",
+ "contentHash": "/7Nmc1EA9lYlGBiyz6qPAaHvlcJHEjFZ1RFpGX+8EBj3GrgoX5kbpnZusuSHoOlLx0l+CnzKuQNE54B8UaGPyw=="
},
"BepInEx.IL2CPP.MSBuild": {
"type": "Direct",
@@ -37,6 +37,15 @@
"Samboy063.Cpp2IL.Core": "2022.0.7.2"
}
},
+ "StyleCop.Analyzers": {
+ "type": "Direct",
+ "requested": "[1.2.0-beta.435, )",
+ "resolved": "1.2.0-beta.435",
+ "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
+ "dependencies": {
+ "StyleCop.Analyzers.Unstable": "1.2.0.435"
+ }
+ },
"AssetRipper.VersionUtilities": {
"type": "Transitive",
"resolved": "1.2.1",
@@ -303,6 +312,11 @@
"resolved": "2.0.2",
"contentHash": "4EQgYdNZ92SyaO7YFk6olVnebF5V+jrHyMUjvPq89tLeMo8NSfgDF+6Zwq/lgh9j/0yfQp9Lkm0ZA0rUATCZFA=="
},
+ "StyleCop.Analyzers.Unstable": {
+ "type": "Transitive",
+ "resolved": "1.2.0.435",
+ "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
+ },
"System.Collections": {
"type": "Transitive",
"resolved": "4.3.0",
diff --git a/Reactor.Example/packages.lock.json b/Reactor.Example/packages.lock.json
index d94a3f8..5e55856 100644
--- a/Reactor.Example/packages.lock.json
+++ b/Reactor.Example/packages.lock.json
@@ -10,9 +10,9 @@
},
"BepInEx.AutoPlugin": {
"type": "Direct",
- "requested": "[1.0.1, )",
- "resolved": "1.0.1",
- "contentHash": "G4YpTHG9rtkDJof+ld7Er4E+sCOlgsjG4bJ1itx1ub7dgff6qqHLy9ksX1ehgO0AdBOPVyVl/GKJg9o7iNl8HA=="
+ "requested": "[1.1.0, )",
+ "resolved": "1.1.0",
+ "contentHash": "/7Nmc1EA9lYlGBiyz6qPAaHvlcJHEjFZ1RFpGX+8EBj3GrgoX5kbpnZusuSHoOlLx0l+CnzKuQNE54B8UaGPyw=="
},
"BepInEx.IL2CPP.MSBuild": {
"type": "Direct",
@@ -37,6 +37,15 @@
"Samboy063.Cpp2IL.Core": "2022.0.7.2"
}
},
+ "StyleCop.Analyzers": {
+ "type": "Direct",
+ "requested": "[1.2.0-beta.435, )",
+ "resolved": "1.2.0-beta.435",
+ "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
+ "dependencies": {
+ "StyleCop.Analyzers.Unstable": "1.2.0.435"
+ }
+ },
"AssetRipper.VersionUtilities": {
"type": "Transitive",
"resolved": "1.2.1",
@@ -303,6 +312,11 @@
"resolved": "2.0.2",
"contentHash": "4EQgYdNZ92SyaO7YFk6olVnebF5V+jrHyMUjvPq89tLeMo8NSfgDF+6Zwq/lgh9j/0yfQp9Lkm0ZA0rUATCZFA=="
},
+ "StyleCop.Analyzers.Unstable": {
+ "type": "Transitive",
+ "resolved": "1.2.0.435",
+ "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
+ },
"System.Collections": {
"type": "Transitive",
"resolved": "4.3.0",
diff --git a/Reactor.Networking.Shared/Mod.cs b/Reactor.Networking.Shared/Mod.cs
index 76a57b9..f540a02 100644
--- a/Reactor.Networking.Shared/Mod.cs
+++ b/Reactor.Networking.Shared/Mod.cs
@@ -8,8 +8,18 @@ using System.Text;
namespace Reactor.Networking;
+///
+/// Represents a Reactor.Protocol mod.
+///
public readonly struct Mod : IEquatable
{
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The id of the mod.
+ /// The version of the mod.
+ /// The flags of the mod.
+ /// The name of the mod.
public Mod(string id, string version, ModFlags flags, string? name = null)
{
Id = id;
@@ -18,38 +28,62 @@ public readonly struct Mod : IEquatable
Name = name;
}
+ ///
+ /// Gets the id of the mod.
+ ///
public string Id { get; }
+
+ ///
+ /// Gets the version of the mod.
+ ///
public string Version { get; }
+
+ ///
+ /// Gets the flags of the mod.
+ ///
public ModFlags Flags { get; }
+
+ ///
+ /// Gets the name of the mod.
+ ///
public string? Name { get; }
+ ///
+ /// Gets a value indicating whether the mod is required on all clients.
+ ///
public bool IsRequiredOnAllClients => (Flags & ModFlags.RequireOnAllClients) != 0;
+ ///
public bool Equals(Mod other)
{
return Id == other.Id && Version == other.Version;
}
+ ///
public override bool Equals(object? obj)
{
return obj is Mod other && Equals(other);
}
+ ///
public static bool operator ==(Mod left, Mod right)
{
return left.Equals(right);
}
+ ///
public static bool operator !=(Mod left, Mod right)
{
return !(left == right);
}
+ ///
public override int GetHashCode()
{
return HashCode.Combine(Id, Version);
}
+ ///
public override string ToString()
{
return $"{Name ?? Id} ({Version})";
diff --git a/Reactor.Networking.Shared/ModFlags.cs b/Reactor.Networking.Shared/ModFlags.cs
index 58c361f..b11c868 100644
--- a/Reactor.Networking.Shared/ModFlags.cs
+++ b/Reactor.Networking.Shared/ModFlags.cs
@@ -2,9 +2,15 @@ using System;
namespace Reactor.Networking;
+///
+/// Represents flags of the mod.
+///
[Flags]
public enum ModFlags : ushort
{
+ ///
+ /// No flags.
+ ///
None = 0,
///
diff --git a/Reactor.Networking.Shared/Reactor.Networking.Shared.csproj b/Reactor.Networking.Shared/Reactor.Networking.Shared.csproj
index 9402022..1ba48f2 100644
--- a/Reactor.Networking.Shared/Reactor.Networking.Shared.csproj
+++ b/Reactor.Networking.Shared/Reactor.Networking.Shared.csproj
@@ -15,6 +15,7 @@
true
true
true
+ true
@@ -22,6 +23,10 @@
true
$(ContentTargetFolders)\cs\any\$(PackageId)\%(RecursiveDir)\
+
+ true
+ contentFiles\cs\any\Reactor.Networking.Shared\\
+
diff --git a/Reactor.Networking.Shared/ReactorGameDataFlag.cs b/Reactor.Networking.Shared/ReactorGameDataFlag.cs
index 1851fd7..50d1d2d 100644
--- a/Reactor.Networking.Shared/ReactorGameDataFlag.cs
+++ b/Reactor.Networking.Shared/ReactorGameDataFlag.cs
@@ -1,6 +1,12 @@
namespace Reactor.Networking;
+///
+/// Represents a GameData flag for Reactor messages.
+///
public enum ReactorGameDataFlag : byte
{
+ ///
+ /// KickWithReason GameData message.
+ ///
KickWithReason,
}
diff --git a/Reactor.Networking.Shared/ReactorMessageFlags.cs b/Reactor.Networking.Shared/ReactorMessageFlags.cs
index 36d5f89..b0f6147 100644
--- a/Reactor.Networking.Shared/ReactorMessageFlags.cs
+++ b/Reactor.Networking.Shared/ReactorMessageFlags.cs
@@ -1,6 +1,12 @@
namespace Reactor.Networking;
+///
+/// Represents a message flag for Reactor messages.
+///
public enum ReactorMessageFlags : byte
{
+ ///
+ /// Handshake message.
+ ///
Handshake,
}
diff --git a/Reactor/Localization/CustomStringName.cs b/Reactor/Localization/CustomStringName.cs
index d2e3b6e..7034dd4 100644
--- a/Reactor/Localization/CustomStringName.cs
+++ b/Reactor/Localization/CustomStringName.cs
@@ -6,14 +6,25 @@ using Il2CppInterop.Runtime.InteropTypes.Arrays;
namespace Reactor.Localization;
+///
+/// Provides a way to use custom static StringNames.
+///
public class CustomStringName
{
private static int _lastId = -1;
private static readonly List _list = new();
+ ///
+ /// Gets a list of all s.
+ ///
public static IReadOnlyList List => _list.AsReadOnly();
+ ///
+ /// Registers a with specified .
+ ///
+ /// The value.
+ /// A .
public static CustomStringName Register(string value)
{
var customStringName = new CustomStringName(_lastId--, value);
@@ -22,8 +33,14 @@ public class CustomStringName
return customStringName;
}
+ ///
+ /// Gets the id.
+ ///
public int Id { get; }
+ ///
+ /// Gets the value.
+ ///
public string Value { get; }
private CustomStringName(int id, string value)
@@ -32,7 +49,18 @@ public class CustomStringName
Value = value;
}
+ ///
+ /// Defines an implicit conversion of a to a .
+ ///
+ /// The .
+ /// A .
public static implicit operator StringNames(CustomStringName name) => (StringNames) name.Id;
+
+ ///
+ /// Defines an explicit conversion of a to a .
+ ///
+ /// The .
+ /// A .
public static explicit operator CustomStringName?(StringNames name) => List.SingleOrDefault(x => x.Id == (int) name);
[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(StringNames), typeof(Il2CppReferenceArray))]
diff --git a/Reactor/Networking/Attributes/MessageConverterAttribute.cs b/Reactor/Networking/Attributes/MessageConverterAttribute.cs
index f792211..e3515be 100644
--- a/Reactor/Networking/Attributes/MessageConverterAttribute.cs
+++ b/Reactor/Networking/Attributes/MessageConverterAttribute.cs
@@ -7,11 +7,19 @@ using Reactor.Networking.Serialization;
namespace Reactor.Networking.Attributes;
+///
+/// Automatically registers a .
+///
[AttributeUsage(AttributeTargets.Class)]
public sealed class MessageConverterAttribute : Attribute
{
private static readonly HashSet _registeredAssemblies = new();
+ ///
+ /// Registers all s annotated with in the specified .
+ ///
+ /// This is called automatically on plugin assemblies so you probably don't need to call this.
+ /// The assembly to search.
public static void Register(Assembly assembly)
{
if (_registeredAssemblies.Contains(assembly)) return;
diff --git a/Reactor/Networking/Attributes/MethodRpcAttribute.cs b/Reactor/Networking/Attributes/MethodRpcAttribute.cs
index 3eb0ffe..0f336dd 100644
--- a/Reactor/Networking/Attributes/MethodRpcAttribute.cs
+++ b/Reactor/Networking/Attributes/MethodRpcAttribute.cs
@@ -10,21 +10,49 @@ using Reactor.Utilities;
namespace Reactor.Networking.Attributes;
+///
+/// Automatically registers a method rpc.
+///
[AttributeUsage(AttributeTargets.Method)]
public sealed class MethodRpcAttribute : Attribute
{
private static readonly HashSet _registeredAssemblies = new();
+ ///
+ /// Gets the id of the rpc.
+ ///
public uint Id { get; }
- public SendOption Option { get; set; } = SendOption.Reliable;
+
+ ///
+ /// Gets or sets the send option of the rpc.
+ ///
+ public SendOption SendOption { get; set; } = SendOption.Reliable;
+
+ ///
+ /// Gets or sets the local handling of the rpc.
+ ///
public RpcLocalHandling LocalHandling { get; set; } = RpcLocalHandling.Before;
+
+ ///
+ /// Gets or sets a value indicating whether the rpc should be sent immediately.
+ ///
public bool SendImmediately { get; set; }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The id of the rpc.
public MethodRpcAttribute(uint id)
{
Id = id;
}
+ ///
+ /// Registers all method rpc's annotated with in the specified .
+ ///
+ /// This is called automatically on plugin assemblies so you probably don't need to call this.
+ /// The assembly to search.
+ /// The plugin to register the rpc to.
public static void Register(Assembly assembly, BasePlugin plugin)
{
if (_registeredAssemblies.Contains(assembly)) return;
@@ -43,7 +71,7 @@ public sealed class MethodRpcAttribute : Attribute
try
{
- var customRpc = new MethodRpc(plugin, method, attribute.Id, attribute.Option, attribute.LocalHandling, attribute.SendImmediately);
+ var customRpc = new MethodRpc(plugin, method, attribute.Id, attribute.SendOption, attribute.LocalHandling, attribute.SendImmediately);
PluginSingleton.Instance.CustomRpcManager.Register(customRpc);
}
catch (Exception e)
diff --git a/Reactor/Networking/Attributes/ReactorModFlagsAttribute.cs b/Reactor/Networking/Attributes/ReactorModFlagsAttribute.cs
index 0f1d8a0..9363cb9 100644
--- a/Reactor/Networking/Attributes/ReactorModFlagsAttribute.cs
+++ b/Reactor/Networking/Attributes/ReactorModFlagsAttribute.cs
@@ -4,17 +4,27 @@ using System.Reflection;
namespace Reactor.Networking.Attributes;
+///
+/// Describes the of the annotated plugin class.
+///
[AttributeUsage(AttributeTargets.Class)]
public sealed class ReactorModFlagsAttribute : Attribute
{
+ ///
+ /// Gets flags of the mod.
+ ///
public ModFlags Flags { get; }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Flags of the mod.
public ReactorModFlagsAttribute(ModFlags flags)
{
Flags = flags;
}
- public static ModFlags GetModFlags(Type type)
+ internal static ModFlags GetModFlags(Type type)
{
var attribute = type.GetCustomAttribute();
if (attribute != null)
diff --git a/Reactor/Networking/Attributes/RegisterCustomRpcAttribute.cs b/Reactor/Networking/Attributes/RegisterCustomRpcAttribute.cs
index fd19434..74d94f9 100644
--- a/Reactor/Networking/Attributes/RegisterCustomRpcAttribute.cs
+++ b/Reactor/Networking/Attributes/RegisterCustomRpcAttribute.cs
@@ -9,25 +9,33 @@ using Reactor.Utilities;
namespace Reactor.Networking.Attributes;
///
-/// Utility attribute for automatically registering CustomRpc
+/// Automatically registers a rpc.
///
[AttributeUsage(AttributeTargets.Class)]
public sealed class RegisterCustomRpcAttribute : Attribute
{
private static readonly HashSet _registeredAssemblies = new();
+ ///
+ /// Gets the id of the rpc.
+ ///
public uint Id { get; }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The id of the rpc.
public RegisterCustomRpcAttribute(uint id)
{
Id = id;
}
///
- /// Registers all types marked with from the specified assembly as custom rpcs
+ /// Registers all rpc's annotated with in the specified .
///
- ///
- ///
+ /// This is called automatically on plugin assemblies so you probably don't need to call this.
+ /// The assembly to search.
+ /// The plugin to register the rpc to.
public static void Register(Assembly assembly, BasePlugin plugin)
{
if (_registeredAssemblies.Contains(assembly)) return;
diff --git a/Reactor/Networking/Extensions/ClientExtensions.cs b/Reactor/Networking/Extensions/ClientExtensions.cs
index 287dfd3..42e025d 100644
--- a/Reactor/Networking/Extensions/ClientExtensions.cs
+++ b/Reactor/Networking/Extensions/ClientExtensions.cs
@@ -3,8 +3,17 @@ using InnerNet;
namespace Reactor.Networking.Extensions;
+///
+/// Provides extension methods for .
+///
public static class ClientExtensions
{
+ ///
+ /// Kicks a client with id equal to with a .
+ ///
+ /// The to send the message from.
+ /// The target client's id.
+ /// The kick reason.
public static void KickWithReason(this InnerNetClient innerNetClient, int targetClientId, string reason)
{
var writer = MessageWriter.Get(SendOption.Reliable);
@@ -22,6 +31,11 @@ public static class ClientExtensions
writer.Recycle();
}
+ ///
+ /// Disconnects a local with a custom reason.
+ ///
+ /// The to disconnect.
+ /// The custom reason to disconnect with.
public static void DisconnectWithReason(this InnerNetClient innerNetClient, string reason)
{
innerNetClient.LastCustomDisconnect = reason;
diff --git a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs
index 7f35e88..f124fa0 100644
--- a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs
+++ b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs
@@ -5,6 +5,9 @@ using UnityEngine;
namespace Reactor.Networking.Extensions;
+///
+/// Provides extension methods for and .
+///
public static class ExtraMessageExtensions
{
private const float MIN = -50f;
@@ -15,6 +18,11 @@ public static class ExtraMessageExtensions
return Mathf.Clamp((t - MIN) / (MAX - MIN), 0f, 1f);
}
+ ///
+ /// Writes a to the .
+ ///
+ /// The to write to.
+ /// The to write.
public static void Write(this MessageWriter writer, Vector2 value)
{
var x = (ushort) (ReverseLerp(value.x) * ushort.MaxValue);
@@ -24,6 +32,11 @@ public static class ExtraMessageExtensions
writer.Write(y);
}
+ ///
+ /// Reads a from the .
+ ///
+ /// The to read from.
+ /// A from the .
public static Vector2 ReadVector2(this MessageReader reader)
{
var x = reader.ReadUInt16() / (float) ushort.MaxValue;
@@ -32,6 +45,12 @@ public static class ExtraMessageExtensions
return new Vector2(Mathf.Lerp(MIN, MAX, x), Mathf.Lerp(MIN, MAX, y));
}
+ ///
+ /// Sends a message on the with an .
+ ///
+ /// The connection to send the message on.
+ /// The message to send.
+ /// The callback to invoke when this packet is acknowledged.
public static void Send(this UdpConnection connection, MessageWriter msg, Action ackCallback)
{
if (msg.SendOption != SendOption.Reliable)
diff --git a/Reactor/Networking/ModList.cs b/Reactor/Networking/ModList.cs
index 2b1c174..89d0ad0 100644
--- a/Reactor/Networking/ModList.cs
+++ b/Reactor/Networking/ModList.cs
@@ -11,13 +11,24 @@ using Reactor.Networking.Patches;
namespace Reactor.Networking;
+///
+/// Represents currently loaded mods.
+///
public static class ModList
{
+ ///
+ /// Gets current mods.
+ ///
public static IReadOnlyCollection Current { get; private set; } = null!;
private static readonly Dictionary _modById = new();
private static readonly Dictionary _modByPluginType = new();
+ ///
+ /// Gets a mod by it's id.
+ ///
+ /// The id of the mod.
+ /// The mod with the specified .
public static Mod GetById(string id)
{
return _modById[id];
@@ -42,6 +53,12 @@ public static class ModList
return _netIdByMod[mod];
}
+ ///
+ /// Reads a reference from the .
+ ///
+ /// The to read from.
+ /// A from the .
+ /// This will try to read by net id and fallback to a regular id otherwise.
public static Mod ReadMod(this MessageReader reader)
{
var netId = reader.ReadPackedUInt32();
@@ -54,16 +71,22 @@ public static class ModList
return GetById(id);
}
- public static void Write(this MessageWriter writer, Mod mod)
+ ///
+ /// Writes a reference to the .
+ ///
+ /// The to write to.
+ /// The to write.
+ /// This will write the net id if is true, regular id otherwise.
+ public static void Write(this MessageWriter writer, Mod value)
{
- if (mod.IsRequiredOnAllClients)
+ if (value.IsRequiredOnAllClients)
{
- writer.WritePacked(mod.GetNetId());
+ writer.WritePacked(value.GetNetId());
}
else
{
writer.WritePacked(0);
- writer.Write(mod.Id);
+ writer.Write(value.Id);
}
}
diff --git a/Reactor/Networking/Patches/ReactorConnection.cs b/Reactor/Networking/Patches/ReactorConnection.cs
index c550546..b0155e7 100644
--- a/Reactor/Networking/Patches/ReactorConnection.cs
+++ b/Reactor/Networking/Patches/ReactorConnection.cs
@@ -3,10 +3,19 @@ using InnerNet;
namespace Reactor.Networking.Patches;
+///
+/// Provides information about the reactor protocol state of the current connection.
+///
public class ReactorConnection
{
+ ///
+ /// Gets the syncer.
+ ///
public Syncer? Syncer { get; internal set; }
+ ///
+ /// Gets the current instance of .
+ ///
public static ReactorConnection? Instance { get; private set; }
[HarmonyPatch]
@@ -30,8 +39,18 @@ public class ReactorConnection
}
}
+///
+/// Specifies who syncs the mod list and handles compatibility.
+///
public enum Syncer
{
+ ///
+ /// A custom region server.
+ ///
Server,
+
+ ///
+ /// The host of the game.
+ ///
Host,
}
diff --git a/Reactor/Networking/Rpc/CustomRpc.cs b/Reactor/Networking/Rpc/CustomRpc.cs
index a310b83..fe161eb 100644
--- a/Reactor/Networking/Rpc/CustomRpc.cs
+++ b/Reactor/Networking/Rpc/CustomRpc.cs
@@ -5,77 +5,137 @@ using InnerNet;
namespace Reactor.Networking.Rpc;
+///
+/// Base type for custom rpc's but typed with generics.
+///
+/// The type of the plugin the the rpc is attached to.
+/// The type of the .
+/// The type of the rpc data.
public abstract class CustomRpc : UnsafeCustomRpc where TPlugin : BasePlugin where TInnerNetObject : InnerNetObject
{
+ ///
protected CustomRpc(TPlugin plugin, uint id) : base(plugin, id)
{
}
+ ///
public TPlugin Plugin => (TPlugin) UnsafePlugin;
+
+ ///
public override Type InnerNetObjectType => typeof(TInnerNetObject);
+ ///
public abstract void Write(MessageWriter writer, TData? data);
+
+ ///
public abstract TData Read(MessageReader reader);
+
+ ///
public abstract void Handle(TInnerNetObject innerNetObject, TData? data);
+ ///
public override void UnsafeWrite(MessageWriter writer, object? data)
{
Write(writer, (TData?) data);
}
+ ///
public override object? UnsafeRead(MessageReader reader)
{
return Read(reader);
}
+ ///
public override void UnsafeHandle(InnerNetObject innerNetObject, object? data)
{
Handle((TInnerNetObject) innerNetObject, (TData?) data);
}
- public void Send(InnerNetObject netObject, TData data, bool immediately = false, Action? ackCallback = null)
+ ///
+ /// Sends this custom rpc on the specified with the specified .
+ ///
+ /// The to send the rpc on.
+ /// The data to send.
+ /// Whether to send it immediately.
+ /// The callback to invoke when this packet is acknowledged.
+ public void Send(InnerNetObject innerNetObject, TData data, bool immediately = false, Action? ackCallback = null)
{
- UnsafeSend(netObject, data, immediately, ackCallback: ackCallback);
+ UnsafeSend(innerNetObject, data, immediately, ackCallback: ackCallback);
}
- public void SendTo(InnerNetObject netObject, int targetId, TData data, Action? ackCallback = null)
+ ///
+ /// Sends this custom rpc on the specified with the specified to the specified target.
+ ///
+ /// The to send the rpc on.
+ /// Target client id, defaults to broadcast.
+ /// The data to send.
+ /// The callback to invoke when this packet is acknowledged.
+ public void SendTo(InnerNetObject innerNetObject, int targetClientId, TData data, Action? ackCallback = null)
{
- UnsafeSend(netObject, data, true, targetId, ackCallback);
+ UnsafeSend(innerNetObject, data, true, targetClientId, ackCallback);
}
}
+///
+/// Base type for custom rpc's but typed with generics and without any data.
+///
+/// The type of the plugin the the rpc is attached to.
+/// The type of the .
public abstract class CustomRpc : UnsafeCustomRpc where TPlugin : BasePlugin where TInnerNetObject : InnerNetObject
{
+ ///
protected CustomRpc(TPlugin plugin, uint id) : base(plugin, id)
{
}
+ ///
public TPlugin Plugin => (TPlugin) UnsafePlugin;
+
+ ///
public override Type InnerNetObjectType => typeof(TInnerNetObject);
+ ///
+ /// Handles the rpc.
+ ///
+ /// The the rpc is being handled on.
public abstract void Handle(TInnerNetObject innerNetObject);
+ ///
public override void UnsafeWrite(MessageWriter writer, object? data)
{
}
+ ///
public override object? UnsafeRead(MessageReader reader)
{
return null;
}
+ ///
public override void UnsafeHandle(InnerNetObject innerNetObject, object? data)
{
Handle((TInnerNetObject) innerNetObject);
}
- public void Send(InnerNetObject netObject, bool immediately = false, Action? ackCallback = null)
+ ///
+ /// Sends this custom rpc on the specified .
+ ///
+ /// The to send the rpc on.
+ /// Whether to send it immediately.
+ /// The callback to invoke when this packet is acknowledged.
+ public void Send(InnerNetObject innerNetObject, bool immediately = false, Action? ackCallback = null)
{
- UnsafeSend(netObject, immediately, ackCallback: ackCallback);
+ UnsafeSend(innerNetObject, immediately, ackCallback: ackCallback);
}
- public void SendTo(InnerNetObject netObject, int targetId, Action? ackCallback = null)
+ ///
+ /// Sends this custom rpc on the specified to the specified target.
+ ///
+ /// The to send the rpc on.
+ /// Target client id, defaults to broadcast.
+ /// The callback to invoke when this packet is acknowledged.
+ public void SendTo(InnerNetObject innerNetObject, int targetClientId, Action? ackCallback = null)
{
- UnsafeSend(netObject, null, true, targetId, ackCallback);
+ UnsafeSend(innerNetObject, null, true, targetClientId, ackCallback);
}
}
diff --git a/Reactor/Networking/Rpc/CustomRpcManager.cs b/Reactor/Networking/Rpc/CustomRpcManager.cs
index 1406969..de260ee 100644
--- a/Reactor/Networking/Rpc/CustomRpcManager.cs
+++ b/Reactor/Networking/Rpc/CustomRpcManager.cs
@@ -10,16 +10,29 @@ using Reactor.Utilities;
namespace Reactor.Networking.Rpc;
+///
+/// Manages custom rpc's.
+///
public class CustomRpcManager
{
+ ///
+ /// Rpc call id for the reactor's custom rpc wrapper.
+ ///
public const byte CallId = byte.MaxValue;
private readonly List _list = new();
private readonly Dictionary>> _map = new();
+ ///
+ /// Gets a list of all custom rpc's.
+ ///
public IReadOnlyList List => _list.AsReadOnly();
- public UnsafeCustomRpc Register(UnsafeCustomRpc customRpc)
+ ///
+ /// Registers a custom rpc.
+ ///
+ /// The custom rpc to register.
+ public void Register(UnsafeCustomRpc customRpc)
{
customRpc.Manager = this;
_list.Add(customRpc);
@@ -31,10 +44,17 @@ public class CustomRpcManager
{
typeof(Rpc<>).MakeGenericType(customRpc.GetType()).GetProperty("Instance")!.SetValue(null, customRpc);
}
-
- return customRpc;
}
+ ///
+ /// Implementation of for reading and handling reactor custom rpc's.
+ /// You can use this in your custom to use reactor custom rpc's on it.
+ ///
+ /// The the rpc is handled on.
+ /// The call id of the rpc.
+ /// The with the data of the rpc.
+ /// A value indicating whether the rpc was handled.
+ /// Reactor patches base game s to use this.
public static bool HandleRpc(InnerNetObject innerNetObject, byte callId, MessageReader reader)
{
if (callId == CallId)
diff --git a/Reactor/Networking/Rpc/MethodRpc.cs b/Reactor/Networking/Rpc/MethodRpc.cs
index ebcb76f..46e2266 100644
--- a/Reactor/Networking/Rpc/MethodRpc.cs
+++ b/Reactor/Networking/Rpc/MethodRpc.cs
@@ -15,10 +15,24 @@ using Reactor.Utilities;
namespace Reactor.Networking.Rpc;
+///
+/// Provides a custom rpc for method rpc.
+///
public class MethodRpc : UnsafeCustomRpc
{
- public delegate object HandleDelegate(InnerNetObject innerNetObject, object[] args);
+ private delegate object HandleDelegate(InnerNetObject innerNetObject, object[] args);
+ private readonly HandleDelegate _handle;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The plugin that the rpc is attached to.
+ /// The method of the method rpc.
+ /// The id of the rpc.
+ /// The send option of the rpc.
+ /// The local handling method of the rpc.
+ /// The value indicating whether the rpc should be sent immediately.
public MethodRpc(BasePlugin plugin, MethodInfo method, uint id, SendOption option, RpcLocalHandling localHandling, bool sendImmediately) : base(plugin, id)
{
Method = method;
@@ -54,35 +68,58 @@ public class MethodRpc : UnsafeCustomRpc
InnerNetObjectType = method.DeclaringType;
}
- Handle = Hook(method, parameters, method.IsStatic);
+ _handle = Hook(method, parameters, method.IsStatic);
}
+ ///
+ /// Gets the method of the method rpc.
+ ///
public MethodInfo Method { get; }
- public HandleDelegate Handle { get; }
+ ///
protected internal override bool IsSingleton => false;
+ ///
public override Type InnerNetObjectType { get; }
+
+ ///
public override RpcLocalHandling LocalHandling { get; }
+
+ ///
public override SendOption SendOption { get; }
+
+ ///
+ /// Gets a value indicating whether the method rpc should be sent immediately.
+ ///
public bool SendImmediately { get; }
+ ///
public override void UnsafeWrite(MessageWriter writer, object? data)
{
var args = (object[]) data!;
MessageSerializer.Serialize(writer, args);
}
+ ///
public override object UnsafeRead(MessageReader reader)
{
- var args = MessageSerializer.Deserialize(reader, this);
+ var parameters = Method.GetParameters();
+ var args = new object[parameters.Length - 1];
+
+ for (var i = 1; i < parameters.Length; i++)
+ {
+ var parameter = parameters[i];
+ args[i - 1] = reader.Deserialize(parameter.ParameterType);
+ }
+
return args;
}
+ ///
public override void UnsafeHandle(InnerNetObject innerNetObject, object? data)
{
var args = (object[]) data!;
- var result = Handle(innerNetObject, args);
+ var result = _handle(innerNetObject, args);
if (result is IEnumerator enumerator)
{
@@ -90,6 +127,11 @@ public class MethodRpc : UnsafeCustomRpc
}
}
+ ///
+ /// Sends this method rpc on the specified with the specified .
+ ///
+ /// The to send the rpc on.
+ /// The arguments to serialize and send.
public void Send(InnerNetObject innerNetObject, object[] args)
{
UnsafeSend(innerNetObject, args, SendImmediately);
@@ -98,7 +140,7 @@ public class MethodRpc : UnsafeCustomRpc
private static readonly MethodInfo _sendMethod = AccessTools.Method(typeof(MethodRpc), nameof(Send));
///
- /// Hooks the rpc with a dynamic method that sends it
+ /// Hooks the rpc with a dynamic method that sends it.
///
private HandleDelegate Hook(MethodInfo method, ParameterInfo[] parameters, bool isStatic)
{
diff --git a/Reactor/Networking/Rpc/PlayerCustomRpc.cs b/Reactor/Networking/Rpc/PlayerCustomRpc.cs
index 5468c3b..47c9d8a 100644
--- a/Reactor/Networking/Rpc/PlayerCustomRpc.cs
+++ b/Reactor/Networking/Rpc/PlayerCustomRpc.cs
@@ -3,36 +3,69 @@ using BepInEx.Unity.IL2CPP;
namespace Reactor.Networking.Rpc;
+///
+/// Shorthand for with as the TInnerNetObject.
+///
+/// The type of the plugin the the rpc is attached to.
+/// The type of the rpc data.
public abstract class PlayerCustomRpc : CustomRpc where TPlugin : BasePlugin
{
+ ///
protected PlayerCustomRpc(TPlugin plugin, uint id) : base(plugin, id)
{
}
+ ///
+ /// Sends this custom rpc on the local player with the specified .
+ ///
+ /// The data to send.
+ /// Whether to send it immediately.
+ /// The callback to invoke when this packet is acknowledged.
public void Send(TData data, bool immediately = false, Action? ackCallback = null)
{
Send(PlayerControl.LocalPlayer, data, immediately, ackCallback);
}
- public void SendTo(int targetId, TData data, Action? ackCallback = null)
+ ///
+ /// Sends this custom rpc on the local player with the specified to the specified target.
+ ///
+ /// Target client id, defaults to broadcast.
+ /// The data to send.
+ /// The callback to invoke when this packet is acknowledged.
+ public void SendTo(int targetClientId, TData data, Action? ackCallback = null)
{
- SendTo(PlayerControl.LocalPlayer, targetId, data, ackCallback);
+ SendTo(PlayerControl.LocalPlayer, targetClientId, data, ackCallback);
}
}
+///
+/// Shorthand for with as the TInnerNetObject.
+///
+/// The type of the plugin the the rpc is attached to.
public abstract class PlayerCustomRpc : CustomRpc where TPlugin : BasePlugin
{
+ ///
protected PlayerCustomRpc(TPlugin plugin, uint id) : base(plugin, id)
{
}
+ ///
+ /// Sends this custom rpc on the local player.
+ ///
+ /// Whether to send it immediately.
+ /// The callback to invoke when this packet is acknowledged.
public void Send(bool immediately = false, Action? ackCallback = null)
{
Send(PlayerControl.LocalPlayer, immediately, ackCallback);
}
- public void SendTo(int targetId, Action? ackCallback = null)
+ ///
+ /// Sends this custom rpc on the local player to the specified target.
+ ///
+ /// Target client id, defaults to broadcast.
+ /// The callback to invoke when this packet is acknowledged.
+ public void SendTo(int targetClientId, Action? ackCallback = null)
{
- SendTo(PlayerControl.LocalPlayer, targetId, ackCallback);
+ SendTo(PlayerControl.LocalPlayer, targetClientId, ackCallback);
}
}
diff --git a/Reactor/Networking/Rpc/Rpc.cs b/Reactor/Networking/Rpc/Rpc.cs
index ee09389..f43c710 100644
--- a/Reactor/Networking/Rpc/Rpc.cs
+++ b/Reactor/Networking/Rpc/Rpc.cs
@@ -2,10 +2,17 @@ using System;
namespace Reactor.Networking.Rpc;
+///
+/// Provides access to singleton custom rpc's.
+///
+/// The type of the custom rpc.
public static class Rpc where T : UnsafeCustomRpc
{
private static T? _instance;
+ ///
+ /// Gets an instance of rpc.
+ ///
public static T Instance
{
get
diff --git a/Reactor/Networking/Rpc/RpcLocalHandling.cs b/Reactor/Networking/Rpc/RpcLocalHandling.cs
index ee4aafb..7c9bf9a 100644
--- a/Reactor/Networking/Rpc/RpcLocalHandling.cs
+++ b/Reactor/Networking/Rpc/RpcLocalHandling.cs
@@ -1,8 +1,22 @@
namespace Reactor.Networking.Rpc;
+///
+/// Specifies how the rpc should be handled locally.
+///
public enum RpcLocalHandling
{
+ ///
+ /// Don't do anything.
+ ///
None,
+
+ ///
+ /// Invoke Handle before sending.
+ ///
Before,
+
+ ///
+ /// Invoke Handle after sending.
+ ///
After,
}
diff --git a/Reactor/Networking/Rpc/UnsafeCustomRpc.cs b/Reactor/Networking/Rpc/UnsafeCustomRpc.cs
index f210527..e04af54 100644
--- a/Reactor/Networking/Rpc/UnsafeCustomRpc.cs
+++ b/Reactor/Networking/Rpc/UnsafeCustomRpc.cs
@@ -11,20 +11,53 @@ using Buffer = Il2CppSystem.Buffer;
namespace Reactor.Networking.Rpc;
+///
+/// Base type for custom rpc's.
+///
public abstract class UnsafeCustomRpc
{
internal CustomRpcManager? Manager { get; set; }
+
+ ///
+ /// Gets a value indicating whether the rpc is a singleton and can be used with .
+ ///
protected internal virtual bool IsSingleton => true;
+ ///
+ /// Gets the id of the rpc.
+ ///
public uint Id { get; }
+
+ ///
+ /// Gets the plugin of the rpc.
+ ///
public BasePlugin UnsafePlugin { get; }
+
+ ///
+ /// Gets the mod of the rpc.
+ ///
public Mod Mod { get; }
+ ///
+ /// Gets the InnerNetObject type the rpc targets.
+ ///
public abstract Type InnerNetObjectType { get; }
+ ///
+ /// Gets the send option of the rpc.
+ ///
public virtual SendOption SendOption => SendOption.Reliable;
+
+ ///
+ /// Gets the local handling method of the rpc.
+ ///
public abstract RpcLocalHandling LocalHandling { get; }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The plugin that the rpc is attached to.
+ /// The id of the rpc.
protected UnsafeCustomRpc(BasePlugin plugin, uint id)
{
UnsafePlugin = plugin;
@@ -32,10 +65,35 @@ public abstract class UnsafeCustomRpc
Id = id;
}
+ ///
+ /// Writes to the .
+ ///
+ /// The writer to write to.
+ /// The data to be written.
public abstract void UnsafeWrite(MessageWriter writer, object? data);
+
+ ///
+ /// Reads rpc data from the .
+ ///
+ /// The reader to read from.
+ /// The rpc data from the .
public abstract object? UnsafeRead(MessageReader reader);
+
+ ///
+ /// Handles rpc data.
+ ///
+ /// The the rpc is being handled on.
+ /// The data associated with the rpc.
public abstract void UnsafeHandle(InnerNetObject innerNetObject, object? data);
+ ///
+ /// Sends this custom rpc on the specified with the specified .
+ ///
+ /// The to send the rpc on.
+ /// The data to send.
+ /// Whether to send it immediately.
+ /// Target client id, defaults to broadcast.
+ /// The callback to invoke when this packet is acknowledged.
public void UnsafeSend(InnerNetObject innerNetObject, object? data, bool immediately = false, int targetClientId = -1, Action? ackCallback = null)
{
if (innerNetObject == null) throw new ArgumentNullException(nameof(innerNetObject));
diff --git a/Reactor/Networking/Serialization/InnerNetObjectConverter.cs b/Reactor/Networking/Serialization/InnerNetObjectConverter.cs
index 93cf47c..ab66380 100644
--- a/Reactor/Networking/Serialization/InnerNetObjectConverter.cs
+++ b/Reactor/Networking/Serialization/InnerNetObjectConverter.cs
@@ -8,30 +8,41 @@ using Reactor.Networking.Attributes;
namespace Reactor.Networking.Serialization;
+///
+/// Provides a MessageConverter for .
+///
[MessageConverter]
-public class InnerNetObjectConverter : MessageConverter
+public class InnerNetObjectConverter : MessageConverter
{
private static readonly MethodInfo _readNetObject = AccessTools.Method(typeof(MessageExtensions), nameof(MessageExtensions.ReadNetObject));
- private static readonly Dictionary> _readNetObjectMap = new();
+ private static readonly Dictionary> _readNetObjectMap = new();
- public static InnerNetObject ReadNetObject(MessageReader reader, Type t)
+ ///
+ /// but without generics.
+ ///
+ /// The to read from.
+ /// The type of the .
+ /// The read from the .
+ public static InnerNetObject? ReadNetObject(MessageReader reader, Type innerNetObjectType)
{
- if (_readNetObjectMap.TryGetValue(t, out var value))
+ if (_readNetObjectMap.TryGetValue(innerNetObjectType, out var value))
{
return value(reader);
}
- var @delegate = _readNetObject.MakeGenericMethod(t).CreateDelegate>();
- _readNetObjectMap[t] = @delegate;
+ var @delegate = _readNetObject.MakeGenericMethod(innerNetObjectType).CreateDelegate>();
+ _readNetObjectMap[innerNetObjectType] = @delegate;
return @delegate(reader);
}
- public override void Write(MessageWriter writer, InnerNetObject value)
+ ///
+ public override void Write(MessageWriter writer, InnerNetObject? value)
{
- MessageExtensions.WriteNetObject(writer, value);
+ writer.WriteNetObject(value);
}
- public override InnerNetObject Read(MessageReader reader, Type objectType)
+ ///
+ public override InnerNetObject? Read(MessageReader reader, Type objectType)
{
return ReadNetObject(reader, objectType);
}
diff --git a/Reactor/Networking/Serialization/MessageConverter.cs b/Reactor/Networking/Serialization/MessageConverter.cs
index 2019464..05c6762 100644
--- a/Reactor/Networking/Serialization/MessageConverter.cs
+++ b/Reactor/Networking/Serialization/MessageConverter.cs
@@ -3,26 +3,60 @@ using Hazel;
namespace Reactor.Networking.Serialization;
+///
+/// Base type for MessageConverter's.
+///
public abstract class UnsafeMessageConverter
{
+ ///
+ /// Writes the to the .
+ ///
+ /// The to write to.
+ /// The value to write.
public abstract void UnsafeWrite(MessageWriter writer, object value);
+
+ ///
+ /// Reads an object of from the .
+ ///
+ /// The to read from.
+ /// The type of the object being read.
+ /// The object read from the .
public abstract object UnsafeRead(MessageReader reader, Type objectType);
+ ///
+ /// Checks whether this MessageConverter can convert the specified type.
+ ///
+ /// The type to check.
+ /// A value indicating whether this MessageConverter can convert the specified type.
public abstract bool CanConvert(Type objectType);
}
+///
+/// Base type for MessageConverter's but typed with generics.
+///
+/// The type of the value being converted.
public abstract class MessageConverter : UnsafeMessageConverter
{
+ ///
public abstract void Write(MessageWriter writer, T value);
+ ///
+ /// Reads a from the .
+ ///
+ /// The to read from.
+ /// The type of the object being read.
+ /// The object read from the .
public abstract T Read(MessageReader reader, Type objectType);
+ ///
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
+ ///
public override void UnsafeWrite(MessageWriter writer, object value) => Write(writer, (T) value);
+ ///
public override object UnsafeRead(MessageReader reader, Type objectType) => Read(reader, objectType)!;
}
diff --git a/Reactor/Networking/Serialization/MessageSerializer.cs b/Reactor/Networking/Serialization/MessageSerializer.cs
index a11799c..3f92591 100644
--- a/Reactor/Networking/Serialization/MessageSerializer.cs
+++ b/Reactor/Networking/Serialization/MessageSerializer.cs
@@ -3,23 +3,34 @@ using System.Collections.Generic;
using System.Linq;
using Hazel;
using Reactor.Networking.Extensions;
-using Reactor.Networking.Rpc;
using UnityEngine;
namespace Reactor.Networking.Serialization;
+///
+/// Provides de/serializing of objects from/into /.
+///
public static class MessageSerializer
{
private static List MessageConverters { get; } = new();
private static Dictionary MessageConverterMap { get; } = new();
+ ///
+ /// Registers a MessageConverter.
+ ///
+ /// The MessageConverter to be registered.
public static void Register(UnsafeMessageConverter messageConverter)
{
MessageConverters.Add(messageConverter);
MessageConverterMap.Clear();
}
+ ///
+ /// Finds a MessageConverter for the specified .
+ ///
+ /// The type of an object.
+ /// A MessageConverted that can convert the specified .
public static UnsafeMessageConverter? FindConverter(Type type)
{
if (MessageConverterMap.TryGetValue(type, out var value))
@@ -33,6 +44,11 @@ public static class MessageSerializer
return converter;
}
+ ///
+ /// Serializes to the .
+ ///
+ /// The to write to.
+ /// The args to be written.
public static void Serialize(MessageWriter writer, object[] args)
{
foreach (var arg in args)
@@ -41,9 +57,14 @@ public static class MessageSerializer
}
}
- public static void Serialize(this MessageWriter writer, object o)
+ ///
+ /// Serializes an to the .
+ ///
+ /// The to write to.
+ /// The to be written.
+ public static void Serialize(this MessageWriter writer, object @object)
{
- switch (o)
+ switch (@object)
{
case int i:
writer.WritePacked(i);
@@ -73,84 +94,76 @@ public static class MessageSerializer
writer.Write(i);
break;
default:
- var converter = FindConverter(o.GetType());
+ var converter = FindConverter(@object.GetType());
if (converter != null)
{
- converter.UnsafeWrite(writer, o);
+ converter.UnsafeWrite(writer, @object);
break;
}
- throw new NotSupportedException("Couldn't serialize " + o.GetType());
+ throw new NotSupportedException("Couldn't serialize " + @object.GetType());
}
}
- public static object[] Deserialize(MessageReader reader, MethodRpc methodRpc)
+ ///
+ /// Deserializes an of from the .
+ ///
+ /// The to read from.
+ /// The of the object.
+ /// An from the .
+ public static object Deserialize(this MessageReader reader, Type objectType)
{
- var parameters = methodRpc.Method.GetParameters();
- var args = new object[parameters.Length - 1];
-
- for (var i = 1; i < parameters.Length; i++)
- {
- var parameter = parameters[i];
- args[i - 1] = reader.Deserialize(parameter.ParameterType);
- }
-
- return args;
- }
-
- public static object Deserialize(this MessageReader reader, Type t)
- {
- if (t == typeof(int))
+ if (objectType == typeof(int))
{
return reader.ReadPackedInt32();
}
- if (t == typeof(uint))
+ if (objectType == typeof(uint))
{
return reader.ReadPackedUInt32();
}
- if (t == typeof(byte))
+ if (objectType == typeof(byte))
{
return reader.ReadByte();
}
- if (t == typeof(float))
+ if (objectType == typeof(float))
{
return reader.ReadSingle();
}
- if (t == typeof(sbyte))
+ if (objectType == typeof(sbyte))
{
return reader.ReadSByte();
}
- if (t == typeof(ushort))
+ if (objectType == typeof(ushort))
{
return reader.ReadUInt16();
}
- if (t == typeof(bool))
+ if (objectType == typeof(bool))
{
return reader.ReadBoolean();
}
- if (t == typeof(Vector2))
+ if (objectType == typeof(Vector2))
{
return reader.ReadVector2();
}
- if (t == typeof(string))
+ if (objectType == typeof(string))
{
return reader.ReadString();
}
- var converter = FindConverter(t);
+ var converter = FindConverter(objectType);
if (converter != null)
{
- return converter.UnsafeRead(reader, t);
+ return converter.UnsafeRead(reader, objectType);
}
- throw new NotSupportedException("Couldn't deserialize " + t);
+ throw new NotSupportedException("Couldn't deserialize " + objectType);
}
}
diff --git a/Reactor/Patches/Fixes/CursorPosPatch.cs b/Reactor/Patches/Fixes/CursorPosPatch.cs
index 01fc3f3..912ebc2 100644
--- a/Reactor/Patches/Fixes/CursorPosPatch.cs
+++ b/Reactor/Patches/Fixes/CursorPosPatch.cs
@@ -6,7 +6,7 @@ using UnityEngine;
namespace Reactor.Patches.Fixes;
///
-/// "Fixes" an issue where empty TextBoxes have wrong cursor positions
+/// "Fixes" an issue where empty TextBoxes have wrong cursor positions.
///
[HarmonyPatch(typeof(TextMeshProExtensions), nameof(TextMeshProExtensions.CursorPos))]
internal static class CursorPosPatch
diff --git a/Reactor/Patches/Fixes/ServerInfoFixesPatch.cs b/Reactor/Patches/Fixes/ServerInfoFixesPatch.cs
index 33244af..b1dce94 100644
--- a/Reactor/Patches/Fixes/ServerInfoFixesPatch.cs
+++ b/Reactor/Patches/Fixes/ServerInfoFixesPatch.cs
@@ -17,9 +17,7 @@ internal static class ServerInfoFixesPatch
Info($"Joining {__instance.networkAddress}:{__instance.networkPort}");
}
- ///
- /// Fixes hardcoded port and filters out IPv6 in DnsRegionInfo
- ///
+ // Fixes hardcoded port and filters out IPv6 in DnsRegionInfo.
[HarmonyPatch(typeof(DnsRegionInfo), nameof(DnsRegionInfo.PopulateServers))]
[HarmonyPrefix]
public static bool FixPopulateServers(DnsRegionInfo __instance)
diff --git a/Reactor/Patches/Miscellaneous/StandaloneSteamPatch.cs b/Reactor/Patches/Miscellaneous/StandaloneSteamPatch.cs
index b1b7dd1..0e6a33a 100644
--- a/Reactor/Patches/Miscellaneous/StandaloneSteamPatch.cs
+++ b/Reactor/Patches/Miscellaneous/StandaloneSteamPatch.cs
@@ -6,7 +6,7 @@ using HarmonyLib;
namespace Reactor.Patches.Miscellaneous;
///
-/// Allows launching steam builds outside of steam
+/// Allows launching steam builds outside of steam.
///
[HarmonyPatch]
internal static class StandaloneSteamPatch
diff --git a/Reactor/Patches/ReactorVersionShower.cs b/Reactor/Patches/ReactorVersionShower.cs
index f5ac84f..d381e8f 100644
--- a/Reactor/Patches/ReactorVersionShower.cs
+++ b/Reactor/Patches/ReactorVersionShower.cs
@@ -10,13 +10,20 @@ using Version = SemanticVersioning.Version;
namespace Reactor.Patches;
+///
+/// Shows the reactor version on the main menu.
+///
public static class ReactorVersionShower
{
+ ///
+ /// Gets the text.
+ ///
public static TextMeshPro? Text { get; private set; }
- public static event TextUpdatedHandler? TextUpdated;
-
- public delegate void TextUpdatedHandler(TextMeshPro text);
+ ///
+ /// Occurs when is updated.
+ ///
+ public static event Action? TextUpdated;
internal static void Initialize()
{
@@ -59,6 +66,9 @@ public static class ReactorVersionShower
return $"{version.Major}.{version.Minor}.{version.Patch}{(version.PreRelease == null ? string.Empty : $"-{version.PreRelease}")}";
}
+ ///
+ /// Updates with reactor version and fires .
+ ///
public static void UpdateText()
{
if (Text == null) return;
diff --git a/Reactor/Reactor.csproj b/Reactor/Reactor.csproj
index cf0fca3..f532132 100644
--- a/Reactor/Reactor.csproj
+++ b/Reactor/Reactor.csproj
@@ -5,6 +5,7 @@
Core mod and API for Among Us
true
+ true
true
diff --git a/Reactor/ReactorPlugin.cs b/Reactor/ReactorPlugin.cs
index ec5d606..228bc3d 100644
--- a/Reactor/ReactorPlugin.cs
+++ b/Reactor/ReactorPlugin.cs
@@ -18,17 +18,28 @@ using UnityEngine.SceneManagement;
namespace Reactor;
+///
+/// Reactor's main class.
+///
[BepInAutoPlugin("gg.reactor.api")]
[BepInProcess("Among Us.exe")]
public partial class ReactorPlugin : BasePlugin
{
+ ///
+ /// Gets harmony instance.
+ ///
public Harmony Harmony { get; } = new(Id);
+
+ ///
+ /// Gets custom rpc manager.
+ ///
public CustomRpcManager CustomRpcManager { get; } = new();
- public ConfigEntry? AllowVanillaServers { get; private set; }
+ internal ConfigEntry? AllowVanillaServers { get; private set; }
internal RegionInfoWatcher RegionInfoWatcher { get; } = new();
+ ///
public ReactorPlugin()
{
PluginSingleton.Instance = this;
@@ -40,6 +51,7 @@ public partial class ReactorPlugin : BasePlugin
MethodRpcAttribute.Initialize();
}
+ ///
public override void Load()
{
AllowVanillaServers = Config.Bind("Features", "Allow vanilla servers", false, "Whether reactor should ignore servers not responding to modded handshake. This config is ignored if any plugin uses custom rpcs!");
@@ -63,6 +75,7 @@ public partial class ReactorPlugin : BasePlugin
}));
}
+ ///
public override bool Unload()
{
Harmony.UnpatchSelf();
diff --git a/Reactor/Utilities/AssetBundleManager.cs b/Reactor/Utilities/AssetBundleManager.cs
index 6cc0d43..6645864 100644
--- a/Reactor/Utilities/AssetBundleManager.cs
+++ b/Reactor/Utilities/AssetBundleManager.cs
@@ -10,10 +10,19 @@ using UnityEngine;
namespace Reactor.Utilities;
+///
+/// Provides a standard way of loading asset bundles from a file or embedded resource.
+///
public static class AssetBundleManager
{
+ ///
+ /// Extension of a asset bundle.
+ ///
public const string BundleExtension = ".bundle";
+ ///
+ /// Gets the target name of the current system.
+ ///
public static string TargetName { get; }
static AssetBundleManager()
@@ -48,6 +57,11 @@ public static class AssetBundleManager
}
}
+ ///
+ /// Gets the file name for an asset bundle named .
+ ///
+ /// The name of the asset bundle.
+ /// File name of the asset bundle.
public static string GetFileName(string assetBundleName) => $"{assetBundleName}-{TargetName}{BundleExtension}";
private static bool TryFindFile(Assembly assembly, string fileName, [NotNullWhen(true)] out string? path)
@@ -85,11 +99,24 @@ public static class AssetBundleManager
return false;
}
+ ///
+ /// Synchronously loads an named from the calling assembly.
+ ///
+ /// The name of the asset bundle.
+ /// The loaded assetbundle.
+ /// Couldn't find an assetbundle named .
public static AssetBundle Load(string name)
{
return Load(Assembly.GetCallingAssembly(), name);
}
+ ///
+ /// Synchronously loads an named from the specified .
+ ///
+ /// The specified assembly.
+ /// The name of the asset bundle.
+ /// The loaded assetbundle.
+ /// Couldn't find an assetbundle named .
public static AssetBundle Load(Assembly assembly, string name)
{
var fileName = GetFileName(name);
@@ -107,11 +134,24 @@ public static class AssetBundleManager
throw new AssetBundleNotFoundException(name);
}
+ ///
+ /// Asynchronously loads an named from the calling assembly.
+ ///
+ /// The name of the asset bundle.
+ /// The loaded assetbundle.
+ /// Couldn't find an assetbundle named .
public static AssetBundleCreateRequest LoadAsync(string name)
{
return LoadAsync(Assembly.GetCallingAssembly(), name);
}
+ ///
+ /// Asynchronously loads an named from the specified .
+ ///
+ /// The specified assembly.
+ /// The name of the asset bundle.
+ /// The loaded assetbundle.
+ /// Couldn't find an assetbundle named .
public static AssetBundleCreateRequest LoadAsync(Assembly assembly, string name)
{
var fileName = GetFileName(name);
@@ -130,6 +170,9 @@ public static class AssetBundleManager
}
}
+///
+/// The exception that is thrown when an assetbundle is not found.
+///
public class AssetBundleNotFoundException : IOException
{
internal AssetBundleNotFoundException(string name) : base("Couldn't find an assetbundle named " + name)
diff --git a/Reactor/Utilities/Attributes/RegisterInIl2CppAttribute.cs b/Reactor/Utilities/Attributes/RegisterInIl2CppAttribute.cs
index 47ec0f6..0235d3f 100644
--- a/Reactor/Utilities/Attributes/RegisterInIl2CppAttribute.cs
+++ b/Reactor/Utilities/Attributes/RegisterInIl2CppAttribute.cs
@@ -8,20 +8,30 @@ using Il2CppInterop.Runtime.Injection;
namespace Reactor.Utilities.Attributes;
///
-/// Utility attribute for automatically calling
+/// Automatically registers an il2cpp type using .
///
[AttributeUsage(AttributeTargets.Class)]
public sealed class RegisterInIl2CppAttribute : Attribute
{
private static readonly HashSet _registeredAssemblies = new();
+ ///
+ /// Gets il2cpp interfaces to be injected with this type.
+ ///
public Type[] Interfaces { get; }
+ ///
+ /// Initializes a new instance of the class without any interfaces.
+ ///
public RegisterInIl2CppAttribute()
{
Interfaces = Type.EmptyTypes;
}
+ ///
+ /// Initializes a new instance of the class with interfaces.
+ ///
+ /// Il2Cpp interfaces to be injected with this type.
public RegisterInIl2CppAttribute(params Type[] interfaces)
{
Interfaces = interfaces;
@@ -51,9 +61,10 @@ public sealed class RegisterInIl2CppAttribute : Attribute
}
///
- /// Registers in Il2Cpp all types marked with from the specified assembly.
+ /// Registers all Il2Cpp types annotated with in the specified .
///
- ///
+ /// This is called automatically on plugin assemblies so you probably don't need to call this.
+ /// The assembly to search.
public static void Register(Assembly assembly)
{
if (_registeredAssemblies.Contains(assembly)) return;
diff --git a/Reactor/Utilities/CanvasUtilities.cs b/Reactor/Utilities/CanvasUtilities.cs
index 7c8b0dc..7ceff92 100644
--- a/Reactor/Utilities/CanvasUtilities.cs
+++ b/Reactor/Utilities/CanvasUtilities.cs
@@ -5,8 +5,15 @@ using UnityEngine.UI;
namespace Reactor.Utilities;
+///
+/// Provides utilities for working with unity canvas ui.
+///
public static class CanvasUtilities
{
+ ///
+ /// Creates a canvas.
+ ///
+ /// A canvas .
public static GameObject CreateCanvas()
{
var gameObject = new GameObject("Canvas");
@@ -23,6 +30,10 @@ public static class CanvasUtilities
return gameObject;
}
+ ///
+ /// Creates an EventSystem.
+ ///
+ /// An EventSystem .
public static GameObject CreateEventSystem()
{
var gameObject = new GameObject("EventSystem");
@@ -34,8 +45,11 @@ public static class CanvasUtilities
}
///
- /// Shortcut for empty texture
+ /// Creates an empty texture of specified and .
///
+ /// The width of the texture.
+ /// The height of the texture.
+ /// An empty texture of specified size.
public static Texture2D CreateEmptyTexture(int width = 0, int height = 0)
{
return new Texture2D(width, height, TextureFormat.RGBA32, Texture.GenerateAllMips, false, IntPtr.Zero);
diff --git a/Reactor/Utilities/Coroutines.cs b/Reactor/Utilities/Coroutines.cs
index 319bf0f..d050a26 100644
--- a/Reactor/Utilities/Coroutines.cs
+++ b/Reactor/Utilities/Coroutines.cs
@@ -8,6 +8,9 @@ using UnityEngine;
namespace Reactor.Utilities;
+///
+/// Provides utilities for starting coroutines.
+///
public static class Coroutines
{
[RegisterInIl2Cpp]
@@ -33,20 +36,29 @@ public static class Coroutines
private static readonly ConditionalWeakTable _ourCoroutineStore = new();
- [return: NotNullIfNotNull("routine")]
- public static IEnumerator? Start(IEnumerator? routine)
+ ///
+ /// Starts a coroutine.
+ ///
+ /// The coroutine to start.
+ /// Specified .
+ [return: NotNullIfNotNull("coroutine")]
+ public static IEnumerator? Start(IEnumerator? coroutine)
{
- if (routine != null)
+ if (coroutine != null)
{
- _ourCoroutineStore.AddOrUpdate(routine, Component.Instance!.StartCoroutine(routine));
+ _ourCoroutineStore.AddOrUpdate(coroutine, Component.Instance!.StartCoroutine(coroutine));
}
- return routine;
+ return coroutine;
}
- public static void Stop(IEnumerator? enumerator)
+ ///
+ /// Stops a coroutine.
+ ///
+ /// The coroutine to stop.
+ public static void Stop(IEnumerator? coroutine)
{
- if (enumerator != null && _ourCoroutineStore.TryGetValue(enumerator, out var routine))
+ if (coroutine != null && _ourCoroutineStore.TryGetValue(coroutine, out var routine))
{
Component.Instance!.StopCoroutine(routine);
}
diff --git a/Reactor/Utilities/DefaultBundle.cs b/Reactor/Utilities/DefaultBundle.cs
index 3de1e0e..8b104a3 100644
--- a/Reactor/Utilities/DefaultBundle.cs
+++ b/Reactor/Utilities/DefaultBundle.cs
@@ -4,8 +4,14 @@ using UnityEngine.UI;
namespace Reactor.Utilities;
+///
+/// Provides unity things that were stripped.
+///
public static class DefaultBundle
{
+ ///
+ /// Gets standard resources used for canvas ui.
+ ///
public static DefaultControls.Resources StandardResources { get; internal set; } = null!;
internal static void Load()
diff --git a/Reactor/Utilities/Dispatcher.cs b/Reactor/Utilities/Dispatcher.cs
index aedf8c6..7e5f25b 100644
--- a/Reactor/Utilities/Dispatcher.cs
+++ b/Reactor/Utilities/Dispatcher.cs
@@ -6,9 +6,15 @@ using UnityEngine;
namespace Reactor.Utilities;
+///
+/// Dispatches actions on Unity main thread.
+///
[RegisterInIl2Cpp]
public sealed class Dispatcher : MonoBehaviour
{
+ ///
+ /// Gets the instance.
+ ///
public static Dispatcher Instance { get; private set; } = null!;
private readonly Queue _queue = new();
@@ -29,6 +35,10 @@ public sealed class Dispatcher : MonoBehaviour
}
}
+ ///
+ /// Enqueues an .
+ ///
+ /// The action to enqueue.
[HideFromIl2Cpp]
public void Enqueue(Action action)
{
diff --git a/Reactor/Utilities/Extensions/AssetBundleExtensions.cs b/Reactor/Utilities/Extensions/AssetBundleExtensions.cs
index 596361a..000c63a 100644
--- a/Reactor/Utilities/Extensions/AssetBundleExtensions.cs
+++ b/Reactor/Utilities/Extensions/AssetBundleExtensions.cs
@@ -3,10 +3,20 @@ using UnityEngine;
namespace Reactor.Utilities.Extensions;
+///
+/// Provides extension methods for .
+///
public static class AssetBundleExtensions
{
- public static T? LoadAsset(this AssetBundle assetBundle, string name) where T : Object
+ ///
+ /// Loads an asset with from the with the specified type.
+ ///
+ /// The to load the asset from.
+ /// The name of the asset.
+ /// The type of the asset.
+ /// The loaded asset or null if it wasn't found.
+ public static T? LoadAsset(this AssetBundle bundle, string name) where T : Object
{
- return assetBundle.LoadAsset(name, Il2CppType.Of())?.Cast();
+ return bundle.LoadAsset(name, Il2CppType.Of())?.Cast();
}
}
diff --git a/Reactor/Utilities/Extensions/GUIExtensions.cs b/Reactor/Utilities/Extensions/GUIExtensions.cs
index ff4a15e..394193e 100644
--- a/Reactor/Utilities/Extensions/GUIExtensions.cs
+++ b/Reactor/Utilities/Extensions/GUIExtensions.cs
@@ -3,13 +3,15 @@ using UnityEngine;
namespace Reactor.Utilities.Extensions;
///
-/// GUI utilities
+/// Provides extension methods for unity imgui.
///
public static class GUIExtensions
{
///
- /// Clamp Rect to screen size
+ /// Clamps to the screen size.
///
+ /// The to clamp.
+ /// A clamped rect.
public static Rect ClampScreen(this Rect rect)
{
rect.x = Mathf.Clamp(rect.x, 0, Screen.width - rect.width);
@@ -19,8 +21,10 @@ public static class GUIExtensions
}
///
- /// Reset Rect size
+ /// Set 's and to 0.
///
+ /// The to reset.
+ /// A rect with reset size.
public static Rect ResetSize(this Rect rect)
{
rect.width = rect.height = 0;
@@ -29,13 +33,23 @@ public static class GUIExtensions
}
///
- /// Create from
+ /// Creates a from the .
///
- public static Sprite CreateSprite(this Texture2D tex)
+ /// Texture from which to obtain the sprite graphic.
+ /// Sprite's pivot point relative to its graphic rectangle.
+ /// The number of pixels in the sprite that correspond to one unit in world space.
+ /// A sprite.
+ public static Sprite CreateSprite(this Texture2D texture, Vector2? pivot = null, float pixelsPerUnit = 100f)
{
- return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f), 100f);
+ return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), pivot ?? new Vector2(0.5f, 0.5f), pixelsPerUnit);
}
+ ///
+ /// Sets 's width and height.
+ ///
+ /// The to set the size of.
+ /// The width.
+ /// The height.
public static void SetSize(this RectTransform rectTransform, float width, float height)
{
rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, width);
diff --git a/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs b/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs
index d13e1f6..41f58ed 100644
--- a/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs
+++ b/Reactor/Utilities/Extensions/Il2CppInteropExtensions.cs
@@ -3,8 +3,17 @@ using Il2CppInterop.Runtime.InteropTypes.Arrays;
namespace Reactor.Utilities.Extensions;
+///
+/// Provides extension methods for Il2CppInterop.
+///
public static class Il2CppInteropExtensions
{
+ ///
+ /// Creates a span over a .
+ ///
+ /// The array to create a span over.
+ /// The type of items in the .
+ /// A span.
public static unsafe Span ToSpan(this Il2CppStructArray array) where T : unmanaged
{
return new Span(IntPtr.Add(array.Pointer, IntPtr.Size * 4).ToPointer(), array.Length);
diff --git a/Reactor/Utilities/Extensions/RandomExtensions.cs b/Reactor/Utilities/Extensions/RandomExtensions.cs
index fb6ea0d..369ec4a 100644
--- a/Reactor/Utilities/Extensions/RandomExtensions.cs
+++ b/Reactor/Utilities/Extensions/RandomExtensions.cs
@@ -4,29 +4,45 @@ using System.Linq;
namespace Reactor.Utilities.Extensions;
+///
+/// Provides Random related extension methods.
+///
public static class RandomExtensions
{
///
- /// Returns random from using
+ /// Returns a random double that is within a specified range.
///
- public static T? Random(this IEnumerable input, Random random)
- {
- var list = input as IList ?? input.ToList();
- return list.Count == 0 ? default : list[random.Next(0, list.Count)];
- }
-
- /// Returns a random double that is within a specified range.
+ /// The to get the random number from.
+ /// The minimum value of the range.
+ /// The maximum value of the range.
+ /// A random double that is within a specified range.
public static double NextDouble(this Random random, double minValue, double maxValue)
{
return random.NextDouble() * (maxValue - minValue) + minValue;
}
///
- /// Returns random from
+ /// Returns a random from the .
///
+ /// The input enumerable to take the item from.
+ /// The type of items.
+ /// A random item from the enumerable.
public static T? Random(this IEnumerable input)
{
var list = input as IList ?? input.ToList();
return list.Count == 0 ? default : list[UnityEngine.Random.Range(0, list.Count)];
}
+
+ ///
+ /// Returns a random from the using .
+ ///
+ /// The input enumerable to take the item from.
+ /// The to get the random number from.
+ /// The type of items.
+ /// A random item from the enumerable.
+ public static T? Random(this IEnumerable input, Random random)
+ {
+ var list = input as IList ?? input.ToList();
+ return list.Count == 0 ? default : list[random.Next(0, list.Count)];
+ }
}
diff --git a/Reactor/Utilities/Extensions/ReflectionExtensions.cs b/Reactor/Utilities/Extensions/ReflectionExtensions.cs
index db66c6f..0eeb8b7 100644
--- a/Reactor/Utilities/Extensions/ReflectionExtensions.cs
+++ b/Reactor/Utilities/Extensions/ReflectionExtensions.cs
@@ -14,17 +14,30 @@ using MethodInfo = System.Reflection.MethodInfo;
namespace Reactor.Utilities.Extensions;
+///
+/// Provides extension methods for reflection.
+///
public static class ReflectionExtensions
{
+ ///
+ /// Gets a for the specified .
+ ///
+ /// The .
+ /// A .
public static Il2CppMethodInfo ToIl2CppMethodInfo(this MethodInfo methodInfo)
{
var il2CppMethodField = Il2CppInteropUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(methodInfo);
if (il2CppMethodField == null) throw new ArgumentException($"'{methodInfo.Name}' is not an il2cpp method", nameof(methodInfo));
var il2CppMethod = (IntPtr) il2CppMethodField.GetValue(null)!;
- return new Il2CppSystem.Reflection.MethodInfo(IL2CPP.il2cpp_method_get_object(il2CppMethod, IntPtr.Zero));
+ return new Il2CppMethodInfo(IL2CPP.il2cpp_method_get_object(il2CppMethod, IntPtr.Zero));
}
+ ///
+ /// Gets enumerator's MoveNext type for the specified .
+ ///
+ /// The enumerator .
+ /// A for enumerator's MoveNext type.
public static Il2CppSystemType GetEnumeratorMoveNextType(this Il2CppMethodInfo methodInfo)
{
var customAttribute = Il2CppCustomAttributeExtensions.GetCustomAttribute(methodInfo, Il2CppType.Of()).TryCast();
@@ -33,6 +46,11 @@ public static class ReflectionExtensions
return customAttribute._StateMachineType_k__BackingField;
}
+ ///
+ /// Gets a for the specified .
+ ///
+ /// The .
+ /// A .
public static Type ToSystemType(this Il2CppSystemType type)
{
var result = Type.GetType(type.AssemblyQualifiedName);
@@ -51,16 +69,37 @@ public static class ReflectionExtensions
throw new TypeLoadException("Failed to find a system type for " + type.AssemblyQualifiedName);
}
+ ///
+ /// Gets MoveNext for specified enumerator method.
+ ///
+ /// The enclosing type of the method.
+ /// The name of the method.
+ /// A .
public static MethodInfo EnumeratorMoveNext(Type type, string methodName)
{
return AccessTools.Method(AccessTools.Method(type, methodName).ToIl2CppMethodInfo().GetEnumeratorMoveNextType().ToSystemType(), "MoveNext");
}
- public static IEnumerable GetMethods(this Type type, BindingFlags bindingAttr, Type returnType, params Type[] parameterTypes)
+ ///
+ /// Gets all method from the with the specified , and .
+ ///
+ /// The type to search the methods in.
+ /// The .
+ /// The return type.
+ /// The parameter types.
+ /// An array of objects representing all methods defined for the current that match the specified binding constraints.
+ public static IEnumerable GetMethods(this Type type, BindingFlags bindingFlags, Type returnType, params Type[] parameterTypes)
{
- return type.GetMethods(bindingAttr).Where(x => x.ReturnType == returnType && x.GetParameters().Select(x => x.ParameterType).SequenceEqual(parameterTypes));
+ return type.GetMethods(bindingFlags).Where(x => x.ReturnType == returnType && x.GetParameters().Select(x => x.ParameterType).SequenceEqual(parameterTypes));
}
+ ///
+ /// Gets all method from the with the specified and .
+ ///
+ /// The type to search the methods in.
+ /// The return type.
+ /// The parameter types.
+ /// An array of objects representing all methods defined for the current that match the specified binding constraints.
public static IEnumerable GetMethods(this Type type, Type returnType, params Type[] parameterTypes)
{
return type.GetMethods(AccessTools.all, returnType, parameterTypes);
diff --git a/Reactor/Utilities/SceneManagerUtilities.cs b/Reactor/Utilities/Extensions/SceneManagerExtensions.cs
similarity index 78%
rename from Reactor/Utilities/SceneManagerUtilities.cs
rename to Reactor/Utilities/Extensions/SceneManagerExtensions.cs
index a410b37..1867f1b 100644
--- a/Reactor/Utilities/SceneManagerUtilities.cs
+++ b/Reactor/Utilities/Extensions/SceneManagerExtensions.cs
@@ -3,13 +3,17 @@ using System.Diagnostics.CodeAnalysis;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
-namespace Reactor.Utilities;
+namespace Reactor.Utilities.Extensions;
-public static class SceneManagerUtilities
+///
+/// Provides extension methods for .
+///
+public static class SceneManagerExtensions
{
///
/// Adds a delegate to get one notification when a scene has loaded.
///
+ /// The action.
[SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "This supplements existing methods like add_sceneLoaded and remove_sceneLoaded")]
public static void once_sceneLoaded(Action value)
{
diff --git a/Reactor/Utilities/Extensions/StreamExtensions.cs b/Reactor/Utilities/Extensions/StreamExtensions.cs
index dd7b80e..5595af9 100644
--- a/Reactor/Utilities/Extensions/StreamExtensions.cs
+++ b/Reactor/Utilities/Extensions/StreamExtensions.cs
@@ -8,13 +8,20 @@ using Reactor.Utilities.Attributes;
namespace Reactor.Utilities.Extensions;
+///
+/// Provides extension methods for .
+///
public static class StreamExtensions
{
+ ///
+ /// Provides a which uses under the hood.
+ ///
[RegisterInIl2Cpp]
public class StreamWrapper : Il2CppSystem.IO.Stream
{
private readonly Stream _stream;
+ ///
public StreamWrapper(Stream stream) : base(ClassInjector.DerivedConstructorPointer())
{
ClassInjector.DerivedConstructorBody(this);
@@ -29,31 +36,37 @@ public static class StreamExtensions
return new Span(rawBuffer + offset, count);
}
+ ///
public override int Read(Il2CppStructArray buffer, int offset, int count)
{
return _stream.Read(GetSpan(buffer, offset, count));
}
+ ///
public override void Write(Il2CppStructArray buffer, int offset, int count)
{
_stream.Write(GetSpan(buffer, offset, count));
}
+ ///
public override void Flush()
{
_stream.Flush();
}
+ ///
public override void Close()
{
_stream.Close();
}
+ ///
public override void Dispose()
{
_stream.Dispose();
}
+ ///
public override long Seek(long offset, Il2CppSystem.IO.SeekOrigin origin)
{
return _stream.Seek(offset, origin switch
@@ -65,16 +78,25 @@ public static class StreamExtensions
});
}
+ ///
public override void SetLength(long value)
{
_stream.SetLength(value);
}
+ ///
public override bool CanRead => _stream.CanRead;
+
+ ///
public override bool CanSeek => _stream.CanSeek;
+
+ ///
public override bool CanWrite => _stream.CanWrite;
+
+ ///
public override long Length => _stream.Length;
+ ///
public override long Position
{
get => _stream.Position;
@@ -83,13 +105,17 @@ public static class StreamExtensions
}
///
- /// Wraps a System Stream into an Il2Cpp Stream
+ /// Wraps a into a .
///
+ /// The stream to wrap.
+ /// A for the specified .
public static StreamWrapper AsIl2Cpp(this Stream stream) => new(stream);
///
- /// Fully read stream, can be used as workaround for il2cpp streams.
+ /// Fully reads the stream.
///
+ /// The stream to read.
+ /// A byte array read from the .
public static byte[] ReadFully(this Stream input)
{
using var ms = new MemoryStream();
diff --git a/Reactor/Utilities/Extensions/UnityExtensions.cs b/Reactor/Utilities/Extensions/UnityExtensions.cs
index e12b2f4..3560b4c 100644
--- a/Reactor/Utilities/Extensions/UnityExtensions.cs
+++ b/Reactor/Utilities/Extensions/UnityExtensions.cs
@@ -2,6 +2,9 @@ using UnityEngine;
namespace Reactor.Utilities.Extensions;
+///
+/// Provides extension methods for unity.
+///
public static class UnityExtensions
{
///
@@ -9,7 +12,7 @@ public static class UnityExtensions
///
/// The color to be converted.
/// Hexadecimal string representing the color.
- /// https://docs.unity3d.com/ScriptReference/ColorUtility.ToHtmlStringRGBA.html
+ /// https://docs.unity3d.com/ScriptReference/ColorUtility.ToHtmlStringRGBA.html.
public static string ToHtmlStringRGBA(this Color32 color)
{
return $"{color.r:X2}{color.g:X2}{color.b:X2}{color.a:X2}";
@@ -26,8 +29,10 @@ public static class UnityExtensions
private static readonly int _addColor = Shader.PropertyToID("_AddColor");
///
- /// Sets color outline for renderers using default Among Us shader
+ /// Sets the outline for renderer using the default Among Us shader.
///
+ /// The renderer to set the color on.
+ /// The color or null to disable the outline.
public static void SetOutline(this Renderer renderer, Color? color)
{
renderer.material.SetFloat(_outline, color.HasValue ? 1 : 0);
diff --git a/Reactor/Utilities/Extensions/UnityObjectExtensions.cs b/Reactor/Utilities/Extensions/UnityObjectExtensions.cs
index 81ffbd2..f87902c 100644
--- a/Reactor/Utilities/Extensions/UnityObjectExtensions.cs
+++ b/Reactor/Utilities/Extensions/UnityObjectExtensions.cs
@@ -1,42 +1,67 @@
using UnityEngine;
+using UnityObject = UnityEngine.Object;
namespace Reactor.Utilities.Extensions;
+///
+/// Provides extension methods for .
+///
public static class UnityObjectExtensions
{
///
- /// Stops from being destroyed
+ /// Stops from being destroyed.
///
- /// Object to stop from being destroyed
- /// Passed
- public static T DontDestroy(this T obj) where T : Object
+ /// The object to stop from being destroyed.
+ /// The type of the object.
+ /// Passed .
+ public static T DontDestroy(this T obj) where T : UnityObject
{
obj.hideFlags |= HideFlags.HideAndDontSave;
return obj.DontDestroyOnLoad();
}
- public static T DontUnload(this T obj) where T : Object
+ ///
+ /// Stops from being unloaded.
+ ///
+ /// The object to stop from being unloaded.
+ /// The type of the object.
+ /// Passed .
+ public static T DontUnload(this T obj) where T : UnityObject
{
obj.hideFlags |= HideFlags.DontUnloadUnusedAsset;
return obj;
}
- public static T DontDestroyOnLoad(this T obj) where T : Object
+ ///
+ /// Stops from being destroyed on load.
+ ///
+ /// The object to stop from being destroyed on load.
+ /// The type of the object.
+ /// Passed .
+ public static T DontDestroyOnLoad(this T obj) where T : UnityObject
{
- Object.DontDestroyOnLoad(obj);
+ UnityObject.DontDestroyOnLoad(obj);
return obj;
}
- public static void Destroy(this Object obj)
+ ///
+ /// Destroys the .
+ ///
+ /// The object to destroy.
+ public static void Destroy(this UnityObject obj)
{
- Object.Destroy(obj);
+ UnityObject.Destroy(obj);
}
- public static void DestroyImmediate(this Object obj)
+ ///
+ /// Destroys the immediately.
+ ///
+ /// The object to destroy immediately.
+ public static void DestroyImmediate(this UnityObject obj)
{
- Object.DestroyImmediate(obj);
+ UnityObject.DestroyImmediate(obj);
}
}
diff --git a/Reactor/Utilities/Il2CppEqualityComparer.cs b/Reactor/Utilities/Il2CppEqualityComparer.cs
index 9096f7e..8064c28 100644
--- a/Reactor/Utilities/Il2CppEqualityComparer.cs
+++ b/Reactor/Utilities/Il2CppEqualityComparer.cs
@@ -3,10 +3,14 @@ using Il2CppSystem.Runtime.CompilerServices;
namespace Reactor.Utilities;
+///
public sealed class Il2CppEqualityComparer : IEqualityComparer where T : Il2CppSystem.Object
{
private static Il2CppEqualityComparer? _instance;
+ ///
+ /// Gets the instance.
+ ///
public static Il2CppEqualityComparer Instance
{
get
diff --git a/Reactor/Utilities/ImGui/DragWindow.cs b/Reactor/Utilities/ImGui/DragWindow.cs
index 6635ea6..14c2545 100644
--- a/Reactor/Utilities/ImGui/DragWindow.cs
+++ b/Reactor/Utilities/ImGui/DragWindow.cs
@@ -4,20 +4,25 @@ using UnityEngine;
namespace Reactor.Utilities.ImGui;
+///
+/// Draggable version of .
+///
public class DragWindow : Window
{
+ ///
public DragWindow(Rect rect, string title, Action func) : base(rect, title, func)
{
Func = id =>
{
func(id);
- UnityEngine.GUI.DragWindow(new Rect(0, 0, 10000, 20));
+ GUI.DragWindow(new Rect(0, 0, 10000, 20));
Rect = Rect.ClampScreen();
};
}
- public DragWindow(Rect rect, string title, Action func) : this(rect, title, id => func())
+ ///
+ public DragWindow(Rect rect, string title, Action func) : this(rect, title, _ => func())
{
}
}
diff --git a/Reactor/Utilities/ImGui/Window.cs b/Reactor/Utilities/ImGui/Window.cs
index 9b19466..f9af416 100644
--- a/Reactor/Utilities/ImGui/Window.cs
+++ b/Reactor/Utilities/ImGui/Window.cs
@@ -4,22 +4,53 @@ using UnityEngine;
namespace Reactor.Utilities.ImGui;
+///
+/// Utility wrapper over ..
+///
public class Window
{
private static int _lastWindowId;
+ ///
+ /// Gets the next window id.
+ ///
+ /// A window id.
public static int NextWindowId()
{
return _lastWindowId++;
}
+ ///
+ /// Gets or sets the id of the window.
+ ///
public int Id { get; set; } = NextWindowId();
+ ///
+ /// Gets or sets a value indicating whether the window is enabled and shown.
+ ///
public bool Enabled { get; set; } = true;
+
+ ///
+ /// Gets or sets the rect of the window.
+ ///
public Rect Rect { get; set; }
+
+ ///
+ /// Gets or sets the render function of the window.
+ ///
public Action Func { get; set; }
+
+ ///
+ /// Gets or sets the title of the window.
+ ///
public string Title { get; set; }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The rect.
+ /// The title.
+ /// The render function.
public Window(Rect rect, string title, Action func)
{
Rect = rect;
@@ -27,11 +58,15 @@ public class Window
Func = func;
}
- public Window(Rect rect, string title, Action func) : this(rect, title, id => func())
+ ///
+ public Window(Rect rect, string title, Action func) : this(rect, title, _ => func())
{
}
- public void OnGUI()
+ ///
+ /// Draws the window gui.
+ ///
+ public virtual void OnGUI()
{
if (Enabled)
{
diff --git a/Reactor/Utilities/Logger.cs b/Reactor/Utilities/Logger.cs
index abcab0b..03e5e5d 100644
--- a/Reactor/Utilities/Logger.cs
+++ b/Reactor/Utilities/Logger.cs
@@ -5,8 +5,15 @@ using BepInEx.Unity.IL2CPP;
namespace Reactor.Utilities;
+///
+/// Provides singleton access to plugins logger.
+///
+/// The type of the plugin.
public static class Logger where T : BasePlugin
{
+ ///
+ /// Gets the instance.
+ ///
public static ManualLogSource Instance => PluginSingleton.Instance.Log;
///
diff --git a/Reactor/Utilities/PluginSingleton.cs b/Reactor/Utilities/PluginSingleton.cs
index 18937c0..0b4cf92 100644
--- a/Reactor/Utilities/PluginSingleton.cs
+++ b/Reactor/Utilities/PluginSingleton.cs
@@ -5,10 +5,17 @@ using BepInEx.Unity.IL2CPP;
namespace Reactor.Utilities;
+///
+/// Provides singleton access to plugins instance.
+///
+/// The type of the plugin.
public static class PluginSingleton where T : BasePlugin
{
private static T? _instance;
+ ///
+ /// Gets or sets an instance of plugin.
+ ///
public static T Instance
{
get => _instance ??= IL2CPPChainloader.Instance.Plugins.Values.Select(x => x.Instance).OfType().Single();
diff --git a/Reactor/packages.lock.json b/Reactor/packages.lock.json
index 4b7f1cb..a901255 100644
--- a/Reactor/packages.lock.json
+++ b/Reactor/packages.lock.json
@@ -10,9 +10,9 @@
},
"BepInEx.AutoPlugin": {
"type": "Direct",
- "requested": "[1.0.1, )",
- "resolved": "1.0.1",
- "contentHash": "G4YpTHG9rtkDJof+ld7Er4E+sCOlgsjG4bJ1itx1ub7dgff6qqHLy9ksX1ehgO0AdBOPVyVl/GKJg9o7iNl8HA=="
+ "requested": "[1.1.0, )",
+ "resolved": "1.1.0",
+ "contentHash": "/7Nmc1EA9lYlGBiyz6qPAaHvlcJHEjFZ1RFpGX+8EBj3GrgoX5kbpnZusuSHoOlLx0l+CnzKuQNE54B8UaGPyw=="
},
"BepInEx.IL2CPP.MSBuild": {
"type": "Direct",
@@ -47,6 +47,15 @@
"Microsoft.SourceLink.Common": "1.1.1"
}
},
+ "StyleCop.Analyzers": {
+ "type": "Direct",
+ "requested": "[1.2.0-beta.435, )",
+ "resolved": "1.2.0-beta.435",
+ "contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
+ "dependencies": {
+ "StyleCop.Analyzers.Unstable": "1.2.0.435"
+ }
+ },
"AssetRipper.VersionUtilities": {
"type": "Transitive",
"resolved": "1.2.1",
@@ -323,6 +332,11 @@
"resolved": "2.0.2",
"contentHash": "4EQgYdNZ92SyaO7YFk6olVnebF5V+jrHyMUjvPq89tLeMo8NSfgDF+6Zwq/lgh9j/0yfQp9Lkm0ZA0rUATCZFA=="
},
+ "StyleCop.Analyzers.Unstable": {
+ "type": "Transitive",
+ "resolved": "1.2.0.435",
+ "contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
+ },
"System.Collections": {
"type": "Transitive",
"resolved": "4.3.0",