using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("MorePlayerList.PingAddon")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("MorePlayerList.PingAddon")] [assembly: AssemblyTitle("MorePlayerList.PingAddon")] [assembly: AssemblyVersion("1.0.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 MorePlayerList.PingAddon { [BepInPlugin("MaDeSu.MorePlayerList.PingAddon", "MorePlayerList Ping Addon", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class PingAddonPlugin : BaseUnityPlugin { public const string GUID = "MaDeSu.MorePlayerList.PingAddon"; public const string Version = "1.1.0"; internal static ManualLogSource Log; private readonly Harmony harmony = new Harmony("MaDeSu.MorePlayerList.PingAddon"); public static ConfigEntry ShowPing; public static ConfigEntry FontSize; public static ConfigEntry XOffset; public static ConfigEntry YOffset; public static ConfigEntry GreenThreshold; public static ConfigEntry YellowThreshold; public static ConfigEntry OrangeThreshold; private void Awake() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected O, but got Unknown //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ShowPing = ((BaseUnityPlugin)this).Config.Bind("Settings", "Show Ping", true, "Show each player's ping next to their entry in the ESC menu list."); FontSize = ((BaseUnityPlugin)this).Config.Bind("Settings", "Font size", 14, new ConfigDescription("Font size of the ping label.", (AcceptableValueBase)(object)new AcceptableValueRange(8, 32), Array.Empty())); XOffset = ((BaseUnityPlugin)this).Config.Bind("Settings", "X offset", 10f, new ConfigDescription("Gap between the ping label and the left edge of the player's row (negative = further left, this is NOT relative to the row's center).", (AcceptableValueBase)(object)new AcceptableValueRange(-400f, 400f), Array.Empty())); YOffset = ((BaseUnityPlugin)this).Config.Bind("Settings", "Y offset", 0f, new ConfigDescription("Vertical offset of the ping label relative to the player's slider.", (AcceptableValueBase)(object)new AcceptableValueRange(-100f, 100f), Array.Empty())); GreenThreshold = ((BaseUnityPlugin)this).Config.Bind("Colors", "Green threshold", 50, new ConfigDescription("Ping (ms) below this value is shown in green.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 1000), Array.Empty())); YellowThreshold = ((BaseUnityPlugin)this).Config.Bind("Colors", "Yellow threshold", 100, new ConfigDescription("Ping (ms) below this value is shown in yellow.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 1000), Array.Empty())); OrangeThreshold = ((BaseUnityPlugin)this).Config.Bind("Colors", "Orange threshold", 200, new ConfigDescription("Ping (ms) below this value is shown in orange, otherwise red.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 1000), Array.Empty())); ShowPing.SettingChanged += delegate { EscPingPatch.RefreshAll(); }; FontSize.SettingChanged += delegate { EscPingPatch.RefreshAll(); }; XOffset.SettingChanged += delegate { EscPingPatch.RefreshAll(); }; YOffset.SettingChanged += delegate { EscPingPatch.RefreshAll(); }; GreenThreshold.SettingChanged += delegate { EscPingPatch.RefreshAll(); }; YellowThreshold.SettingChanged += delegate { EscPingPatch.RefreshAll(); }; OrangeThreshold.SettingChanged += delegate { EscPingPatch.RefreshAll(); }; harmony.PatchAll(); Log.LogInfo((object)"MorePlayerList Ping Addon loaded."); } } [HarmonyPatch(typeof(MenuPageEsc), "Update")] public static class EscPingPatch { private static readonly FieldInfo SlidersField = AccessTools.Field(typeof(MenuPageEsc), "playerMicGainSliders"); private static readonly FieldInfo PingField = FindPingField(); private static readonly Dictionary pingTexts = new Dictionary(); private static Font cachedFont; private static FieldInfo FindPingField() { string[] array = new string[3] { "playerPing", "PlayerPing", "ping" }; string[] array2 = array; foreach (string name in array2) { FieldInfo field = typeof(PlayerAvatar).GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field; } } ManualLogSource log = PingAddonPlugin.Log; if (log != null) { log.LogWarning((object)"MorePlayerList.PingAddon: could not find a ping field on PlayerAvatar - ping display disabled."); } return null; } private static void Postfix(MenuPageEsc __instance) { //IL_014e: Unknown result type (might be due to invalid IL or missing references) if (!PingAddonPlugin.ShowPing.Value || PingField == null || SlidersField == null || !(SlidersField.GetValue(__instance) is Dictionary { Count: not 0 } dictionary)) { return; } CleanupStaleEntries(dictionary); foreach (KeyValuePair item in dictionary) { PlayerAvatar key = item.Key; MenuSliderPlayerMicGain value = item.Value; if (key != null && value != null) { if (!pingTexts.TryGetValue(key, out var value2) || (Object)(object)value2 == (Object)null) { value2 = CreatePingText(((Component)value).transform); pingTexts[key] = value2; } int ping = GetPing(key); bool flag = !IsLocalPlayer(key) && IsHost(key); string arg = (flag ? "[H] " : ""); value2.text = ((ping >= 0) ? $"{arg}{ping}ms" : (flag ? "[H] --" : "--")); ((Graphic)value2).color = GetPingColor(ping); } } } private static void CleanupStaleEntries(Dictionary current) { List list = null; foreach (KeyValuePair pingText in pingTexts) { if (pingText.Key == null || !current.ContainsKey(pingText.Key) || (Object)(object)pingText.Value == (Object)null) { (list ?? (list = new List())).Add(pingText.Key); } } if (list == null) { return; } foreach (PlayerAvatar item in list) { pingTexts.Remove(item); } } public static void RefreshAll() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair pingText in pingTexts) { Text value = pingText.Value; if (!((Object)(object)value == (Object)null)) { RectTransform rectTransform = ((Graphic)value).rectTransform; rectTransform.anchoredPosition = new Vector2(PingAddonPlugin.XOffset.Value, PingAddonPlugin.YOffset.Value); value.fontSize = PingAddonPlugin.FontSize.Value; ((Component)value).gameObject.SetActive(PingAddonPlugin.ShowPing.Value); } } } private static int GetPing(PlayerAvatar player) { try { if (PingField.GetValue(player) is int result) { return result; } return -1; } catch { return -1; } } private static bool IsLocalPlayer(PlayerAvatar player) { try { PhotonView component = ((Component)player).GetComponent(); return (Object)(object)component != (Object)null && component.IsMine; } catch { return false; } } private static bool IsHost(PlayerAvatar player) { try { PhotonView component = ((Component)player).GetComponent(); if ((Object)(object)component == (Object)null) { return false; } Player owner = component.Owner; return owner != null && owner.IsMasterClient; } catch { return false; } } private static Color GetPingColor(int ping) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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) //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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) if (ping < 0) { return new Color(0.5f, 0.5f, 0.5f); } if (ping < PingAddonPlugin.GreenThreshold.Value) { return new Color(0f, 1f, 0.4f); } if (ping < PingAddonPlugin.YellowThreshold.Value) { return new Color(1f, 0.9f, 0f); } if (ping < PingAddonPlugin.OrangeThreshold.Value) { return new Color(1f, 0.55f, 0f); } return new Color(1f, 0.2f, 0.2f); } private static Text CreatePingText(Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: 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) GameObject val = new GameObject("PingAddon_PingText"); val.transform.SetParent(parent, false); val.layer = ((Component)parent).gameObject.layer; RectTransform val2 = val.AddComponent(); val2.sizeDelta = new Vector2(80f, 20f); val2.anchorMin = new Vector2(0f, 0.5f); val2.anchorMax = new Vector2(0f, 0.5f); val2.pivot = new Vector2(1f, 0.5f); val2.anchoredPosition = new Vector2(PingAddonPlugin.XOffset.Value, PingAddonPlugin.YOffset.Value); Text val3 = val.AddComponent(); val3.font = GetFont(); val3.fontSize = PingAddonPlugin.FontSize.Value; val3.alignment = (TextAnchor)5; val3.text = ""; Outline val4 = val.AddComponent(); ((Shadow)val4).effectColor = Color.black; ((Shadow)val4).effectDistance = new Vector2(1f, -1f); return val3; } private static Font GetFont() { if ((Object)(object)cachedFont != (Object)null) { return cachedFont; } try { cachedFont = Resources.GetBuiltinResource("Arial.ttf"); } catch { } if ((Object)(object)cachedFont == (Object)null) { try { Object builtinResource = Resources.GetBuiltinResource(typeof(Font), "LegacyRuntime.ttf"); cachedFont = (Font)(object)((builtinResource is Font) ? builtinResource : null); } catch { } } if ((Object)(object)cachedFont == (Object)null) { cachedFont = Font.CreateDynamicFontFromOSFont("Arial", 14); } return cachedFont; } } }