Decompiled source of Room Hub v2.6.8
RoomHub.dll
Decompiled 6 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using PEAKLib.UI; using PEAKLib.UI.Elements; using Photon.Pun; using Photon.Realtime; using Steamworks; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; using Zorro.UI.Modal; [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("RoomHub")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+77d72fe7aa78cbcd5bd93ba2ab02923e6b3c14a4")] [assembly: AssemblyProduct("RoomHub")] [assembly: AssemblyTitle("RoomHub")] [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.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] [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] [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 RoomHub { public enum FriendGameMode { Joinable, InviteOnly, Solo, MainMenu, Unknown } public readonly struct FriendRoomInfo { public readonly ulong SteamId; public readonly string Name; public readonly ulong LobbyId; public readonly FriendGameMode Mode; public FriendRoomInfo(ulong steamId, string name, ulong lobbyId, FriendGameMode mode) { SteamId = steamId; Name = name ?? ""; LobbyId = lobbyId; Mode = mode; } } internal static class FriendRoomsService { public const uint PeakAppId = 3527290u; private const float RefreshIntervalSec = 10f; private static Callback<PersonaStateChange_t>? _personaChanged; private static Callback<FriendRichPresenceUpdate_t>? _richPresenceUpdate; private static float _nextRefresh; private static List<FriendRoomInfo>? _cache; private static float _lastNotify; private const float NotifyMinIntervalSec = 1.5f; private static bool _inited; private static readonly Dictionary<ulong, float> _lastRpRequest = new Dictionary<ulong, float>(); private const float RpRequestMinIntervalSec = 30f; public static event Action? Changed; public static void Init() { if (_inited) { return; } try { _personaChanged = Callback<PersonaStateChange_t>.Create((DispatchDelegate<PersonaStateChange_t>)OnPersonaChanged); _richPresenceUpdate = Callback<FriendRichPresenceUpdate_t>.Create((DispatchDelegate<FriendRichPresenceUpdate_t>)OnFriendRichPresenceUpdate); _inited = true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("FriendRoomsService init failed: " + ex.Message)); } } public static IReadOnlyList<FriendRoomInfo> GetFriends() { RefreshIfDue(force: false); IReadOnlyList<FriendRoomInfo> cache = _cache; return cache ?? Array.Empty<FriendRoomInfo>(); } private static void RefreshIfDue(bool force) { //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) if (!_inited || (!force && _cache != null && Time.unscaledTime < _nextRefresh)) { return; } _nextRefresh = Time.unscaledTime + 10f; try { List<FriendRoomInfo> list = new List<FriendRoomInfo>(); int friendCount = SteamFriends.GetFriendCount((EFriendFlags)4); FriendGameInfo_t val = default(FriendGameInfo_t); for (int i = 0; i < friendCount; i++) { CSteamID friendByIndex = SteamFriends.GetFriendByIndex(i, (EFriendFlags)4); if (friendByIndex == CSteamID.Nil || friendByIndex.m_SteamID == 0L) { continue; } bool flag = false; ulong lobbyId = 0uL; FriendGameMode mode = FriendGameMode.MainMenu; if (SteamFriends.GetFriendGamePlayed(friendByIndex, ref val) && ((CGameID)(ref val.m_gameID)).AppID().m_AppId == 3527290) { flag = true; try { float unscaledTime = Time.unscaledTime; if (!_lastRpRequest.TryGetValue(friendByIndex.m_SteamID, out var value) || unscaledTime - value >= 30f) { _lastRpRequest[friendByIndex.m_SteamID] = unscaledTime; SteamFriends.RequestFriendRichPresence(friendByIndex); } } catch { } if (((CSteamID)(ref val.m_steamIDLobby)).IsValid() && val.m_steamIDLobby.m_SteamID != 0L) { lobbyId = val.m_steamIDLobby.m_SteamID; mode = FriendGameMode.Joinable; } else { int num = 0; try { num = SteamFriends.GetFriendRichPresenceKeyCount(friendByIndex); } catch { } if (num == 0) { mode = FriendGameMode.Unknown; } else { try { string friendRichPresence = SteamFriends.GetFriendRichPresence(friendByIndex, "steam_display"); string friendRichPresence2 = SteamFriends.GetFriendRichPresence(friendByIndex, "players"); string friendRichPresence3 = SteamFriends.GetFriendRichPresence(friendByIndex, "max_players"); mode = (string.Equals(friendRichPresence, "#Status_MainMenu", StringComparison.Ordinal) ? FriendGameMode.MainMenu : (string.Equals(friendRichPresence3, "1", StringComparison.Ordinal) ? FriendGameMode.Solo : (string.Equals(friendRichPresence2, "1", StringComparison.Ordinal) ? FriendGameMode.MainMenu : ((!string.IsNullOrEmpty(friendRichPresence3)) ? FriendGameMode.InviteOnly : FriendGameMode.MainMenu)))); } catch { } } } } string name = SteamFriends.GetFriendPersonaName(friendByIndex) ?? ""; if (flag) { list.Add(new FriendRoomInfo(friendByIndex.m_SteamID, name, lobbyId, mode)); } } _cache = list.OrderByDescending((FriendRoomInfo f) => f.LobbyId != 0).ThenBy<FriendRoomInfo, string>((FriendRoomInfo f) => f.Name, StringComparer.OrdinalIgnoreCase).ToList(); } catch (Exception ex) { Plugin.Log.LogDebug((object)("FriendRoomsService refresh failed: " + ex.Message)); } } private static void OnPersonaChanged(PersonaStateChange_t cb) { _cache = null; float unscaledTime = Time.unscaledTime; if (unscaledTime - _lastNotify < 1.5f) { return; } _lastNotify = unscaledTime; try { FriendRoomsService.Changed?.Invoke(); } catch { } } private static void OnFriendRichPresenceUpdate(FriendRichPresenceUpdate_t cb) { _cache = null; float unscaledTime = Time.unscaledTime; if (unscaledTime - _lastNotify < 1.5f) { return; } _lastNotify = unscaledTime; try { FriendRoomsService.Changed?.Invoke(); } catch { } } } internal sealed class HistoryPageController { private const string SearchViewId = "__search__"; private const float FriendPanelWidth = 400f; private const float ListWidth = 800f; private const float RoomRowHeight = 120f; private const float PlayerRowHeight = 110f; private const float DoubleClickSeconds = 0.4f; private PeakCustomPage? _page; private PeakScrollableContent? _list; private PeakScrollableContent? _friendList; private PeakText? _titleText; private PeakText? _hintText; private PeakText? _hintText2; private PeakText? _deleteBanner; private PeakText? _friendPanelTitle; private PeakMenuButton? _trashButton; private PeakMenuButton? _backButton; private PeakMenuButton? _searchButton; private PeakMenuButton? _closeButton; private PeakTextInput? _searchInput; private bool _deleteMode; private string? _viewingLobbyId; private string? _searchQuery; private string? _lastClickLobbyId; private float _lastClickTime; private readonly List<GameObject> _avatarRefreshTargets = new List<GameObject>(); private HistoryRowFactory? _rows; private HistoryRowFactory? _friendRows; private bool _cursorCaptured; private CursorLockMode _prevLockMode = (CursorLockMode)1; private bool _prevCursorVisible; private static readonly MethodInfo? MenuWindowOpen = typeof(MenuWindow).GetMethod("Open", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly MethodInfo? MenuWindowClose = typeof(MenuWindow).GetMethod("Close", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private bool _openedViaMenuWindow; public bool HasLivePage { get { if ((Object)(object)_page == (Object)null) { return false; } Component page = (Component)(object)_page; return (Object)(object)page != (Object)null; } } public bool IsPageOpen { get { if (!HasLivePage || !_openedViaMenuWindow) { return false; } try { return ((Component)_page).gameObject.activeInHierarchy; } catch { return false; } } } public void Hide() { if (!HasLivePage) { _openedViaMenuWindow = false; ReleaseGameplayInputBlock(); return; } try { CloseMenuWindow(); } catch { } _openedViaMenuWindow = false; try { if (HasLivePage && ((Component)_page).gameObject.activeInHierarchy) { ((MenuWindow)_page).Hide(); } } catch { } ReleaseGameplayInputBlock(); } public void Discard() { try { if (HasLivePage) { CloseMenuWindow(); } } catch { } ReleaseGameplayInputBlock(); try { if (HasLivePage) { Object.Destroy((Object)(object)((Component)_page).gameObject); } } catch { } _page = null; _list = null; _friendList = null; _friendPanelTitle = null; _titleText = null; _hintText = null; _hintText2 = null; _deleteBanner = null; _trashButton = null; _backButton = null; _closeButton = null; _searchButton = null; _searchInput = null; _rows = null; _friendRows = null; _avatarRefreshTargets.Clear(); _deleteMode = false; _viewingLobbyId = null; _searchQuery = null; _openedViaMenuWindow = false; LocalizationSync.Unregister(OnGameLanguageChanged); UnsubscribeExternalEvents(); } public void Open() { _deleteMode = false; _viewingLobbyId = null; HistoryUiFont.CaptureFromMenuButton(); EnsurePage(); if (!HasLivePage) { return; } ShowRoomsView(); try { _page.BlocksPlayerInput = true; _page.ShowCursorWhileOpen = true; _page.CloseOnUICancel = false; _page.CloseOnPause = false; if (!OpenMenuWindow()) { if (!HistoryUi.IsTitleScene) { Plugin.Log.LogError((object)"MenuWindow.Open unavailable in-game — aborting open."); Discard(); return; } ((MenuWindow)_page).Show(); _openedViaMenuWindow = true; Plugin.Log.LogWarning((object)"MenuWindow.Open unavailable — using Show on title."); } else { _openedViaMenuWindow = true; } CaptureGameplayInputBlock(); EnsurePageBlocksRaycasts(); } catch (Exception arg) { Plugin.Log.LogError((object)$"History page Open failed: {arg}"); Discard(); } } private bool OpenMenuWindow() { if (!HasLivePage || MenuWindowOpen == null) { return false; } try { MenuWindowOpen.Invoke(_page, null); return true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("MenuWindow.Open invoke failed: " + ex.Message)); return false; } } private void CloseMenuWindow() { if (!HasLivePage) { return; } try { if (MenuWindowClose != null) { MenuWindowClose.Invoke(_page, null); } else { ((MenuWindow)_page).Hide(); } } catch { try { ((MenuWindow)_page).Hide(); } catch { } } } private void CaptureGameplayInputBlock() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (!_cursorCaptured && !HistoryUi.IsTitleScene) { _prevLockMode = (CursorLockMode)1; _prevCursorVisible = false; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; _cursorCaptured = true; } } private void ReleaseGameplayInputBlock() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (!_cursorCaptured) { return; } _cursorCaptured = false; try { Cursor.lockState = _prevLockMode; Cursor.visible = _prevCursorVisible; } catch { } } public void TickInputBlock() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (!IsPageOpen || HistoryUi.IsTitleScene) { if (_cursorCaptured && !IsPageOpen) { ReleaseGameplayInputBlock(); } return; } if (!_cursorCaptured) { CaptureGameplayInputBlock(); } if ((int)Cursor.lockState != 0) { Cursor.lockState = (CursorLockMode)0; } if (!Cursor.visible) { Cursor.visible = true; } } private void EnsurePageBlocksRaycasts() { if (!HasLivePage) { return; } try { GameObject gameObject = ((Component)_page).gameObject; Canvas component = gameObject.GetComponent<Canvas>(); if ((Object)(object)component != (Object)null && component.sortingOrder < 500) { component.sortingOrder = 500; } if ((Object)(object)gameObject.GetComponent<GraphicRaycaster>() == (Object)null) { gameObject.AddComponent<GraphicRaycaster>(); } Image[] componentsInChildren = gameObject.GetComponentsInChildren<Image>(true); foreach (Image val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && (((Object)((Component)val).gameObject).name == "Background" || (Object)(object)((Component)val).transform.parent == (Object)(object)gameObject.transform)) { ((Graphic)val).raycastTarget = true; } } } catch (Exception ex) { Plugin.Log.LogDebug((object)("EnsurePageBlocksRaycasts: " + ex.Message)); } } public void HandleBackOrClose() { if (IsPageOpen) { if (_viewingLobbyId != null) { ShowRoomsView(); } else if (_deleteMode) { _deleteMode = false; RefreshCurrentView(); } else { Hide(); } } } public void TickAvatarRefresh() { //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) if (!IsPageOpen || Time.frameCount % 45 != 0) { return; } for (int num = _avatarRefreshTargets.Count - 1; num >= 0; num--) { GameObject val = _avatarRefreshTargets[num]; if ((Object)(object)val == (Object)null) { _avatarRefreshTargets.RemoveAt(num); } else { Image component = val.GetComponent<Image>(); if ((Object)(object)component == (Object)null || !((Object)val).name.StartsWith("Avatar_", StringComparison.Ordinal)) { _avatarRefreshTargets.RemoveAt(num); } else { string steamIdStr = ((Object)val).name.Substring("Avatar_".Length); Texture2D avatar = SteamAvatarService.GetAvatar(steamIdStr); if (!((Object)(object)avatar == (Object)null)) { for (int num2 = val.transform.childCount - 1; num2 >= 0; num2--) { Transform child = val.transform.GetChild(num2); if (((Object)child).name != "Border") { Object.Destroy((Object)(object)((Component)child).gameObject); } } if ((Object)(object)component.sprite != (Object)null) { Sprite sprite = component.sprite; component.sprite = null; Object.Destroy((Object)(object)sprite); } component.sprite = Sprite.Create(avatar, new Rect(0f, 0f, (float)((Texture)avatar).width, (float)((Texture)avatar).height), new Vector2(0.5f, 0.5f)); ((Graphic)component).color = Color.white; component.preserveAspect = true; _avatarRefreshTargets.RemoveAt(num); } } } } } private void EnsurePage() { //IL_04f8: Unknown result type (might be due to invalid IL or missing references) //IL_050c: Unknown result type (might be due to invalid IL or missing references) //IL_0520: Unknown result type (might be due to invalid IL or missing references) //IL_053b: Unknown result type (might be due to invalid IL or missing references) //IL_0545: Expected O, but got Unknown //IL_056f: Unknown result type (might be due to invalid IL or missing references) //IL_0583: Unknown result type (might be due to invalid IL or missing references) //IL_0597: Unknown result type (might be due to invalid IL or missing references) //IL_05ab: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Expected O, but got Unknown //IL_03d7: Unknown result type (might be due to invalid IL or missing references) //IL_03eb: Unknown result type (might be due to invalid IL or missing references) //IL_03ff: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Unknown result type (might be due to invalid IL or missing references) //IL_0424: Expected O, but got Unknown //IL_067a: Unknown result type (might be due to invalid IL or missing references) //IL_069e: Unknown result type (might be due to invalid IL or missing references) //IL_06b2: Unknown result type (might be due to invalid IL or missing references) //IL_06c6: Unknown result type (might be due to invalid IL or missing references) //IL_06da: Unknown result type (might be due to invalid IL or missing references) //IL_044e: Unknown result type (might be due to invalid IL or missing references) //IL_0462: Unknown result type (might be due to invalid IL or missing references) //IL_0476: Unknown result type (might be due to invalid IL or missing references) //IL_048a: Unknown result type (might be due to invalid IL or missing references) //IL_077c: Unknown result type (might be due to invalid IL or missing references) //IL_0790: Unknown result type (might be due to invalid IL or missing references) //IL_07a4: Unknown result type (might be due to invalid IL or missing references) //IL_07b8: Unknown result type (might be due to invalid IL or missing references) //IL_08cc: Unknown result type (might be due to invalid IL or missing references) //IL_08e0: Unknown result type (might be due to invalid IL or missing references) //IL_08f4: Unknown result type (might be due to invalid IL or missing references) //IL_090f: Unknown result type (might be due to invalid IL or missing references) //IL_0919: Expected O, but got Unknown if (!HasLivePage) { if ((Object)(object)_page != (Object)null) { Discard(); } UiButtonFactory.EnsureTemplate(); _page = MenuAPI.CreatePageWithBackground("RoomHub Page"); _page.CloseOnUICancel = false; _page.BlocksPlayerInput = true; _page.ShowCursorWhileOpen = true; EnsurePageBlocksRaycasts(); _titleText = ElementExtensions.SetPosition<PeakText>(ElementExtensions.SetPivot<PeakText>(ElementExtensions.SetAnchorMinMax<PeakText>(ElementExtensions.ParentTo<PeakText>(MenuAPI.CreateText(Loc.T("ROOMHISTORY_PAGE_TITLE")).SetFontSize(44f), ((Component)_page).transform), new Vector2(0.5f, 1f)), new Vector2(0.5f, 1f)), new Vector2(0f, -36f)); HistoryUiFont.Apply(_titleText); HistoryUiFont.ForceCenteredLabel(_titleText, 900f, 50f, new Vector2(0f, -36f)); _hintText = ElementExtensions.SetPosition<PeakText>(ElementExtensions.SetPivot<PeakText>(ElementExtensions.SetAnchorMinMax<PeakText>(ElementExtensions.ParentTo<PeakText>(MenuAPI.CreateText("").SetFontSize(20f).SetColor(new Color(1f, 0.92f, 0.35f)), ((Component)_page).transform), new Vector2(0.5f, 1f)), new Vector2(0.5f, 1f)), new Vector2(0f, -88f)); HistoryUiFont.Apply(_hintText); HistoryUiFont.ForceCenteredLabel(_hintText, 880f, 36f, new Vector2(0f, -88f)); _hintText2 = ElementExtensions.SetPosition<PeakText>(ElementExtensions.SetPivot<PeakText>(ElementExtensions.SetAnchorMinMax<PeakText>(ElementExtensions.ParentTo<PeakText>(MenuAPI.CreateText("").SetFontSize(18f).SetColor(new Color(0.75f, 0.9f, 1f)), ((Component)_page).transform), new Vector2(0.5f, 1f)), new Vector2(0.5f, 1f)), new Vector2(0f, -118f)); HistoryUiFont.Apply(_hintText2); HistoryUiFont.ForceCenteredLabel(_hintText2, 880f, 32f, new Vector2(0f, -118f)); _deleteBanner = ElementExtensions.SetPosition<PeakText>(ElementExtensions.SetPivot<PeakText>(ElementExtensions.SetAnchorMinMax<PeakText>(ElementExtensions.ParentTo<PeakText>(MenuAPI.CreateText(Loc.T("ROOMHISTORY_DELETE_BANNER")).SetFontSize(22f).SetColor(new Color(1f, 0.35f, 0.3f)), ((Component)_page).transform), new Vector2(0.5f, 1f)), new Vector2(0.5f, 1f)), new Vector2(0f, -88f)); HistoryUiFont.Apply(_deleteBanner); HistoryUiFont.ForceCenteredLabel(_deleteBanner, 900f, 40f, new Vector2(0f, -88f)); ((Component)_deleteBanner).gameObject.SetActive(false); _backButton = ElementExtensions.SetPosition<PeakMenuButton>(ElementExtensions.SetPivot<PeakMenuButton>(ElementExtensions.SetAnchorMinMax<PeakMenuButton>(ElementExtensions.ParentTo<PeakMenuButton>(UiButtonFactory.CreateMenuButtonSafe("← " + Loc.T("ROOMHISTORY_BACK")), ((Component)_page).transform), new Vector2(0f, 1f)), new Vector2(0f, 1f)), new Vector2(36f, -36f)).SetWidth(170f).OnClick(new UnityAction(ShowRoomsView)); ((Component)_backButton).gameObject.SetActive(false); _trashButton = ElementExtensions.SetPosition<PeakMenuButton>(ElementExtensions.SetPivot<PeakMenuButton>(ElementExtensions.SetAnchorMinMax<PeakMenuButton>(ElementExtensions.ParentTo<PeakMenuButton>(UiButtonFactory.CreateMenuButtonSafe(Loc.T("ROOMHISTORY_DELETE_MODE_ON")), ((Component)_page).transform), new Vector2(1f, 1f)), new Vector2(1f, 1f)), new Vector2(-28f, -36f)).SetWidth(200f).OnClick(new UnityAction(ToggleDeleteMode)); try { _searchInput = ElementExtensions.SetSize<PeakTextInput>(ElementExtensions.SetPosition<PeakTextInput>(ElementExtensions.SetPivot<PeakTextInput>(ElementExtensions.SetAnchorMinMax<PeakTextInput>(ElementExtensions.ParentTo<PeakTextInput>(MenuAPI.CreateTextInput("RoomHubSearchInput"), ((Component)_page).transform), new Vector2(1f, 1f)), new Vector2(1f, 1f)), new Vector2(-240f, -100f)), new Vector2(220f, 56f)).SetPlaceholder(Loc.T("ROOMHISTORY_SEARCH_PLACEHOLDER")); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Search input create failed (game not fully ready?): " + ex.Message)); _searchInput = null; } _searchButton = ElementExtensions.SetPosition<PeakMenuButton>(ElementExtensions.SetPivot<PeakMenuButton>(ElementExtensions.SetAnchorMinMax<PeakMenuButton>(ElementExtensions.ParentTo<PeakMenuButton>(UiButtonFactory.CreateMenuButtonSafe(Loc.T("ROOMHISTORY_SEARCH")), ((Component)_page).transform), new Vector2(1f, 1f)), new Vector2(1f, 1f)), new Vector2(-28f, -100f)).SetWidth(140f).OnClick(new UnityAction(RunPlayerSearch)); _list = ElementExtensions.SetSize<PeakScrollableContent>(ElementExtensions.SetPosition<PeakScrollableContent>(ElementExtensions.SetPivot<PeakScrollableContent>(ElementExtensions.SetAnchorMinMax<PeakScrollableContent>(ElementExtensions.ParentTo<PeakScrollableContent>(MenuAPI.CreateScrollableContent("RoomHubList"), ((Component)_page).transform), new Vector2(0.5f, 1f)), new Vector2(0.5f, 1f)), new Vector2(0f, -200f)), new Vector2(800f, 600f)); VerticalLayoutGroup component = ((Component)_list.Content).GetComponent<VerticalLayoutGroup>(); if ((Object)(object)component != (Object)null) { ((HorizontalOrVerticalLayoutGroup)component).spacing = 8f; ((LayoutGroup)component).childAlignment = (TextAnchor)1; ((HorizontalOrVerticalLayoutGroup)component).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)component).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = false; } _rows = new HistoryRowFactory((Transform)(object)_list.Content, 800f, 120f, 110f, _avatarRefreshTargets, RefreshCurrentView, ShowPlayersView, OnRoomRowClicked); _friendPanelTitle = ElementExtensions.SetSize<PeakText>(ElementExtensions.SetPosition<PeakText>(ElementExtensions.SetPivot<PeakText>(ElementExtensions.SetAnchorMinMax<PeakText>(ElementExtensions.ParentTo<PeakText>(MenuAPI.CreateText(Loc.T("ROOMHISTORY_FRIENDS_TITLE")).SetFontSize(32f).SetColor(new Color(1f, 0.92f, 0.35f)), ((Component)_page).transform), new Vector2(0f, 1f)), new Vector2(0.5f, 1f)), new Vector2(240f, -100f)), new Vector2(400f, 40f)); HistoryUiFont.Apply(_friendPanelTitle); if ((Object)(object)_friendPanelTitle.TextMesh != (Object)null) { ((TMP_Text)_friendPanelTitle.TextMesh).alignment = (TextAlignmentOptions)514; ((TMP_Text)_friendPanelTitle.TextMesh).enableAutoSizing = true; ((TMP_Text)_friendPanelTitle.TextMesh).fontSizeMin = 20f; ((TMP_Text)_friendPanelTitle.TextMesh).fontSizeMax = 36f; } _friendList = ElementExtensions.SetSize<PeakScrollableContent>(ElementExtensions.SetPosition<PeakScrollableContent>(ElementExtensions.SetPivot<PeakScrollableContent>(ElementExtensions.SetAnchorMinMax<PeakScrollableContent>(ElementExtensions.ParentTo<PeakScrollableContent>(MenuAPI.CreateScrollableContent("RoomHubFriendList"), ((Component)_page).transform), new Vector2(0f, 1f)), new Vector2(0f, 1f)), new Vector2(40f, -150f)), new Vector2(400f, 650f)); VerticalLayoutGroup component2 = ((Component)_friendList.Content).GetComponent<VerticalLayoutGroup>(); if ((Object)(object)component2 != (Object)null) { ((HorizontalOrVerticalLayoutGroup)component2).spacing = 8f; ((LayoutGroup)component2).childAlignment = (TextAnchor)1; ((HorizontalOrVerticalLayoutGroup)component2).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)component2).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)component2).childForceExpandHeight = false; } ((Component)_friendList).gameObject.SetActive(false); _friendRows = new HistoryRowFactory((Transform)(object)_friendList.Content, 400f, 120f, 110f, _avatarRefreshTargets, RefreshCurrentView, ShowPlayersView, OnRoomRowClicked); JoinGate.StateChanged += OnExternalStateChanged; FriendRoomsService.Changed += OnExternalStateChanged; LocalizationSync.Register(OnGameLanguageChanged); _closeButton = ElementExtensions.SetPosition<PeakMenuButton>(ElementExtensions.SetPivot<PeakMenuButton>(ElementExtensions.SetAnchorMinMax<PeakMenuButton>(ElementExtensions.ParentTo<PeakMenuButton>(UiButtonFactory.CreateMenuButtonSafe(Loc.T("ROOMHISTORY_CLOSE")), ((Component)_page).transform), new Vector2(0.5f, 0f)), new Vector2(0.5f, 0f)), new Vector2(0f, 80f)).SetWidth(220f).OnClick((UnityAction)delegate { _deleteMode = false; Hide(); }); } } private void OnGameLanguageChanged() { try { RefreshStaticChrome(); if (IsPageOpen) { RefreshCurrentView(); } } catch (Exception ex) { Plugin.Log.LogDebug((object)("OnGameLanguageChanged: " + ex.Message)); } } private void RefreshStaticChrome() { PeakText? friendPanelTitle = _friendPanelTitle; if ((Object)(object)((friendPanelTitle != null) ? friendPanelTitle.TextMesh : null) != (Object)null) { ((TMP_Text)_friendPanelTitle.TextMesh).text = Loc.T("ROOMHISTORY_FRIENDS_TITLE"); HistoryUiFont.Apply(_friendPanelTitle); ((TMP_Text)_friendPanelTitle.TextMesh).ForceMeshUpdate(true, false); } if ((Object)(object)_closeButton != (Object)null) { try { _closeButton.SetText(Loc.T("ROOMHISTORY_CLOSE")); } catch { } } } private void ToggleDeleteMode() { if (_viewingLobbyId == null) { _deleteMode = !_deleteMode; RefreshCurrentView(); } } private void ShowRoomsView() { _viewingLobbyId = null; _searchQuery = null; _deleteMode = false; RefreshCurrentView(); } private void ShowPlayersView(string lobbyId) { _viewingLobbyId = lobbyId; _searchQuery = null; _deleteMode = false; RefreshCurrentView(); } private void UnsubscribeExternalEvents() { JoinGate.StateChanged -= OnExternalStateChanged; FriendRoomsService.Changed -= OnExternalStateChanged; } private void OnExternalStateChanged() { if (!IsPageOpen) { return; } try { RefreshCurrentView(); } catch { } } private void RunPlayerSearch() { string text = ""; try { PeakTextInput? searchInput = _searchInput; if ((Object)(object)((searchInput != null) ? searchInput.InputField : null) != (Object)null) { text = _searchInput.InputField.text ?? ""; } } catch { } text = text.Trim(); if (text.Length == 0) { ShowRoomsView(); return; } _searchQuery = text; _viewingLobbyId = "__search__"; _deleteMode = false; RefreshCurrentView(); } private void RefreshCurrentView() { //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_045b: Unknown result type (might be due to invalid IL or missing references) //IL_048a: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_057e: Unknown result type (might be due to invalid IL or missing references) //IL_052e: Unknown result type (might be due to invalid IL or missing references) //IL_0545: Unknown result type (might be due to invalid IL or missing references) //IL_0649: Unknown result type (might be due to invalid IL or missing references) //IL_0678: Unknown result type (might be due to invalid IL or missing references) //IL_05b8: Unknown result type (might be due to invalid IL or missing references) //IL_06c2: Unknown result type (might be due to invalid IL or missing references) //IL_0407: Unknown result type (might be due to invalid IL or missing references) //IL_06f5: Unknown result type (might be due to invalid IL or missing references) //IL_06fc: Expected O, but got Unknown //IL_0751: Unknown result type (might be due to invalid IL or missing references) //IL_0758: Expected O, but got Unknown if ((Object)(object)_list == (Object)null || (Object)(object)_page == (Object)null || _rows == null) { return; } _avatarRefreshTargets.Clear(); bool flag = _viewingLobbyId == "__search__"; bool flag2 = _viewingLobbyId != null && !flag; bool flag3 = _viewingLobbyId != null; bool flag4 = !flag3; if ((Object)(object)_backButton != (Object)null) { ((Component)_backButton).gameObject.SetActive(flag3); try { _backButton.SetText("← " + Loc.T("ROOMHISTORY_BACK")); } catch { } } if ((Object)(object)_trashButton != (Object)null) { ((Component)_trashButton).gameObject.SetActive(flag4); try { _trashButton.SetText(_deleteMode ? Loc.T("ROOMHISTORY_DELETE_MODE_OFF") : Loc.T("ROOMHISTORY_DELETE_MODE_ON")); _trashButton.SetWidth(200f); _trashButton.SetColor(_deleteMode ? new Color(0.55f, 0.12f, 0.12f) : new Color(0.22f, 0.18f, 0.15f), true); } catch { } } if ((Object)(object)_searchButton != (Object)null) { ((Component)_searchButton).gameObject.SetActive(flag4); try { _searchButton.SetText(Loc.T("ROOMHISTORY_SEARCH")); } catch { } } if ((Object)(object)_searchInput != (Object)null) { ((Component)_searchInput).gameObject.SetActive(flag4); try { if (flag4) { _searchInput.SetPlaceholder(Loc.T("ROOMHISTORY_SEARCH_PLACEHOLDER")); } } catch { } } PeakText? titleText = _titleText; if ((Object)(object)((titleText != null) ? titleText.TextMesh : null) != (Object)null) { if (flag) { ((TMP_Text)_titleText.TextMesh).text = Loc.T("ROOMHISTORY_SEARCH_TITLE"); } else if (flag2) { ((TMP_Text)_titleText.TextMesh).text = Loc.T("ROOMHISTORY_PLAYERS_TITLE"); } else { ((TMP_Text)_titleText.TextMesh).text = Loc.T("ROOMHISTORY_PAGE_TITLE"); } HistoryUiFont.Apply(_titleText); HistoryUiFont.ForceCenteredLabel(_titleText, 900f, 50f, new Vector2(0f, -36f)); ((TMP_Text)_titleText.TextMesh).ForceMeshUpdate(true, false); } bool flag5 = _deleteMode && flag4; PeakText? hintText = _hintText; if ((Object)(object)((hintText != null) ? hintText.TextMesh : null) != (Object)null) { if (flag5) { ((TMP_Text)_hintText.TextMesh).text = ""; ((Component)_hintText).gameObject.SetActive(false); } else { ((Component)_hintText).gameObject.SetActive(true); if (flag) { ((TMP_Text)_hintText.TextMesh).text = (string.IsNullOrEmpty(_searchQuery) ? Loc.T("ROOMHISTORY_SEARCH_HINT") : ("\"" + _searchQuery + "\"")); ((Graphic)_hintText.TextMesh).color = new Color(0.85f, 0.9f, 1f); } else if (flag2) { RoomRecord room = Plugin.Store.GetRoom(_viewingLobbyId); string text = ((room == null || string.IsNullOrWhiteSpace(room.HostName)) ? Loc.T("ROOMHISTORY_UNKNOWN_HOST") : room.HostName); int num = room?.Players.Count ?? 0; string text2 = Loc.Tf("ROOMHISTORY_ROOM_TITLE", text); if (num > 0) { text2 = text2 + " · " + Loc.Tf("ROOMHISTORY_PLAYER_COUNT", num); } ((TMP_Text)_hintText.TextMesh).text = text2; ((Graphic)_hintText.TextMesh).color = new Color(0.85f, 0.9f, 1f); } else { ((TMP_Text)_hintText.TextMesh).text = Loc.T("ROOMHISTORY_HINT_JOIN_VIEW") + " · " + Loc.T("ROOMHISTORY_HINT_DOUBLECLICK"); ((Graphic)_hintText.TextMesh).color = new Color(1f, 0.92f, 0.35f); } HistoryUiFont.Apply(_hintText); HistoryUiFont.ForceCenteredLabel(_hintText, 880f, 36f, new Vector2(0f, -88f)); ((TMP_Text)_hintText.TextMesh).ForceMeshUpdate(true, false); } } PeakText? hintText2 = _hintText2; if ((Object)(object)((hintText2 != null) ? hintText2.TextMesh : null) != (Object)null) { if (flag5 || flag3) { ((TMP_Text)_hintText2.TextMesh).text = ""; ((Component)_hintText2).gameObject.SetActive(false); } else { ((Component)_hintText2).gameObject.SetActive(true); if (HistoryUi.IsTitleScene) { ((TMP_Text)_hintText2.TextMesh).text = Loc.Tf("ROOMHISTORY_HINT_HOTKEY", Plugin.ModConfig.QuickJoinHotkey.Value, Plugin.ModConfig.ModMenuHotkey.Value); } else { ((TMP_Text)_hintText2.TextMesh).text = Loc.Tf("ROOMHISTORY_HINT_HOTKEY_INGAME", Plugin.ModConfig.ModMenuHotkey.Value); } HistoryUiFont.Apply(_hintText2); HistoryUiFont.ForceCenteredLabel(_hintText2, 880f, 32f, new Vector2(0f, -118f)); ((TMP_Text)_hintText2.TextMesh).ForceMeshUpdate(true, false); } } if ((Object)(object)_deleteBanner != (Object)null) { bool flag6 = flag5; ((Component)_deleteBanner).gameObject.SetActive(flag6); if (flag6 && (Object)(object)_deleteBanner.TextMesh != (Object)null) { ((TMP_Text)_deleteBanner.TextMesh).text = Loc.T("ROOMHISTORY_DELETE_BANNER"); ((Graphic)_deleteBanner.TextMesh).color = new Color(1f, 0.35f, 0.3f); HistoryUiFont.Apply(_deleteBanner); HistoryUiFont.ForceCenteredLabel(_deleteBanner, 900f, 40f, new Vector2(0f, -88f)); ((TMP_Text)_deleteBanner.TextMesh).ForceMeshUpdate(true, false); } } RectTransform component = ((Component)_list).GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null) { component.anchoredPosition = new Vector2(0f, flag5 ? (-210f) : (-200f)); } if ((Object)(object)_list != (Object)null) { foreach (Transform item in (Transform)_list.Content) { Transform val = item; DestroyRowSafely(((Component)val).gameObject); } } if ((Object)(object)_friendList != (Object)null) { foreach (Transform item2 in (Transform)_friendList.Content) { Transform val2 = item2; DestroyRowSafely(((Component)val2).gameObject); } ((Component)_friendList).gameObject.SetActive(flag4); } if ((Object)(object)_friendPanelTitle != (Object)null) { ((Component)_friendPanelTitle).gameObject.SetActive(flag4); } if (flag) { PopulateSearchResults(_searchQuery ?? ""); return; } if (flag2) { PopulatePlayers(_viewingLobbyId); return; } PopulateFriendPanel(); PopulateRooms(); } private static void DestroyRowSafely(GameObject row) { if ((Object)(object)row == (Object)null) { return; } try { Image[] componentsInChildren = row.GetComponentsInChildren<Image>(true); foreach (Image val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sprite == (Object)null) && ((Object)((Component)val).gameObject).name.StartsWith("Avatar", StringComparison.Ordinal)) { Sprite sprite = val.sprite; val.sprite = null; Object.Destroy((Object)(object)sprite); } } } catch { } Object.Destroy((Object)(object)row); } private void PopulateFriendPanel() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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) IReadOnlyList<FriendRoomInfo> friends = FriendRoomsService.GetFriends(); if (friends.Count == 0) { PeakText peakText = ElementExtensions.SetPosition<PeakText>(ElementExtensions.SetPivot<PeakText>(ElementExtensions.SetAnchorMinMax<PeakText>(ElementExtensions.ParentTo<PeakText>(MenuAPI.CreateText(Loc.T("ROOMHISTORY_FRIENDS_EMPTY")).SetFontSize(22f).SetColor(Color.yellow), (Transform)(object)_friendList.Content), new Vector2(0.5f, 1f)), new Vector2(0.5f, 1f)), new Vector2(0f, -40f)); HistoryUiFont.Apply(peakText); return; } foreach (FriendRoomInfo item in friends) { _friendRows.CreateFriendRow(item); } } private void PopulateSearchResults(string query) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList<PlayerSearchHit> readOnlyList = Plugin.Store.SearchPlayers(query); if (readOnlyList.Count == 0) { PeakText peakText = ElementExtensions.ParentTo<PeakText>(MenuAPI.CreateText(Loc.T("ROOMHISTORY_SEARCH_EMPTY")).SetFontSize(28f).SetColor(Color.yellow), (Transform)(object)_list.Content); HistoryUiFont.Apply(peakText); return; } foreach (PlayerSearchHit item in readOnlyList) { _rows.CreateSearchHitRow(item); } } private void PopulateRooms() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList<RoomRecord> rooms = Plugin.Store.GetRooms(); if (rooms.Count == 0) { PeakText peakText = ElementExtensions.ParentTo<PeakText>(MenuAPI.CreateText(Loc.T("ROOMHISTORY_EMPTY_ROOMS")).SetFontSize(28f).SetColor(Color.yellow), (Transform)(object)_list.Content); HistoryUiFont.Apply(peakText); return; } foreach (RoomRecord item in rooms) { _rows.CreateRoomRow(item, _deleteMode); } } private void PopulatePlayers(string lobbyId) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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) RoomRecord room = Plugin.Store.GetRoom(lobbyId); if (room == null || room.Players.Count == 0) { PeakText val = ElementExtensions.ParentTo<PeakText>(MenuAPI.CreateText(Loc.T("ROOMHISTORY_EMPTY_PLAYERS")).SetFontSize(28f).SetColor(Color.yellow), (Transform)(object)_list.Content); HistoryUiFont.Apply(val); RectTransform component = ((Component)val).GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null) { ElementExtensions.SetAnchorMinMax<PeakText>(val, new Vector2(0.5f, 1f)); ElementExtensions.SetPivot<PeakText>(val, new Vector2(0.5f, 1f)); ElementExtensions.SetPosition<PeakText>(val, new Vector2(0f, -20f)); } return; } foreach (PlayerRecord item in from x in room.Players orderby x.WasHost descending, x.LastSeenUtcTicks descending select x) { _rows.CreatePlayerRow(item); } } private void OnRoomRowClicked(RoomRecord room) { float unscaledTime = Time.unscaledTime; bool flag = _lastClickLobbyId != null && string.Equals(_lastClickLobbyId, room.LobbyId, StringComparison.Ordinal) && unscaledTime - _lastClickTime <= 0.4f; _lastClickLobbyId = room.LobbyId; _lastClickTime = unscaledTime; if (flag) { if (!HistoryUi.IsTitleScene && HistoryUi.IsInLiveLobby) { Plugin.Log.LogDebug((object)"Double-click join ignored: already in live lobby."); return; } _lastClickLobbyId = null; RoomJoiner.TryJoin(room); } } } internal sealed class HistoryRowFactory { private readonly Transform _listContent; private readonly float _listWidth; private readonly float _roomRowHeight; private readonly float _playerRowHeight; private readonly List<GameObject> _avatarRefreshTargets; private readonly Action _refreshView; private readonly Action<string> _showPlayers; private readonly Action<RoomRecord> _onRoomRowClicked; public HistoryRowFactory(Transform listContent, float listWidth, float roomRowHeight, float playerRowHeight, List<GameObject> avatarRefreshTargets, Action refreshView, Action<string> showPlayers, Action<RoomRecord> onRoomRowClicked) { _listContent = listContent; _listWidth = listWidth; _roomRowHeight = roomRowHeight; _playerRowHeight = playerRowHeight; _avatarRefreshTargets = avatarRefreshTargets; _refreshView = refreshView; _showPlayers = showPlayers; _onRoomRowClicked = onRoomRowClicked; } public void CreateRoomRow(RoomRecord room, bool deleteMode) { //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Expected O, but got Unknown //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Expected O, but got Unknown //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Expected O, but got Unknown //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Expected O, but got Unknown string text = (string.IsNullOrWhiteSpace(room.HostName) ? Loc.T("ROOMHISTORY_UNKNOWN_HOST") : room.HostName); string item = Loc.Tf("ROOMHISTORY_ROOM_TITLE", text); string text2 = Loc.Tf("ROOMHISTORY_JOINED_AGO", Loc.Relative(room.JoinedAtUtc)); PeakButton val = ElementExtensions.ParentTo<PeakButton>(MenuAPI.CreateButton("Room_" + room.LobbyId), _listContent).SetHeight(_roomRowHeight); PinRowSize(((Component)val).gameObject, _listWidth, _roomRowHeight, pinMinHeight: true); if (deleteMode) { Image componentInChildren = ((Component)val).GetComponentInChildren<Image>(); if ((Object)(object)componentInChildren != (Object)null) { ((Graphic)componentInChildren).color = new Color(0.55f, 0.12f, 0.12f, 0.95f); } } PeakText text3 = val.Text; if ((Object)(object)((text3 != null) ? text3.TextMesh : null) != (Object)null) { ((TMP_Text)val.Text.TextMesh).text = ""; } CreateAvatarBox(((Component)val).transform, room.HostSteamId, text, new Vector2(12f, 0f), 72f); List<string> list = new List<string> { item, "<size=20><color=#CCCCCC>" + text2 + "</color></size>" }; if (!string.IsNullOrWhiteSpace(room.LobbyName)) { list.Add("<size=18><color=#DDDD88>" + Loc.Tf("ROOMHISTORY_LOBBY_NAME", room.LobbyName) + "</color></size>"); } if (room.Players.Count > 0) { list.Add("<size=18><color=#88CCFF>" + Loc.Tf("ROOMHISTORY_PLAYER_COUNT", room.Players.Count) + "</color></size>"); } if (deleteMode) { list.Add("<size=18><color=#FF8888>" + Loc.T("ROOMHISTORY_DELETE_ROOM") + "</color></size>"); } string body = string.Join("\n", list); CreateBodyText(((Component)val).transform, body); if (deleteMode) { val.OnClick((UnityAction)delegate { Plugin.Store.DeleteRoom(room.LobbyId); _refreshView(); }); return; } val.OnClick((UnityAction)delegate { _onRoomRowClicked(room); }); bool flag = HistoryUi.IsTitleScene || !HistoryUi.IsInLiveLobby; if (flag && !JoinGate.IsJoinAllowed(room.LobbyId, room.JoinedAtUtcTicks)) { flag = false; } if (flag) { ElementExtensions.SetPosition<PeakMenuButton>(ElementExtensions.SetPivot<PeakMenuButton>(ElementExtensions.SetAnchorMinMax<PeakMenuButton>(ElementExtensions.ParentTo<PeakMenuButton>(UiButtonFactory.CreateMenuButtonSafe(Loc.T("ROOMHISTORY_JOIN")), ((Component)val).transform), new Vector2(1f, 0.5f)), new Vector2(1f, 0.5f)), new Vector2(-16f, 22f)).SetWidth(150f).OnClick((UnityAction)delegate { RoomJoiner.TryJoin(room); }); } ElementExtensions.SetPosition<PeakMenuButton>(ElementExtensions.SetPivot<PeakMenuButton>(ElementExtensions.SetAnchorMinMax<PeakMenuButton>(ElementExtensions.ParentTo<PeakMenuButton>(UiButtonFactory.CreateMenuButtonSafe(Loc.T("ROOMHISTORY_VIEW")), ((Component)val).transform), new Vector2(1f, 0.5f)), new Vector2(1f, 0.5f)), new Vector2(-16f, flag ? (-28f) : 0f)).SetWidth(150f).OnClick((UnityAction)delegate { _showPlayers(room.LobbyId); }); } public void CreatePlayerRow(PlayerRecord player) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) string text = (string.IsNullOrWhiteSpace(player.DisplayName) ? Loc.T("ROOMHISTORY_UNKNOWN_PLAYER") : player.DisplayName); PeakButton val = ElementExtensions.ParentTo<PeakButton>(MenuAPI.CreateButton("Player_" + player.SteamId), _listContent).SetHeight(_playerRowHeight); PinRowSize(((Component)val).gameObject, _listWidth, _playerRowHeight, pinMinHeight: false); PeakText text2 = val.Text; if ((Object)(object)((text2 != null) ? text2.TextMesh : null) != (Object)null) { ((TMP_Text)val.Text.TextMesh).text = ""; } CreateAvatarBox(((Component)val).transform, player.SteamId, text, new Vector2(12f, 0f), 72f); List<string> list = new List<string>(); if (player.WasHost) { list.Add("<color=#FFD070>" + Loc.T("ROOMHISTORY_HOST_BADGE") + "</color>"); } bool flag = SteamAvatarService.IsFriend(player.SteamId); if (flag) { list.Add("<color=#88CCFF>" + Loc.T("ROOMHISTORY_ALREADY_FRIEND") + "</color>"); } string text3 = text + ((list.Count > 0) ? (" " + string.Join(" ", list)) : ""); string text4 = "<size=18><color=#CCCCCC>" + Loc.Tf("ROOMHISTORY_MET_AGO", Loc.Relative(player.LastSeenUtc)) + "</color></size>"; CreateBodyText(((Component)val).transform, text3 + "\n" + text4); AddPlayerActionButtons(((Component)val).transform, player.SteamId, flag); } public void CreateSearchHitRow(PlayerSearchHit hit) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) string text = (string.IsNullOrWhiteSpace(hit.DisplayName) ? Loc.T("ROOMHISTORY_UNKNOWN_PLAYER") : hit.DisplayName); PeakButton val = ElementExtensions.ParentTo<PeakButton>(MenuAPI.CreateButton("Search_" + hit.SteamId), _listContent).SetHeight(_playerRowHeight); PinRowSize(((Component)val).gameObject, _listWidth, _playerRowHeight, pinMinHeight: false); PeakText text2 = val.Text; if ((Object)(object)((text2 != null) ? text2.TextMesh : null) != (Object)null) { ((TMP_Text)val.Text.TextMesh).text = ""; } CreateAvatarBox(((Component)val).transform, hit.SteamId, text, new Vector2(12f, 0f), 72f); List<string> list = new List<string>(); if (hit.WasHost) { list.Add("<color=#FFD070>" + Loc.T("ROOMHISTORY_HOST_BADGE") + "</color>"); } bool flag = SteamAvatarService.IsFriend(hit.SteamId); if (flag) { list.Add("<color=#88CCFF>" + Loc.T("ROOMHISTORY_ALREADY_FRIEND") + "</color>"); } string text3 = text + ((list.Count > 0) ? (" " + string.Join(" ", list)) : ""); string text4 = "<size=18><color=#CCCCCC>" + Loc.Tf("ROOMHISTORY_MET_AGO", Loc.Relative(hit.LastSeenUtc)) + "</color></size> <size=18><color=#DDDD88>" + Loc.Tf("ROOMHISTORY_MET_IN_ROOM", hit.RoomHostName) + "</color></size>"; CreateBodyText(((Component)val).transform, text3 + "\n" + text4); AddPlayerActionButtons(((Component)val).transform, hit.SteamId, flag); } private void AddPlayerActionButtons(Transform row, string steamId, bool friend) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown //IL_0196: Unknown result type (might be due to invalid IL or missing references) string text = SteamAvatarService.LocalSteamIdString(); if (text != null && string.Equals(text, steamId, StringComparison.Ordinal)) { return; } string sid = steamId; bool canShowInvite = HistoryUi.CanShowInvite; if (canShowInvite) { PeakMenuButton inviteBtn = ElementExtensions.SetPosition<PeakMenuButton>(ElementExtensions.SetPivot<PeakMenuButton>(ElementExtensions.SetAnchorMinMax<PeakMenuButton>(ElementExtensions.ParentTo<PeakMenuButton>(UiButtonFactory.CreateMenuButtonSafe(Loc.T("ROOMHISTORY_INVITE")), row), new Vector2(1f, 0.5f)), new Vector2(1f, 0.5f)), new Vector2(-16f, 22f)).SetWidth(150f); inviteBtn.OnClick((UnityAction)delegate { //IL_006a: Unknown result type (might be due to invalid IL or missing references) if (!SteamInviteService.InvitePlayer(sid)) { return; } try { if ((Object)(object)inviteBtn.Button != (Object)null) { ((Selectable)inviteBtn.Button).interactable = false; } if ((Object)(object)((PeakLocalizableElement)inviteBtn).Text != (Object)null) { ((Graphic)((PeakLocalizableElement)inviteBtn).Text).color = new Color(0.6f, 0.6f, 0.6f, 1f); } inviteBtn.SetText(Loc.T("ROOMHISTORY_INVITED")); } catch { } }); } string text2 = (friend ? Loc.T("ROOMHISTORY_ALREADY_FRIEND") : Loc.T("ROOMHISTORY_ADD_FRIEND")); PeakMenuButton val = ElementExtensions.SetPosition<PeakMenuButton>(ElementExtensions.SetPivot<PeakMenuButton>(ElementExtensions.SetAnchorMinMax<PeakMenuButton>(ElementExtensions.ParentTo<PeakMenuButton>(UiButtonFactory.CreateMenuButtonSafe(text2), row), new Vector2(1f, 0.5f)), new Vector2(1f, 0.5f)), new Vector2(-16f, canShowInvite ? (-28f) : 0f)).SetWidth(150f); if (!friend) { val.OnClick((UnityAction)delegate { SteamAvatarService.OpenAddFriend(sid); }); return; } try { if ((Object)(object)val.Button != (Object)null) { ((Selectable)val.Button).interactable = false; } if ((Object)(object)((PeakLocalizableElement)val).Text != (Object)null) { ((Graphic)((PeakLocalizableElement)val).Text).color = new Color(0.6f, 0.6f, 0.6f, 1f); } } catch { } } public void CreateFriendRow(FriendRoomInfo friend) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Expected O, but got Unknown //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Expected O, but got Unknown //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) string text = (string.IsNullOrWhiteSpace(friend.Name) ? Loc.T("ROOMHISTORY_UNKNOWN_PLAYER") : friend.Name); PeakButton val = ElementExtensions.ParentTo<PeakButton>(MenuAPI.CreateButton("Friend_" + friend.SteamId), _listContent).SetHeight(_playerRowHeight); PinRowSize(((Component)val).gameObject, _listWidth, _playerRowHeight, pinMinHeight: false); PeakText text2 = val.Text; if ((Object)(object)((text2 != null) ? text2.TextMesh : null) != (Object)null) { ((TMP_Text)val.Text.TextMesh).text = ""; } CreateAvatarBox(((Component)val).transform, friend.SteamId.ToString(), text, new Vector2(12f, 0f), 72f); FriendGameMode mode = friend.Mode; string text3 = mode switch { FriendGameMode.Joinable => "<color=#88FF88>" + Loc.T("ROOMHISTORY_FRIEND_IN_GAME") + "</color>", FriendGameMode.Solo => "<color=#A0A0A0>" + Loc.T("ROOMHISTORY_FRIEND_SOLO") + "</color>", FriendGameMode.InviteOnly => "<color=#A0A0A0>" + Loc.T("ROOMHISTORY_FRIEND_INVITE_ONLY") + "</color>", FriendGameMode.Unknown => "<color=#A0A0A0>" + Loc.T("ROOMHISTORY_FRIEND_UNKNOWN") + "</color>", _ => "<color=#88FF88>" + Loc.T("ROOMHISTORY_FRIEND_MAIN_MENU") + "</color>", }; string text4 = text; string text5 = "<size=20>" + text3 + "</size>"; CreateBodyText(((Component)val).transform, text4 + "\n" + text5); bool flag = mode == FriendGameMode.Joinable && (HistoryUi.IsTitleScene || !HistoryUi.IsInLiveLobby); bool flag2 = mode == FriendGameMode.MainMenu && HistoryUi.IsInLiveLobby; if (flag) { string lobbyId = friend.LobbyId.ToString(); ElementExtensions.SetPosition<PeakMenuButton>(ElementExtensions.SetPivot<PeakMenuButton>(ElementExtensions.SetAnchorMinMax<PeakMenuButton>(ElementExtensions.ParentTo<PeakMenuButton>(UiButtonFactory.CreateMenuButtonSafe(Loc.T("ROOMHISTORY_JOIN")), ((Component)val).transform), new Vector2(1f, 0.5f)), new Vector2(1f, 0.5f)), new Vector2(-16f, 0f)).SetWidth(150f).OnClick((UnityAction)delegate { RoomJoiner.TryJoinLobbyId(lobbyId, hidePage: true); }); return; } if (flag2) { string sid = friend.SteamId.ToString(); PeakMenuButton inviteBtn = ElementExtensions.SetPosition<PeakMenuButton>(ElementExtensions.SetPivot<PeakMenuButton>(ElementExtensions.SetAnchorMinMax<PeakMenuButton>(ElementExtensions.ParentTo<PeakMenuButton>(UiButtonFactory.CreateMenuButtonSafe(Loc.T("ROOMHISTORY_INVITE")), ((Component)val).transform), new Vector2(1f, 0.5f)), new Vector2(1f, 0.5f)), new Vector2(-16f, 0f)).SetWidth(150f); inviteBtn.OnClick((UnityAction)delegate { //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (!SteamInviteService.InvitePlayer(sid)) { return; } try { if ((Object)(object)inviteBtn.Button != (Object)null) { ((Selectable)inviteBtn.Button).interactable = false; } if ((Object)(object)((PeakLocalizableElement)inviteBtn).Text != (Object)null) { ((Graphic)((PeakLocalizableElement)inviteBtn).Text).color = new Color(0.6f, 0.6f, 0.6f, 1f); } inviteBtn.SetText(Loc.T("ROOMHISTORY_INVITED")); } catch { } }); return; } string text6 = mode switch { FriendGameMode.MainMenu => Loc.T("ROOMHISTORY_FRIEND_MAIN_MENU"), FriendGameMode.Unknown => Loc.T("ROOMHISTORY_FRIEND_UNKNOWN"), _ => Loc.T("ROOMHISTORY_FRIEND_IN_GAME"), }; try { PeakText val2 = ElementExtensions.SetPosition<PeakText>(ElementExtensions.SetPivot<PeakText>(ElementExtensions.SetAnchorMinMax<PeakText>(ElementExtensions.ParentTo<PeakText>(MenuAPI.CreateText(text6), ((Component)val).transform), new Vector2(1f, 0.5f)), new Vector2(1f, 0.5f)), new Vector2(-16f, 0f)).SetFontSize(20f); HistoryUiFont.Apply(val2); if ((Object)(object)val2.TextMesh != (Object)null) { ((Graphic)val2.TextMesh).color = new Color(0.6f, 0.6f, 0.6f, 1f); } } catch { } } private void CreateBodyText(Transform parent, string body) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) PeakText val = ElementExtensions.SetPosition<PeakText>(ElementExtensions.SetPivot<PeakText>(ElementExtensions.SetAnchorMinMax<PeakText>(ElementExtensions.ParentTo<PeakText>(MenuAPI.CreateText(body), parent), new Vector2(0f, 0.5f)), new Vector2(0f, 0.5f)), new Vector2(96f, 0f)).SetFontSize(24f); HistoryUiFont.Apply(val); if ((Object)(object)val.TextMesh != (Object)null) { ((Graphic)val.TextMesh).color = Color.white; ((TMP_Text)val.TextMesh).richText = true; ((Graphic)val.TextMesh).raycastTarget = false; ((TMP_Text)val.TextMesh).text = body; ((TMP_Text)val.TextMesh).ForceMeshUpdate(true, false); } } private void CreateAvatarBox(Transform parent, string steamId, string displayName, Vector2 pos, float size) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(string.IsNullOrEmpty(steamId) ? "AvatarPlaceholder" : ("Avatar_" + steamId), new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0f, 0.5f); component.anchorMax = val2; component.anchorMin = val2; component.pivot = new Vector2(0f, 0.5f); component.anchoredPosition = pos; component.sizeDelta = new Vector2(size, size); Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = new Color(0.18f, 0.14f, 0.11f, 1f); ((Graphic)component2).raycastTarget = false; Texture2D val3 = null; if (!string.IsNullOrEmpty(steamId)) { val3 = SteamAvatarService.GetAvatar(steamId); if ((Object)(object)val3 == (Object)null) { _avatarRefreshTargets.Add(val); } } if ((Object)(object)val3 != (Object)null) { component2.sprite = Sprite.Create(val3, new Rect(0f, 0f, (float)((Texture)val3).width, (float)((Texture)val3).height), new Vector2(0.5f, 0.5f)); ((Graphic)component2).color = Color.white; component2.preserveAspect = true; return; } string text = "?"; if (!string.IsNullOrWhiteSpace(displayName)) { text = displayName.Trim().Substring(0, 1); } PeakText val4 = ElementExtensions.SetPosition<PeakText>(ElementExtensions.SetPivot<PeakText>(ElementExtensions.SetAnchorMinMax<PeakText>(ElementExtensions.ParentTo<PeakText>(MenuAPI.CreateText(text), val.transform), new Vector2(0.5f, 0.5f)), new Vector2(0.5f, 0.5f)), Vector2.zero).SetFontSize(size * 0.4f); HistoryUiFont.Apply(val4); if ((Object)(object)val4.TextMesh != (Object)null) { ((TMP_Text)val4.TextMesh).alignment = (TextAlignmentOptions)514; ((Graphic)val4.TextMesh).color = Color.white; ((TMP_Text)val4.TextMesh).text = text; } } private static void PinRowSize(GameObject go, float width, float height, bool pinMinHeight) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) RectTransform component = go.GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null) { component.sizeDelta = new Vector2(width, height); } LayoutElement val = go.GetComponent<LayoutElement>() ?? go.AddComponent<LayoutElement>(); val.preferredWidth = width; val.minWidth = width; val.preferredHeight = height; if (pinMinHeight) { val.minHeight = height; } } } public sealed class HistoryStore { private const int FormatVersion = 3; private const char Sep = '\t'; private static readonly Regex RichTextTag = new Regex("<[^>]+>", RegexOptions.Compiled); private readonly string _filePath; private readonly string _legacyReTracePath; private readonly string _legacyQuickRejoinPath; private readonly PluginConfig _config; private readonly object _lock = new object(); private List<RoomRecord> _rooms = new List<RoomRecord>(); private bool _dirty; private float _lastDirtyUnscaledTime; public string StoragePath => _filePath; public HistoryStore(string configPath, PluginConfig config) { _config = config; string text = Path.Combine(configPath, "RoomHub"); Directory.CreateDirectory(text); _filePath = Path.Combine(text, "history.tsv"); _legacyReTracePath = Path.Combine(configPath, "ReTrace", "history.tsv"); _legacyQuickRejoinPath = Path.Combine(configPath, "QuickRejoin", "recent_rooms.tsv"); } public IReadOnlyList<RoomRecord> GetRooms() { lock (_lock) { PruneUnlocked(saveIfChanged: true); return _rooms.OrderByDescending((RoomRecord r) => r.JoinedAtUtcTicks).Take(Math.Max(1, _config.MaxRecentRooms.Value)).Select(CloneRoom) .ToList(); } } public RoomRecord? GetMostRecent() { IReadOnlyList<RoomRecord> rooms = GetRooms(); if (rooms.Count <= 0) { return null; } return rooms[0]; } public RoomRecord? GetRoom(string lobbyId) { lock (_lock) { RoomRecord roomRecord = _rooms.FirstOrDefault((RoomRecord x) => string.Equals(x.LobbyId, lobbyId, StringComparison.Ordinal)); return (roomRecord == null) ? null : CloneRoom(roomRecord); } } public IReadOnlyList<PlayerSearchHit> SearchPlayers(string query) { string text = (query ?? "").Trim(); if (text.Length == 0) { return Array.Empty<PlayerSearchHit>(); } lock (_lock) { PruneUnlocked(saveIfChanged: true); Dictionary<string, PlayerSearchHit> dictionary = new Dictionary<string, PlayerSearchHit>(StringComparer.Ordinal); foreach (RoomRecord room in _rooms) { string roomHostName = (string.IsNullOrWhiteSpace(room.HostName) ? room.LobbyId : room.HostName); foreach (PlayerRecord player in room.Players) { if (!string.IsNullOrWhiteSpace(player.SteamId) && player.DisplayName.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0 && (!dictionary.TryGetValue(player.SteamId, out var value) || player.LastSeenUtcTicks > value.LastSeenUtcTicks)) { dictionary[player.SteamId] = new PlayerSearchHit { SteamId = player.SteamId, DisplayName = player.DisplayName, WasHost = player.WasHost, LastSeenUtcTicks = player.LastSeenUtcTicks, LobbyId = room.LobbyId, RoomHostName = roomHostName }; } } } return dictionary.Values.OrderByDescending((PlayerSearchHit h) => h.LastSeenUtcTicks).ToList(); } } public void UpsertRoom(string lobbyId, string hostSteamId, string hostName, string lobbyName) { if (string.IsNullOrWhiteSpace(lobbyId)) { return; } long ticks = DateTime.UtcNow.Ticks; long num = 0L; lock (_lock) { RoomRecord roomRecord = _rooms.FirstOrDefault((RoomRecord r) => string.Equals(r.LobbyId, lobbyId, StringComparison.Ordinal)); if (roomRecord != null) { num = roomRecord.JoinedAtUtcTicks; roomRecord.JoinedAtUtcTicks = ticks; if (!string.IsNullOrWhiteSpace(hostSteamId)) { roomRecord.HostSteamId = hostSteamId.Trim(); } if (!string.IsNullOrWhiteSpace(hostName)) { roomRecord.HostName = Sanitize(hostName); } if (!string.IsNullOrWhiteSpace(lobbyName)) { roomRecord.LobbyName = Sanitize(lobbyName); } _rooms.Remove(roomRecord); _rooms.Insert(0, roomRecord); } else { _rooms.Insert(0, new RoomRecord { LobbyId = lobbyId.Trim(), HostSteamId = (hostSteamId ?? "").Trim(), HostName = Sanitize(hostName), LobbyName = Sanitize(lobbyName), JoinedAtUtcTicks = ticks }); } PruneUnlocked(saveIfChanged: false); SaveUnlocked(); } if (num > 0) { long num2 = (ticks - num) / 600000000; Plugin.Log.LogInfo((object)("Room saved (rejoin): lobby=" + lobbyId + ", host='" + hostName + "', " + $"joinedAt refreshed (+{num2} min since previous) → {_filePath}")); } else { Plugin.Log.LogInfo((object)("Room saved (new): lobby=" + lobbyId + ", host='" + hostName + "' → " + _filePath)); } } public void TouchRoomJoinedNow(string lobbyId, string reason) { if (string.IsNullOrWhiteSpace(lobbyId)) { return; } long ticks = DateTime.UtcNow.Ticks; long num = 0L; bool flag = false; lock (_lock) { RoomRecord roomRecord = _rooms.FirstOrDefault((RoomRecord r) => string.Equals(r.LobbyId, lobbyId, StringComparison.Ordinal)); if (roomRecord == null) { return; } num = roomRecord.JoinedAtUtcTicks; if (ticks > roomRecord.JoinedAtUtcTicks) { roomRecord.JoinedAtUtcTicks = ticks; _rooms.Remove(roomRecord); _rooms.Insert(0, roomRecord); flag = true; MarkDirtyUnlocked(); } } if (flag) { long num2 = ((num > 0) ? ((ticks - num) / 10000000) : 0); Plugin.Log.LogInfo((object)$"Room joinedAt touched ({reason}): lobby={lobbyId}, +{num2}s since previous write"); } } public void UpsertPlayer(string lobbyId, string steamId, string displayName, bool wasHost) { if (string.IsNullOrWhiteSpace(lobbyId) || string.IsNullOrWhiteSpace(steamId)) { return; } lock (_lock) { RoomRecord roomRecord = _rooms.FirstOrDefault((RoomRecord r) => string.Equals(r.LobbyId, lobbyId, StringComparison.Ordinal)); if (roomRecord == null) { return; } long ticks = DateTime.UtcNow.Ticks; string sid = steamId.Trim(); PlayerRecord playerRecord = roomRecord.Players.FirstOrDefault((PlayerRecord x) => string.Equals(x.SteamId, sid, StringComparison.Ordinal)); if (playerRecord == null) { playerRecord = new PlayerRecord { SteamId = sid, DisplayName = Sanitize(displayName), WasHost = false, FirstSeenUtcTicks = ticks, LastSeenUtcTicks = ticks }; roomRecord.Players.Add(playerRecord); } else { if (!string.IsNullOrWhiteSpace(displayName)) { playerRecord.DisplayName = Sanitize(displayName); } playerRecord.LastSeenUtcTicks = ticks; } if (wasHost) { ApplySoleHostUnlocked(roomRecord, sid, playerRecord.DisplayName); } int num = 20; if (roomRecord.Players.Count > num) { roomRecord.Players.Sort((PlayerRecord a, PlayerRecord b) => b.LastSeenUtcTicks.CompareTo(a.LastSeenUtcTicks)); roomRecord.Players.RemoveRange(num, roomRecord.Players.Count - num); } MarkDirtyUnlocked(); } } public void SetCurrentHost(string lobbyId, string hostSteamId, string? hostDisplayName) { if (string.IsNullOrWhiteSpace(lobbyId) || string.IsNullOrWhiteSpace(hostSteamId)) { return; } lock (_lock) { RoomRecord roomRecord = _rooms.FirstOrDefault((RoomRecord r) => string.Equals(r.LobbyId, lobbyId, StringComparison.Ordinal)); if (roomRecord != null) { ApplySoleHostUnlocked(roomRecord, hostSteamId.Trim(), hostDisplayName); MarkDirtyUnlocked(); } } } private static void ApplySoleHostUnlocked(RoomRecord room, string hostSteamId, string? hostDisplayName) { foreach (PlayerRecord player in room.Players) { player.WasHost = string.Equals(player.SteamId, hostSteamId, StringComparison.Ordinal); } room.HostSteamId = hostSteamId; if (!string.IsNullOrWhiteSpace(hostDisplayName)) { room.HostName = Sanitize(hostDisplayName); } } public void DeleteRoom(string lobbyId) { if (string.IsNullOrWhiteSpace(lobbyId)) { return; } lock (_lock) { int num = _rooms.RemoveAll((RoomRecord r) => string.Equals(r.LobbyId, lobbyId, StringComparison.Ordinal)); if (num > 0) { SaveUnlocked(); Plugin.Log.LogInfo((object)("Deleted room history: " + lobbyId)); } } } public void TickDeferredSave(float unscaledTime) { lock (_lock) { if (_dirty && !(unscaledTime - _lastDirtyUnscaledTime < 0.75f)) { SaveUnlocked(); } } } private void MarkDirtyUnlocked() { _dirty = true; try { _lastDirtyUnscaledTime = Time.unscaledTime; } catch { _lastDirtyUnscaledTime = 0f; } } public void Load() { lock (_lock) { _rooms = new List<RoomRecord>(); try { if (File.Exists(_filePath)) { LoadFileUnlocked(_filePath); } else if (File.Exists(_legacyReTracePath)) { LoadFileUnlocked(_legacyReTracePath); if (_rooms.Count > 0) { SaveUnlocked(); } Plugin.Log.LogInfo((object)$"Migrated {_rooms.Count} room(s) from ReTrace history."); } else if (File.Exists(_legacyQuickRejoinPath)) { LoadFileUnlocked(_legacyQuickRejoinPath); if (_rooms.Count > 0) { SaveUnlocked(); } Plugin.Log.LogInfo((object)$"Migrated {_rooms.Count} room(s) from Quick Rejoin TSV."); } PruneUnlocked(saveIfChanged: true); Plugin.Log.LogInfo((object)$"Loaded {_rooms.Count} room(s) from {_filePath}"); } catch (Exception arg) { Plugin.Log.LogError((object)$"History load failed: {arg}"); _rooms = new List<RoomRecord>(); } } } public void Flush() { lock (_lock) { SaveUnlocked(); } } private void LoadFileUnlocked(string path) { string[] array = File.ReadAllLines(path, Encoding.UTF8); if (array.Length == 0) { return; } int num = 0; if (array[0].StartsWith("QR_RECENT_V", StringComparison.Ordinal) || array[0].StartsWith("RETRACE_V", StringComparison.Ordinal) || array[0].StartsWith("ROOMHISTORY_V", StringComparison.Ordinal)) { num = 1; } Dictionary<string, RoomRecord> dictionary = new Dictionary<string, RoomRecord>(StringComparer.Ordinal); for (int i = num; i < array.Length; i++) { string text = array[i]; if (string.IsNullOrWhiteSpace(text) || text.StartsWith("#")) { continue; } string[] array2 = text.Split('\t'); if (array2.Length < 2) { continue; } long result4; if (array2[0] == "R" && array2.Length >= 6) { if (long.TryParse(array2[5], out var result) && result > 0) { string text2 = Unescape(array2[1]); if (!string.IsNullOrWhiteSpace(text2)) { RoomRecord value = new RoomRecord { LobbyId = text2, HostSteamId = Unescape(array2[2]), HostName = Sanitize(Unescape(array2[3])), LobbyName = Sanitize(Unescape(array2[4])), JoinedAtUtcTicks = result }; dictionary[text2] = value; } } } else if (array2[0] == "P" && array2.Length >= 7) { string key = Unescape(array2[1]); if (dictionary.TryGetValue(key, out var value2) && long.TryParse(array2[5], out var result2)) { if (!long.TryParse(array2[6], out var result3)) { result3 = result2; } value2.Players.Add(new PlayerRecord { SteamId = Unescape(array2[2]), DisplayName = Sanitize(Unescape(array2[3])), WasHost = (array2[4] == "1" || array2[4].Equals("true", StringComparison.OrdinalIgnoreCase)), FirstSeenUtcTicks = result2, LastSeenUtcTicks = result3 }); } } else if (array2.Length == 4 && !array2[0].Equals("R") && !array2[0].Equals("P") && long.TryParse(array2[3], out result4) && result4 > 0) { string text3 = Unescape(array2[0]); if (!string.IsNullOrWhiteSpace(text3)) { dictionary[text3] = new RoomRecord { LobbyId = text3, HostName = Sanitize(Unescape(array2[1])), LobbyName = Sanitize(Unescape(array2[2])), JoinedAtUtcTicks = result4 }; } } } foreach (RoomRecord value3 in dictionary.Values) { value3.HostName = Sanitize(value3.HostName); value3.LobbyName = Sanitize(value3.LobbyName); value3.HostSteamId = (value3.HostSteamId ?? "").Trim(); if (!string.IsNullOrWhiteSpace(value3.HostSteamId)) { ApplySoleHostUnlocked(value3, value3.HostSteamId, value3.HostName); continue; } List<PlayerRecord> list = value3.Players.Where((PlayerRecord p) => p.WasHost).ToList(); if (list.Count > 1) { PlayerRecord playerRecord = list.OrderByDescending((PlayerRecord p) => p.LastSeenUtcTicks).First(); ApplySoleHostUnlocked(value3, playerRecord.SteamId, playerRecord.DisplayName); } } _rooms = dictionary.Values.OrderByDescending((RoomRecord r) => r.JoinedAtUtcTicks).ToList(); } private void PruneUnlocked(bool saveIfChanged) { int count = Math.Max(1, _config.MaxRecentRooms.Value); int num = Math.Max(1, _config.HistoryExpireHours.Value); long cutoff = DateTime.UtcNow.AddHours(-num).Ticks; int count2 = _rooms.Count; _rooms = (from r in _rooms where r != null && !string.IsNullOrWhiteSpace(r.LobbyId) && r.JoinedAtUtcTicks >= cutoff group r by r.LobbyId into g select g.OrderByDescending((RoomRecord x) => x.JoinedAtUtcTicks).First() into r orderby r.JoinedAtUtcTicks descending select r).Take(count).ToList(); if (saveIfChanged && _rooms.Count != count2) { SaveUnlocked(); } } private void SaveUnlocked() { try { string directoryName = Path.GetDirectoryName(_filePath); if (!string.IsNullOrEmpty(directoryName)) { Directory.CreateDirectory(directoryName); } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("ROOMHISTORY_V").Append(3).Append('\n'); stringBuilder.Append("# R lobbyId hostSteamId hostName lobbyName joinedTicks\n"); stringBuilder.Append("# P lobbyId steamId displayName wasHost firstTicks lastTicks\n"); foreach (RoomRecord item in _rooms.OrderByDescending((RoomRecord x) => x.JoinedAtUtcTicks)) { stringBuilder.Append("R").Append('\t').Append(Escape(item.LobbyId)) .Append('\t') .Append(Escape(item.HostSteamId)) .Append('\t') .Append(Escape(item.HostName)) .Append('\t') .Append(Escape(item.LobbyName)) .Append('\t') .Append(item.JoinedAtUtcTicks) .Append('\n'); foreach (PlayerRecord item2 in item.Players.OrderByDescending((PlayerRecord x) => x.LastSeenUtcTicks)) { stringBuilder.Append("P").Append('\t').Append(Escape(item.LobbyId)) .Append('\t') .Append(Escape(item2.SteamId)) .Append('\t') .Append(Escape(item2.DisplayName)) .Append('\t') .Append(item2.WasHost ? "1" : "0") .Append('\t') .Append(item2.FirstSeenUtcTicks) .Append('\t') .Append(item2.LastSeenUtcTicks) .Append('\n'); } } string text = _filePath + ".tmp"; File.WriteAllText(text, stringBuilder.ToString(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); if (File.Exists(_filePath)) { File.Replace(text, _filePath, null); } else { File.Move(text, _filePath); } _dirty = false; } catch (Exception arg) { Plugin.Log.LogError((object)$"History save failed: {arg}"); } } private static RoomRecord CloneRoom(RoomRecord r) { RoomRecord roomRecord = new RoomRecord { LobbyId = r.LobbyId, HostSteamId = r.HostSteamId, HostName = r.HostName, LobbyName = r.LobbyName, JoinedAtUtcTicks = r.JoinedAtUtcTicks }; foreach (PlayerRecord player in r.Players) { roomRecord.Players.Add(new PlayerRecord { SteamId = player.SteamId, DisplayName = player.DisplayName, WasHost = player.WasHost, FirstSeenUtcTicks = player.FirstSeenUtcTicks, LastSeenUtcTicks = player.LastSeenUtcTicks }); } return roomRecord; } private static string Sanitize(string? s) { if (string.IsNullOrEmpty(s)) { return ""; } string text = RichTextTag.Replace(s, ""); return text.Replace('\t', ' ').Replace('\r', ' ').Replace('\n', ' ') .Trim(); } private static string Escape(string? s) { if (string.IsNullOrEmpty(s)) { return ""; } return s.Replace("\\", "\\\\").Replace("\t", "\\t").Replace("\n", "\\n") .Replace("\r", "\\r"); } private static string Unescape(string? s) { if (string.IsNullOrEmpty(s)) { return ""; } StringBuilder stringBuilder = new StringBuilder(s.Length); for (int i = 0; i < s.Length; i++) { if (s[i] == '\\' && i + 1 < s.Length) { char c = s[++i]; StringBuilder stringBuilder2 = stringBuilder; stringBuilder2.Append(c switch { 't' => '\t', 'n' => '\n', 'r' => '\r', '\\' => '\\', _ => c, }); } else { stringBuilder.Append(s[i]); } } return stringBuilder.ToString(); } } internal static class HistoryUi { private static HistoryPageController? _page; public static bool IsOpen { get { if (_page != null) { return _page.IsPageOpen; } return false; } } public static bool IsTitleScene { get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).IsValid()) { return string.Equals(((Scene)(ref activeScene)).name, "Title", StringComparison.Ordinal); } return false; } } public static bool IsInLiveLobby { get { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) try { SteamLobbyHandler service = GameHandler.GetService<SteamLobbyHandler>(); CSteamID val = default(CSteamID); return service != null && service.InSteamLobby(ref val) && val != CSteamID.Nil; } catch { return false; } } } public static bool CanShowInvite { get { if (!IsTitleScene) { return IsInLiveLobby; } return false; } } public static void Open() { if (!Plugin.ModConfig.Enabled.Value) { RoomJoiner.ShowFeedback(Loc.T("ROOMHISTORY_DISABLED"), Loc.T("ROOMHISTORY_DISABLED")); return; } try { PauseMenuHook.ClosePauseMenuIfOpen(); UiButtonFactory.EnsureTemplate(); EnsureController(); _page.Open(); } catch (Exception arg) { Plugin.Log.LogError((object)$"HistoryUi.Open: {arg}"); DropPage(); } } public static void Hide() { try { _page?.Hide(); } catch { } } public static void Toggle() { if (IsOpen) { Hide(); } else { Open(); } } public static void DropPage() { try { _page?.Discard(); } catch { } _page = null; } public static void OnSceneLoaded() { DropPage(); } public static void Tick() { if (_page == null) { return; } if (!_page.HasLivePage) { DropPage(); } else if (_page.IsPageOpen) { _page.TickInputBlock(); if (Input.GetKeyDown((KeyCode)27) && !IsTextInputFocused()) { _page.HandleBackOrClose(); } else { _page.TickAvatarRefresh(); } } } public static bool IsTextInputFocused() { try { EventSystem current = EventSystem.current; if ((Object)(object)current == (Object)null) { return false; } GameObject currentSelectedGameObject = current.currentSelectedGameObject; if ((Object)(object)currentSelectedGameObject == (Object)null) { return false; } if ((Object)(object)currentSelectedGameObject.GetComponent<TMP_InputField>() != (Object)null) { return true; } if ((Object)(object)currentSelectedGameObject.GetComponent<InputField>() != (Object)null) { return true; } Transform parent = currentSelectedGameObject.transform.parent; int num = 0; while (num < 4 && (Object)(object)parent != (Object)null) { if ((Object)(object)((Component)parent).GetComponent<TMP_InputField>() != (Object)null || (Object)(object)((Component)parent).GetComponent<InputField>() != (Object)null) { return true; } num++; parent = parent.parent; } } catch { } return false; } private static void EnsureController() { if (_page != null && !_page.HasLivePage) { DropPage(); } if (_page == null) { _page = new HistoryPageController(); } } } internal static class HistoryUiFont { private static TMP_FontAsset? _uiFont; private static Material? _uiFontMat; public static void Reset() { _uiFont = null; _uiFontMat = null; } public static void CaptureFromMenuButton() { if ((Object)(object)_uiFont != (Object)null) { return; } try { if (TryCaptureFromScene()) { return; } PeakMenuButton val = UiButtonFactory.CreateMenuButtonSafe("字"); try { TextMeshProUGUI componentInChildren = ((Component)val).GetComponentInChildren<TextMeshProUGUI>(true); if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((TMP_Text)componentInChildren).font != (Object)null) { _uiFont = ((TMP_Text)componentInChildren).font; _uiFontMat = ((TMP_Text)componentInChildren).fontSharedMaterial; Plugin.Log.LogInfo((object)("UI font from PeakMenuButton: " + ((Object)_uiFont).name + " mat=" + (((Object)(object)_uiFontMat != (Object)null) ? ((Object)_uiFontMat).name : "null"))); } } finally { Object.Destroy((Object)(object)((Component)val).gameObject); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("CaptureUiFont: " + ex.Message)); } } private static bool TryCaptureFromScene() { try { TextMeshProUGUI[] array = Object.FindObjectsByType<TextMeshProUGUI>((FindObjectsSortMode)0); foreach (TextMeshProUGUI val in array) { if (!((Object)(object)((val != null) ? ((TMP_Text)val).font : null) == (Object)null) && !string.IsNullOrEmpty(((TMP_Text)val).text) && ((Component)val).gameObject.activeInHierarchy && (ContainsCjk(((TMP_Text)val).text) || ((Object)val).name.IndexOf("Button", StringComparison.OrdinalIgnoreCase) >= 0 || (Object)(object)((Component)val).GetComponentInParent<PeakMenuButton>() != (Object)null)) { _uiFont = ((TMP_Text)val).font; _uiFontMat = ((TMP_Text)val).fontSharedMaterial; Plugin.Log.LogInfo((object)("UI font from scene " + ((Object)val).name + ": " + ((Object)_uiFont).name)); return true; } } } catch { } return false; } public static void Apply(PeakText? peakText) { if (!((Object)(object)((peakText != null) ? peakText.TextMesh : null) == (Object)null) && !((Object)(object)_uiFont == (Object)null)) { ((TMP_Text)peakText.TextMesh).font = _uiFont; if ((Object)(object)_uiFontMat != (Object)null) { ((TMP_Text)peakText.TextMesh).fontSharedMaterial = _uiFontMat; } } } public static void ForceCenteredLabel(PeakText? peakText, float width, float height, Vector2 anchoredPos) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)peakText == (Object)null) { return; } RectTransform component = ((Component)peakText).GetComponent<RectTransform>(); if (!((Object)(object)component == (Object)null)) { Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 1f); component.anchorMax = val; component.anchorMin = val; component.pivot = new Vector2(0.5f, 1f); component.anchoredPosition = anchoredPos; component.sizeDelta = new Vector2(width, height); if ((Object)(object)peakText.TextMesh != (Object)null) { ((TMP_Text)peakText.TextMesh).alignment = (TextAlignmentOptions)514; ((TMP_Text)peakText.TextMesh).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)peakText.TextMesh).overflowMode = (TextOverflowModes)1; ((TMP_Text)peakText.TextMesh).enableAutoSizing = true; ((TMP_Text)peakText.TextMesh).fontSizeMin = 16f; ((TMP_Text)peakText.TextMesh).fontSizeMax = ((((TMP_Text)peakText.TextMesh).fontSize > 0f) ? ((TMP_Text)peakText.TextMesh).fontSize : 44f); } } } private static bool ContainsCjk(string text) { foreach (char c in text) { if (c >= '㐀' && c <= '鿿') { return true; } } return false; } } internal static class JoinGate { private sealed class Entry { public float CooldownUntil; } public const double MaxLobbyAgeHours = 2.5; private const float JoinFailCooldownSec = 600f; private static readonly Dictionary<ulong, Entry> _cooldowns = new Dictionary<ulong, Entry>(); public static event Action? StateChanged; public static bool IsJoinAllowed(string lobbyId, long joinedAtUtcTicks) { if (joinedAtUtcTicks > 0) { DateTime dateTime = new DateTime(joinedAtUtcTicks, DateTimeKind.Utc); if ((DateTime.UtcNow - dateTime).TotalHours > 2.5) { return false; } } if (ulong.TryParse(lobbyId, out var result) && result != 0L && _cooldowns.TryGetValue(result, out Entry value) && Time.unscaledTime < value.CooldownUntil) { return false; } return true; } public static void MarkJoinFailed(ulong lobbyId) { if (lobbyId == 0L) { return; } _cooldowns[lobbyId] = new Entry { CooldownUntil = Time.unscaledTime + 600f }; try { JoinGate.StateChanged?.Invoke(); } catch { } } } internal static class LobbyJoinFeedback { private static Callback<LobbyEnter_t>? _callback; private static bool _inited; private static float _lastShownUnscaled; private const float MinShowIntervalSec = 2f; public static void Init() { if (_inited) { return; } try { _callback = Callback<LobbyEnter_t>.Create((DispatchDelegate<LobbyEnter_t>)OnLobbyEnter); _inited = true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("LobbyJoinFeedback init failed: " + ex.Message)); } } private static void OnLobbyEnter(LobbyEnter_t param) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) EChatRoomEnterResponse val = (EChatRoomEnterResponse)param.m_EChatRoomEnterResponse; if ((int)val != 1) { float unscaledTime = Time.unscaledTime; if (!(unscaledTime - _lastShownUnscaled < 2f)) { _lastShownUnscaled = unscaledTime; string text = Describe(val); Plugin.Log.LogInfo((object)($"Join lobby failed lobby={param.m_ulSteamIDLobby} " + $"code={(int)param.m_EChatRoomEnterResponse} ({text})")); JoinGate.MarkJoinFailed(param.m_ulSteamIDLobby); RoomJoiner.ShowFeedback(Loc.T("ROOMHISTORY_JOIN_FAILED_TITLE"), text); } } } private static string Describe(EChatRoomEnterResponse code) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected I4, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected I4, but got Unknown return (code - 2) switch { 0 => Loc.T("ROOMHISTORY_JOIN_FAIL_DOESNT_EXIST"), 1 => Loc.T("ROOMHISTORY_JOIN_FAIL_NOT_ALLOWED"), 2 => Loc.T("ROOMHISTORY_JOIN_FAIL_FULL"), 4 => Loc.T("ROOMHISTORY_JOIN_FAIL_BANNED"), _ => Loc.Tf("ROOMHISTORY_JOIN_FAIL_OTHER", (int)code), }; } } [HarmonyPatch(typeof(SteamLobbyHandler), "OnLobbyEnter")] internal static class SteamLobbyEnterPatch { private static void Postfix(SteamLobbyHandler __instance, LobbyEnter_t param) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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) try { if (!Plugin.ModConfig.Enabled.Value || param.m_EChatRoomEnterResponse != 1) { return; } CSteamID val = default(CSteamID); ((CSteamID)(ref val))..ctor(param.m_ulSteamIDLobby); if (val == CSteamID.Nil || param.m_ulSteamIDLobby == 0L) { return; } CSteamID steamID = SteamUser.GetSteamID(); CSteamID lobbyOwner = SteamMatchmaking.GetLobbyOwner(val); bool flag = lobbyOwner == steamID; string hostSteamId = lobbyOwner.m_SteamID.ToString(); string lobbyId = val.m_SteamID.ToString(); if (flag && !Plugin.ModConfig.RecordWhenHosting.Value) { Plugin.Log.LogDebug((object)"Skip room list entry (hosting)."); PlayerTracker.SetActiveLobby(lobbyId, hostSteamId); return; } string text = SteamMatchmaking.GetLobbyData(val, "host_Name"); if (string.IsNullOrWhiteSpace(text)) { try { text = SteamFriends.GetFriendPersonaName(lobbyOwner); } catch { text = ""; } } if (string.IsNullOrWhiteSpace(text)) { text = Loc.T("ROOMHISTORY_UNKNOWN_HOST"); } string lobbyName = SteamMatchmaking.GetLobbyData(val, "lobby_Name") ?? ""; Plugin.Store.UpsertRoom(lobbyId, hostSteamId, text, lobbyName); PlayerTracker.SetActiveLobby(lobbyId, hostSteamId); SnapshotMembers(val, lobbyOwner); Plugin.Store.SetCurrentHost(lobbyId, hostSteamId, text); } catch (Exception arg) { Plugin.Log.LogError((object)$"Lobby record failed: {arg}"); } } private static void SnapshotMembers(CSteamID lobbyId, CSteamID owner) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) try { int numLobbyMembers = SteamMatchmaking.GetNumLobbyMembers(lobbyId); CSteamID steamID = SteamUser.GetSteamID(); string lobbyId2 = lobbyId.m_SteamID.ToString(); for (int i = 0; i < numLobbyMembers; i++) { CSteamID lobbyMemberByIndex = SteamMatchmaking.GetLobbyMemberByIndex(lobbyId, i); if (!(lobbyMemberByIndex == CSteamID.Nil) && !(lobbyMemberByIndex == steamID)) { string text; try { text = SteamFriends.GetFriendPersonaName(lobbyMemberByIndex); } catch { text = ""; } if (string.IsNullOrWhiteSpace(text)) { text = Loc.T("ROOMHISTORY_UNKNOWN_PLAYER"); } bool wasHost = lobbyMemberByIndex == owner; Plugin.Store.UpsertPlayer(lobbyId2, lobbyMemberByIndex.m_Stea