diff --git a/.editorconfig b/.editorconfig
index deb2065..cc3c781 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -149,6 +149,16 @@ dotnet_diagnostic.IDE0043.severity = warning
# IDE0044: Make field readonly
dotnet_diagnostic.IDE0044.severity = warning
+dotnet_diagnostic.CA1000.severity = none
+dotnet_diagnostic.CA1016.severity = none
+dotnet_diagnostic.CA1711.severity = none
+dotnet_diagnostic.CA1716.severity = none
+dotnet_diagnostic.CA1720.severity = none
+
+[Reactor.Benchmarks/*.cs]
+dotnet_diagnostic.CA1707.severity = none
+dotnet_diagnostic.CA1822.severity = none
+
# CSharp code style settings:
[*.cs]
# Newline settings
diff --git a/Directory.Build.props b/Directory.Build.props
index c18cbd4..3052ee6 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -21,4 +21,19 @@
+
+
+ true
+ latest
+ recommended
+ true
+
+
+
+
+
+
+
+ $(MSBuildThisFileDirectory)\stylecop.ruleset
+
diff --git a/Reactor.Benchmarks/AssetBundleBenchmarks.cs b/Reactor.Benchmarks/AssetBundleBenchmarks.cs
index ec9d4bc..e80e177 100644
--- a/Reactor.Benchmarks/AssetBundleBenchmarks.cs
+++ b/Reactor.Benchmarks/AssetBundleBenchmarks.cs
@@ -84,7 +84,7 @@ public class AssetBundleBenchmarks
var length = (int) stream.Length;
var array = new Il2CppStructArray(length);
- if (stream.Read(array.ToSpan()) < length) throw new Exception("Failed to read in full");
+ if (stream.Read(array.ToSpan()) < length) throw new IOException("Failed to read in full");
return LoadAll(AssetBundle.LoadFromMemory(array));
}
diff --git a/Reactor.Example/ExampleRpc.cs b/Reactor.Example/ExampleRpc.cs
index c60b8ec..2eaf2ff 100644
--- a/Reactor.Example/ExampleRpc.cs
+++ b/Reactor.Example/ExampleRpc.cs
@@ -11,15 +11,7 @@ public class ExampleRpc : PlayerCustomRpc
{
}
- public readonly struct Data
- {
- public readonly string Message;
-
- public Data(string message)
- {
- Message = message;
- }
- }
+ public readonly record struct Data(string Message);
public override RpcLocalHandling LocalHandling => RpcLocalHandling.None;
diff --git a/Reactor.Networking.Shared/Mod.cs b/Reactor.Networking.Shared/Mod.cs
index 7a600bb..76a57b9 100644
--- a/Reactor.Networking.Shared/Mod.cs
+++ b/Reactor.Networking.Shared/Mod.cs
@@ -8,7 +8,7 @@ using System.Text;
namespace Reactor.Networking;
-public readonly struct Mod
+public readonly struct Mod : IEquatable
{
public Mod(string id, string version, ModFlags flags, string? name = null)
{
diff --git a/Reactor/Compiler/IsUnmanagedAttribute.cs b/Reactor/Compiler/IsUnmanagedAttribute.cs
index 4c137c3..067161a 100644
--- a/Reactor/Compiler/IsUnmanagedAttribute.cs
+++ b/Reactor/Compiler/IsUnmanagedAttribute.cs
@@ -7,6 +7,7 @@ namespace System.Runtime.CompilerServices;
/// It should be generated automatically, but for whatever reason its not.
///
[Obsolete("Do not use directly.", true)]
-internal class IsUnmanagedAttribute : Attribute
+[AttributeUsage(AttributeTargets.All)]
+internal sealed class IsUnmanagedAttribute : Attribute
{
}
diff --git a/Reactor/Localization/CustomStringName.cs b/Reactor/Localization/CustomStringName.cs
index 404f5f5..d2e3b6e 100644
--- a/Reactor/Localization/CustomStringName.cs
+++ b/Reactor/Localization/CustomStringName.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
@@ -43,7 +44,7 @@ public class CustomStringName
if (customStringName != null)
{
- __result = string.Format(customStringName.Value, parts);
+ __result = string.Format(CultureInfo.InvariantCulture, customStringName.Value, parts);
return false;
}
diff --git a/Reactor/Networking/Attributes/MessageConverterAttribute.cs b/Reactor/Networking/Attributes/MessageConverterAttribute.cs
index dda11c4..f792211 100644
--- a/Reactor/Networking/Attributes/MessageConverterAttribute.cs
+++ b/Reactor/Networking/Attributes/MessageConverterAttribute.cs
@@ -8,7 +8,7 @@ using Reactor.Networking.Serialization;
namespace Reactor.Networking.Attributes;
[AttributeUsage(AttributeTargets.Class)]
-public class MessageConverterAttribute : Attribute
+public sealed class MessageConverterAttribute : Attribute
{
private static readonly HashSet _registeredAssemblies = new();
diff --git a/Reactor/Networking/Attributes/MethodRpcAttribute.cs b/Reactor/Networking/Attributes/MethodRpcAttribute.cs
index cf276a3..3eb0ffe 100644
--- a/Reactor/Networking/Attributes/MethodRpcAttribute.cs
+++ b/Reactor/Networking/Attributes/MethodRpcAttribute.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@@ -11,7 +11,7 @@ using Reactor.Utilities;
namespace Reactor.Networking.Attributes;
[AttributeUsage(AttributeTargets.Method)]
-public class MethodRpcAttribute : Attribute
+public sealed class MethodRpcAttribute : Attribute
{
private static readonly HashSet _registeredAssemblies = new();
diff --git a/Reactor/Networking/Attributes/ReactorModFlagsAttribute.cs b/Reactor/Networking/Attributes/ReactorModFlagsAttribute.cs
index e41c546..0f1d8a0 100644
--- a/Reactor/Networking/Attributes/ReactorModFlagsAttribute.cs
+++ b/Reactor/Networking/Attributes/ReactorModFlagsAttribute.cs
@@ -5,7 +5,7 @@ using System.Reflection;
namespace Reactor.Networking.Attributes;
[AttributeUsage(AttributeTargets.Class)]
-public class ReactorModFlagsAttribute : Attribute
+public sealed class ReactorModFlagsAttribute : Attribute
{
public ModFlags Flags { get; }
diff --git a/Reactor/Networking/Attributes/RegisterCustomRpcAttribute.cs b/Reactor/Networking/Attributes/RegisterCustomRpcAttribute.cs
index 37ccb96..fd19434 100644
--- a/Reactor/Networking/Attributes/RegisterCustomRpcAttribute.cs
+++ b/Reactor/Networking/Attributes/RegisterCustomRpcAttribute.cs
@@ -12,7 +12,7 @@ namespace Reactor.Networking.Attributes;
/// Utility attribute for automatically registering CustomRpc
///
[AttributeUsage(AttributeTargets.Class)]
-public class RegisterCustomRpcAttribute : Attribute
+public sealed class RegisterCustomRpcAttribute : Attribute
{
private static readonly HashSet _registeredAssemblies = new();
diff --git a/Reactor/Networking/ModList.cs b/Reactor/Networking/ModList.cs
index 84c2adf..2b1c174 100644
--- a/Reactor/Networking/ModList.cs
+++ b/Reactor/Networking/ModList.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using System.Text;
using BepInEx;
@@ -93,8 +94,8 @@ public static class ModList
foreach (var mod in Current)
{
debug.AppendLine();
- debug.Append($" - {mod.Id} version: {mod.Version}, flags: {mod.Flags}");
- if (mod.IsRequiredOnAllClients) debug.Append($", netId: {mod.GetNetId()}");
+ debug.Append(CultureInfo.InvariantCulture, $" - {mod.Id} version: {mod.Version}, flags: {mod.Flags}");
+ if (mod.IsRequiredOnAllClients) debug.Append(CultureInfo.InvariantCulture, $", netId: {mod.GetNetId()}");
}
Debug(debug.ToString());
diff --git a/Reactor/Networking/Patches/ClientPatches.cs b/Reactor/Networking/Patches/ClientPatches.cs
index 58e4f13..aa1a4af 100644
--- a/Reactor/Networking/Patches/ClientPatches.cs
+++ b/Reactor/Networking/Patches/ClientPatches.cs
@@ -125,7 +125,6 @@ internal static class ClientPatches
Debug("Injecting ReactorHandshakeC2S to CoSendSceneChange");
ReactorHeader.Write(writer);
ModdedHandshakeC2S.Serialize(writer, ModList.Current);
- //
writer.EndMessage();
writer.EndMessage();
@@ -206,7 +205,6 @@ internal static class ClientPatches
ReactorHeader.Write(msg);
ModdedHandshakeS2C.Serialize(msg, "Among Us", Application.version, 0); // TODO
}
- //
msg.EndMessage();
diff --git a/Reactor/Networking/Rpc/CustomRpcManager.cs b/Reactor/Networking/Rpc/CustomRpcManager.cs
index a83cf16..1406969 100644
--- a/Reactor/Networking/Rpc/CustomRpcManager.cs
+++ b/Reactor/Networking/Rpc/CustomRpcManager.cs
@@ -15,7 +15,7 @@ public class CustomRpcManager
public const byte CallId = byte.MaxValue;
private readonly List _list = new();
- internal readonly Dictionary>> _map = new();
+ private readonly Dictionary>> _map = new();
public IReadOnlyList List => _list.AsReadOnly();
diff --git a/Reactor/Networking/Rpc/Rpc.cs b/Reactor/Networking/Rpc/Rpc.cs
index e1f7c18..ee09389 100644
--- a/Reactor/Networking/Rpc/Rpc.cs
+++ b/Reactor/Networking/Rpc/Rpc.cs
@@ -12,7 +12,7 @@ public static class Rpc where T : UnsafeCustomRpc
{
if (_instance == null)
{
- throw new Exception($"{typeof(T).FullName} isn't registered");
+ throw new InvalidOperationException($"{typeof(T).FullName} isn't registered");
}
return _instance;
@@ -22,7 +22,7 @@ public static class Rpc where T : UnsafeCustomRpc
{
if (_instance != null)
{
- throw new Exception($"{typeof(T).FullName} is already registered");
+ throw new InvalidOperationException($"{typeof(T).FullName} is already registered");
}
_instance = value;
diff --git a/Reactor/Patches/Miscellaneous/FreeNamePatch.cs b/Reactor/Patches/Miscellaneous/FreeNamePatch.cs
index 37c869a..bdd900e 100644
--- a/Reactor/Patches/Miscellaneous/FreeNamePatch.cs
+++ b/Reactor/Patches/Miscellaneous/FreeNamePatch.cs
@@ -23,7 +23,7 @@ internal static class FreeNamePatch
{
SceneManager.add_sceneLoaded((Action) ((scene, _) =>
{
- if (!scene.name.Equals("MMOnline")) return;
+ if (!scene.name.Equals("MMOnline", StringComparison.Ordinal)) return;
if (!TryMoveObjects()) return;
var editName = DestroyableSingleton.Instance.accountTab.editNameScreen;
diff --git a/Reactor/Patches/ReactorVersionShower.cs b/Reactor/Patches/ReactorVersionShower.cs
index b564138..f5ac84f 100644
--- a/Reactor/Patches/ReactorVersionShower.cs
+++ b/Reactor/Patches/ReactorVersionShower.cs
@@ -56,7 +56,7 @@ public static class ReactorVersionShower
private static string ToStringWithoutBuild(Version version)
{
- return $"{version.Major}.{version.Minor}.{version.Patch}{(version.PreRelease == null ? "" : $"-{version.PreRelease}")}";
+ return $"{version.Major}.{version.Minor}.{version.Patch}{(version.PreRelease == null ? string.Empty : $"-{version.PreRelease}")}";
}
public static void UpdateText()
diff --git a/Reactor/ReactorPlugin.cs b/Reactor/ReactorPlugin.cs
index fe5b3cd..ec5d606 100644
--- a/Reactor/ReactorPlugin.cs
+++ b/Reactor/ReactorPlugin.cs
@@ -72,7 +72,7 @@ public partial class ReactorPlugin : BasePlugin
}
[RegisterInIl2Cpp]
- public class ReactorComponent : MonoBehaviour
+ private class ReactorComponent : MonoBehaviour
{
[HideFromIl2Cpp]
public ReactorPlugin? Plugin { get; internal set; }
diff --git a/Reactor/Utilities/AssetBundleManager.cs b/Reactor/Utilities/AssetBundleManager.cs
index 6507bca..6cc0d43 100644
--- a/Reactor/Utilities/AssetBundleManager.cs
+++ b/Reactor/Utilities/AssetBundleManager.cs
@@ -69,14 +69,14 @@ public static class AssetBundleManager
private static bool TryLoadResource(Assembly assembly, string fileName, [NotNullWhen(true)] out Il2CppStructArray? data)
{
- var resourceName = assembly.GetManifestResourceNames().SingleOrDefault(n => n.EndsWith(fileName));
+ var resourceName = assembly.GetManifestResourceNames().SingleOrDefault(n => n.EndsWith(fileName, StringComparison.Ordinal));
if (resourceName != null)
{
- using var stream = assembly.GetManifestResourceStream(resourceName) ?? throw new NullReferenceException("Resource stream was null");
+ using var stream = assembly.GetManifestResourceStream(resourceName) ?? throw new InvalidOperationException("Resource stream was null");
var length = (int) stream.Length;
data = new Il2CppStructArray(length);
- if (stream.Read(data.ToSpan()) < length) throw new Exception("Failed to read in full");
+ if (stream.Read(data.ToSpan()) < length) throw new IOException("Failed to read in full");
return true;
}
diff --git a/Reactor/Utilities/Coroutines.cs b/Reactor/Utilities/Coroutines.cs
index b1531d5..319bf0f 100644
--- a/Reactor/Utilities/Coroutines.cs
+++ b/Reactor/Utilities/Coroutines.cs
@@ -24,6 +24,7 @@ public static class Coroutines
Instance = this;
}
+ [SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "OnDestroy is an unity event and can't be static")]
private void OnDestroy()
{
Instance = null;
diff --git a/Reactor/Utilities/Dispatcher.cs b/Reactor/Utilities/Dispatcher.cs
index 9ecc4ba..aedf8c6 100644
--- a/Reactor/Utilities/Dispatcher.cs
+++ b/Reactor/Utilities/Dispatcher.cs
@@ -7,15 +7,11 @@ using UnityEngine;
namespace Reactor.Utilities;
[RegisterInIl2Cpp]
-public class Dispatcher : MonoBehaviour
+public sealed class Dispatcher : MonoBehaviour
{
- public Dispatcher(IntPtr ptr) : base(ptr)
- {
- }
-
public static Dispatcher Instance { get; private set; } = null!;
- private static readonly Queue _queue = new();
+ private readonly Queue _queue = new();
private void Awake()
{
diff --git a/Reactor/Utilities/Extensions/ReflectionExtensions.cs b/Reactor/Utilities/Extensions/ReflectionExtensions.cs
index cde4408..db66c6f 100644
--- a/Reactor/Utilities/Extensions/ReflectionExtensions.cs
+++ b/Reactor/Utilities/Extensions/ReflectionExtensions.cs
@@ -48,7 +48,7 @@ public static class ReflectionExtensions
return t;
}
- throw new Exception("Failed to find a system type for " + type.AssemblyQualifiedName);
+ throw new TypeLoadException("Failed to find a system type for " + type.AssemblyQualifiedName);
}
public static MethodInfo EnumeratorMoveNext(Type type, string methodName)
diff --git a/Reactor/Utilities/Extensions/StreamExtensions.cs b/Reactor/Utilities/Extensions/StreamExtensions.cs
index 0c73bfc..dd7b80e 100644
--- a/Reactor/Utilities/Extensions/StreamExtensions.cs
+++ b/Reactor/Utilities/Extensions/StreamExtensions.cs
@@ -15,10 +15,6 @@ public static class StreamExtensions
{
private readonly Stream _stream;
-#pragma warning disable 8618
- public StreamWrapper(IntPtr ptr) : base(ptr) { }
-#pragma warning restore 8618
-
public StreamWrapper(Stream stream) : base(ClassInjector.DerivedConstructorPointer())
{
ClassInjector.DerivedConstructorBody(this);
diff --git a/Reactor/Utilities/Il2CppEqualityComparer.cs b/Reactor/Utilities/Il2CppEqualityComparer.cs
index 9500ea6..9096f7e 100644
--- a/Reactor/Utilities/Il2CppEqualityComparer.cs
+++ b/Reactor/Utilities/Il2CppEqualityComparer.cs
@@ -20,18 +20,20 @@ public sealed class Il2CppEqualityComparer : IEqualityComparer where T : I
{
}
- public int GetHashCode(T value)
+ ///
+ public int GetHashCode(T obj)
{
- return RuntimeHelpers.GetHashCode(value);
+ return RuntimeHelpers.GetHashCode(obj);
}
- public bool Equals(T? left, T? right)
+ ///
+ public bool Equals(T? x, T? y)
{
- if (left == null || right == null)
+ if (x == null || y == null)
{
- return left == null && right == null;
+ return x == null && y == null;
}
- return left.Equals(right);
+ return x.Equals(y);
}
}
diff --git a/Reactor/Utilities/SceneManagerUtilities.cs b/Reactor/Utilities/SceneManagerUtilities.cs
index b0c51ce..a410b37 100644
--- a/Reactor/Utilities/SceneManagerUtilities.cs
+++ b/Reactor/Utilities/SceneManagerUtilities.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
@@ -9,6 +10,7 @@ public static class SceneManagerUtilities
///
/// Adds a delegate to get one notification when a scene has loaded.
///
+ [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)
{
UnityAction? unityAction = null;
diff --git a/stylecop.json b/stylecop.json
new file mode 100644
index 0000000..09546e5
--- /dev/null
+++ b/stylecop.json
@@ -0,0 +1,16 @@
+{
+ "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
+ "settings": {
+ "orderingRules": {
+ "usingDirectivesPlacement": "outsideNamespace"
+ },
+ "layoutRules": {
+ "newlineAtEndOfFile": "require",
+ "allowDoWhileOnClosingBrace": true
+ },
+ "documentationRules": {
+ "xmlHeader": false,
+ "documentInterfaces": false
+ }
+ }
+}
diff --git a/stylecop.ruleset b/stylecop.ruleset
new file mode 100644
index 0000000..ac9ef64
--- /dev/null
+++ b/stylecop.ruleset
@@ -0,0 +1,219 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+