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 PurpleTurtle AdminToolNotifier v0.1.0
BepInEx/plugins/PurpleTurtleAdminToolNotifier/MagiCorp.PurpleTurtleAdminToolNotifier.Client.dll
Decompiled 4 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using HarmonyLib; using UnityEngine; using UnityEngine.Events; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("MagiCorp.PurpleTurtleAdminToolNotifier.Client")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+dc87b9315a533b989877c4e4b7185e445a0c55e7")] [assembly: AssemblyProduct("MagiCorp.PurpleTurtleAdminToolNotifier.Client")] [assembly: AssemblyTitle("MagiCorp.PurpleTurtleAdminToolNotifier.Client")] [assembly: AssemblyVersion("1.0.0.0")] namespace MagiCorp.PurpleTurtleAdminToolNotifier; [BepInPlugin("magicorp.purpleturtle.admintoolnotifier.client", "Purple Turtle Admin Tool Notifier", "0.1.0")] public sealed class ClientNotifier : BaseUnityPlugin { private const string PluginVersion = "0.1.0"; private const string EventRpc = "MagiCorp_QolAudit_v1"; private const string HelloRpc = "MagiCorp_QolHello_v1"; private const string AckRpc = "MagiCorp_QolAck_v1"; private static ClientNotifier I; private Harmony harmony; private bool hooked; private float nextScan; private float nextHello; private ZRpc serverRpc; private bool ack; private readonly Dictionary<FieldInfo, bool> flags = new Dictionary<FieldInfo, bool>(); private readonly Queue<string> pending = new Queue<string>(); private static readonly BindingFlags All = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private void Awake() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown I = this; harmony = new Harmony("magicorp.purpleturtle.admintoolnotifier.client"); TryHook(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Purple Turtle Admin Tool Notifier 0.1.0 loaded. Client-side telemetry for the Purple Turtle server only."); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } I = null; } private void Update() { if (Time.unscaledTime < nextScan) { return; } nextScan = Time.unscaledTime + 0.25f; try { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || instance.IsServer()) { ResetConnection(); return; } TryHook(); ZNetPeer serverPeer = instance.GetServerPeer(); if (serverPeer == null || !serverPeer.IsReady()) { ResetConnection(); return; } if (serverRpc != serverPeer.m_rpc) { ResetConnection(); serverRpc = serverPeer.m_rpc; serverRpc.Register<string>("MagiCorp_QolAck_v1", (Action<ZRpc, string>)delegate(ZRpc rpc, string v) { if (rpc == serverRpc) { if (!ack) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Purple Turtle audit receiver acknowledged this client."); } ack = true; } }); } if (Time.unscaledTime >= nextHello) { nextHello = Time.unscaledTime + 10f; serverRpc.Invoke("MagiCorp_QolHello_v1", new object[1] { "0.1.0;Purple Turtle client;" + (hooked ? "QoL hooks active" : "target mod absent or hooks incomplete") }); } if ((Object)(object)Player.m_localPlayer != (Object)null) { ReadFlags(); } if (!ack) { return; } for (int num = 0; num < 16; num++) { if (pending.Count <= 0) { break; } serverRpc.Invoke("MagiCorp_QolAudit_v1", new object[1] { pending.Dequeue() }); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogDebug((object)ex.Message); } } private void ResetConnection() { serverRpc = null; ack = false; nextHello = 0f; pending.Clear(); FieldInfo[] array = flags.Keys.ToArray(); foreach (FieldInfo key in array) { flags[key] = false; } } private void Report(string feature, string detail) { if (!((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer() && !((Object)(object)Player.m_localPlayer == (Object)null)) { if (pending.Count >= 1024) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Purple Turtle audit queue full; report dropped"); return; } pending.Enqueue(Clean(feature, 80) + "\t" + Clean(detail, 700)); ((BaseUnityPlugin)this).Logger.LogWarning((object)("[PurpleTurtleAudit] " + Clean(feature, 80) + ": " + Clean(detail, 300))); } } private void TryHook() { //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Expected O, but got Unknown if (hooked || AccessTools.TypeByName("ValheimAdminTool.Menus.CheatsMenu") == null) { return; } string[,] array = new string[5, 3] { { "ValheimAdminTool.Menus.ItemsMenu", "SpawnItem", "ActionPrefix" }, { "ValheimAdminTool.Menus.EntitiesMenu", "SpawnEntity", "ActionPrefix" }, { "ValheimAdminTool.Menus.SkillsMenu", "SetSkill", "ActionPrefix" }, { "ValheimAdminTool.Controls.ModButton", "CreateButton", "ButtonPrefix" }, { "ValheimAdminTool.Controls.ModSwitch", "CreateSwitch", "SwitchPrefix" } }; int num = 0; for (int i = 0; i < array.GetLength(0); i++) { MethodInfo methodInfo = AccessTools.Method(AccessTools.TypeByName(array[i, 0]), array[i, 1], (Type[])null, (Type[])null); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Missing audit hook: " + array[i, 0] + "." + array[i, 1])); continue; } Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo); if (patchInfo == null || !patchInfo.Owners.Contains(harmony.Id)) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(ClientNotifier), array[i, 2], (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } num++; } string[] array2 = new string[3] { "CheatsMenu", "ToolsMenu", "ESPMenu" }; foreach (string text in array2) { Type type = AccessTools.TypeByName("ValheimAdminTool.Menus." + text); if (!(type != null)) { continue; } foreach (FieldInfo item in from f in type.GetFields(All) where f.FieldType == typeof(bool) select f) { if (!flags.ContainsKey(item)) { flags.Add(item, value: false); } } } hooked = num == 5; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Purple Turtle Admin Tool hooks: " + num + "/5; monitored switches: " + flags.Count)); } private void ReadFlags() { FieldInfo[] array = flags.Keys.ToArray(); foreach (FieldInfo fieldInfo in array) { bool flag = (bool)fieldInfo.GetValue(null); if (flag != flags[fieldInfo]) { flags[fieldInfo] = flag; Report(fieldInfo.DeclaringType.Name + "." + fieldInfo.Name, flag ? "enabled" : "disabled"); } } } private static string Clean(string s, int max) { s = new string((s ?? "").Select((char c) => (!char.IsControl(c)) ? c : ' ').ToArray()); if (s.Length <= max) { return s; } return s.Substring(0, max); } private static void ActionPrefix(MethodBase __originalMethod, object[] __args) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)I == (Object)null)) { string name = __originalMethod.Name; if (!(name == "SetSkill") || !((Object)(object)Player.m_localPlayer != (Object)null) || !Enum.TryParse<SkillType>(Convert.ToString(__args[0]), ignoreCase: true, out SkillType result) || !(Math.Abs(((Character)Player.m_localPlayer).GetSkills().GetSkillLevel(result) - Mathf.Clamp(Convert.ToSingle(__args[1]), 0f, 100f)) < 0.001f)) { string text = ((name == "SetSkill") ? ("skill=" + __args[0]?.ToString() + " value=" + Convert.ToString(__args[1], CultureInfo.InvariantCulture)) : ("prefab=" + __args[0]?.ToString() + " requested_amount=" + __args[2]?.ToString() + ((name == "SpawnEntity") ? (" tamed=" + __args[3]?.ToString() + " level=" + __args[4]) : ""))); I.Report(name, "attempt: " + text); } } } private static void ButtonPrefix(object[] __args) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown if ((Object)(object)I == (Object)null || __args.Length < 10) { return; } object obj = __args[9]; UnityAction original = (UnityAction)((obj is UnityAction) ? obj : null); if (original == null) { return; } string text = ((Delegate)(object)original).Method.DeclaringType?.FullName ?? ""; if (text.Contains("CheatsMenu") || text.Contains("ToolsMenu")) { string label = Convert.ToString(__args[2]); __args[9] = (object)(UnityAction)delegate { I?.Report("button", "attempt: " + label); original.Invoke(); }; } } private static void SwitchPrefix(object[] __args) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown for (int i = 6; i <= 7; i++) { object obj = __args[i]; UnityAction original = (UnityAction)((obj is UnityAction) ? obj : null); if (original != null) { __args[i] = (object)(UnityAction)delegate { original.Invoke(); I?.ReadFlags(); }; } } } }