using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.UI; [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("PlayerCountFixed")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("PlayerCountFixed")] [assembly: AssemblyTitle("PlayerCountFixed")] [assembly: AssemblyVersion("1.0.0.0")] [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 PlayerCountFixed { [BepInPlugin("local.playercountfixed", "PlayerCountFixed", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(MenuPageLobby), "Awake")] private static class MenuPageLobbyAwakePatch { private static void Postfix(MenuPageLobby __instance) { TryAttachLobbyCounter(__instance); } } [HarmonyPatch(typeof(MenuPageLobby), "Start")] private static class MenuPageLobbyStartPatch { private static void Postfix(MenuPageLobby __instance) { TryAttachLobbyCounter(__instance); } } private sealed class PlayerCountFixedUpdater : MonoBehaviour { [CompilerGenerated] private sealed class d__7 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PlayerCountFixedUpdater <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; PlayerCountFixedUpdater playerCountFixedUpdater = <>4__this; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; } else { <>1__state = -1; } playerCountFixedUpdater.RefreshOnce(); <>2__current = playerCountFixedUpdater._refreshDelay; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private TextMeshProUGUI? _text; private Coroutine? _refreshCoroutine; private string? _lastText; private readonly WaitForSeconds _refreshDelay = new WaitForSeconds(0.25f); internal void SetText(TextMeshProUGUI text) { _text = text; if (_refreshCoroutine == null && ((Behaviour)this).isActiveAndEnabled) { _refreshCoroutine = ((MonoBehaviour)this).StartCoroutine(RefreshLoop()); } } private void OnEnable() { if ((Object)(object)_text != (Object)null && _refreshCoroutine == null) { _refreshCoroutine = ((MonoBehaviour)this).StartCoroutine(RefreshLoop()); } } private void OnDisable() { if (_refreshCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_refreshCoroutine); _refreshCoroutine = null; } } [IteratorStateMachine(typeof(d__7))] private IEnumerator RefreshLoop() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__7(0) { <>4__this = this }; } internal void RefreshNow() { _lastText = null; RefreshOnce(); } private void RefreshOnce() { try { if ((Object)(object)_text == (Object)null) { return; } string text = string.Empty; Room currentRoom = PhotonNetwork.CurrentRoom; if (PhotonNetwork.InRoom && currentRoom != null) { if ((Object)(object)Instance == (Object)null || Instance.UseNewColorMode()) { string arg = ((currentRoom.PlayerCount == currentRoom.MaxPlayers) ? "#FF0000" : "#00FF00"); text = $"Players: {currentRoom.PlayerCount}/{currentRoom.MaxPlayers}"; } else { text = $"Players: {currentRoom.PlayerCount}/{currentRoom.MaxPlayers}"; } } if (!string.Equals(_lastText, text, StringComparison.Ordinal)) { ((TMP_Text)_text).text = text; _lastText = text; } } catch (Exception ex) { Instance?.LogUpdateFailureOnce(ex); } } } public const string PluginGuid = "local.playercountfixed"; public const string PluginName = "PlayerCountFixed"; public const string PluginVersion = "1.0.0"; private const string LobbyTextObjectName = "PlayerCountFixedTextLobby"; private const float DefaultPositionX1080 = 240f; private const float DefaultPositionY1080 = 30f; private const float DefaultFontSize = 22f; private const float MinFontSize = 1f; private const float MaxFontSize = 200f; private const float MinPosition = 0f; private const float MaxPosition = 10000f; private Harmony? _harmony; private ConfigEntry? _positionX1080; private ConfigEntry? _positionY1080; private ConfigEntry? _fontSize; private ConfigEntry? _colorMode; private bool _loggedUiAttached; private bool _loggedUiAttachFailure; private bool _loggedUiConfigFailure; private bool _loggedUpdateFailure; internal static Plugin? Instance { get; private set; } private void Awake() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown Instance = this; BindConfig(); _harmony = new Harmony("local.playercountfixed"); _harmony.PatchAll(typeof(Plugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"PlayerCountFixed loaded."); } private void OnDestroy() { UnsubscribeUiConfigChanged(); Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } internal static void TryAttachLobbyCounter(MenuPageLobby lobby) { Instance?.AttachLobbyCounter(lobby); } private void AttachLobbyCounter(MenuPageLobby lobby) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)lobby == (Object)null) { return; } Transform transform = ((Component)lobby).transform; Transform val = transform.Find("Panel"); Transform val2 = val ?? transform; Transform val3 = FindExistingCounter(transform); if ((Object)(object)val3 != (Object)null) { if ((Object)(object)val != (Object)null && (Object)(object)val3.parent != (Object)(object)val) { val3.SetParent(val, false); } ApplyUiConfig(val3, ((Component)val3).GetComponent()); EnsureUpdater(((Component)val3).gameObject, ((Component)val3).GetComponent()); return; } TextMeshProUGUI val4 = FindReferenceText(transform); GameObject val5 = new GameObject("PlayerCountFixedTextLobby"); val5.transform.SetParent(val2, false); RectTransform obj = val5.AddComponent(); obj.anchorMin = new Vector2(0f, 1f); obj.anchorMax = new Vector2(0f, 1f); obj.pivot = new Vector2(0f, 1f); obj.sizeDelta = new Vector2(240f, 30f); TextMeshProUGUI val6 = val5.AddComponent(); if ((Object)(object)val4 != (Object)null) { ((TMP_Text)val6).font = ((TMP_Text)val4).font; ((TMP_Text)val6).fontSharedMaterial = ((TMP_Text)val4).fontSharedMaterial; ((TMP_Text)val6).fontStyle = ((TMP_Text)val4).fontStyle; } ((TMP_Text)val6).alignment = (TextAlignmentOptions)513; ((Graphic)val6).color = Color.yellow; ((Graphic)val6).raycastTarget = false; ((TMP_Text)val6).text = string.Empty; ApplyUiConfig(val5.transform, val6); EnsureUpdater(val5, val6); if (!_loggedUiAttached) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Lobby player count UI attached."); _loggedUiAttached = true; } } catch (Exception ex) { LogUiAttachFailureOnce(ex); } } private void BindConfig() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown _positionX1080 = ((BaseUnityPlugin)this).Config.Bind("UI", "Position X (1080p)", 240f, new ConfigDescription("Horizontal RectTransform anchored-position UI offset from the top-left anchor, in UI units. Values are clamped to a safe non-negative range.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 10000f), Array.Empty())); _positionY1080 = ((BaseUnityPlugin)this).Config.Bind("UI", "Position Y (1080p)", 30f, new ConfigDescription("Vertical RectTransform anchored-position UI offset from the top-left anchor, in UI units. Values are clamped to a safe non-negative range.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 10000f), Array.Empty())); _fontSize = ((BaseUnityPlugin)this).Config.Bind("UI", "Font Size", 22f, new ConfigDescription("Lobby counter TextMeshPro font size. Values are clamped to a safe positive range.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 200f), Array.Empty())); _colorMode = ((BaseUnityPlugin)this).Config.Bind("UI", "Color Mode", "new", new ConfigDescription("Lobby counter color style. Use 'new' for colored player counts or 'old' for the plain all-yellow display.", (AcceptableValueBase)(object)new AcceptableValueList(new string[2] { "new", "old" }), Array.Empty())); SubscribeUiConfigChanged(); } private void SubscribeUiConfigChanged() { ((BaseUnityPlugin)this).Config.ConfigReloaded += OnUiConfigChanged; if (_positionX1080 != null) { _positionX1080.SettingChanged += OnUiConfigChanged; } if (_positionY1080 != null) { _positionY1080.SettingChanged += OnUiConfigChanged; } if (_fontSize != null) { _fontSize.SettingChanged += OnUiConfigChanged; } if (_colorMode != null) { _colorMode.SettingChanged += OnUiConfigChanged; } } private void UnsubscribeUiConfigChanged() { ((BaseUnityPlugin)this).Config.ConfigReloaded -= OnUiConfigChanged; if (_positionX1080 != null) { _positionX1080.SettingChanged -= OnUiConfigChanged; } if (_positionY1080 != null) { _positionY1080.SettingChanged -= OnUiConfigChanged; } if (_fontSize != null) { _fontSize.SettingChanged -= OnUiConfigChanged; } if (_colorMode != null) { _colorMode.SettingChanged -= OnUiConfigChanged; } } private void OnUiConfigChanged(object sender, EventArgs args) { try { MenuPageLobby instance = MenuPageLobby.instance; if (!((Object)(object)instance == (Object)null)) { Transform val = FindExistingCounter(((Component)instance).transform); if (!((Object)(object)val == (Object)null)) { ApplyUiConfig(val, ((Component)val).GetComponent()); ((Component)val).GetComponent()?.RefreshNow(); } } } catch (Exception ex) { LogUiConfigFailureOnce(ex); } } private void ApplyUiConfig(Transform transform, TextMeshProUGUI? text) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (val != null) { float num = ClampConfigValue(_positionX1080?.Value, 240f, 0f, 10000f); float num2 = ClampConfigValue(_positionY1080?.Value, 30f, 0f, 10000f); val.anchoredPosition = new Vector2(num, num2); } if ((Object)(object)text != (Object)null) { ((TMP_Text)text).fontSize = ClampConfigValue(_fontSize?.Value, 22f, 1f, 200f); ((TMP_Text)text).richText = true; } } private static float ClampConfigValue(float? value, float fallback, float min, float max) { float num = value.GetValueOrDefault(fallback); if (float.IsNaN(num) || float.IsInfinity(num)) { num = fallback; } return Mathf.Clamp(num, min, max); } private bool UseNewColorMode() { return !string.Equals(_colorMode?.Value, "old", StringComparison.OrdinalIgnoreCase); } private static TextMeshProUGUI? FindReferenceText(Transform root) { Transform val = root.Find("Menu Button - Leave/ButtonText") ?? root.Find("Menu Button - Settings/ButtonText"); if (!((Object)(object)val != (Object)null)) { return null; } return ((Component)val).GetComponent(); } private static Transform? FindExistingCounter(Transform root) { Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, "PlayerCountFixedTextLobby", StringComparison.Ordinal)) { return val; } } return null; } private static void EnsureUpdater(GameObject go, TextMeshProUGUI? text) { if (!((Object)(object)go == (Object)null) && !((Object)(object)text == (Object)null)) { (go.GetComponent() ?? go.AddComponent()).SetText(text); } } internal void LogUpdateFailureOnce(Exception ex) { if (!_loggedUpdateFailure) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Player count update failed; suppressing further update errors. " + ex.GetType().Name + ": " + ex.Message)); _loggedUpdateFailure = true; } } private void LogUiAttachFailureOnce(Exception ex) { if (!_loggedUiAttachFailure) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Lobby player count UI attach failed; suppressing further attach errors. " + ex.GetType().Name + ": " + ex.Message)); _loggedUiAttachFailure = true; } } private void LogUiConfigFailureOnce(Exception ex) { if (!_loggedUiConfigFailure) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Lobby player count UI config reload failed; suppressing further config reload errors. " + ex.GetType().Name + ": " + ex.Message)); _loggedUiConfigFailure = true; } } } }