Decompiled source of HowToFishDirectConnect v1.3.0
BepInEx/plugins/HowToFishDirect.dll
Decompiled a day 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.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using FishNet.Broadcast; using FishNet.Connection; using FishNet.Managing; using FishNet.Managing.Logging; using FishNet.Managing.Server; using FishNet.Object; using FishNet.Serializing; using FishNet.Transporting; using FishNet.Transporting.Multipass; using FishNet.Transporting.UTP; using HarmonyLib; using Microsoft.CodeAnalysis; using Steamworks; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("HowToFishDirect")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.3.0.0")] [assembly: AssemblyInformationalVersion("1.3.0")] [assembly: AssemblyProduct("HowToFishDirect")] [assembly: AssemblyTitle("HowToFishDirect")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.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 HowToFishDirect { public struct ClientHelloBroadcast : IBroadcast { public int Protocol; public ulong SteamId; public string InstallId; public string GameVersion; public string ModVersion; } public struct SessionInfoBroadcast : IBroadcast { public int Seed; public string HostGameVersion; public string HostModVersion; } public struct SessionRejectBroadcast : IBroadcast { public byte ReasonCode; public string HostVersion; public string ClientVersion; public string Reason; } public static class DirectNet { private sealed class Identity { public ulong SteamId; public string InstallId; } private static readonly Dictionary<int, Identity> ClientIdentities = new Dictionary<int, Identity>(); private static readonly HashSet<ulong> UsedSteamIds = new HashSet<ulong>(); private static readonly HashSet<ulong> UsedIdentities = new HashSet<ulong>(); private static NetworkManager _networkManager; private static bool _registered; private static PropertyInfo _seedProperty; private static bool _localClientStarted; private static bool _helloAcked; private static int _helloAttempts; private static float _lastHelloSent; private const int MaxHelloAttempts = 8; private const float HelloRetryInterval = 0.75f; private static byte _rejectCode; private static string _rejectHost = ""; private static string _rejectClient = ""; private static string _rejectText = ""; public static bool DirectSessionActive { get; internal set; } public static string LastRejectReason { get { if (_rejectCode == 1) { return Loc.T("游戏版本不一致:主机 " + _rejectHost + ",本机 " + _rejectClient, "Game version mismatch: host " + _rejectHost + ", you " + _rejectClient); } if (_rejectCode == 2) { return Loc.T("模组协议不兼容(主机 " + _rejectHost + ",本机 " + _rejectClient + "),请双方更新到同一版本", "Incompatible mod protocol (host " + _rejectHost + ", you " + _rejectClient + "); please update to the same version"); } return _rejectText; } } public static void RegisterSerializers() { GenericWriter<ClientHelloBroadcast>.SetWrite((Action<Writer, ClientHelloBroadcast>)delegate(Writer w, ClientHelloBroadcast v) { w.WriteInt32(v.Protocol); w.WriteUInt64(v.SteamId); w.WriteString(v.InstallId ?? ""); w.WriteString(v.GameVersion ?? ""); w.WriteString(v.ModVersion ?? ""); }); GenericReader<ClientHelloBroadcast>.SetRead((Func<Reader, ClientHelloBroadcast>)delegate(Reader r) { ClientHelloBroadcast result = new ClientHelloBroadcast { Protocol = r.ReadInt32() }; if (result.Protocol == 1) { result.SteamId = r.ReadUInt64(); result.InstallId = r.ReadStringAllocated(); result.GameVersion = r.ReadStringAllocated(); result.ModVersion = r.ReadStringAllocated(); } else { r.Skip(r.Remaining); } return result; }); GenericWriter<SessionInfoBroadcast>.SetWrite((Action<Writer, SessionInfoBroadcast>)delegate(Writer w, SessionInfoBroadcast v) { w.WriteInt32(v.Seed); w.WriteString(v.HostGameVersion ?? ""); w.WriteString(v.HostModVersion ?? ""); }); GenericReader<SessionInfoBroadcast>.SetRead((Func<Reader, SessionInfoBroadcast>)((Reader r) => new SessionInfoBroadcast { Seed = r.ReadInt32(), HostGameVersion = r.ReadStringAllocated(), HostModVersion = r.ReadStringAllocated() })); GenericWriter<SessionRejectBroadcast>.SetWrite((Action<Writer, SessionRejectBroadcast>)delegate(Writer w, SessionRejectBroadcast v) { w.WriteUInt8Unpacked(v.ReasonCode); w.WriteString(v.HostVersion ?? ""); w.WriteString(v.ClientVersion ?? ""); w.WriteString(v.Reason ?? ""); }); GenericReader<SessionRejectBroadcast>.SetRead((Func<Reader, SessionRejectBroadcast>)((Reader r) => new SessionRejectBroadcast { ReasonCode = r.ReadUInt8Unpacked(), HostVersion = r.ReadStringAllocated(), ClientVersion = r.ReadStringAllocated(), Reason = r.ReadStringAllocated() })); } public static void Register(NetworkManager nm) { if ((Object)(object)nm == (Object)null || (_networkManager == nm && _registered)) { return; } if ((Object)(object)_networkManager != (Object)null && _networkManager != nm) { try { _networkManager.ClientManager.OnClientConnectionState -= OnClientConnectionState; _networkManager.ServerManager.OnRemoteConnectionState -= OnRemoteConnectionState; } catch (Exception ex) { Plugin.LogVerbose("Detach old NetworkManager: " + ex.Message); } } _networkManager = nm; try { nm.ServerManager.RegisterBroadcast<ClientHelloBroadcast>((Action<NetworkConnection, ClientHelloBroadcast, Channel>)OnClientHello, false); nm.ClientManager.RegisterBroadcast<SessionInfoBroadcast>((Action<SessionInfoBroadcast, Channel>)OnSessionInfo); nm.ClientManager.RegisterBroadcast<SessionRejectBroadcast>((Action<SessionRejectBroadcast, Channel>)OnSessionReject); nm.ClientManager.OnClientConnectionState -= OnClientConnectionState; nm.ClientManager.OnClientConnectionState += OnClientConnectionState; nm.ServerManager.OnRemoteConnectionState -= OnRemoteConnectionState; nm.ServerManager.OnRemoteConnectionState += OnRemoteConnectionState; _registered = true; Plugin.LogInfo("Direct broadcast handlers registered."); } catch (Exception ex2) { _registered = false; Plugin.LogError("Register broadcast handlers failed: " + ex2); } } public static void Shutdown() { try { if ((Object)(object)_networkManager != (Object)null) { _networkManager.ClientManager.OnClientConnectionState -= OnClientConnectionState; _networkManager.ServerManager.OnRemoteConnectionState -= OnRemoteConnectionState; } } catch { } _registered = false; _networkManager = null; Clear(); } private static void OnClientConnectionState(ClientConnectionStateArgs args) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0033: 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_003a: Invalid comparison between Unknown and I4 if ((int)args.ConnectionState == 1) { _localClientStarted = false; _helloAcked = false; _helloAttempts = 0; if (DirectSessionActive) { Plugin.LogInfo("Direct session ended (local client stopped)."); DirectSessionActive = false; } } else if ((int)args.ConnectionState == 8) { _localClientStarted = true; _helloAcked = false; _helloAttempts = 0; SendHello(); } } private static void SendHello() { if (!DirectSessionActive) { return; } try { ulong num = LocalSteamId(); ClientHelloBroadcast clientHelloBroadcast = new ClientHelloBroadcast { SteamId = num, InstallId = Plugin.InstallId, GameVersion = (Application.version ?? ""), ModVersion = "1.3.0", Protocol = 1 }; _networkManager.ClientManager.Broadcast<ClientHelloBroadcast>(clientHelloBroadcast, (Channel)0); _helloAttempts++; _lastHelloSent = Time.unscaledTime; Plugin.LogInfo($"Sent client hello #{_helloAttempts} (SteamID {num}, install {Short(Plugin.InstallId)}, game {clientHelloBroadcast.GameVersion}, mod {clientHelloBroadcast.ModVersion})."); } catch (Exception ex) { Plugin.LogError("Failed to send client hello: " + ex); } } public static void TickHandshake() { if (_localClientStarted && !_helloAcked && _helloAttempts < 8 && !(Time.unscaledTime - _lastHelloSent < 0.75f)) { SendHello(); } } private static void OnRemoteConnectionState(NetworkConnection conn, RemoteConnectionStateArgs args) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (conn == (NetworkConnection)null || (int)args.ConnectionState != 0) { return; } if (ClientIdentities.TryGetValue(conn.ClientId, out var value)) { ClientIdentities.Remove(conn.ClientId); if (value.SteamId != 0L) { UsedSteamIds.Remove(value.SteamId); UsedIdentities.Remove(value.SteamId); } } Patches.RemovePending(conn.ClientId); try { if ((Object)(object)Server.Instance != (Object)null && ((NetworkBehaviour)Server.Instance).IsServerInitialized) { SaveManager.SaveServer(true); Plugin.LogInfo("Saved host world after a client disconnected."); } } catch (Exception ex) { Plugin.LogVerbose("Save after disconnect failed: " + ex.Message); } } private static void OnClientHello(NetworkConnection conn, ClientHelloBroadcast msg, Channel channel) { if (!DirectSessionActive) { return; } try { if (conn == (NetworkConnection)null) { return; } string text = Application.version ?? ""; if (msg.Protocol != 1) { Plugin.LogWarn($"Rejecting client {conn.ClientId}: mod protocol {msg.Protocol} vs host {1}."); try { _networkManager.ServerManager.Broadcast<SessionRejectBroadcast>(conn, new SessionRejectBroadcast { ReasonCode = 2, HostVersion = 1.ToString(), ClientVersion = msg.Protocol.ToString() }, false, (Channel)0); conn.Kick((KickReason)6, (LoggingType)2, "Direct connect protocol mismatch."); return; } catch (Exception ex) { Plugin.LogWarn("Kick failed: " + ex.Message); return; } } if (ClientIdentities.ContainsKey(conn.ClientId)) { Plugin.LogVerbose($"Duplicate hello from client {conn.ClientId}; re-sending session info."); if (Patches.HasPendingSpawn(conn.ClientId)) { Patches.OnIdentityReady(conn); } try { SendSessionInfo(conn); return; } catch (Exception ex2) { Plugin.LogWarn("Failed to re-send session info: " + ex2.Message); return; } } if (!string.Equals(msg.GameVersion, text, StringComparison.Ordinal)) { Plugin.LogWarn(string.Format("Rejecting client {0}: game {1} vs host {2} (peer mod {3}, host mod {4}).", conn.ClientId, msg.GameVersion, text, msg.ModVersion, "1.3.0")); try { _networkManager.ServerManager.Broadcast<SessionRejectBroadcast>(conn, new SessionRejectBroadcast { ReasonCode = 1, HostVersion = text, ClientVersion = msg.GameVersion }, false, (Channel)0); conn.Kick((KickReason)6, (LoggingType)2, "Direct connect game version mismatch (peer " + msg.GameVersion + " vs host " + text + ")."); return; } catch (Exception ex3) { Plugin.LogWarn("Kick failed: " + ex3.Message); return; } } if (!string.Equals(msg.ModVersion, "1.3.0", StringComparison.Ordinal)) { Plugin.LogInfo(string.Format("Client {0} is running mod {1} (host {2}); accepted (mod versions do not need to match).", conn.ClientId, msg.ModVersion, "1.3.0")); } if (conn.IsLocalClient) { ulong num = ResolveSteamId(conn); ClientIdentities[conn.ClientId] = new Identity { SteamId = num, InstallId = msg.InstallId }; Plugin.LogInfo($"Host local client identity {num}."); Patches.OnIdentityReady(conn); try { SendSessionInfo(conn); return; } catch (Exception ex4) { Plugin.LogWarn("Failed to send session info: " + ex4.Message); return; } } ulong num2; if (msg.SteamId != 0L && UsedSteamIds.Add(msg.SteamId)) { num2 = msg.SteamId; } else { num2 = SyntheticFromInstall(msg.InstallId); if (msg.SteamId != 0L) { Plugin.LogWarn($"Client {conn.ClientId} reports SteamID {msg.SteamId} which is already in use; using install-based id {num2}."); } else { Plugin.LogWarn($"Client {conn.ClientId} reported no SteamID; using install-based id {num2}."); } } if (!UsedIdentities.Add(num2)) { ulong num3 = SyntheticFromInstall(msg.InstallId + "#" + conn.ClientId); int num4 = 1; while (!UsedIdentities.Add(num3) && num4 <= 1000) { num3 = SyntheticFromInstall(msg.InstallId + "#" + conn.ClientId + "#" + num4); num4++; } Plugin.LogWarn($"Identity {num2} is already in use; assigning {num3} to client {conn.ClientId} instead."); num2 = num3; } ClientIdentities[conn.ClientId] = new Identity { SteamId = num2, InstallId = msg.InstallId }; Plugin.LogInfo($"Host accepted client {conn.ClientId}: SteamID {msg.SteamId} -> identity {num2}."); try { SendSessionInfo(conn); } catch (Exception ex5) { Plugin.LogWarn("Failed to send session info: " + ex5.Message); } Patches.OnIdentityReady(conn); } catch (Exception ex6) { Plugin.LogError("OnClientHello failed: " + ex6); } } private static void SendSessionInfo(NetworkConnection conn) { _networkManager.ServerManager.Broadcast<SessionInfoBroadcast>(conn, new SessionInfoBroadcast { Seed = GameInfo.Seed, HostGameVersion = (Application.version ?? ""), HostModVersion = "1.3.0" }, false, (Channel)0); } private static void OnSessionInfo(SessionInfoBroadcast msg, Channel channel) { try { _helloAcked = true; SetSeed(msg.Seed); Plugin.LogInfo($"Received session info from host (seed {msg.Seed}, game {msg.HostGameVersion}, mod {msg.HostModVersion})."); } catch (Exception ex) { Plugin.LogError("OnSessionInfo failed: " + ex); } } private static void OnSessionReject(SessionRejectBroadcast msg, Channel channel) { _helloAcked = true; _rejectCode = msg.ReasonCode; _rejectHost = msg.HostVersion ?? ""; _rejectClient = msg.ClientVersion ?? ""; _rejectText = msg.Reason ?? ""; Plugin.LogWarn("Host rejected the connection: " + LastRejectReason); } private static void SetSeed(int seed) { try { if (_seedProperty == null) { _seedProperty = typeof(GameInfo).GetProperty("Seed", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } if (_seedProperty == null || !_seedProperty.CanWrite) { Plugin.LogWarn("GameInfo.Seed is not writable; seed not synced."); } else { _seedProperty.SetValue(null, seed, null); } } catch (Exception ex) { Plugin.LogWarn("Failed to set GameInfo.Seed: " + ex.Message); } } public static bool HasIdentity(NetworkConnection conn) { if (conn != (NetworkConnection)null) { return ClientIdentities.ContainsKey(conn.ClientId); } return false; } public static ulong ResolveSteamId(NetworkConnection conn) { if (conn == (NetworkConnection)null) { ulong num = LocalSteamId(); if (num == 0L) { return SyntheticFromInstall(Plugin.InstallId); } return num; } if (conn.IsLocalClient) { ulong num2 = LocalSteamId(); if (num2 == 0L) { return SyntheticFromInstall(Plugin.InstallId); } return num2; } if (ClientIdentities.TryGetValue(conn.ClientId, out var value) && value.SteamId != 0L) { return value.SteamId; } return SyntheticFromInstall(Plugin.InstallId + ":pending:" + conn.ClientId); } public static ulong SyntheticFromInstall(string installId) { ulong num = Fnv1a64(installId ?? ""); return 0x1000000000000000L | (num & 0xFFFFFFFFFFFFFFFL); } public static void ReserveHostIdentity() { try { ulong num = LocalSteamId(); if (num != 0L) { UsedSteamIds.Add(num); UsedIdentities.Add(num); } UsedIdentities.Add(SyntheticFromInstall(Plugin.InstallId)); } catch (Exception ex) { Plugin.LogVerbose("ReserveHostIdentity failed: " + ex.Message); } } private static ulong Fnv1a64(string s) { ulong num = 14695981039346656037uL; foreach (char c in s) { num ^= c; num *= 1099511628211L; } return num; } private static ulong LocalSteamId() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) try { return SteamUser.GetSteamID().m_SteamID; } catch { return 0uL; } } private static string Short(string s) { if (string.IsNullOrEmpty(s)) { return ""; } if (s.Length > 8) { return s.Substring(0, 8); } return s; } public static void Clear() { ClientIdentities.Clear(); UsedSteamIds.Clear(); UsedIdentities.Clear(); _localClientStarted = false; _helloAcked = false; _helloAttempts = 0; DirectSessionActive = false; } public static void ResetRejectReason() { _rejectCode = 0; _rejectHost = ""; _rejectClient = ""; _rejectText = ""; } } public class DirectOverlay : MonoBehaviour { private enum Page { Home, Host, Join, Config } private const int MaxHistory = 8; private const float TopBarH = 58f; private const float TransitionTime = 0.18f; private UiTheme _ui; private int _uiFontSize = -1; private Rect _window = new Rect(20f, 20f, 560f, 664f); private bool _positionInitialized; private bool _visible = true; private bool _mouseInWindow; private float _drawW = 560f; private float _drawH = 664f; private Page _page; private float _pageAnim = 1f; private string _port = "7777"; private int _maxPlayers = 8; private string _joinIp = "127.0.0.1"; private string _joinPort = "7777"; private Vector2 _scroll; private readonly Dictionary<string, float> _hover = new Dictionary<string, float>(); private float _pulse; private float _toastAge = 99f; private string _toastText = ""; private int _toastKind; private string _lastStatusSeen = ""; private readonly List<string> _ipLabels = new List<string>(); private readonly List<string> _ipValues = new List<string>(); private float _ipRefreshTimer; private bool _saveListLoaded; private string _selectedSaveName = ""; private readonly List<string> _history = new List<string>(); private string _pendingHistoryIp; private int _pendingHistoryPort; private bool _awaitingKey; private string _hotKey; private bool _lastChinese; private Coroutine _watchdog; private static readonly string[] VirtualHints = new string[15] { "radmin", "zerotier", "tailscale", "hamachi", "vpn", "tap-", "tap ", "wsl", "hyper-v", "vethernet", "virtualbox", "vmware", "docker", "loopback", "虚拟" }; private static bool InMenu { get { try { return MainMenuManager.IsInMenu; } catch { return false; } } } private void Awake() { try { if (Plugin.CfgPort != null) { _port = Plugin.CfgPort.Value.ToString(); } if (Plugin.CfgMaxPlayers != null) { _maxPlayers = Plugin.CfgMaxPlayers.Value; } if (Plugin.CfgJoinIp != null) { _joinIp = Plugin.CfgJoinIp.Value; } if (Plugin.CfgShowOverlay != null) { _visible = Plugin.CfgShowOverlay.Value; } } catch { } LoadHistory(); RefreshLocalIps(); _lastChinese = Loc.Chinese; } private void OnDestroy() { StopWatchdog(); try { _ui?.Dispose(); } catch { } _ui = null; } private void Update() { _pulse += Time.unscaledDeltaTime; bool chinese = Loc.Chinese; if (chinese != _lastChinese) { _lastChinese = chinese; _toastText = ""; _toastAge = 99f; } _ipRefreshTimer += Time.unscaledDeltaTime; if (_ipRefreshTimer >= 3f) { _ipRefreshTimer = 0f; RefreshLocalIps(); } _pageAnim = Mathf.MoveTowards(_pageAnim, 1f, Time.unscaledDeltaTime / 0.18f); if (_toastAge < 99f) { _toastAge += Time.unscaledDeltaTime; } WatchStatus(); } private void WatchStatus() { string lastStatus = DirectTransport.LastStatus; if (!string.Equals(lastStatus, _lastStatusSeen, StringComparison.Ordinal)) { _lastStatusSeen = lastStatus; if (!string.IsNullOrEmpty(lastStatus)) { ShowToast(lastStatus, ToastKind(lastStatus)); } } } private static int ToastKind(string s) { if (Contains(s, "错误") || Contains(s, "失败") || Contains(s, "异常") || Contains(s, "超时") || Contains(s, "拒绝") || Contains(s, "error", ignoreCase: true) || Contains(s, "fail", ignoreCase: true) || Contains(s, "exception", ignoreCase: true) || Contains(s, "reject", ignoreCase: true) || Contains(s, "timeout", ignoreCase: true) || Contains(s, "invalid", ignoreCase: true) || Contains(s, "not found", ignoreCase: true)) { return 2; } if (Contains(s, "已") || Contains(s, "copied", ignoreCase: true) || Contains(s, "hosting", ignoreCase: true) || Contains(s, "filled", ignoreCase: true) || Contains(s, "restored", ignoreCase: true)) { return 1; } return 0; } private static bool Contains(string s, string sub, bool ignoreCase = false) { if (string.IsNullOrEmpty(s)) { return false; } return s.IndexOf(sub, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal) >= 0; } private void OnGUI() { //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: 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_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Expected O, but got Unknown //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) try { EnsureUi(); HandleKeyCapture(); HandleToggleKey(); if (!_visible) { _hotKey = null; return; } if (!_positionInitialized) { _positionInitialized = true; try { float num = Mathf.Min(((Rect)(ref _window)).width, Mathf.Max(1f, (float)Screen.width - 20f)); float num2 = Mathf.Min(((Rect)(ref _window)).height, Mathf.Max(1f, (float)Screen.height - 20f)); ((Rect)(ref _window)).x = Mathf.Max(0f, (float)Screen.width - num - 16f); ((Rect)(ref _window)).y = Mathf.Max(0f, ((float)Screen.height - num2) * 0.5f); } catch { } } Rect window = _window; ((Rect)(ref window)).width = Mathf.Max(1f, Mathf.Min(((Rect)(ref _window)).width, (float)Screen.width - 20f)); ((Rect)(ref window)).height = Mathf.Max(1f, Mathf.Min(((Rect)(ref _window)).height, (float)Screen.height - 20f)); ((Rect)(ref window)).x = Mathf.Clamp(((Rect)(ref _window)).x, 0f, Mathf.Max(0f, (float)Screen.width - ((Rect)(ref window)).width)); ((Rect)(ref window)).y = Mathf.Clamp(((Rect)(ref _window)).y, 0f, Mathf.Max(0f, (float)Screen.height - ((Rect)(ref window)).height)); _drawW = ((Rect)(ref window)).width; _drawH = ((Rect)(ref window)).height; Vector2 val = (Vector2)((Event.current != null) ? Event.current.mousePosition : new Vector2(-1000f, -1000f)); _mouseInWindow = ((Rect)(ref window)).Contains(val); Rect val2 = GUI.Window(1213482033, window, new WindowFunction(DrawWindow), "", _ui.Window); ((Rect)(ref _window)).x = Mathf.Clamp(((Rect)(ref val2)).x, 0f, Mathf.Max(0f, (float)Screen.width - 40f)); ((Rect)(ref _window)).y = Mathf.Clamp(((Rect)(ref val2)).y, 0f, Mathf.Max(0f, (float)Screen.height - 40f)); } catch (Exception ex) { Plugin.LogError("OnGUI failed: " + ex); } } private void EnsureUi() { int num = 16; try { if (Plugin.CfgFontSize != null) { num = Mathf.Clamp(Plugin.CfgFontSize.Value, 10, 28); } } catch { } if (_ui == null || num != _uiFontSize) { try { _ui?.Dispose(); } catch { } _uiFontSize = num; _ui = new UiTheme(num); } } private void DrawWindow(int id) { //IL_0031: 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_0051: 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) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Invalid comparison between Unknown and I4 //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: 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_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: 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_01c1: 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_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Invalid comparison between Unknown and I4 float drawW = _drawW; float drawH = _drawH; DrawTopBar(drawW); GUILayout.BeginArea(new Rect(0f, 58f, drawW, Mathf.Max(1f, drawH - 58f))); float num = EaseOutCubic(Mathf.Clamp01(_pageAnim)); Color color = GUI.color; GUI.color = new Color(1f, 1f, 1f, Mathf.Clamp01(num * 1.2f)); _scroll = GUILayout.BeginScrollView(_scroll, false, false, GUIStyle.none, _ui.Scrollbar, GUIStyle.none, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Space(18f); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUILayout.Space(14f + (1f - num) * 14f); try { switch (_page) { case Page.Home: DrawHome(); break; case Page.Host: DrawHost(); break; case Page.Join: DrawJoin(); break; case Page.Config: DrawConfig(); break; } } catch (Exception ex) { Plugin.LogError("Page draw failed: " + ex); } GUILayout.Space(18f); GUILayout.EndVertical(); GUILayout.Space(18f); GUILayout.EndHorizontal(); Event current = Event.current; bool num2 = _mouseInWindow && current != null && (int)current.type == 6; Vector2 val = default(Vector2); if (num2) { val = current.delta; current.delta = new Vector2(val.x, val.y * ScrollMultiplier()); } GUILayout.EndScrollView(); if (num2) { current.delta = val; } GUI.color = color; GUILayout.EndArea(); if (Event.current != null && (int)Event.current.type == 1) { _hotKey = null; } DrawToast(drawW, drawH); GUI.DragWindow(new Rect(0f, 0f, drawW, 58f)); } private void DrawTopBar(float W) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_015a: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0126: 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_01ef: 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) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0282: 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_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: 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_030f: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_0364: 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_03a1: Unknown result type (might be due to invalid IL or missing references) //IL_03e6: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_042d: Unknown result type (might be due to invalid IL or missing references) float num = 18f; if (_page != Page.Home) { Rect r = default(Rect); ((Rect)(ref r))..ctor(num, 12f, 34f, 34f); if (IconButton(r, "top.back", IconKind.ChevronLeft)) { Go(Page.Home); } num += 46f; } else { Rect r2 = default(Rect); ((Rect)(ref r2))..ctor(num, 14f, 30f, 30f); _ui.Fill(r2, 15f, _ui.Primary); _ui.Ring(new Rect(((Rect)(ref r2)).x + 8f, ((Rect)(ref r2)).y + 8f, 14f, 14f), 7f, new Color(1f, 1f, 1f, 0.92f)); num += 42f; } string s = PageTitle(_page); string text = PageCaption(_page); float num2 = Mathf.Max(80f, W - num - 214f); if (string.IsNullOrEmpty(text)) { _ui.DrawText(new Rect(num, 16f, num2, 26f), s, _ui.Title); } else { _ui.DrawText(new Rect(num, 5f, num2, 26f), s, _ui.Title); _ui.DrawText(new Rect(num, 31f, num2, 18f), text, _ui.Caption); } string s2 = ToggleKeyName(); Vector2 val = _ui.TextSize(s2, _ui.Caption); string s3 = Loc.T("显示/隐藏", "show/hide"); Vector2 val2 = _ui.TextSize(s3, _ui.Caption); float num3 = val.x + 18f; float num4 = num3 + 8f + val2.x + 20f; Rect r3 = default(Rect); ((Rect)(ref r3))..ctor(W - 18f - 30f - 12f - num4, 15f, num4, 28f); _ui.Fill(r3, 14f, new Color(1f, 1f, 1f, 0.05f)); _ui.Ring(r3, 14f, _ui.Border); Rect r4 = default(Rect); ((Rect)(ref r4))..ctor(((Rect)(ref r3)).x + 8f, ((Rect)(ref r3)).y + 5f, num3, 18f); _ui.Fill(r4, 5f, new Color(1f, 1f, 1f, 0.1f)); _ui.Ring(r4, 5f, _ui.BorderHi); float x = _ui.TextSize(s2, _ui.Caption).x; _ui.DrawText(new Rect(((Rect)(ref r4)).center.x - x * 0.5f, ((Rect)(ref r4)).y, x + 2f, ((Rect)(ref r4)).height), s2, _ui.Caption, _ui.Text); _ui.DrawText(new Rect(((Rect)(ref r4)).xMax + 6f, ((Rect)(ref r3)).y, val2.x + 6f, ((Rect)(ref r3)).height), s3, _ui.Caption); Rect r5 = default(Rect); ((Rect)(ref r5))..ctor(W - 18f - 30f, 14f, 30f, 30f); if (IconButton(r5, "top.close", IconKind.Close)) { HidePanel(); } _ui.Fill(new Rect(16f, 57f, W - 32f, 1f), 0f, _ui.Divider); } private static string PageTitle(Page p) { return p switch { Page.Host => Loc.T("创建房间", "Create Room"), Page.Join => Loc.T("加入房间", "Join Room"), Page.Config => Loc.T("模组配置", "Mod Settings"), _ => Loc.T("How to Fish · 直连", "How to Fish · Direct"), }; } private static string PageCaption(Page p) { return p switch { Page.Host => Loc.T("作为主机开一局", "Host a game"), Page.Join => Loc.T("连接到好友的世界", "Join a friend's world"), Page.Config => Loc.T("外观、行为与诊断", "Appearance, behavior & diagnostics"), _ => Loc.T("IP 直连联机 · 无需 Steam", "IP direct connect · no Steam"), }; } private void DrawHome() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) DrawStatusCard(); GUILayout.Space(16f); Rect r = Row(20f); _ui.DrawText(r, Loc.T("选择一项开始", "Pick one to start"), _ui.Muted); GUILayout.Space(8f); NavCard("home.host", IconKind.Plus, _ui.Primary, Loc.T("创建房间", "Create Room"), Loc.T("作为主机开一局,把本机 IP 发给朋友", "Host a game and send your IP to a friend"), enabled: true, Page.Host); GUILayout.Space(12f); NavCard("home.join", IconKind.ArrowRight, _ui.Amber, Loc.T("加入房间", "Join Room"), Loc.T("输入好友的 IP,进入他的世界", "Enter a friend's IP to join their world"), enabled: true, Page.Join); GUILayout.Space(12f); NavCard("home.config", IconKind.Sliders, _ui.Blue, Loc.T("模组配置", "Mod Settings"), Loc.T("字体、滚轮、快捷键与诊断信息", "Font, scroll, hotkey & diagnostics"), enabled: true, Page.Config); GUILayout.Space(12f); DrawQuickGuide(); if (DirectNet.DirectSessionActive) { GUILayout.Space(18f); Rect r2 = Row(48f); if (PrimaryButton(r2, Loc.T("断开连接", "Disconnect"), IconKind.Power, _ui.Danger, _ui.DangerHi, _ui.OnDanger, enabled: true, "home.disconnect")) { StopWatchdog(); DirectTransport.Disconnect(); } } GUILayout.Space(18f); DrawFooter(); } private void DrawStatusCard() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) Rect r = Row(68f); _ui.Fill(r, 12f, _ui.Card); _ui.Ring(r, 12f, _ui.Border); Color c = StatusColor(); float a = ((DirectNet.DirectSessionActive && !DirectTransport.SessionReady) ? (0.4f + 0.6f * (0.5f + 0.5f * Mathf.Sin(_pulse * 5f))) : 1f); Rect r2 = default(Rect); ((Rect)(ref r2))..ctor(((Rect)(ref r)).x + 18f, ((Rect)(ref r)).center.y - 7f, 14f, 14f); _ui.Fill(r2, 7f, UiTheme.WithA(c, a)); _ui.DrawText(new Rect(((Rect)(ref r)).x + 44f, ((Rect)(ref r)).y + 12f, ((Rect)(ref r)).width - 60f, 24f), StatusTitle(), _ui.CardTitle); _ui.DrawText(new Rect(((Rect)(ref r)).x + 44f, ((Rect)(ref r)).y + 37f, ((Rect)(ref r)).width - 60f, 20f), StatusDetail(), _ui.Muted); } private string StatusTitle() { if (!Plugin.Ready) { return Loc.T("初始化失败", "Initialization failed"); } if (!string.IsNullOrEmpty(DirectNet.LastRejectReason)) { return Loc.T("连接被拒绝", "Connection rejected"); } if (DirectTransport.SessionReady) { return Loc.T("已连接", "Connected"); } if (DirectNet.DirectSessionActive) { return Loc.T("连接中…", "Connecting…"); } return Loc.T("未连接", "Not connected"); } private string StatusDetail() { if (!Plugin.Ready) { return Loc.T("补丁或序列化器未生效(本模组适配 1.1.3)", "Patches or serializers failed (this mod targets 1.1.3)"); } if (!string.IsNullOrEmpty(DirectNet.LastRejectReason)) { return DirectNet.LastRejectReason; } if (DirectTransport.SessionReady) { return Loc.T("已进入房间,按 " + ToggleKeyName() + " 可隐藏面板", "In the room. Press " + ToggleKeyName() + " to hide the panel"); } if (DirectNet.DirectSessionActive) { return Loc.T("正在与主机建立连接…", "Connecting to the host…"); } if (!InMenu) { return Loc.T("游戏中(回到主菜单才能创建/加入)", "In game (return to the main menu to host/join)"); } return Loc.T("在主菜单选择「创建房间」或「加入房间」", "Choose Create Room or Join Room in the main menu"); } private Color StatusColor() { //IL_000d: 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_0038: 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_004b: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.Ready) { return _ui.Danger; } if (!string.IsNullOrEmpty(DirectNet.LastRejectReason)) { return _ui.Danger; } if (DirectTransport.SessionReady) { return _ui.Primary; } if (DirectNet.DirectSessionActive) { return _ui.Amber; } return _ui.TextDim; } private void DrawFooter() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) Rect r = Row(22f); string s = Loc.T("HowToFishDirect v1.3.0\u3000·\u3000适配游戏 1.1.3", "HowToFishDirect v1.3.0 · for game 1.1.3"); _ui.DrawText(r, s, _ui.Caption); } private void DrawQuickGuide() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_014f: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) Rect r = Row(104f); _ui.Fill(r, 12f, new Color(1f, 1f, 1f, 0.025f)); _ui.Ring(r, 12f, _ui.Divider); _ui.DrawText(new Rect(((Rect)(ref r)).x + 16f, ((Rect)(ref r)).y + 12f, ((Rect)(ref r)).width - 32f, 20f), Loc.T("快速上手", "Quick start"), _ui.Section); string[] array = new string[3] { Loc.T("主机:进入「创建房间」,点一下复制本机 IP", "Host: open Create Room and click to copy your IP"), Loc.T("把 IP 与端口发给朋友(同一虚拟局域网最省事)", "Send the IP and port to your friend (a virtual LAN is easiest)"), Loc.T("朋友:进入「加入房间」,填入 IP 后点「加入房间」", "Friend: open Join Room, enter the IP and click Join Room") }; Rect r2 = default(Rect); for (int i = 0; i < array.Length; i++) { float num = ((Rect)(ref r)).y + 38f + (float)i * 24f; ((Rect)(ref r2))..ctor(((Rect)(ref r)).x + 18f, num + 2f, 18f, 18f); _ui.Fill(r2, 9f, UiTheme.WithA(_ui.Primary, 0.18f)); string s = (i + 1).ToString(); float x = _ui.TextSize(s, _ui.Caption).x; _ui.DrawText(new Rect(((Rect)(ref r2)).center.x - x * 0.5f, ((Rect)(ref r2)).y, x + 2f, ((Rect)(ref r2)).height), s, _ui.Caption, _ui.Primary); _ui.DrawText(new Rect(((Rect)(ref r)).x + 46f, num, ((Rect)(ref r)).width - 62f, 22f), array[i], _ui.Muted); } } private void DrawHost() { //IL_0065: 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_0072: 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_0129: 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_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_018a: 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_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) bool inMenu = InMenu; bool flag = CanAct(); if (!flag) { Banner(inMenu ? Loc.T("补丁未生效,无法创建房间", "Patches not applied — cannot host") : Loc.T("仅能在主菜单创建房间,请先回到主菜单", "You can only host from the main menu"), warn: true); } Section(Loc.T("存档", "Save")); if (inMenu) { EnsureSaveList(force: false); DrawSaveSection(); } else { Rect r = Row(26f); _ui.DrawText(r, Loc.T("当前:", "Current: ") + SaveName() + Loc.T("\u3000(游戏中不可更改)", " (cannot change in game)"), _ui.Muted); } Section(Loc.T("房间设置", "Room")); FieldRow(Loc.T("UDP 端口", "UDP port"), ref _port, "7777", 6); _maxPlayers = StepperRow(Loc.T("总人数(含主机)", "Max players (incl. host)"), _maxPlayers, 1, 8, "host.max"); GUILayout.Space(12f); Rect r2 = Row(52f); if (PrimaryButton(r2, Loc.T("创建房间", "Create Room"), IconKind.Plus, _ui.Primary, _ui.PrimaryHi, _ui.OnPrimary, flag, "host.create")) { StartHost(); } Section(Loc.T("本机 IP(点击复制)", "Local IP (click to copy)")); Rect val = Row(24f); _ui.DrawText(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width - 88f, 24f), Loc.T("把其中一个发给朋友", "Send one to your friend"), _ui.Caption); Rect r3 = default(Rect); ((Rect)(ref r3))..ctor(((Rect)(ref val)).xMax - 84f, ((Rect)(ref val)).y, 84f, 24f); if (GhostButton(r3, Loc.T("刷新", "Refresh"), "host.refresh", enabled: true)) { RefreshLocalIps(); } GUILayout.Space(4f); DrawIpList(); GUILayout.Space(14f); Rect r4 = Row(46f); _ui.DrawText(r4, Loc.T("提示:若双方不在同一局域网,请用内网穿透工具(如 Radmin / ZeroTier)后再填入其 IP。", "Tip: if you are not on the same LAN, use a virtual-LAN tool (Radmin / ZeroTier) and enter that IP."), _ui.Wrap); } private void DrawIpList() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) if (_ipValues.Count == 0) { Rect r = Row(24f); _ui.DrawText(r, Loc.T("(未检测到可用 IP)", "(no usable IP found)"), _ui.Muted); return; } for (int i = 0; i < _ipValues.Count; i++) { string text = _ipValues[i]; Rect r2 = Row(36f); bool hovered = ((Rect)(ref r2)).Contains(Event.current.mousePosition); float num = Hover("ip." + text, hovered, 10f); _ui.Fill(r2, 8f, new Color(1f, 1f, 1f, 0.04f * num)); _ui.Icon(new Rect(((Rect)(ref r2)).x + 10f, ((Rect)(ref r2)).center.y - 8f, 16f, 16f), IconKind.Copy, Color.Lerp(_ui.TextDim, _ui.Primary, num)); _ui.DrawText(new Rect(((Rect)(ref r2)).x + 34f, ((Rect)(ref r2)).y, ((Rect)(ref r2)).width - 120f, ((Rect)(ref r2)).height), _ipLabels[i], _ui.Body); _ui.DrawText(new Rect(((Rect)(ref r2)).xMax - 96f, ((Rect)(ref r2)).y, 86f, ((Rect)(ref r2)).height), Loc.T("点击复制", "click to copy"), _ui.Caption, UiTheme.WithA(_ui.TextMuted, 0.4f + 0.6f * num)); if (Click(r2, enabled: true, "ip." + text)) { CopyToClipboard(text); } } } private void DrawJoin() { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_00df: Unknown result type (might be due to invalid IL or missing references) bool flag = CanAct(); if (!flag) { Banner(InMenu ? Loc.T("补丁未生效,无法加入房间", "Patches not applied — cannot join") : Loc.T("仅能在主菜单加入房间,请先回到主菜单", "You can only join from the main menu"), warn: true); } Section(Loc.T("连接信息", "Connection")); FieldRow(Loc.T("主机 IP", "Host IP"), ref _joinIp, Loc.T("例如 192.168.0.10 或域名", "e.g. 192.168.0.10 or a domain"), 128); FieldRow(Loc.T("UDP 端口", "UDP port"), ref _joinPort, "7777", 6); GUILayout.Space(12f); Rect r = Row(52f); if (PrimaryButton(r, Loc.T("加入房间", "Join Room"), IconKind.ArrowRight, _ui.Amber, _ui.AmberHi, _ui.OnAmber, flag, "join.connect")) { StartJoin(); } Section(Loc.T("最近房间", "Recent rooms")); DrawHistory(); } private void DrawHistory() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_012e: 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_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: 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_0220: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) Rect val = Row(24f); _ui.DrawText(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width - 76f, 24f), (_history.Count == 0) ? Loc.T("暂无记录", "No records") : Loc.T("共 " + _history.Count + " 条,点击填入", _history.Count + " entries, click to fill"), _ui.Muted); Rect r = default(Rect); ((Rect)(ref r))..ctor(((Rect)(ref val)).xMax - 68f, ((Rect)(ref val)).y, 68f, 24f); if (GhostButton(r, Loc.T("清空", "Clear"), "join.clear", _history.Count > 0)) { _history.Clear(); SaveHistory(); } GUILayout.Space(4f); if (_history.Count == 0) { Rect r2 = Row(24f); _ui.DrawText(r2, Loc.T("成功加入一次后会自动记录。", "Saved automatically after you join a room once."), _ui.Caption); return; } for (int i = 0; i < _history.Count; i++) { string text = _history[i]; Rect r3 = Row(36f); bool hovered = ((Rect)(ref r3)).Contains(Event.current.mousePosition); float num = Hover("hist." + text, hovered, 10f); _ui.Fill(r3, 8f, new Color(1f, 1f, 1f, 0.04f * num)); _ui.Icon(new Rect(((Rect)(ref r3)).x + 10f, ((Rect)(ref r3)).center.y - 8f, 16f, 16f), IconKind.ArrowRight, Color.Lerp(_ui.TextDim, _ui.Amber, num)); _ui.DrawText(new Rect(((Rect)(ref r3)).x + 34f, ((Rect)(ref r3)).y, ((Rect)(ref r3)).width - 110f, ((Rect)(ref r3)).height), text, _ui.Body); _ui.DrawText(new Rect(((Rect)(ref r3)).xMax - 80f, ((Rect)(ref r3)).y, 70f, ((Rect)(ref r3)).height), Loc.T("填入", "fill"), _ui.Caption, UiTheme.WithA(_ui.TextMuted, 0.4f + 0.6f * num)); if (Click(r3, enabled: true, "hist." + text)) { ApplyHistory(text); } } } private void DrawConfig() { //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) Section(Loc.T("外观", "Appearance")); int num = ((Plugin.CfgFontSize != null) ? Plugin.CfgFontSize.Value : 16); int num2 = StepperRow(Loc.T("字号", "Font size"), num, 10, 28, "cfg.font"); if (num2 != num && Plugin.CfgFontSize != null) { Plugin.CfgFontSize.Value = num2; } int num3 = ((Plugin.CfgScrollSpeed != null) ? Plugin.CfgScrollSpeed.Value : 3); int num4 = StepperRow(Loc.T("滚轮速度", "Scroll speed"), num3, 1, 8, "cfg.scroll"); if (num4 != num3 && Plugin.CfgScrollSpeed != null) { Plugin.CfgScrollSpeed.Value = num4; } Section(Loc.T("行为", "Behavior")); bool flag = Plugin.CfgShowOverlay != null && Plugin.CfgShowOverlay.Value; bool flag2 = ToggleRow("cfg.show", Loc.T("显示面板", "Show panel"), Loc.T("关闭后可用快捷键再次打开", "Reopen with the hotkey after closing"), flag, enabled: true); if (flag2 != flag) { if (Plugin.CfgShowOverlay != null) { Plugin.CfgShowOverlay.Value = flag2; } _visible = flag2; if (!flag2) { _awaitingKey = false; } } bool flag3 = Plugin.CfgVerbose != null && Plugin.CfgVerbose.Value; bool flag4 = ToggleRow("cfg.verbose", Loc.T("详细日志", "Verbose log"), Loc.T("在 BepInEx 日志中记录更多调试信息", "Write extra debug info to the BepInEx log"), flag3, enabled: true); if (flag4 != flag3 && Plugin.CfgVerbose != null) { Plugin.CfgVerbose.Value = flag4; } KeyCaptureRow(); Section(Loc.T("关于", "About")); AboutRow(Loc.T("模组版本", "Mod version"), "v1.3.0"); AboutRow(Loc.T("适配游戏", "Game version"), "1.1.3" + Loc.T("(当前 ", " (current ") + Application.version + Loc.T(")", ")")); AboutRow(Loc.T("补丁状态", "Patch status"), Plugin.PatchesCriticalOk ? Loc.T("正常", "OK") : Loc.T("异常", "Failed"), Plugin.PatchesCriticalOk ? _ui.Primary : _ui.Danger); AboutRow(Loc.T("本机 ID", "Install ID"), ShortId(Plugin.InstallId)); Section(Loc.T("诊断", "Diagnostics")); DrawDiagnostics(); GUILayout.Space(14f); Rect r = Row(44f); if (GhostButton(r, Loc.T("恢复默认设置", "Reset to defaults"), "cfg.reset", enabled: true)) { ResetConfig(); } } private void KeyCaptureRow() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) Rect val = Row(48f); _ui.DrawText(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width - 200f, ((Rect)(ref val)).height), Loc.T("切换按键", "Toggle key"), _ui.Body); Rect r = default(Rect); ((Rect)(ref r))..ctor(((Rect)(ref val)).xMax - 190f, ((Rect)(ref val)).center.y - 18f, 190f, 36f); string label = (_awaitingKey ? Loc.T("请按下任意键…(Esc 取消)", "Press any key… (Esc to cancel)") : (ToggleKeyName() + Loc.T("\u3000点击修改", " click to change"))); if (GhostButton(r, label, "cfg.key", enabled: true)) { _awaitingKey = true; } } private void AboutRow(string label, string value, Color? valueColor = null) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) Rect val = Row(30f); _ui.DrawText(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, 150f, ((Rect)(ref val)).height), label, _ui.Muted); _ui.DrawText(new Rect(((Rect)(ref val)).x + 150f, ((Rect)(ref val)).y, ((Rect)(ref val)).width - 150f, ((Rect)(ref val)).height), value, _ui.Body, (Color)(((??)valueColor) ?? _ui.Text)); } private void DrawDiagnostics() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0048: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_00c2: Unknown result type (might be due to invalid IL or missing references) string text = DirectTransport.BuildStatusText(); float num = Mathf.Max(60f, _drawW - 36f - 11f - 24f); float num2 = _ui.Wrap.CalcHeight(new GUIContent(text), num); Rect r = Row(num2 + 12f); _ui.Fill(r, 8f, new Color(1f, 1f, 1f, 0.03f)); _ui.Ring(r, 8f, _ui.Divider); _ui.DrawText(new Rect(((Rect)(ref r)).x + 12f, ((Rect)(ref r)).y + 6f, ((Rect)(ref r)).width - 24f, num2), text, _ui.Wrap); } private void ResetConfig() { try { if (Plugin.CfgFontSize != null) { Plugin.CfgFontSize.Value = 16; } if (Plugin.CfgScrollSpeed != null) { Plugin.CfgScrollSpeed.Value = 3; } if (Plugin.CfgToggleKey != null) { Plugin.CfgToggleKey.Value = "F7"; } if (Plugin.CfgShowOverlay != null) { Plugin.CfgShowOverlay.Value = true; } if (Plugin.CfgVerbose != null) { Plugin.CfgVerbose.Value = true; } ShowToast(Loc.T("已恢复默认设置", "Defaults restored"), 1); } catch (Exception ex) { Plugin.LogVerbose("ResetConfig failed: " + ex.Message); } } private static string ShortId(string id) { if (string.IsNullOrEmpty(id)) { return Loc.T("(未知)", "(unknown)"); } if (id.Length > 12) { return id.Substring(0, 12) + "…"; } return id; } private static Rect Row(float h) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) return GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(true), GUILayout.Height(h) }); } private bool Click(Rect r, bool enabled, string key) { //IL_0011: 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_004b: Invalid comparison between Unknown and I4 //IL_0023: 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) if (!enabled) { return false; } Event current = Event.current; if (current == null) { return false; } if ((int)current.type == 0) { if (current.button == 0 && ((Rect)(ref r)).Contains(current.mousePosition)) { _hotKey = key; GUIUtility.keyboardControl = 0; current.Use(); } return false; } if ((int)current.type == 1 && current.button == 0 && _hotKey == key) { _hotKey = null; if (((Rect)(ref r)).Contains(current.mousePosition)) { current.Use(); return true; } } return false; } private float Hover(string key, bool hovered, float speed) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 if (!_hover.TryGetValue(key, out var value)) { value = 0f; } Event current = Event.current; if (current != null && (int)current.type == 7) { value = Mathf.MoveTowards(value, hovered ? 1f : 0f, Time.unscaledDeltaTime * speed); _hover[key] = value; } return value; } private bool IconButton(Rect r, string key, IconKind icon, bool enabled = true, float iconSize = 18f) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) bool hovered = enabled && ((Rect)(ref r)).Contains(Event.current.mousePosition); float num = Hover(key, hovered, 12f); _ui.Fill(r, 8f, new Color(1f, 1f, 1f, 0.07f * num)); _ui.Icon(UiTheme.Center(r, iconSize, iconSize), icon, enabled ? Color.Lerp(_ui.TextMuted, _ui.Text, num) : UiTheme.WithA(_ui.TextDim, 0.5f)); return Click(r, enabled, key); } private bool GhostButton(Rect r, string label, string key, bool enabled) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00db: Unknown result type (might be due to invalid IL or missing references) bool hovered = enabled && ((Rect)(ref r)).Contains(Event.current.mousePosition); float num = Hover(key, hovered, 10f); _ui.Fill(r, 9f, new Color(1f, 1f, 1f, 0.05f + 0.05f * num)); _ui.Ring(r, 9f, Color.Lerp(_ui.Border, _ui.BorderHi, num)); _ui.DrawText(r, label, _ui.ButtonText, enabled ? Color.Lerp(_ui.TextMuted, _ui.Text, num) : UiTheme.WithA(_ui.TextMuted, 0.5f)); return Click(r, enabled, key); } private bool PrimaryButton(Rect r, string label, IconKind icon, Color fill, Color fillHi, Color textColor, bool enabled, string key) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_012d: 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_014a: Unknown result type (might be due to invalid IL or missing references) bool hovered = enabled && ((Rect)(ref r)).Contains(Event.current.mousePosition); float num = Hover(key, hovered, 10f); Color color = (enabled ? Color.Lerp(fill, fillHi, num) : UiTheme.WithA(fill, 0.32f)); _ui.Fill(r, 10f, color); if (enabled && num > 0.01f) { _ui.Ring(r, 10f, UiTheme.WithA(Color.white, 0.12f * num)); } Color val = (enabled ? textColor : UiTheme.WithA(textColor, 0.5f)); float x = _ui.TextSize(label, _ui.ButtonText).x; float num2 = x + 28f; float num3 = ((Rect)(ref r)).center.x - num2 * 0.5f; _ui.Icon(new Rect(num3, ((Rect)(ref r)).center.y - 10f, 20f, 20f), icon, val); _ui.DrawText(new Rect(num3 + 28f, ((Rect)(ref r)).y, x + 6f, ((Rect)(ref r)).height), label, _ui.ButtonText, val); return Click(r, enabled, key); } private bool NavCard(string key, IconKind icon, Color accent, string title, string desc, bool enabled, Page target) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_0055: 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_0071: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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_011a: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0254: 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_028f: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) Rect r = Row(92f); bool hovered = enabled && ((Rect)(ref r)).Contains(Event.current.mousePosition); float num = Hover(key, hovered, 9f); _ui.Fill(r, 12f, Color.Lerp(_ui.Card, _ui.CardHover, num)); _ui.Ring(r, 12f, Color.Lerp(_ui.Border, UiTheme.WithA(accent, 0.55f), num)); _ui.Fill(new Rect(((Rect)(ref r)).x + 1f, ((Rect)(ref r)).y + 16f, 3f, ((Rect)(ref r)).height - 32f), 1.5f, UiTheme.WithA(accent, 0.9f)); Rect r2 = default(Rect); ((Rect)(ref r2))..ctor(((Rect)(ref r)).x + 20f, ((Rect)(ref r)).center.y - 19f, 38f, 38f); _ui.Fill(r2, 11f, UiTheme.WithA(accent, 0.14f)); _ui.Icon(new Rect(((Rect)(ref r2)).x + 9f, ((Rect)(ref r2)).y + 9f, 20f, 20f), icon, accent); _ui.DrawText(new Rect(((Rect)(ref r)).x + 74f, ((Rect)(ref r)).y + 18f, ((Rect)(ref r)).width - 74f - 46f, 24f), title, _ui.CardTitle); _ui.DrawText(new Rect(((Rect)(ref r)).x + 74f, ((Rect)(ref r)).y + 44f, ((Rect)(ref r)).width - 74f - 46f, 36f), desc, _ui.CardSub); _ui.Icon(new Rect(((Rect)(ref r)).xMax - 36f + num * 5f, ((Rect)(ref r)).center.y - 9f, 18f, 18f), IconKind.ChevronRight, Color.Lerp(_ui.TextDim, accent, num)); if (!enabled) { _ui.Fill(r, 12f, new Color(0f, 0f, 0f, 0.3f)); } if (Click(r, enabled, key)) { Go(target); return true; } return false; } private int StepperRow(string label, int value, int min, int max, string key) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_012c: 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) Rect val = Row(46f); _ui.DrawText(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width - 150f, ((Rect)(ref val)).height), label, _ui.Body); Rect r = default(Rect); ((Rect)(ref r))..ctor(((Rect)(ref val)).xMax - 34f, ((Rect)(ref val)).center.y - 17f, 34f, 34f); Rect r2 = default(Rect); ((Rect)(ref r2))..ctor(((Rect)(ref r)).x - 52f, ((Rect)(ref val)).y, 52f, ((Rect)(ref val)).height); Rect r3 = default(Rect); ((Rect)(ref r3))..ctor(((Rect)(ref r2)).x - 34f, ((Rect)(ref val)).center.y - 17f, 34f, 34f); int num = value; if (IconButton(r3, key + ".m", IconKind.Minus, value > min)) { num = value - 1; } if (IconButton(r, key + ".p", IconKind.Plus, value < max)) { num = value + 1; } _ui.DrawText(r2, num.ToString(), _ui.ButtonText, _ui.Text); return Mathf.Clamp(num, min, max); } private bool ToggleRow(string key, string label, string desc, bool value, bool enabled) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0132: 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_013d: 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) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: 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_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: 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_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) Rect r = Row(58f); _ui.DrawText(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y + 7f, ((Rect)(ref r)).width - 90f, 22f), label, _ui.Body); _ui.DrawText(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y + 30f, ((Rect)(ref r)).width - 90f, 18f), desc, _ui.Caption); Rect r2 = default(Rect); ((Rect)(ref r2))..ctor(((Rect)(ref r)).xMax - 56f, ((Rect)(ref r)).center.y - 14f, 48f, 28f); bool hovered = enabled && ((Rect)(ref r)).Contains(Event.current.mousePosition); Hover(key, hovered, 10f); float num = Hover(key + ".v", value, 14f); Color val = Color.Lerp(new Color(1f, 1f, 1f, 0.13f), _ui.Primary, num); if (!enabled) { val = UiTheme.WithA(val, 0.4f); } _ui.Fill(r2, 14f, val); float num2 = Mathf.Lerp(((Rect)(ref r2)).x + 4f, ((Rect)(ref r2)).xMax - 24f, num); _ui.Fill(new Rect(num2, ((Rect)(ref r2)).y + 4f, 20f, 20f), 10f, Color.Lerp(_ui.TextMuted, Color.white, num)); if (Click(r, enabled, key)) { return !value; } return value; } private void Section(string text) { //IL_000f: 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) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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) GUILayout.Space(10f); Rect val = Row(22f); _ui.Fill(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 5f, 3f, 12f), 1.5f, _ui.Primary); _ui.DrawText(new Rect(((Rect)(ref val)).x + 11f, ((Rect)(ref val)).y, ((Rect)(ref val)).width - 11f, 22f), text, _ui.Section); GUILayout.Space(4f); } private void Banner(string text, bool warn) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0055: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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_00e7: Unknown result type (might be due to invalid IL or missing references) Rect r = Row(42f); Color val = (warn ? _ui.Amber : _ui.Blue); _ui.Fill(r, 9f, UiTheme.WithA(val, 0.1f)); _ui.Ring(r, 9f, UiTheme.WithA(val, 0.32f)); _ui.Icon(new Rect(((Rect)(ref r)).x + 12f, ((Rect)(ref r)).center.y - 9f, 18f, 18f), warn ? IconKind.Warn : IconKind.Info, val); _ui.DrawText(new Rect(((Rect)(ref r)).x + 38f, ((Rect)(ref r)).y, ((Rect)(ref r)).width - 50f, ((Rect)(ref r)).height), text, _ui.Muted, _ui.Text); GUILayout.Space(10f); } private void FieldRow(string label, ref string value, string placeholder, int maxLen) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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) Rect val = Row(42f); _ui.DrawText(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, 118f, ((Rect)(ref val)).height), label, _ui.Muted); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref val)).x + 118f, ((Rect)(ref val)).y, ((Rect)(ref val)).width - 118f, ((Rect)(ref val)).height); value = GUI.TextField(val2, value ?? "", maxLen, _ui.Field); if (string.IsNullOrEmpty(value)) { _ui.DrawText(new Rect(((Rect)(ref val2)).x + 14f, ((Rect)(ref val2)).y, ((Rect)(ref val2)).width - 24f, ((Rect)(ref val2)).height), placeholder, _ui.Placeholder); } GUILayout.Space(4f); } private void ShowToast(string text, int kind) { _toastText = text ?? ""; _toastKind = kind; _toastAge = 0f; } private void DrawToast(float W, float H) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013b: 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) //IL_015e: 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_0185: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(_toastText)) { if (_toastAge > 3.4f) { _toastText = ""; return; } float num = Mathf.Min(1f, _toastAge / 0.16f) * Mathf.Min(1f, (3.4f - _toastAge) / 0.45f); num = Mathf.Clamp01(num); Color c = ((_toastKind == 2) ? _ui.Danger : ((_toastKind == 1) ? _ui.Primary : _ui.Blue)); IconKind kind = ((_toastKind == 2) ? IconKind.Warn : ((_toastKind == 1) ? IconKind.Check : IconKind.Info)); Vector2 val = _ui.TextSize(_toastText, _ui.Body); float num2 = Mathf.Min(W - 40f, val.x + 64f); float num3 = (W - num2) * 0.5f; float num4 = H - 26f - 44f + (1f - num) * 10f; Rect r = default(Rect); ((Rect)(ref r))..ctor(num3, num4, num2, 44f); _ui.Fill(r, 10f, UiTheme.WithA(_ui.Card, 0.98f * num)); _ui.Ring(r, 10f, UiTheme.WithA(c, 0.55f * num)); _ui.Icon(new Rect(((Rect)(ref r)).x + 15f, ((Rect)(ref r)).center.y - 9f, 18f, 18f), kind, UiTheme.WithA(c, num)); _ui.DrawText(new Rect(((Rect)(ref r)).x + 44f, ((Rect)(ref r)).y, ((Rect)(ref r)).width - 56f, ((Rect)(ref r)).height), _toastText, _ui.Body, UiTheme.WithA(_ui.Text, num)); } } private void Go(Page p) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) _page = p; _pageAnim = 0f; _scroll = Vector2.zero; _awaitingKey = false; } private void HidePanel() { _visible = false; _awaitingKey = false; try { if (Plugin.CfgShowOverlay != null) { Plugin.CfgShowOverlay.Value = false; } } catch { } } private void StartHost() { if (!int.TryParse(_port, out var result) || result <= 0 || result >= 65536) { ShowToast(Loc.T("错误:UDP 端口不合法", "Error: invalid UDP port"), 2); Plugin.LogWarn("Invalid host port: " + _port); return; } if (Plugin.CfgPort != null) { Plugin.CfgPort.Value = result; } if (Plugin.CfgMaxPlayers != null) { Plugin.CfgMaxPlayers.Value = _maxPlayers; } if (ApplySaveSelection() && DirectTransport.Host(result, _maxPlayers)) { StartWatchdog(); Go(Page.Home); } } private void StartJoin() { if (!int.TryParse(_joinPort, out var result) || result <= 0 || result >= 65536) { ShowToast(Loc.T("错误:UDP 端口不合法", "Error: invalid UDP port"), 2); Plugin.LogWarn("Invalid join port: " + _joinPort); return; } string text = (_joinIp ?? "").Trim(); if (Plugin.CfgJoinIp != null) { Plugin.CfgJoinIp.Value = text; } if (DirectTransport.Join(text, result)) { _pendingHistoryIp = text; _pendingHistoryPort = result; StartWatchdog(); Go(Page.Home); } } private static void CopyToClipboard(string value) { try { GUIUtility.systemCopyBuffer = value; DirectTransport.SetStatus(Loc.T("已复制 IP:" + value, "Copied IP: " + value)); } catch (Exception ex) { DirectTransport.SetStatus(Loc.T("复制失败,请手动记录:" + value, "Copy failed, please note it down: " + value)); Plugin.LogWarn("Clipboard copy failed: " + ex.Message); } } private void ApplyHistory(string entry) { try { int num = entry.LastIndexOf(':'); if (num > 0) { _joinIp = entry.Substring(0, num); _joinPort = entry.Substring(num + 1); DirectTransport.SetStatus(Loc.T("已填入加入栏:" + entry, "Filled the join field: " + entry)); } } catch (Exception ex) { Plugin.LogVerbose("ApplyHistory failed: " + ex.Message); } } private static bool CanAct() { if (InMenu) { return Plugin.Ready; } return false; } private static float EaseOutCubic(float t) { t = Mathf.Clamp01(t); float num = 1f - t; return 1f - num * num * num; } private static float ScrollMultiplier() { try { if (Plugin.CfgScrollSpeed != null) { return Mathf.Clamp(Plugin.CfgScrollSpeed.Value, 1, 8); } } catch { } return 3f; } private static string ConfiguredToggleKey() { if (Plugin.CfgToggleKey == null) { return "F7"; } return Plugin.CfgToggleKey.Value; } private unsafe static string ToggleKeyName() { if (!TryParseKey(ConfiguredToggleKey(), out var key)) { return "F7"; } return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); } private static bool TryParseKey(string value, out KeyCode key) { key = (KeyCode)288; if (string.IsNullOrEmpty(value)) { return false; } if (!Enum.TryParse<KeyCode>(value.Trim(), ignoreCase: true, out key)) { return false; } try { return key && Enum.IsDefined(typeof(KeyCode), key); } catch { return (int)key != 0; } } private void HandleToggleKey() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (_awaitingKey) { return; } try { Event current = Event.current; if (current == null || (int)current.type != 4 || (GUIUtility.keyboardControl != 0 && current.character != 0)) { return; } if (!TryParseKey(ConfiguredToggleKey(), out var key)) { key = (KeyCode)288; } if (current.keyCode != key) { return; } _visible = !_visible; try { if (Plugin.CfgShowOverlay != null) { Plugin.CfgShowOverlay.Value = _visible; } } catch { } current.Use(); } catch { } } private void HandleKeyCapture() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_005e: Unknown result type (might be due to invalid IL or missing references) if (!_awaitingKey || !_visible) { return; } try { Event current = Event.current; if (current == null || (int)current.type != 4) { return; } if ((int)current.keyCode == 27) { _awaitingKey = false; current.Use(); } else if ((int)current.keyCode != 0) { if (Plugin.CfgToggleKey != null) { Plugin.CfgToggleKey.Value = ((object)current.keyCode/*cast due to .constrained prefix*/).ToString(); } _awaitingKey = false; ShowToast(Loc.T("切换按键已设为 ", "Toggle key set to ") + ((object)current.keyCode/*cast due to .constrained prefix*/).ToString(), 1); current.Use(); } } catch { } } private string SaveName() { if (!string.IsNullOrEmpty(_selectedSaveName)) { return _selectedSaveName; } return Loc.T("(未选择)", "(none)"); } private void DrawSaveSection() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) Rect val = Row(28f); _ui.DrawText(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width - 76f, ((Rect)(ref val)).height), Loc.T("当前存档:", "Current save: ") + SaveName(), string.IsNullOrEmpty(_selectedSaveName) ? _ui.Muted : _ui.Success); Rect r = default(Rect); ((Rect)(ref r))..ctor(((Rect)(ref val)).xMax - 72f, ((Rect)(ref val)).y, 72f, 28f); if (GhostButton(r, Loc.T("刷新", "Refresh"), "save.refresh", enabled: true)) { EnsureSaveList(force: true); } GUILayout.Space(2f); List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>(); try { if (SaveManager.ServerSaves != null) { foreach (ServerSaveObject serverSafe in SaveManager.ServerSaves) { if (serverSafe != null && !string.IsNullOrEmpty(serverSafe.Name)) { list.Add(new KeyValuePair<string, string>(serverSafe.Name, Loc.T("岛 ", "Island ") + (serverSafe.SpawnedIsland + 1) + " · " + DifficultyName(serverSafe.Difficulty))); } } } } catch (Exception ex) { Plugin.LogVerbose("DrawSaveSection list: " + ex.Message); } if (list.Count == 0) { Rect r2 = Row(24f); _ui.DrawText(r2, Loc.T("(暂无存档:请先用游戏原版的「新游戏」创建一个)", "(no saves yet: create one with the game's New Game first)"), _ui.Muted); return; } for (int i = 0; i < list.Count; i++) { string key = list[i].Key; if (SaveRow(key, list[i].Value, key == _selectedSaveName)) { _selectedSaveName = key; try { SaveManager.SelectServer(key); } catch { } } } } private bool SaveRow(string name, string meta, bool selected) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_010f: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: 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) Rect r = Row(44f); bool hovered = ((Rect)(ref r)).Contains(Event.current.mousePosition); float num = Hover("save." + name, hovered, 10f); if (selected) { _ui.Fill(r, 8f, UiTheme.WithA(_ui.Primary, 0.1f)); } else if (num > 0.01f) { _ui.Fill(r, 8f, new Color(1f, 1f, 1f, 0.04f * num)); } if (selected) { _ui.Fill(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y + 10f, 3f, ((Rect)(ref r)).height - 20f), 1.5f, _ui.Primary); } _ui.DrawText(new Rect(((Rect)(ref r)).x + 14f, ((Rect)(ref r)).y + 3f, ((Rect)(ref r)).width - 120f, 20f), name, selected ? _ui.CardTitle : _ui.Body); _ui.DrawText(new Rect(((Rect)(ref r)).x + 14f, ((Rect)(ref r)).y + 23f, ((Rect)(ref r)).width - 120f, 16f), meta, _ui.Caption); bool flag = false; if (!selected) { Rect r2 = default(Rect); ((Rect)(ref r2))..ctor(((Rect)(ref r)).xMax - 88f, ((Rect)(ref r)).center.y - 15f, 76f, 30f); if (GhostButton(r2, Loc.T("选择", "Select"), "savebtn." + name, enabled: true)) { flag = true; } } else { _ui.DrawText(new Rect(((Rect)(ref r)).xMax - 88f, ((Rect)(ref r)).center.y - 12f, 76f, 24f), Loc.T("使用中", "In use"), _ui.Success, _ui.PrimaryHi); } if (!flag && Click(r, enabled: true, "save." + name)) { flag = true; } return flag; } private void EnsureSaveList(bool force) { if (_saveListLoaded && !force) { return; } bool flag = false; try { flag = MainMenuManager.IsInMenu; } catch { } if (!flag) { return; } string text = null; try { text = ((SaveManager.CurServerSave != null) ? SaveManager.CurServerSave.Name : null); } catch { } try { SaveManager.LoadAllServers(); _saveListLoaded = true; } catch (Exception ex) { Plugin.LogWarn("LoadAllServers failed: " + ex.Message); return; } if (!string.IsNullOrEmpty(text)) { try { SaveManager.SelectServer(text); } catch { } if (SaveManager.CurServerSave != null) { _selectedSaveName = text; return; } } bool flag2 = false; string text2 = null; long num = long.MinValue; try { if (SaveManager.ServerSaves != null) { foreach (ServerSaveObject serverSafe in SaveManager.ServerSaves) { if (serverSafe != null && !string.IsNullOrEmpty(serverSafe.Name)) { if (serverSafe.Name == "IP Host") { flag2 = true; } if (serverSafe.LastSave > num) { num = serverSafe.LastSave; text2 = serverSafe.Name; } } } } } catch { } if (flag2) { _selectedSaveName = "IP Host"; } else if (text2 != null) { _selectedSaveName = text2; } else { _selectedSaveName = ""; } } private bool ApplySaveSelection() { try { if (string.IsNullOrEmpty(_selectedSaveName)) { ShowToast(Loc.T("错误:请先在「存档」里选择一个存档", "Error: select a save first"), 2); return false; } SaveManager.OnServerLoaded(); SaveManager.SelectServer(_selectedSaveName); if (SaveManager.CurServerSave == null) { SaveManager.LoadAllServers(); SaveManager.SelectServer(_selectedSaveName); } if (SaveManager.CurServerSave == null) { ShowToast(Loc.T("错误:找不到存档 ", "Error: save not found: ") + _selectedSaveName, 2); return false; } Plugin.LogInfo("Hosting save '" + _selectedSaveName + "' in direct mode."); return true; } catch (Exception ex) { Plugin.LogError("ApplySaveSelection failed: " + ex); ShowToast(Loc.T("错误:", "Error: ") + ex.Message, 2); return false; } } private static string DifficultyName(Difficulty d) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 if ((int)d == 0) { return Loc.T("简单", "Easy"); } if ((int)d == 2) { return Loc.T("困难", "Hard"); } return Loc.T("默认", "Default"); } private void AddHistory(string ip, int port) { try { if (!string.IsNullOrEmpty(ip)) { string entry = ip + ":" + port; _history.RemoveAll((string e) => string.Equals(e, entry, StringComparison.OrdinalIgnoreCase)); _history.Insert(0, entry); while (_history.Count > 8) { _history.RemoveAt(_history.Count - 1); } SaveHistory(); } } catch (Exception ex) { Plugin.LogVerbose("AddHistory failed: " + ex.Message); } } private void LoadHistory() { try { _history.Clear(); string text = ((Plugin.CfgHistory != null) ? Plugin.CfgHistory.Value : ""); if (string.IsNullOrEmpty(text)) { return; } string[] array = text.Split(new char[1] { '|' }); foreach (string text2 in array) { string t = text2.Trim(); if (t.Length != 0 && !_history.Exists((string e) => string.Equals(e, t, StringComparison.OrdinalIgnoreCase))) { _history.Add(t); if (_history.Count >= 8) { break; } } } } catch (Exception ex) { Plugin.LogVerbose("LoadHistory failed: " + ex.Message); } } private void SaveHistory() { try { if (Plugin.CfgHistory != null) { Plugin.CfgHistory.Value = string.Join("|", _history.ToArray()); } } catch (Exception ex) { Plugin.LogVerbose("SaveHistory failed: " + ex.Message); } } private void StartWatchdog() { StopWatchdog(); _watchdog = ((MonoBehaviour)this).StartCoroutine(WatchdogRoutine()); } private void StopWatchdog() { if (_watchdog != null) { ((MonoBehaviour)this).StopCoroutine(_watchdog); _watchdog = null; } } private IEnumerator WatchdogRoutine() { float t = 0f; while (t < 40f) { if (!DirectNet.DirectSessionActive) { _pendingHistoryIp = null; _watchdog = null; yield break; } if (!string.IsNullOrEmpty(DirectNet.LastRejectReason)) { _pendingHistoryIp = null; _watchdog = null; DirectTransport.AbortToMenu(DirectNet.LastRejectReason); y