using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.zsdm15.RPC_monitor")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("com.zsdm15.RPC_monitor")] [assembly: AssemblyTitle("RPC_monitor")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.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 BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace RPCControlMod { [BepInPlugin("com.zsdm15.RPC_monitor", "RPC_monitor", "1.0.0")] public class RPCControlPlugin : BaseUnityPlugin { public static RPCControlPlugin Instance; private List allRPCMethods; private Dictionary blockedMap = new Dictionary(); private ConfigEntry favoritesConfig; private HashSet favoritesSet = new HashSet(); private List rpcLogs = new List(); private ConfigEntry maxLogEntries; private ConfigEntry ignoreListConfig; private ConfigEntry sensitiveListConfig; private HashSet sensitiveSet = new HashSet(); private Queue<(string method, int sender, int viewId, float time)> dedupQueue = new Queue<(string, int, int, float)>(); private const float DedupWindow = 2f; private Vector2 scrollControl; private Vector2 scrollMonitor; private string searchText = ""; private string monitorFilter = ""; private bool showWindow; private int currentPage; private string editIgnoreList = ""; private string editSensitiveList = ""; private GUIStyle labelStyle; private GUIStyle buttonStyle; private GUIStyle textFieldStyle; private GUIStyle windowStyle; private GUIStyle boxStyle; private GUIStyle toolbarStyle; private GUIStyle toggleStyle; public static HashSet BlockedMethods = new HashSet(); private void Awake() { Instance = this; List source = (from m in AppDomain.CurrentDomain.GetAssemblies().SelectMany((Assembly a) => a.GetTypes()).SelectMany((Type t) => t.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) where ((MemberInfo)m).GetCustomAttribute() != null select m).ToList(); IEnumerable> enumerable = from m in source group m by m.DeclaringType.FullName + "." + m.Name; allRPCMethods = new List(); foreach (IGrouping item in enumerable) { List list = item.ToList(); MethodInfo methodInfo = list.FirstOrDefault((MethodInfo m) => m.GetParameters().Any((ParameterInfo p) => p.ParameterType == typeof(PhotonMessageInfo))); allRPCMethods.Add(methodInfo ?? list[0]); } allRPCMethods = allRPCMethods.OrderBy((MethodInfo m) => m.Name).ToList(); foreach (MethodInfo allRPCMethod in allRPCMethods) { string methodId = GetMethodId(allRPCMethod); blockedMap[methodId] = false; } favoritesConfig = ((BaseUnityPlugin)this).Config.Bind("Favorites", "List", "", "Comma-separated method IDs."); if (!string.IsNullOrEmpty(favoritesConfig.Value)) { string[] array = favoritesConfig.Value.Split(','); foreach (string text in array) { favoritesSet.Add(text.Trim()); } } maxLogEntries = ((BaseUnityPlugin)this).Config.Bind("Monitor", "MaxLogEntries", 200, "Max log entries."); ignoreListConfig = ((BaseUnityPlugin)this).Config.Bind("Monitor", "IgnoreList", "Jump,Update,Set,Get,Animator,Crouch,Use,Spores,Heat,Energy,Movement", "Keywords to hide from RPC log."); sensitiveListConfig = ((BaseUnityPlugin)this).Config.Bind("Monitor", "SensitiveList", "SyncInventoryRPC,RPC_SpawnResourceAtPosition,InstantiateAndGrabRPC", "RPC methods to highlight/cheat-detect."); RefreshSensitiveSet(); sensitiveListConfig.SettingChanged += delegate { RefreshSensitiveSet(); }; editIgnoreList = ignoreListConfig.Value; editSensitiveList = sensitiveListConfig.Value; PatchAllRPCMethods(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"RPC_monitor loaded. {allRPCMethods.Count} methods patched."); } private void RefreshSensitiveSet() { sensitiveSet = (from s in sensitiveListConfig.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select s.Trim() into s where !string.IsNullOrEmpty(s) select s).ToHashSet(); } private void Update() { if (Input.GetKeyDown((KeyCode)282)) { showWindow = !showWindow; } } private void OnGUI() { //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown if (showWindow) { if (labelStyle == null) { labelStyle = new GUIStyle(GUI.skin.label) { fontSize = 22, clipping = (TextClipping)1 }; buttonStyle = new GUIStyle(GUI.skin.button) { fontSize = 22, fixedHeight = 36f }; textFieldStyle = new GUIStyle(GUI.skin.textField) { fontSize = 22, fixedHeight = 36f }; windowStyle = new GUIStyle(GUI.skin.window) { fontSize = 22 }; boxStyle = new GUIStyle(GUI.skin.box) { fontSize = 22 }; toolbarStyle = new GUIStyle(GUI.skin.button) { fontSize = 22, fixedHeight = 44f, stretchWidth = true }; toggleStyle = new GUIStyle(GUI.skin.toggle) { fontSize = 22 }; } Rect val = default(Rect); ((Rect)(ref val))..ctor(0f, 0f, (float)Screen.width, (float)Screen.height); GUI.Window(123456, val, new WindowFunction(DrawWindow), "RPC Control & Monitor", windowStyle); } } private void DrawWindow(int id) { float num = Screen.width - 20; GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num) }); GUILayout.BeginHorizontal(Array.Empty()); string[] array = new string[2] { "Control Panel", "Monitor & Cheat" }; currentPage = GUILayout.Toolbar(currentPage, array, toolbarStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(44f) }); GUILayout.EndHorizontal(); switch (currentPage) { case 0: DrawControlPanel(num); break; case 1: DrawMonitorCheatPanel(num); break; } GUILayout.EndVertical(); } private void DrawControlPanel(float w) { //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Search:", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }); searchText = GUILayout.TextField(searchText, textFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }); if (GUILayout.Button("Clear", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) })) { searchText = ""; } GUILayout.FlexibleSpace(); if (GUILayout.Button("Block All", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(120f), GUILayout.Height(36f) })) { SetAllBlocked(block: true); } if (GUILayout.Button("Unblock All", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(120f), GUILayout.Height(36f) })) { SetAllBlocked(block: false); } GUILayout.EndHorizontal(); float num = Screen.height - 120; scrollControl = GUILayout.BeginScrollView(scrollControl, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(w), GUILayout.Height(num) }); IOrderedEnumerable orderedEnumerable = from m in allRPCMethods orderby favoritesSet.Contains(GetMethodId(m)) descending, m.Name select m; foreach (MethodInfo item in orderedEnumerable) { string methodId = GetMethodId(item); if (string.IsNullOrEmpty(searchText) || item.Name.ToLower().Contains(searchText.ToLower())) { GUILayout.BeginHorizontal(boxStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(52f) }); string text = (favoritesSet.Contains(methodId) ? "★" : "☆"); if (GUILayout.Button(text, buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(36f), GUILayout.Height(36f) })) { ToggleFavorite(methodId); } bool flag = blockedMap[methodId]; bool flag2 = GUILayout.Toggle(flag, "", toggleStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) }); if (flag2 != flag) { blockedMap[methodId] = flag2; UpdateBlockedSet(methodId); } string text2 = item.Name + "(" + string.Join(", ", from p in item.GetParameters() select p.Name) + ")"; GUILayout.Label(text2, labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(650f), GUILayout.ExpandWidth(false) }); GUILayout.EndHorizontal(); } } GUILayout.EndScrollView(); } private void DrawMonitorCheatPanel(float w) { //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_049b: Unknown result type (might be due to invalid IL or missing references) //IL_0494: Unknown result type (might be due to invalid IL or missing references) //IL_048d: Unknown result type (might be due to invalid IL or missing references) //IL_05dc: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label($"Log (max {maxLogEntries.Value})", labelStyle, Array.Empty()); GUILayout.Space(20f); GUILayout.Label("Filter:", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }); monitorFilter = GUILayout.TextField(monitorFilter, textFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }); if (GUILayout.Button("Clear", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) })) { monitorFilter = ""; } GUILayout.FlexibleSpace(); if (GUILayout.Button("Clear Log", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(120f), GUILayout.Height(36f) })) { rpcLogs.Clear(); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Ignore:", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }); editIgnoreList = GUILayout.TextField(editIgnoreList, textFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(600f) }); if (GUILayout.Button("Apply", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) })) { ignoreListConfig.Value = editIgnoreList; ((BaseUnityPlugin)this).Config.Save(); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Sensitive:", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }); editSensitiveList = GUILayout.TextField(editSensitiveList, textFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(600f) }); if (GUILayout.Button("Apply", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) })) { sensitiveListConfig.Value = editSensitiveList; ((BaseUnityPlugin)this).Config.Save(); } GUILayout.EndHorizontal(); float num = Screen.height - 260; scrollMonitor = GUILayout.BeginScrollView(scrollMonitor, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(w), GUILayout.Height(num) }); string[] array = (from s in ignoreListConfig.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select s.Trim().ToLower() into s where !string.IsNullOrEmpty(s) select s).ToArray(); GUILayout.BeginHorizontal(boxStyle, Array.Empty()); GUILayout.Label("Time", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }); GUILayout.Label("Method", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(300f) }); GUILayout.Label("Sender", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }); GUILayout.Label("Receiver", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }); GUILayout.Label("Actions", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) }); GUILayout.EndHorizontal(); for (int num2 = rpcLogs.Count - 1; num2 >= 0; num2--) { RPCLogEntry rPCLogEntry = rpcLogs[num2]; if (string.IsNullOrEmpty(monitorFilter) || rPCLogEntry.MethodName.ToLower().Contains(monitorFilter.ToLower())) { bool flag = false; string text = rPCLogEntry.MethodName.ToLower(); string[] array2 = array; foreach (string value in array2) { if (text.Contains(value)) { flag = true; break; } } if (!flag) { bool flag2 = sensitiveSet.Contains(rPCLogEntry.MethodName); GUI.backgroundColor = ((flag2 && rPCLogEntry.SenderName != "Local" && PhotonNetwork.InRoom && PhotonNetwork.MasterClient != null && !rPCLogEntry.SenderName.StartsWith(PhotonNetwork.MasterClient.NickName)) ? Color.red : (flag2 ? Color.yellow : Color.white)); GUILayout.BeginHorizontal(boxStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(36f) }); GUILayout.Label(rPCLogEntry.TimeString, labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }); GUILayout.Label(rPCLogEntry.MethodName, labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(300f) }); GUILayout.Label(rPCLogEntry.SenderName, labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }); GUILayout.Label(rPCLogEntry.ReceiverName, labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }); if (GUILayout.Button("Ign", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) })) { AddToIgnoreList(rPCLogEntry.MethodName); editIgnoreList = ignoreListConfig.Value; } if (GUILayout.Button("Sens", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) })) { ToggleSensitive(rPCLogEntry.MethodName); editSensitiveList = sensitiveListConfig.Value; } GUILayout.EndHorizontal(); GUI.backgroundColor = Color.white; } } } GUILayout.EndScrollView(); } private void AddLog(string methodName, int senderActor, PhotonView receiverView) { string methodName2 = methodName; int viewId = (((Object)(object)receiverView != (Object)null) ? receiverView.ViewID : (-1)); float time = Time.time; while (dedupQueue.Count > 0 && dedupQueue.Peek().time < time - 2f) { dedupQueue.Dequeue(); } if (dedupQueue.Any<(string, int, int, float)>(((string method, int sender, int viewId, float time) x) => x.method == methodName2 && x.sender == senderActor && x.viewId == viewId)) { return; } dedupQueue.Enqueue((methodName2, senderActor, viewId, time)); string senderName; if (senderActor == -1) { senderName = "Local"; } else if (PhotonNetwork.InRoom) { Player player = PhotonNetwork.CurrentRoom.GetPlayer(senderActor, false); senderName = ((player != null) ? player.NickName : $"Actor {senderActor}"); } else { senderName = $"Actor {senderActor}"; } string text = "?"; if ((Object)(object)receiverView != (Object)null) { text = ((Object)((Component)receiverView).gameObject).name; Player owner = receiverView.Owner; if (owner != null) { text = text + " (" + owner.NickName + ")"; } } rpcLogs.Add(new RPCLogEntry { TimeString = DateTime.Now.ToString("HH:mm:ss"), MethodName = methodName2, SenderName = senderName, ReceiverName = text }); while (rpcLogs.Count > maxLogEntries.Value) { rpcLogs.RemoveAt(0); } } private void PatchAllRPCMethods() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown Harmony val = new Harmony("com.rpccontrol.mod.patch"); foreach (MethodInfo allRPCMethod in allRPCMethods) { try { val.Patch((MethodBase)allRPCMethod, new HarmonyMethod(typeof(RPCControlPlugin), "RPCPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch { } } } public static bool RPCPrefix(MethodBase __originalMethod, object __instance, object[] __args) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) string methodId = GetMethodId((MethodInfo)__originalMethod); bool flag = BlockedMethods.Contains(methodId); int senderActor = -1; PhotonView val = null; if (__args != null) { ParameterInfo[] parameters = __originalMethod.GetParameters(); for (int i = 0; i < parameters.Length; i++) { if (parameters[i].ParameterType == typeof(PhotonMessageInfo) && i < __args.Length && __args[i] is PhotonMessageInfo val2) { senderActor = val2.Sender.ActorNumber; val = val2.photonView; break; } } } if ((Object)(object)val == (Object)null) { Component val3 = (Component)((__instance is Component) ? __instance : null); if (val3 != null) { val = val3.GetComponent(); if ((Object)(object)val == (Object)null) { val = val3.GetComponentInParent(); } } } Instance?.AddLog(__originalMethod.Name, senderActor, val); return !flag; } private void AddToIgnoreList(string methodName) { List list = (from s in ignoreListConfig.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select s.Trim()).ToList(); if (!list.Contains(methodName)) { list.Add(methodName); ignoreListConfig.Value = string.Join(",", list); ((BaseUnityPlugin)this).Config.Save(); } } private void ToggleSensitive(string methodName) { if (sensitiveSet.Contains(methodName)) { sensitiveSet.Remove(methodName); } else { sensitiveSet.Add(methodName); } sensitiveListConfig.Value = string.Join(",", sensitiveSet); ((BaseUnityPlugin)this).Config.Save(); } private void SetAllBlocked(bool block) { foreach (string item in blockedMap.Keys.ToList()) { blockedMap[item] = block; UpdateBlockedSet(item); } } private static void UpdateBlockedSet(string methodId) { if (Instance.blockedMap[methodId]) { BlockedMethods.Add(methodId); } else { BlockedMethods.Remove(methodId); } } private void ToggleFavorite(string methodId) { if (favoritesSet.Contains(methodId)) { favoritesSet.Remove(methodId); } else { favoritesSet.Add(methodId); } favoritesConfig.Value = string.Join(",", favoritesSet); ((BaseUnityPlugin)this).Config.Save(); } public static string GetMethodId(MethodInfo m) { return m.DeclaringType.FullName + "." + m.Name; } } public class RPCLogEntry { public string TimeString; public string MethodName; public string SenderName; public string ReceiverName; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }