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 PingDisplay v1.0.0
plugins\Freddy.PingDisplay.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; [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("PingDisplayMod")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Показывает пинг игроков над головами и ваш собственный пинг")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("PingDisplayMod")] [assembly: AssemblyTitle("PingDisplay")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PingDisplayMod { [BepInPlugin("Freddy.PingDisplay", "PingDisplay", "1.0.0")] public class PingDisplayMod : BaseUnityPlugin { public static ManualLogSource Logger; private readonly Harmony harmony = new Harmony("Freddy.PingDisplay"); private object pingUI; private object pingText; private Dictionary<ulong, object> playerPingLabels = new Dictionary<ulong, object>(); private float updateTimer; private const float UPDATE_INTERVAL = 1f; private void Awake() { Logger = Logger.CreateLogSource("Freddy.PingDisplay"); Logger.LogInfo((object)"Plugin Freddy.PingDisplay is loaded!"); harmony.PatchAll(); } private void Start() { try { CreatePingUI(); } catch (Exception ex) { Logger.LogError((object)("Error in Start: " + ex.Message)); } } private void Update() { try { object gameNetworkManager = GetGameNetworkManager(); object startOfRound = GetStartOfRound(); if (gameNetworkManager != null && startOfRound != null) { updateTimer += GetDeltaTime(); if (updateTimer >= 1f) { updateTimer = 0f; UpdatePingDisplay(); UpdatePlayerPingLabels(); } } } catch (Exception ex) { Logger.LogError((object)("Error in Update: " + ex.Message)); } } private void CreatePingUI() { try { Type unityType = GetUnityType("UnityEngine.Canvas"); object obj = FindObjectOfType(unityType); if (obj == null) { Logger.LogWarning((object)"Canvas not found, UI will not be created"); return; } Type unityType2 = GetUnityType("UnityEngine.GameObject"); Type unityType3 = GetUnityType("UnityEngine.RectTransform"); Type unityType4 = GetUnityType("UnityEngine.UI.Image"); Type unityType5 = GetUnityType("UnityEngine.UI.Text"); pingUI = Activator.CreateInstance(unityType2); SetProperty(pingUI, "name", "PingDisplayUI"); object property = GetProperty(pingUI, "transform"); SetProperty(property, "parent", GetProperty(obj, "transform")); SetProperty(property, "localScale", new object[3] { 1f, 1f, 1f }); object obj2 = InvokeMethod(pingUI, "AddComponent", unityType3); SetProperty(obj2, "anchorMin", new object[2] { 0f, 1f }); SetProperty(obj2, "anchorMax", new object[2] { 0f, 1f }); SetProperty(obj2, "anchoredPosition", new object[2] { 10f, -10f }); SetProperty(obj2, "sizeDelta", new object[2] { 200f, 50f }); object obj3 = InvokeMethod(pingUI, "AddComponent", unityType4); Type unityType6 = GetUnityType("UnityEngine.Color"); object value = Activator.CreateInstance(unityType6, 0f, 0f, 0f, 0.7f); SetProperty(obj3, "color", value); object obj4 = Activator.CreateInstance(unityType2); SetProperty(obj4, "name", "PingText"); object property2 = GetProperty(obj4, "transform"); SetProperty(property2, "parent", property); SetProperty(property2, "localScale", new object[3] { 1f, 1f, 1f }); object obj5 = InvokeMethod(obj4, "AddComponent", unityType3); SetProperty(obj5, "anchorMin", new object[2] { 0f, 0f }); SetProperty(obj5, "anchorMax", new object[2] { 1f, 1f }); SetProperty(obj5, "offsetMin", new object[2] { 0f, 0f }); SetProperty(obj5, "offsetMax", new object[2] { 0f, 0f }); pingText = InvokeMethod(obj4, "AddComponent", unityType5); SetProperty(pingText, "text", "Ping: --"); Type unityType7 = GetUnityType("UnityEngine.Font"); object value2 = InvokeStaticMethod(unityType7, "CreateDynamicFontFromOSFont", "Arial", 16); SetProperty(pingText, "font", value2); SetProperty(pingText, "fontSize", 16); SetProperty(pingText, "color", Activator.CreateInstance(unityType6, 1f, 1f, 1f, 1f)); object value3 = Enum.Parse(GetUnityType("UnityEngine.TextAnchor"), "MiddleLeft"); SetProperty(pingText, "alignment", value3); Logger.LogInfo((object)"Ping UI created successfully"); } catch (Exception ex) { Logger.LogError((object)("Error creating ping UI: " + ex.Message)); } } private void UpdatePingDisplay() { if (pingText == null) { return; } try { object gameNetworkManager = GetGameNetworkManager(); if (gameNetworkManager == null) { return; } int num = 0; object property = GetProperty(gameNetworkManager, "NetworkManager"); if (property != null) { object property2 = GetProperty(property, "NetworkConfig"); if (property2 != null) { object property3 = GetProperty(property2, "NetworkTransport"); if (property3 != null) { num = (int)InvokeMethod(property3, "GetCurrentRtt", 0); } } } if (num <= 0) { SetProperty(pingText, "text", "Ping: ---"); return; } SetProperty(pingText, "text", $"Ping: {num}ms"); Type unityType = GetUnityType("UnityEngine.Color"); SetProperty(value: (num < 50) ? Activator.CreateInstance(unityType, 0f, 1f, 0f, 1f) : ((num >= 100) ? Activator.CreateInstance(unityType, 1f, 0f, 0f, 1f) : Activator.CreateInstance(unityType, 1f, 1f, 0f, 1f)), obj: pingText, propertyName: "color"); } catch (Exception ex) { Logger.LogError((object)("Error updating ping display: " + ex.Message)); SetProperty(pingText, "text", "Ping: Error"); } } private void UpdatePlayerPingLabels() { try { object startOfRound = GetStartOfRound(); if (startOfRound == null || !(GetProperty(startOfRound, "allPlayerScripts") is Array array)) { return; } foreach (object value in playerPingLabels.Values) { if (value != null) { Destroy(value); } } playerPingLabels.Clear(); foreach (object item in array) { if (item != null) { object property = GetProperty(startOfRound, "localPlayerController"); if (item != property) { CreatePlayerPingLabel(item); } } } } catch (Exception ex) { Logger.LogError((object)("Error updating player ping labels: " + ex.Message)); } } private void CreatePlayerPingLabel(object player) { if (player == null) { return; } try { object property = GetProperty(player, "playerClientId"); string text = GetProperty(player, "playerUsername") as string; object obj = Activator.CreateInstance(GetUnityType("UnityEngine.GameObject")); SetProperty(obj, "name", $"PingLabel_{property}"); object property2 = GetProperty(obj, "transform"); object property3 = GetProperty(player, "transform"); SetProperty(property2, "parent", property3); SetProperty(property2, "localPosition", new object[3] { 0f, 2.5f, 0f }); Type unityType = GetUnityType("UnityEngine.Canvas"); object obj2 = InvokeMethod(obj, "AddComponent", unityType); SetProperty(obj2, "renderMode", 1); Type unityType2 = GetUnityType("UnityEngine.Camera"); object value = InvokeStaticMethod(unityType2, "main"); SetProperty(obj2, "worldCamera", value); Type unityType3 = GetUnityType("UnityEngine.UI.Text"); object obj3 = InvokeMethod(obj, "AddComponent", unityType3); SetProperty(obj3, "text", text + "\nPing: ---"); Type unityType4 = GetUnityType("UnityEngine.Font"); object value2 = InvokeStaticMethod(unityType4, "CreateDynamicFontFromOSFont", "Arial", 12); SetProperty(obj3, "font", value2); SetProperty(obj3, "fontSize", 12); Type unityType5 = GetUnityType("UnityEngine.Color"); SetProperty(obj3, "color", Activator.CreateInstance(unityType5, 1f, 1f, 1f, 1f)); object value3 = Enum.Parse(GetUnityType("UnityEngine.TextAnchor"), "MiddleCenter"); SetProperty(obj3, "alignment", value3); playerPingLabels[(ulong)property] = obj; Logger.LogInfo((object)("Created ping label for player " + text)); } catch (Exception ex) { Logger.LogError((object)("Error creating player ping label: " + ex.Message)); } } private Type GetUnityType(string typeName) { return Type.GetType(typeName) ?? Type.GetType(typeName + ", UnityEngine") ?? Type.GetType(typeName + ", UnityEngine.CoreModule") ?? Type.GetType(typeName + ", UnityEngine.UI"); } private object GetGameNetworkManager() { Type unityType = GetUnityType("GameNetcodeStuff.GameNetworkManager"); if (unityType == null) { return null; } return InvokeStaticMethod(unityType, "get_Instance"); } private object GetStartOfRound() { Type unityType = GetUnityType("GameNetcodeStuff.StartOfRound"); if (unityType == null) { return null; } return InvokeStaticMethod(unityType, "get_Instance"); } private float GetDeltaTime() { Type unityType = GetUnityType("UnityEngine.Time"); if (unityType == null) { return 0f; } return (float)InvokeStaticMethod(unityType, "get_deltaTime"); } private object FindObjectOfType(Type type) { Type unityType = GetUnityType("UnityEngine.Object"); if (unityType == null) { return null; } return InvokeStaticMethod(unityType, "FindObjectOfType", type); } private object InvokeMethod(object obj, string methodName, params object[] parameters) { if (obj == null) { return null; } MethodInfo method = obj.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { return null; } return method.Invoke(obj, parameters); } private object InvokeStaticMethod(Type type, string methodName, params object[] parameters) { if (type == null) { return null; } MethodInfo method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { return null; } return method.Invoke(null, parameters); } private object GetProperty(object obj, string propertyName) { if (obj == null) { return null; } PropertyInfo property = obj.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property == null) { return null; } return property.GetValue(obj); } private void SetProperty(object obj, string propertyName, object value) { if (obj != null) { PropertyInfo property = obj.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(property == null)) { property.SetValue(obj, value); } } } private void Destroy(object obj) { if (obj != null) { Type unityType = GetUnityType("UnityEngine.Object"); if (!(unityType == null)) { InvokeStaticMethod(unityType, "Destroy", obj); } } } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } if (pingUI != null) { Destroy(pingUI); } foreach (object value in playerPingLabels.Values) { if (value != null) { Destroy(value); } } } } public static class PluginInfo { public const string PLUGIN_GUID = "Freddy.PingDisplay"; public const string PLUGIN_NAME = "PingDisplay"; public const string PLUGIN_VERSION = "1.0.0"; } public static class MyPluginInfo { public const string PLUGIN_GUID = "PingDisplayMod"; public const string PLUGIN_NAME = "PingDisplayMod"; public const string PLUGIN_VERSION = "1.0.0"; } }