Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RustyHeathensControllerAudit v0.1.0
RustyHeathensControllerAudit.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("RustyHeathensControllerAudit")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+53644460c4405c784c83f30f8a806ea966ac4b58")] [assembly: AssemblyProduct("RustyHeathensControllerAudit")] [assembly: AssemblyTitle("RustyHeathensControllerAudit")] [assembly: AssemblyVersion("0.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RustyHeathens.ControllerAudit { [BepInPlugin("com.rustylasergaming.controlleraudit", "Rusty Heathens Controller Audit", "0.1.0")] public sealed class Plugin : BaseUnityPlugin { private sealed class DeviceSnapshot { public List<string> Legacy = new List<string>(); public List<string> InputSystem = new List<string>(); public bool InputSystemUpdatedThisFrame; public bool Detected { get { if (Legacy.Count <= 0) { return InputSystem.Count > 0; } return true; } } public string Fingerprint => string.Join(";;", Legacy.ToArray()) + "##" + string.Join(";;", InputSystem.ToArray()); public static DeviceSnapshot Capture() { DeviceSnapshot deviceSnapshot = new DeviceSnapshot(); try { string[] array = Input.GetJoystickNames() ?? new string[0]; for (int i = 0; i < array.Length; i++) { string text = Safe(array[i], 160).Trim(); if (!string.IsNullOrEmpty(text) && !deviceSnapshot.Legacy.Contains(text)) { deviceSnapshot.Legacy.Add(text); } } } catch { } CaptureInputSystem(deviceSnapshot); deviceSnapshot.Legacy.Sort(StringComparer.OrdinalIgnoreCase); deviceSnapshot.InputSystem.Sort(StringComparer.OrdinalIgnoreCase); return deviceSnapshot; } private static void CaptureInputSystem(DeviceSnapshot snapshot) { Type type = FindType("UnityEngine.InputSystem.Gamepad"); if (type == null) { return; } try { PropertyInfo property = type.GetProperty("all", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); object obj = ((property == null) ? null : property.GetValue(null, null)); if (obj == null) { return; } foreach (object item2 in EnumerateReadOnlyArray(obj)) { if (item2 == null) { continue; } string value = Convert.ToString(ReadMember(item2, "displayName")) ?? ""; string value2 = Convert.ToString(ReadMember(item2, "name")) ?? ""; string value3 = Convert.ToString(ReadMember(item2, "layout")) ?? ""; string value4 = Convert.ToString(ReadMember(item2, "deviceId")) ?? ""; object instance = ReadMember(item2, "description"); string value5 = Convert.ToString(ReadMember(instance, "product")) ?? ""; string value6 = Convert.ToString(ReadMember(instance, "manufacturer")) ?? ""; string value7 = Convert.ToString(ReadMember(instance, "interfaceName")) ?? ""; string capabilities = Convert.ToString(ReadMember(instance, "capabilities")) ?? ""; string text = MatchId(VendorRegex, capabilities); string text2 = MatchId(ProductRegex, capabilities); bool flag = false; object obj2 = ReadMember(item2, "wasUpdatedThisFrame"); if (obj2 != null) { try { flag = Convert.ToBoolean(obj2); } catch { } } if (flag) { snapshot.InputSystemUpdatedThisFrame = true; } string item = "display=" + Safe(value, 120) + ";product=" + Safe(value5, 120) + ";manufacturer=" + Safe(value6, 100) + ";interface=" + Safe(value7, 80) + ";layout=" + Safe(value3, 80) + ";name=" + Safe(value2, 80) + ";deviceId=" + Safe(value4, 20) + ";vendorId=" + text + ";productId=" + text2; if (!snapshot.InputSystem.Contains(item)) { snapshot.InputSystem.Add(item); } } } catch { } } private static IEnumerable EnumerateReadOnlyArray(object value) { if (value is IEnumerable result) { return result; } List<object> list = new List<object>(); Type type = value.GetType(); object value2 = ReadMember(value, "Count"); int num = 0; try { num = Convert.ToInt32(value2); } catch { } PropertyInfo property = type.GetProperty("Item", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { for (int i = 0; i < num; i++) { try { list.Add(property.GetValue(value, new object[1] { i })); } catch { } } } return list; } private static string MatchId(Regex regex, string capabilities) { Match match = regex.Match(capabilities ?? ""); if (!match.Success) { return ""; } return match.Groups[1].Value; } public string ToPayload(bool activitySeen) { return "protocol=1|detected=" + (Detected ? "1" : "0") + "|activity=" + (activitySeen ? "1" : "0") + "|legacy=" + Safe(string.Join(" ;; ", Legacy.ToArray()), 800) + "|input=" + Safe(string.Join(" ;; ", InputSystem.ToArray()), 1800); } public string ToLocalSummary() { return "legacy=[" + Safe(string.Join(" ;; ", Legacy.ToArray()), 500) + "] input_system=[" + Safe(string.Join(" ;; ", InputSystem.ToArray()), 900) + "]"; } } private sealed class AuditReport { public bool Detected; public bool ActivitySeen; public string Legacy = ""; public string InputSystem = ""; public static AuditReport Parse(string payload) { AuditReport auditReport = new AuditReport(); string[] array = (payload ?? "").Split(new char[1] { '|' }); foreach (string text in array) { int num = text.IndexOf('='); if (num > 0) { string text2 = text.Substring(0, num); string text3 = text.Substring(num + 1); switch (text2) { case "detected": auditReport.Detected = text3 == "1"; break; case "activity": auditReport.ActivitySeen = text3 == "1"; break; case "legacy": auditReport.Legacy = text3; break; case "input": auditReport.InputSystem = text3; break; } } } return auditReport; } } public const string PluginGuid = "com.rustylasergaming.controlleraudit"; public const string PluginName = "Rusty Heathens Controller Audit"; public const string PluginVersion = "0.1.0"; private const string RpcName = "RHCA_ControllerAudit_v1"; private ConfigEntry<bool> _enabled; private ConfigEntry<float> _reportEverySeconds; private ConfigEntry<bool> _logClientChanges; private object _lastZNet; private bool _rpcRegistered; private float _nextRpcCheck; private float _nextReport; private string _lastFingerprint = ""; private bool _activitySeen; private static readonly Regex VendorRegex = new Regex("\\\"vendorId\\\"\\s*:\\s*(\\d+)", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex ProductRegex = new Regex("\\\"productId\\\"\\s*:\\s*(\\d+)", RegexOptions.IgnoreCase | RegexOptions.Compiled); private void Awake() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown _enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Audit", "Enabled", true, "Audit only. Detects controller/gamepad device names and reports them to the server. No controller input is blocked."); _reportEverySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Audit", "ReportEverySeconds", 15f, new ConfigDescription("How often a connected client sends a controller audit heartbeat. Device changes send immediately.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 120f), Array.Empty<object>())); _logClientChanges = ((BaseUnityPlugin)this).Config.Bind<bool>("Audit", "LogClientChanges", true, "Write a local log line when the detected controller list changes."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[RHCA] 0.1.0 loaded. AUDIT ONLY: no input is blocked and no serial numbers are collected."); } private void Update() { if (!_enabled.Value) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup >= _nextRpcCheck) { _nextRpcCheck = realtimeSinceStartup + 2f; EnsureRpc(); } if (!_rpcRegistered || IsServer()) { return; } if (LegacyControllerButtonPressed()) { _activitySeen = true; } DeviceSnapshot deviceSnapshot = DeviceSnapshot.Capture(); if (deviceSnapshot.InputSystemUpdatedThisFrame) { _activitySeen = true; } string fingerprint = deviceSnapshot.Fingerprint; if (!string.Equals(fingerprint, _lastFingerprint, StringComparison.Ordinal)) { _lastFingerprint = fingerprint; _nextReport = 0f; if (_logClientChanges.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[RHCA] Controller devices changed: " + deviceSnapshot.ToLocalSummary())); } } if (realtimeSinceStartup < _nextReport) { return; } long serverPeerUid = GetServerPeerUid(); if (serverPeerUid != 0L) { _nextReport = realtimeSinceStartup + Mathf.Clamp(_reportEverySeconds.Value, 5f, 120f); string payload = deviceSnapshot.ToPayload(_activitySeen); if (InvokeRoutedRpc(serverPeerUid, "RHCA_ControllerAudit_v1", payload)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[RHCA] Controller audit sent. detected=" + deviceSnapshot.Detected + " activity_seen=" + _activitySeen)); _activitySeen = false; } } } private void EnsureRpc() { object staticInstance = GetStaticInstance(FindType("ZNet")); if (staticInstance == null) { _rpcRegistered = false; _lastZNet = null; return; } if (staticInstance != _lastZNet) { _lastZNet = staticInstance; _rpcRegistered = false; } if (_rpcRegistered) { return; } Type type = FindType("ZRoutedRpc"); object staticInstance2 = GetStaticInstance(type); if (staticInstance2 == null || type == null) { return; } try { MethodInfo methodInfo = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "Register" && m.IsGenericMethodDefinition && m.GetParameters().Length == 2); if (!(methodInfo == null)) { MethodInfo methodInfo2 = methodInfo.MakeGenericMethod(typeof(string)); Action<long, string> action = OnAuditReport; methodInfo2.Invoke(staticInstance2, new object[2] { "RHCA_ControllerAudit_v1", action }); _rpcRegistered = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[RHCA] Routed controller-audit RPC registered."); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[RHCA] Could not register audit RPC: " + ex.GetType().Name)); } } private void OnAuditReport(long sender, string payload) { if (!IsServer()) { return; } try { AuditReport auditReport = AuditReport.Parse(payload); string value = FindPeerName(sender); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[RHCA] CONTROLLER_AUDIT player=\\\"" + Safe(value, 80) + "\\\" uid=" + sender + " detected=" + auditReport.Detected + " activity_seen=" + auditReport.ActivitySeen + " legacy=[" + Safe(auditReport.Legacy, 700) + "] input_system=[" + Safe(auditReport.InputSystem, 1400) + "]")); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[RHCA] Controller audit from uid=" + sender + " could not be parsed: " + ex.GetType().Name)); } } private static bool LegacyControllerButtonPressed() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) try { for (int i = 0; i <= 19; i++) { if (Enum.TryParse<KeyCode>("JoystickButton" + i, out KeyCode result) && Input.GetKey(result)) { return true; } } } catch { } return false; } private bool IsServer() { object staticInstance = GetStaticInstance(FindType("ZNet")); if (staticInstance == null) { return false; } try { MethodInfo method = staticInstance.GetType().GetMethod("IsServer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); return method != null && Convert.ToBoolean(method.Invoke(staticInstance, null)); } catch { return false; } } private long GetServerPeerUid() { object staticInstance = GetStaticInstance(FindType("ZNet")); if (staticInstance == null) { return 0L; } try { MethodInfo method = staticInstance.GetType().GetMethod("GetServerPeer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); return ConvertToLong(ReadMember((method == null) ? null : method.Invoke(staticInstance, null), "m_uid")); } catch { return 0L; } } private string FindPeerName(long uid) { object staticInstance = GetStaticInstance(FindType("ZNet")); if (staticInstance == null) { return "unknown"; } try { MethodInfo method = staticInstance.GetType().GetMethod("GetPeers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(((method == null) ? ReadMember(staticInstance, "m_peers") : method.Invoke(staticInstance, null)) is IEnumerable enumerable)) { return "unknown"; } foreach (object item in enumerable) { if (ConvertToLong(ReadMember(item, "m_uid")) == uid) { string text = Convert.ToString(ReadMember(item, "m_playerName")) ?? Convert.ToString(ReadMember(item, "m_playerNameCached")); return string.IsNullOrWhiteSpace(text) ? "unknown" : text; } } } catch { } return "unknown"; } private bool InvokeRoutedRpc(long target, string methodName, string payload) { Type type = FindType("ZRoutedRpc"); object staticInstance = GetStaticInstance(type); if (type == null || staticInstance == null) { return false; } try { MethodInfo methodInfo = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo m) { if (m.Name != "InvokeRoutedRPC") { return false; } ParameterInfo[] parameters = m.GetParameters(); return parameters.Length == 3 && parameters[0].ParameterType == typeof(long) && parameters[1].ParameterType == typeof(string); }); if (methodInfo == null) { return false; } methodInfo.Invoke(staticInstance, new object[3] { target, methodName, new object[1] { payload } }); return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[RHCA] Audit send failed: " + ex.GetType().Name)); return false; } } private static Type FindType(string fullName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType(fullName, throwOnError: false); if (type != null) { return type; } } catch { } } return null; } private static object GetStaticInstance(Type type) { if (type == null) { return null; } PropertyInfo property = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { return property.GetValue(null, null); } FieldInfo field = type.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field.GetValue(null); } return null; } private static object ReadMember(object instance, string name) { if (instance == null) { return null; } Type type = instance.GetType(); PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { try { return property.GetValue(instance, null); } catch { } } FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { try { return field.GetValue(instance); } catch { } } return null; } private static long ConvertToLong(object value) { if (value == null) { return 0L; } try { return Convert.ToInt64(value); } catch { Match match = Regex.Match(Convert.ToString(value) ?? "", "(\\d{5,})"); long result; return (match.Success && long.TryParse(match.Groups[1].Value, out result)) ? result : 0; } } private static string Safe(string value, int max) { string text = (value ?? "").Replace("\\r", " ").Replace("\\n", " ").Replace("|", "/"); if (text.Length > max) { text = text.Substring(0, max); } return text; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "RustyHeathensControllerAudit"; public const string PLUGIN_NAME = "RustyHeathensControllerAudit"; public const string PLUGIN_VERSION = "0.1.0"; } }