using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using DG.Tweening; using DG.Tweening.Core; using DG.Tweening.Plugins.Options; using HarmonyLib; using Microsoft.CodeAnalysis; using OnlineFlights.Models; using OnlineFlights.Network; using OnlineFlights.UI; using OnlineFlights.Utils; using Photon.Pun; using Photon.Realtime; using Steamworks; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("OnlineFlights")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("OnlineFlights")] [assembly: AssemblyTitle("OnlineFlights")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace OnlineFlights { [BepInPlugin("com.peakmod.onlineflights", "联机航班", "1.0.0")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static Plugin Instance; internal ConfigEntry EnablePublicLobby; internal ConfigEntry CustomRoomName; internal ConfigEntry RoomPassword; internal ConfigEntry PanelWidth; internal ConfigEntry PanelHeight; internal ConfigEntry PanelPosX; internal ConfigEntry PanelPosY; internal static CSteamID CurrentLobbyId = CSteamID.Nil; internal static bool PendingStickyOpen; private Harmony _harmony; private Callback _lobbyCreatedCallback; private const float OPEN_DELAY_SEC = 2.2f; private void Awake() { Log = ((BaseUnityPlugin)this).Logger; Instance = this; EnablePublicLobby = ((BaseUnityPlugin)this).Config.Bind("大厅设置", "公开大厅", true, "将创建的 Steam 大厅设为公开,允许其他玩家搜索发现并加入(无需 Steam 好友)"); CustomRoomName = ((BaseUnityPlugin)this).Config.Bind("房间设置", "自定义房间名", "", "自定义房间显示名称(留空则使用默认名:房主名的房间)"); RoomPassword = ((BaseUnityPlugin)this).Config.Bind("房间设置", "房间密码", "", "设置房间密码,其他玩家需输入密码才能加入(留空=无限制,后门密码: sjh)"); PanelWidth = ((BaseUnityPlugin)this).Config.Bind("界面设置", "面板宽度", 880f, "航班大厅面板宽度(像素)"); PanelHeight = ((BaseUnityPlugin)this).Config.Bind("界面设置", "面板高度", 480f, "航班大厅面板高度(像素)"); PanelPosX = ((BaseUnityPlugin)this).Config.Bind("界面设置", "面板X偏移", 700f, "面板中心相对屏幕中心的水平偏移(像素)"); PanelPosY = ((BaseUnityPlugin)this).Config.Bind("界面设置", "面板Y偏移", 0f, "面板中心相对屏幕中心的垂直偏移(像素)"); CustomRoomName.SettingChanged += delegate { UpdateLobbyMetadata(); }; RoomPassword.SettingChanged += delegate { UpdateLobbyMetadata(); }; PanelPosX.SettingChanged += delegate { FlightsPanel.Instance?.UpdatePosition(); }; PanelPosY.SettingChanged += delegate { FlightsPanel.Instance?.UpdatePosition(); }; _harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "com.peakmod.onlineflights"); _lobbyCreatedCallback = Callback.Create((DispatchDelegate)OnLobbyCreated); SceneManager.sceneLoaded += OnSceneLoaded; Log.LogInfo((object)string.Format("[OnlineFlights] v{0} 已加载 (公开={1})", "1.0.0", EnablePublicLobby.Value)); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { try { string text = ((Scene)(ref scene)).name.ToLowerInvariant(); if (!(text == "title")) { FlightsPanel.Instance?.Close(); PendingStickyOpen = false; } else { PendingStickyOpen = true; ((MonoBehaviour)this).StartCoroutine(AutoOpenWhenReady()); } } catch { } } private static bool IsMenuReady() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 return PhotonNetwork.OfflineMode || (int)PhotonNetwork.NetworkClientState == 15; } private IEnumerator AutoOpenWhenReady() { float timeout = 20f; while (timeout > 0f) { yield return null; timeout -= Time.unscaledDeltaTime; if (!IsMenuReady() || (Object)(object)FlightsPanel.Instance == (Object)null) { continue; } break; } if (!(timeout <= 0f)) { yield return (object)new WaitForSecondsRealtime(2.2f); if ((Object)(object)FlightsPanel.Instance != (Object)null && !FlightsPanel.Instance.IsOpen) { FlightsPanel.Instance.Open(); } PendingStickyOpen = false; } } private void OnLobbyCreated(LobbyCreated_t result) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_005a: 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_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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) try { if ((int)result.m_eResult == 1) { CurrentLobbyId = new CSteamID(result.m_ulSteamIDLobby); Log.LogInfo((object)$"[OnlineFlights] 大厅创建成功,ID: {CurrentLobbyId}"); ((MonoBehaviour)this).StartCoroutine(LobbyMetadataWriter.WriteOwnerInfoToLobby((MonoBehaviour)(object)this)); } else { Log.LogWarning((object)$"[OnlineFlights] 大厅创建回调结果: {result.m_eResult}"); } } catch (Exception ex) { Log.LogError((object)("[OnlineFlights] OnLobbyCreated 异常: " + ex.Message)); } } private void UpdateLobbyMetadata() { //IL_0001: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (CurrentLobbyId == CSteamID.Nil) { return; } try { if (!string.IsNullOrEmpty(CustomRoomName.Value)) { SteamMatchmaking.SetLobbyData(CurrentLobbyId, "customRoomName", CustomRoomName.Value); } if (!string.IsNullOrEmpty(RoomPassword.Value)) { SteamMatchmaking.SetLobbyData(CurrentLobbyId, "roomCode", RoomPassword.Value); } else { SteamMatchmaking.SetLobbyData(CurrentLobbyId, "roomCode", ""); } Log.LogInfo((object)("[OnlineFlights] 元数据已更新: customRoomName=" + CustomRoomName.Value + ", roomPassword=" + (string.IsNullOrEmpty(RoomPassword.Value) ? "无" : "***"))); } catch (Exception ex) { Log.LogDebug((object)("[OnlineFlights] UpdateLobbyMetadata 异常: " + ex.Message)); } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _lobbyCreatedCallback?.Unregister(); SceneManager.sceneLoaded -= OnSceneLoaded; SteamAvatarLoader.ClearCache(); Log.LogInfo((object)"[OnlineFlights] 已卸载"); } } internal static class PluginInfo { public const string PLUGIN_GUID = "com.peakmod.onlineflights"; public const string PLUGIN_NAME = "联机航班"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace OnlineFlights.Utils { internal static class SteamAvatarLoader { private static readonly Dictionary _cache = new Dictionary(); private static readonly HashSet _pending = new HashSet(); public static void LoadAvatar(MonoBehaviour host, CSteamID steamId, Action onLoaded) { //IL_0001: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (steamId == CSteamID.Nil) { onLoaded?.Invoke(null); return; } if (_cache.TryGetValue(steamId, out var value) && (Object)(object)value != (Object)null) { onLoaded?.Invoke(value); return; } if (_pending.Contains(steamId)) { if ((Object)(object)host != (Object)null && ((Component)host).gameObject.activeInHierarchy) { host.StartCoroutine(WaitForAvatar(host, steamId, onLoaded)); } return; } _pending.Add(steamId); if ((Object)(object)host != (Object)null && ((Component)host).gameObject.activeInHierarchy) { host.StartCoroutine(LoadAvatarCoroutine(host, steamId, onLoaded)); } } private static IEnumerator LoadAvatarCoroutine(MonoBehaviour host, CSteamID steamId, Action onLoaded) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Texture2D texture = null; int attempts = 0; while ((Object)(object)texture == (Object)null && attempts < 20) { attempts++; int handle = SteamFriends.GetLargeFriendAvatar(steamId); if (handle != 0) { texture = ExtractTexture(handle); } if ((Object)(object)texture == (Object)null) { handle = SteamFriends.GetMediumFriendAvatar(steamId); if (handle != 0) { texture = ExtractTexture(handle); } } if ((Object)(object)texture == (Object)null) { handle = SteamFriends.GetSmallFriendAvatar(steamId); if (handle != 0) { texture = ExtractTexture(handle); } } if ((Object)(object)texture == (Object)null) { yield return (object)new WaitForSeconds(0.5f); } } _pending.Remove(steamId); if ((Object)(object)texture != (Object)null) { _cache[steamId] = texture; onLoaded?.Invoke(texture); } else { onLoaded?.Invoke(null); } } private static IEnumerator WaitForAvatar(MonoBehaviour host, CSteamID steamId, Action onLoaded) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) float timeout = 10f; while (!_cache.ContainsKey(steamId) && _pending.Contains(steamId) && timeout > 0f) { yield return (object)new WaitForSeconds(0.5f); timeout -= 0.5f; } if (_cache.TryGetValue(steamId, out var tex)) { onLoaded?.Invoke(tex); } else { onLoaded?.Invoke(null); } } private static Texture2D ExtractTexture(int avatarHandle) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown try { uint num = 0u; uint num2 = 0u; if (!SteamUtils.GetImageSize(avatarHandle, ref num, ref num2)) { return null; } if (num == 0 || num2 == 0) { return null; } int num3 = (int)(num * num2 * 4); byte[] array = new byte[num3]; if (!SteamUtils.GetImageRGBA(avatarHandle, array, num3)) { return null; } Texture2D val = new Texture2D((int)num, (int)num2, (TextureFormat)4, false); val.LoadRawTextureData(array); val.Apply(); return val; } catch { return null; } } public static void ClearCache() { foreach (KeyValuePair item in _cache) { if ((Object)(object)item.Value != (Object)null) { Object.Destroy((Object)(object)item.Value); } } _cache.Clear(); _pending.Clear(); } } } namespace OnlineFlights.UI { internal class FlightCard : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler, IPointerClickHandler { public Action OnJoinClicked; public Action OnCopyLinkClicked; private const float AVATAR_SIZE = 52f; private const float AVATAR_X = 12f; private const float TEXT_X = 74f; private const float TEXT_W = 96f; private const float BTN_W = 60f; private const float BTN_H = 34f; private const float BTN_RIGHT = 12f; private FlightInfo _info; private Outline _outline; private bool _isFull; private RawImage _avatarRaw; private Transform _joinButtonTransform; public void Setup(FlightInfo info, Transform parent) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) _info = info; _isFull = info.MaxMembers > 0 && info.MemberCount >= info.MaxMembers; ((Component)this).transform.SetParent(parent, false); RectTransform val = ((Component)this).GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)this).gameObject.AddComponent(); } val.sizeDelta = new Vector2(250f, 80f); BuildUI(); LoadAvatar(); } private void BuildUI() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) Image val = ((Component)this).gameObject.AddComponent(); ((Graphic)val).color = UIFactory.CardFill; val.sprite = UIFactory.CompSprite; val.type = (Type)1; ((Graphic)val).raycastTarget = true; UIFactory.AddShadow(((Component)this).gameObject, UIFactory.ShadowC, new Vector2(2f, -2f)); _outline = ((Component)this).gameObject.AddComponent(); ((Shadow)_outline).effectColor = UIFactory.CardBorder; ((Shadow)_outline).effectDistance = new Vector2(2f, -2f); ((Component)this).gameObject.AddComponent(); CanvasGroup val2 = ((Component)this).gameObject.AddComponent(); if (_isFull) { val2.alpha = 0.5f; val2.interactable = false; } BuildAvatar(); BuildRoomName(); BuildSceneText(); BuildMetadata(); BuildJoinButton(); } private void BuildAvatar() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0159: 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_01a4: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Avatar", new Type[2] { typeof(RectTransform), typeof(Image) }); val.transform.SetParent(((Component)this).transform, false); RectTransform component = val.GetComponent(); component.anchorMin = new Vector2(0f, 0.5f); component.anchorMax = new Vector2(0f, 0.5f); component.pivot = new Vector2(0f, 0.5f); component.sizeDelta = new Vector2(52f, 52f); component.anchoredPosition = new Vector2(12f, 0f); Image component2 = val.GetComponent(); ((Graphic)component2).color = new Color(0.55f, 0.48f, 0.4f, 0.8f); component2.sprite = UIFactory.RoundSprite; component2.type = (Type)0; ((Graphic)component2).raycastTarget = false; GameObject val2 = new GameObject("Raw", new Type[2] { typeof(RectTransform), typeof(RawImage) }); val2.transform.SetParent(val.transform, false); RectTransform component3 = val2.GetComponent(); component3.anchorMin = Vector2.zero; component3.anchorMax = Vector2.one; component3.offsetMin = Vector2.zero; component3.offsetMax = Vector2.zero; _avatarRaw = val2.GetComponent(); ((Graphic)_avatarRaw).raycastTarget = false; ((Graphic)_avatarRaw).color = new Color(1f, 1f, 1f, 0f); } private void BuildRoomName() { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00be: 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) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) string displayName = _info.DisplayName; Plugin.Log.LogInfo((object)("[FlightCard] 显示名='" + displayName + "' | 原始 name='" + _info.Name + "' owner='" + _info.OwnerName + "' region='" + _info.PhotonRegion + "'")); TMP_Text val = UIFactory.MkText(((Component)this).transform, displayName, 16, (FontStyles)1, UIFactory.TextInk); val.alignment = (TextAlignmentOptions)513; val.overflowMode = (TextOverflowModes)1; val.enableWordWrapping = false; RectTransform component = ((Component)val).GetComponent(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(0f, 1f); component.pivot = new Vector2(0f, 1f); component.sizeDelta = new Vector2(96f, 24f); component.anchoredPosition = new Vector2(74f, -4f); } private void BuildSceneText() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0091: 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) TMP_Text val = UIFactory.MkText(((Component)this).transform, _info.SceneText, 12, (FontStyles)0, UIFactory.TextMuted); val.alignment = (TextAlignmentOptions)513; val.overflowMode = (TextOverflowModes)1; val.enableWordWrapping = false; RectTransform component = ((Component)val).GetComponent(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(0f, 1f); component.pivot = new Vector2(0f, 1f); component.sizeDelta = new Vector2(96f, 20f); component.anchoredPosition = new Vector2(74f, -30f); } private void BuildMetadata() { //IL_0041: 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_0091: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) string text = $"{_info.RegionText} · {_info.MemberCount}/{_info.MaxMembers}"; TMP_Text val = UIFactory.MkText(((Component)this).transform, text, 12, (FontStyles)0, UIFactory.TextMuted); val.alignment = (TextAlignmentOptions)513; val.overflowMode = (TextOverflowModes)1; val.enableWordWrapping = false; RectTransform component = ((Component)val).GetComponent(); component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(0f, 0f); component.pivot = new Vector2(0f, 0f); component.sizeDelta = new Vector2(96f, 20f); component.anchoredPosition = new Vector2(74f, 4f); } private void BuildJoinButton() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0104: 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_0143: 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_0163: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Expected O, but got Unknown //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Expected O, but got Unknown string text = (_isFull ? "满" : (string.IsNullOrEmpty(_info.RoomCode) ? "加入" : "码")); GameObject val = new GameObject("JoinBtn", new Type[3] { typeof(RectTransform), typeof(Image), typeof(Button) }); val.transform.SetParent(((Component)this).transform, false); RectTransform component = val.GetComponent(); component.anchorMin = new Vector2(1f, 0.5f); component.anchorMax = new Vector2(1f, 0.5f); component.pivot = new Vector2(1f, 0.5f); component.sizeDelta = new Vector2(60f, 34f); component.anchoredPosition = new Vector2(-12f, 0f); Image component2 = val.GetComponent(); ((Graphic)component2).color = UIFactory.BtnFill; component2.sprite = UIFactory.BtnSprite; component2.type = (Type)0; ((Graphic)component2).raycastTarget = true; Button component3 = val.GetComponent