Decompiled source of PingDisplay v1.0.0

plugins\Freddy.PingDisplay.dll

Decompiled 3 days ago
using 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";
	}
}