using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Entiffo.UEXPDedicatedClient.Config; using Entiffo.UEXPDedicatedClient.Patches; using Entiffo.UEXPDedicatedClient.Util; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Steamworks; using Steamworks.Data; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("UEXP_Dedicated_Client")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.3.0")] [assembly: AssemblyInformationalVersion("1.0.3")] [assembly: AssemblyProduct("UEXP_Dedicated_Client")] [assembly: AssemblyTitle("UEXP_Dedicated_Client")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Entiffo.UEXPDedicatedClient { [BepInPlugin("Entiffo.UEXP_Dedicated_Client", "UEXP_Dedicated_Client", "1.0.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string ModGuid = "Entiffo.UEXP_Dedicated_Client"; public const string MoreCompanyGuid = "me.swipez.melonloader.morecompany"; private readonly Harmony _harmony = new Harmony("Entiffo.UEXP_Dedicated_Client"); private static bool _moreCompanyResizePatched; private static bool _moreCompanyUpdateBoxPatched; internal static Plugin Instance { get; private set; } internal static ModConfig Config { get; private set; } internal static ManualLogSource Log { get; private set; } private static bool MoreCompanyGuardsFullyPatched { get { if (_moreCompanyResizePatched) { return _moreCompanyUpdateBoxPatched; } return false; } } internal static bool IsEnabled => Config.Enabled.Value; private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; Config = new ModConfig(((BaseUnityPlugin)this).Config); try { GameObject[] array = Resources.FindObjectsOfTypeAll(); foreach (GameObject val in array) { if (!((Object)(object)val == (Object)null)) { string name = ((Object)val).name; switch (name) { case "UEXP_PasswordPrompt": case "UEXP_ModsModal": case "UEXP_OrbitQueue": case "UEXP_EventSystem": case "UEXP_GameplayInputRestore": Log.LogWarning((object)("Destroying leftover UI object from older build: " + name)); Object.Destroy((Object)(object)val); break; } } } } catch { } if (!IsEnabled) { Log.LogInfo((object)"UEXP_Dedicated_Client 1.0.3 is DISABLED (General.Enabled=false). Vanilla menus/join. Set Enabled=true and restart for dedicated client features."); return; } Type[] types = typeof(Plugin).Assembly.GetTypes(); foreach (Type type in types) { if (Attribute.GetCustomAttribute(type, typeof(HarmonyPatch)) != null) { try { _harmony.CreateClassProcessor(type).Patch(); } catch (Exception ex) { Log.LogWarning((object)("Harmony skip " + type.Name + ": " + ex.Message)); } } } TryPatchMoreCompanyGuards(); if (Config.EnableQuatSpamProbe.Value) { QuatSpamProbe.EnsureHooked(); } QuatUnityLogFilter.TryPatch(_harmony); OpenBodyCamsGhostGuard.TryPatch(_harmony); try { SteamMatchmaking.OnLobbyEntered += MoreCompanyLobbyMatch.OnSteamLobbyEntered; SteamFriends.OnGameLobbyJoinRequested += delegate(Lobby lobby, SteamId _) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) MoreCompanyLobbyMatch.OnSteamLobbyEntered(lobby); }; } catch (Exception ex2) { Log.LogWarning((object)("Steam lobby crew hooks failed: " + ex2.Message)); } Log.LogInfo((object)"UEXP_Dedicated_Client 1.0.3 loaded. Install on every joiner of a UEXP dedicated lobby."); } private void TryPatchMoreCompanyGuards() { TryPatchMoreCompanyGuardsRetry("Awake"); } internal static void TryPatchMoreCompanyGuardsRetry(string reason) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown if (MoreCompanyGuardsFullyPatched || (Object)(object)Instance == (Object)null) { return; } try { Type type = AccessTools.TypeByName("MoreCompany.MainClass"); if (type == null) { if (reason == "Awake") { Log.LogInfo((object)"MoreCompany not loaded yet — ResizeGuard will retry on dedicated join."); } return; } if (!_moreCompanyResizePatched) { MethodBase methodBase = AccessTools.Method(type, "ResizePlayerCache", (Type[])null, (Type[])null); if (methodBase != null) { Instance._harmony.Patch(methodBase, new HarmonyMethod(typeof(MoreCompanyResizeGuardPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _moreCompanyResizePatched = true; Log.LogInfo((object)("MoreCompany ResizePlayerCache guard patched (" + reason + ").")); } else { Log.LogWarning((object)("MoreCompany ResizePlayerCache not found (" + reason + ").")); } } if (!_moreCompanyUpdateBoxPatched) { Type type2 = AccessTools.TypeByName("MoreCompany.MenuManagerHost"); MethodBase methodBase2 = ((type2 == null) ? null : AccessTools.Method(type2, "UpdateTextBox", new Type[2] { typeof(TMP_InputField), typeof(string) }, (Type[])null)); if (methodBase2 != null) { Instance._harmony.Patch(methodBase2, new HarmonyMethod(typeof(MoreCompanyCrewCountUiGuardPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _moreCompanyUpdateBoxPatched = true; Log.LogInfo((object)("MoreCompany UpdateTextBox guard patched (" + reason + ").")); } else if (type2 != null) { Log.LogWarning((object)("MoreCompany UpdateTextBox not found (" + reason + ") — will retry on dedicated join.")); } } if (!MoreCompanyGuardsFullyPatched && reason != "Awake") { Log.LogWarning((object)("MoreCompany guards incomplete (" + reason + "): " + $"resize={_moreCompanyResizePatched} updateBox={_moreCompanyUpdateBoxPatched}")); } } catch (Exception ex) { Log.LogWarning((object)("MoreCompany manual guards failed (" + reason + "): " + ex.Message)); } } internal static void DebugLog(string message) { if (Config.DebugLogging.Value) { Log.LogInfo((object)message); } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "Entiffo.UEXP_Dedicated_Client"; public const string PLUGIN_NAME = "UEXP_Dedicated_Client"; public const string PLUGIN_VERSION = "1.0.3"; } } namespace Entiffo.UEXPDedicatedClient.Util { public static class DedicatedLobby { public const string FlagKey = "uexpDedicated"; public const string FlagValue = "1"; public const string VerKey = "uexpDedicatedVer"; public const string ReqClientKey = "uexpReqClient"; public const string MaxKey = "uexpMax"; public const string HumansKey = "uexpHumans"; public const string ModCountKey = "uexpModN"; public const string ModsKey = "uexpMods"; public const string ModsKey2 = "uexpMods2"; public const string HasPassKey = "uexpHasPass"; public const string PassHashKey = "uexpPassHash"; public const string ProfileCodeKey = "uexpProfile"; public const string PhaseKey = "uexpPhase"; public const string MoonKey = "uexpMoon"; public const string RiskKey = "uexpRisk"; public const string WeatherKey = "uexpWeather"; public const string DayKey = "uexpDay"; public const string QuotaKey = "uexpQuota"; public const string TipKey = "uexpTip"; public const string MotdKey = "uexpMotd"; public const string TimeKey = "uexpTime"; public const string QueueableKey = "uexpQueueable"; public const string QueueCountKey = "uexpQueueN"; public const string AdmitKey = "uexpAdmit"; public const string MemberQueueKey = "uexpQ"; public const string QueueDenyKey = "uexpQDeny"; public const string BanHintsKey = "uexpBanHints"; public const string MinLeaveKey = "uexpMinLeave"; private static bool _sessionDedicated; private const string RoleSyncLobbyKey = "uexpRoles"; public static bool SessionLatched => _sessionDedicated; public static bool IsCurrentLobbyDedicated() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (_sessionDedicated) { return true; } try { GameNetworkManager instance = GameNetworkManager.Instance; if ((Object)(object)instance == (Object)null || instance.disableSteam || !instance.currentLobby.HasValue) { return false; } if (!IsDedicatedLobby(instance.currentLobby.Value)) { return false; } MarkSessionDedicated("lobby data"); return true; } catch { return false; } } public static void MarkSessionDedicated(string reason = "") { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown if (_sessionDedicated) { return; } _sessionDedicated = true; Plugin.DebugLog("Dedicated session latched" + (string.IsNullOrEmpty(reason) ? "" : (" (" + reason + ")")) + "."); try { if (Plugin.Config != null && Plugin.Config.EnableQuatSpamProbe.Value) { QuatSpamProbe.EnsureHooked(); QuatSpamProbe.Arm("dedicated latch" + (string.IsNullOrEmpty(reason) ? "" : (":" + reason))); } OpenBodyCamsGhostGuard.TryPatch(new Harmony("Entiffo.UEXP_Dedicated_Client.obc-retry")); } catch { } } public static void ClearSessionDedicated(string reason = "") { if (!_sessionDedicated) { return; } _sessionDedicated = false; Plugin.DebugLog("Dedicated session cleared" + (string.IsNullOrEmpty(reason) ? "" : (" (" + reason + ")")) + "."); try { QuatSpamProbe.ClearSession(); HostBodyHidePatches.ResetHideLatch(); GhostSeatLateJoinEnforcer.ResetSession(); } catch { } } public static bool IsDedicatedLobby(Lobby lobby) { try { return ((Lobby)(ref lobby)).GetData("uexpDedicated") == "1"; } catch { return false; } } public static bool TryGetClientVersionMismatch(Lobby lobby, out string message) { //IL_0007: 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_004c: Unknown result type (might be due to invalid IL or missing references) message = ""; try { if (!IsDedicatedLobby(lobby)) { return false; } try { ((Lobby)(ref lobby)).Refresh(); } catch { } string text = ReadData(lobby, "uexpReqClient").Trim(); if (string.IsNullOrEmpty(text)) { return false; } string text2 = "1.0.3"; string text3 = ReadData(lobby, "uexpDedicatedVer").Trim(); string text4 = (string.IsNullOrEmpty(text3) ? "" : (" (host " + text3 + ")")); if (!TryCompareVersions(text2, text, out var cmp)) { message = "UEXP Dedicated Client version unreadable.\nYou have v" + text2 + ". This server needs v" + text + text4 + ".\nUpdate the client from the UEXP site (lethal.uexp.org), then rejoin."; return true; } if (cmp < 0) { message = "UEXP Dedicated Client is outdated.\nYou have v" + text2 + ". This server needs v" + text + text4 + ".\nUpdate the client from the UEXP site (lethal.uexp.org), then rejoin."; return true; } if (cmp > 0) { message = "This dedicated host is outdated.\nServer expects client v" + text + text4 + "; you have v" + text2 + ".\nWait until the host administrator updates the server."; return true; } return false; } catch { return false; } } public static string FormatBrowserHostVersionBadge(Lobby lobby) { //IL_0000: 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) try { string text = ReadData(lobby, "uexpDedicatedVer").Trim(); if (string.IsNullOrEmpty(text)) { return ""; } string text2 = "host " + text; string text3 = ReadData(lobby, "uexpReqClient").Trim(); string a = "1.0.3"; if (string.IsNullOrEmpty(text3)) { return "" + text2 + ""; } if (!TryCompareVersions(a, text3, out var cmp)) { return "" + text2 + ""; } if (cmp == 0) { return "" + text2 + ""; } return "" + text2 + ""; } catch { return ""; } } private static bool TryCompareVersions(string a, string b, out int cmp) { cmp = 0; try { if (!Version.TryParse(NormalizeVersion(a), out Version result) || !Version.TryParse(NormalizeVersion(b), out Version result2) || result == null || result2 == null) { return false; } cmp = result.CompareTo(result2); return true; } catch { return false; } } private static string NormalizeVersion(string v) { string text = (v ?? "").Trim(); int num = 0; for (int i = 0; i < text.Length; i++) { if (text[i] == '.') { num++; } } return num switch { 0 => text + ".0", 1 => text + ".0", _ => text, }; } public static bool IsQueueableLobby(Lobby lobby) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) try { return IsDedicatedLobby(lobby) && ((Lobby)(ref lobby)).GetData("uexpQueueable") == "1"; } catch { return false; } } public static bool IsJoinableListing(Lobby lobby) { //IL_0000: 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_0050: 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) try { if (!IsDedicatedLobby(lobby)) { return false; } if (((Lobby)(ref lobby)).GetData("started") == "1") { return false; } if (((Lobby)(ref lobby)).GetData("joinable") == "false") { return false; } if (IsQueueableLobby(lobby)) { return true; } int num = DisplayMemberCount(lobby); int num2 = ReadHumanCapacity(lobby); if (num2 > 0 && num >= num2) { return false; } return true; } catch { return false; } } public static int DisplayMemberCount(Lobby lobby) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return DisplayMemberCountExcludingQueue(lobby); } public static int DisplayMemberCountExcludingQueue(Lobby lobby) { //IL_0000: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_0071: 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_0088: Unknown result type (might be due to invalid IL or missing references) try { if (!IsDedicatedLobby(lobby)) { return ((Lobby)(ref lobby)).MemberCount; } string data = ((Lobby)(ref lobby)).GetData("uexpHumans"); if (!string.IsNullOrEmpty(data) && int.TryParse(data, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && result >= 0) { return result; } SteamId id = ((Lobby)(ref lobby)).Owner.Id; int num = 0; foreach (Friend member in ((Lobby)(ref lobby)).Members) { if (SteamId.op_Implicit(member.Id) != SteamId.op_Implicit(id)) { string value = null; try { value = ((Lobby)(ref lobby)).GetMemberData(member, "uexpQ"); } catch { } if (string.IsNullOrEmpty(value)) { num++; } } } return num; } catch { try { string data2 = ((Lobby)(ref lobby)).GetData("uexpHumans"); if (!string.IsNullOrEmpty(data2) && int.TryParse(data2, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2) && result2 >= 0) { return result2; } } catch { } int memberCount = ((Lobby)(ref lobby)).MemberCount; return (memberCount > 0) ? (memberCount - 1) : 0; } } public static int ReadHumanCapacity(Lobby lobby) { try { string data = ((Lobby)(ref lobby)).GetData("uexpMax"); if (!string.IsNullOrEmpty(data) && int.TryParse(data, out var result) && result > 0) { return result; } } catch { } return 3; } public static int ReadQueueCount(Lobby lobby) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) try { string data = ((Lobby)(ref lobby)).GetData("uexpQueueN"); if (!string.IsNullOrEmpty(data) && int.TryParse(data, out var result) && result >= 0) { return result; } } catch { } return CountQueuedMembers(lobby); } public static int CountQueuedMembers(Lobby lobby) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) int num = 0; try { SteamId id = ((Lobby)(ref lobby)).Owner.Id; foreach (Friend member in ((Lobby)(ref lobby)).Members) { if (SteamId.op_Implicit(member.Id) != SteamId.op_Implicit(id)) { string text = null; try { text = ((Lobby)(ref lobby)).GetMemberData(member, "uexpQ"); } catch { continue; } if (!string.IsNullOrEmpty(text)) { num++; } } } } catch { } return num; } public static void ReadLocalQueuePosition(Lobby lobby, long localStamp, out int position, out int total) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0167: 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_0198: Unknown result type (might be due to invalid IL or missing references) position = 0; total = 0; try { SteamId self = SteamClient.SteamId; SteamId id = ((Lobby)(ref lobby)).Owner.Id; List<(SteamId, long, int)> list = new List<(SteamId, long, int)>(); foreach (Friend member in ((Lobby)(ref lobby)).Members) { if (SteamId.op_Implicit(member.Id) == SteamId.op_Implicit(id)) { continue; } string text = null; try { text = ((Lobby)(ref lobby)).GetMemberData(member, "uexpQ"); } catch { continue; } if (!string.IsNullOrWhiteSpace(text)) { if (!long.TryParse(text.Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { result = 0L; } list.Add((member.Id, result, QueuePriorityRank(lobby, SteamId.op_Implicit(member.Id)))); } } list = (from s in list orderby s.Prio, s.Ts, s.Id.Value select s).ToList(); total = list.Count; for (int num = 0; num < list.Count; num++) { if (SteamId.op_Implicit(list[num].Item1) == SteamId.op_Implicit(self)) { position = num + 1; return; } } if (localStamp > 0) { int myPrio = QueuePriorityRank(lobby, SteamId.op_Implicit(self)); int num2 = list.Count<(SteamId, long, int)>(((SteamId Id, long Ts, int Prio) s) => s.Prio < myPrio || (s.Prio == myPrio && (s.Ts < localStamp || (s.Ts == localStamp && s.Id.Value < self.Value)))); position = num2 + 1; total = Math.Max(total + 1, position); } } catch { position = 0; total = 0; } } public static int QueuePriorityRank(Lobby lobby, ulong steamId) { if (steamId == 0L) { return 3; } if (DeveloperRoster.IsDeveloper(steamId)) { return 0; } try { string text = ((Lobby)(ref lobby)).GetData("uexpRoles") ?? ""; if (!string.IsNullOrWhiteSpace(text)) { string[] array = text.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); int num = text2.IndexOf('='); if (num > 0 && ulong.TryParse(text2.Substring(0, num).Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && result == steamId) { string text3 = text2.Substring(num + 1).Trim().ToLowerInvariant(); if (text3.StartsWith("a")) { return 1; } if (text3.StartsWith("m")) { return 2; } } } } } catch { } return 3; } public static int ReadModCount(Lobby lobby) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) try { string data = ((Lobby)(ref lobby)).GetData("uexpModN"); if (!string.IsNullOrEmpty(data) && int.TryParse(data, out var result)) { return result; } } catch { } string text = ReadModList(lobby); if (string.IsNullOrWhiteSpace(text)) { return 0; } return text.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries).Length; } public static string ReadModList(Lobby lobby) { try { string text = ((Lobby)(ref lobby)).GetData("uexpMods") ?? ""; string text2 = ((Lobby)(ref lobby)).GetData("uexpMods2") ?? ""; if (string.IsNullOrEmpty(text)) { return text2 ?? ""; } if (string.IsNullOrEmpty(text2)) { return text; } return text + ";" + text2; } catch { return ""; } } public static string ReadData(Lobby lobby, string key) { try { return ((Lobby)(ref lobby)).GetData(key) ?? ""; } catch { return ""; } } public static string ReadProfileCode(Lobby lobby) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ReadData(lobby, "uexpProfile"); } public static string ReadMotd(Lobby lobby) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ReadData(lobby, "uexpMotd").Trim(); } public static bool TryGetLocalBanRemaining(Lobby lobby, out TimeSpan remaining, out bool permanent) { //IL_000e: 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) remaining = TimeSpan.Zero; permanent = false; try { string text = ReadData(lobby, "uexpBanHints"); if (string.IsNullOrWhiteSpace(text)) { return false; } ulong num = SteamId.op_Implicit(SteamClient.SteamId); if (num == 0L) { return false; } string value = num.ToString(CultureInfo.InvariantCulture); string[] array = text.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Trim().Split(':'); if (array2.Length == 2 && array2[0].Equals(value, StringComparison.OrdinalIgnoreCase) && long.TryParse(array2[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { if (result < 0) { permanent = true; remaining = TimeSpan.MaxValue; return true; } DateTimeOffset dateTimeOffset = new DateTimeOffset(result, TimeSpan.Zero); remaining = dateTimeOffset - DateTimeOffset.UtcNow; if (remaining <= TimeSpan.Zero) { return false; } return true; } } } catch { } return false; } public static string FormatBanCountdown(TimeSpan remaining) { if (remaining == TimeSpan.MaxValue || remaining.TotalDays > 3650.0) { return "permanently"; } int num = (int)Math.Ceiling(remaining.TotalMinutes); if (num < 1) { num = 1; } int num2 = num / 60; int num3 = num % 60; if (num2 <= 0) { if (num3 != 1) { return $"{num3} minutes"; } return "1 minute"; } if (num3 == 0) { if (num2 != 1) { return $"{num2} hours"; } return "1 hour"; } return $"{num2}h {num3}m"; } public static string ReadSessionTip(Lobby lobby) { //IL_0000: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_005c: 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_00e6: Unknown result type (might be due to invalid IL or missing references) string text = ReadData(lobby, "uexpTip").Trim(); string text2 = ReadData(lobby, "uexpPhase"); string text3 = ReadData(lobby, "uexpMoon"); string text4 = ReadData(lobby, "uexpRisk"); string text5 = ReadData(lobby, "uexpWeather"); string text6 = ReadData(lobby, "uexpDay"); string text7 = ReadData(lobby, "uexpQuota"); string text8 = ReadData(lobby, "uexpTime"); bool flag = text.Equals("starting up", StringComparison.OrdinalIgnoreCase) || text.Equals("hosting…", StringComparison.OrdinalIgnoreCase) || text.Equals("hosting...", StringComparison.OrdinalIgnoreCase); bool flag2 = (!string.IsNullOrEmpty(text2) && text2 != "boot") || !string.IsNullOrEmpty(text3) || !string.IsNullOrEmpty(text6) || !string.IsNullOrEmpty(text7) || !string.IsNullOrEmpty(text8); bool flag3 = !string.IsNullOrEmpty(ReadData(lobby, "uexpMax")) || !string.IsNullOrEmpty(ReadData(lobby, "uexpHumans")); if (!string.IsNullOrWhiteSpace(text) && (!flag || !(flag2 || flag3))) { return text; } List list = new List(6); if (text2 == "orbit" || (string.IsNullOrEmpty(text2) && flag3 && !flag2)) { list.Add(string.IsNullOrEmpty(text3) ? "in orbit" : ("orbit · " + text3)); } else if (text2 == "landing") { list.Add(string.IsNullOrEmpty(text3) ? "landing…" : ("landing · " + text3)); if (!string.IsNullOrEmpty(text4)) { list.Add(text4); } } else if (text2 == "moon") { if (!string.IsNullOrEmpty(text3)) { list.Add(text3); } else { list.Add("on moon"); } if (!string.IsNullOrEmpty(text4)) { list.Add(text4); } if (!string.IsNullOrEmpty(text5)) { list.Add(text5); } } else { if (flag && !flag2 && !flag3) { if (text.Length <= 0) { return "starting up"; } return text; } if (flag3) { list.Add("in orbit"); } } if (!string.IsNullOrEmpty(text6)) { list.Add(text6); } if (!string.IsNullOrEmpty(text8)) { list.Add(text8); } if (!string.IsNullOrEmpty(text7)) { list.Add("quota " + text7); } string text9 = string.Join(" · ", list); if (!string.IsNullOrEmpty(text9)) { return text9; } if (!string.IsNullOrEmpty(text)) { return text; } return "in orbit"; } public static bool RequiresPassword(Lobby lobby) { try { return ((Lobby)(ref lobby)).GetData("uexpHasPass") == "1" && !string.IsNullOrEmpty(((Lobby)(ref lobby)).GetData("uexpPassHash")); } catch { return false; } } public static string ExpectedPasswordHash(Lobby lobby) { try { return ((Lobby)(ref lobby)).GetData("uexpPassHash") ?? ""; } catch { return ""; } } } internal static class DeveloperRoster { public const ulong EntiffoSteamId = 76561198051556575uL; private static readonly HashSet Ids = new HashSet { 76561198051556575uL }; public static bool IsDeveloper(ulong steamId) { if (steamId != 0L) { return Ids.Contains(steamId); } return false; } public static IReadOnlyCollection Snapshot() { return Ids; } } } namespace Entiffo.UEXPDedicatedClient.Patches { internal static class AdminOpsClient { public const string HealPrefix = "[UEXP]heal:"; public const string TpPrefix = "[UEXP]tp:"; public const string MutePrefix = "[UEXP]mute:"; public const string WeatherPrefix = "[UEXP]weather:"; public const string QuotaPrefix = "[UEXP]quota:"; private static readonly HashSet MutedSteamIds = new HashSet(); public static bool TryHandleSystemMessage(string? chatMessage) { if (string.IsNullOrEmpty(chatMessage)) { return false; } if (chatMessage.StartsWith("[UEXP]heal:", StringComparison.Ordinal)) { ApplyHeal(chatMessage.Substring("[UEXP]heal:".Length).Trim()); return true; } if (chatMessage.StartsWith("[UEXP]tp:", StringComparison.Ordinal)) { ApplyTp(chatMessage.Substring("[UEXP]tp:".Length).Trim()); return true; } if (chatMessage.StartsWith("[UEXP]mute:", StringComparison.Ordinal)) { ApplyMute(chatMessage.Substring("[UEXP]mute:".Length).Trim()); return true; } if (chatMessage.StartsWith("[UEXP]weather:", StringComparison.Ordinal)) { ApplyWeather(chatMessage.Substring("[UEXP]weather:".Length).Trim()); return true; } if (chatMessage.StartsWith("[UEXP]quota:", StringComparison.Ordinal)) { ApplyQuota(chatMessage.Substring("[UEXP]quota:".Length).Trim()); return true; } return false; } public static bool TryHandleWarnWhisper(string? chatMessage) { if (string.IsNullOrEmpty(chatMessage)) { return false; } if (!chatMessage.StartsWith("[WARN]@", StringComparison.OrdinalIgnoreCase)) { return false; } string text = chatMessage.Substring("[WARN]@".Length); int num = text.IndexOf('|'); if (num <= 0) { return true; } string s = text.Substring(0, num).Trim(); string text2 = text.Substring(num + 1).Trim(); if (!ulong.TryParse(s, out var result) || result == 0L) { return true; } try { ulong num2 = LocalSteam(); if (num2 != 0L && num2 == result && !string.IsNullOrEmpty(text2)) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("Warning", Truncate(text2, 120), true, false, "UEXP_Warn"); } } } catch { } return true; } public static bool IsSteamMuted(ulong steam) { if (steam != 0L) { return MutedSteamIds.Contains(steam); } return false; } private static void ApplyHeal(string rest) { string[] array = rest.Split(':'); if (array.Length < 1 || !int.TryParse(array[0].Trim(), out var result)) { return; } int num = 100; if (array.Length >= 2 && int.TryParse(array[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2) && result2 > 0) { num = result2; } StartOfRound instance = StartOfRound.Instance; if (instance?.allPlayerScripts == null || result < 0 || result >= instance.allPlayerScripts.Length) { return; } PlayerControllerB val = instance.allPlayerScripts[result]; if ((Object)(object)val == (Object)null || val.isPlayerDead) { return; } try { val.health = num; val.criticallyInjured = false; val.hasBeenCriticallyInjured = false; val.bleedingHeavily = false; try { val.MakeCriticallyInjured(false); } catch { } if ((Object)(object)val.playerBodyAnimator != (Object)null) { val.playerBodyAnimator.SetBool("Limp", false); } if (((NetworkBehaviour)val).IsOwner) { HUDManager instance2 = HUDManager.Instance; if (instance2 != null) { instance2.UpdateHealthUI(num, false); } } } catch (Exception ex) { Plugin.DebugLog("Client heal: " + ex.Message); } } private static void ApplyTp(string rest) { //IL_0100: Unknown result type (might be due to invalid IL or missing references) string[] array = rest.Split(':'); if (array.Length < 7 || !int.TryParse(array[0], out var result) || !float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) || !float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3) || !float.TryParse(array[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result4)) { return; } bool isInElevator = array[4] == "1"; bool isInHangarShipRoom = array[5] == "1"; bool isInsideFactory = array[6] == "1"; StartOfRound instance = StartOfRound.Instance; if (instance?.allPlayerScripts == null || result < 0 || result >= instance.allPlayerScripts.Length) { return; } PlayerControllerB val = instance.allPlayerScripts[result]; if ((Object)(object)val == (Object)null || val.isPlayerDead) { return; } try { Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(result2, result3, result4); val.isInElevator = isInElevator; val.isInHangarShipRoom = isInHangarShipRoom; val.isInsideFactory = isInsideFactory; val.TeleportPlayer(val2, false, 0f, false, true); val.teleportingThisFrame = true; } catch (Exception ex) { Plugin.DebugLog("Client tp: " + ex.Message); } } private static void ApplyMute(string rest) { string[] array = rest.Split(':'); if (array.Length >= 2 && ulong.TryParse(array[0].Trim(), out var result) && result != 0L) { if (array[1].Trim() == "1") { MutedSteamIds.Add(result); } else { MutedSteamIds.Remove(result); } ApplyVoiceMuteState(); } } private static void ApplyWeather(string rest) { //IL_0049: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Invalid comparison between Unknown and I4 //IL_0063: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected I4, but got Unknown if (!Enum.TryParse(rest, ignoreCase: true, out LevelWeatherType result)) { return; } TimeOfDay instance = TimeOfDay.Instance; StartOfRound instance2 = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null) { return; } try { DisableAllWeatherFully(instance); instance.currentWeatherVariable = 0f; instance.currentWeatherVariable2 = 0f; instance.currentLevelWeather = result; if ((Object)(object)instance2.currentLevel != (Object)null) { instance2.currentLevel.currentWeather = result; } if ((int)result == -1) { StopStormyLightningResidue(); return; } int num = (int)result; if (instance.effects == null || num < 0 || num >= instance.effects.Length) { return; } WeatherEffect val = instance.effects[num]; if (val != null) { val.effectEnabled = true; val.transitioning = false; if ((Object)(object)val.effectObject != (Object)null) { val.effectObject.SetActive(true); } if ((Object)(object)val.effectPermanentObject != (Object)null) { val.effectPermanentObject.SetActive(true); } } } catch (Exception ex) { Plugin.DebugLog("Client weather: " + ex.Message); } } private static void DisableAllWeatherFully(TimeOfDay tod) { if (tod?.effects == null) { return; } try { tod.DisableAllWeather(true); } catch { } for (int i = 0; i < tod.effects.Length; i++) { WeatherEffect val = tod.effects[i]; if (val == null) { continue; } try { val.effectEnabled = false; val.transitioning = false; if ((Object)(object)val.effectObject != (Object)null) { val.effectObject.SetActive(false); } if ((Object)(object)val.effectPermanentObject != (Object)null) { val.effectPermanentObject.SetActive(false); } } catch { } } } private static void StopStormyLightningResidue() { try { StormyWeather val = Object.FindObjectOfType(true); if ((Object)(object)val == (Object)null) { return; } try { if ((Object)(object)val.staticElectricityParticle != (Object)null) { val.staticElectricityParticle.Stop(true, (ParticleSystemStopBehavior)0); AudioSource component = ((Component)val.staticElectricityParticle).GetComponent(); if ((Object)(object)component != (Object)null) { component.Stop(); } } } catch { } if ((Object)(object)((Component)val).gameObject != (Object)null && ((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(false); } } catch (Exception ex) { Plugin.DebugLog("StopStormyLightningResidue: " + ex.Message); } } private static void ApplyQuota(string rest) { if (!int.TryParse(rest, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return; } TimeOfDay instance = TimeOfDay.Instance; if ((Object)(object)instance == (Object)null) { return; } try { instance.profitQuota = result; try { instance.UpdateProfitQuotaCurrentTime(); } catch { } } catch { } } internal static void ApplyVoiceMuteState() { StartOfRound instance = StartOfRound.Instance; SoundManager instance2 = SoundManager.Instance; if (instance?.allPlayerScripts == null || instance2?.playerVoiceVolumes == null) { return; } for (int i = 0; i < instance.allPlayerScripts.Length; i++) { PlayerControllerB val = instance.allPlayerScripts[i]; if (!((Object)(object)val == (Object)null) && val.playerSteamId != 0L && MutedSteamIds.Contains(val.playerSteamId) && i >= 0 && i < instance2.playerVoiceVolumes.Length) { instance2.playerVoiceVolumes[i] = 0f; } } } private static ulong LocalSteam() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)GameNetworkManager.Instance?.localPlayerController != (Object)null) { return GameNetworkManager.Instance.localPlayerController.playerSteamId; } } catch { } try { return SteamId.op_Implicit(SteamClient.SteamId); } catch { return 0uL; } } private static string Truncate(string s, int max) { if (string.IsNullOrEmpty(s) || s.Length <= max) { return s; } return s.Substring(0, max - 1) + "…"; } } [HarmonyPatch(typeof(HUDManager), "AddChatMessage")] internal static class AdminOpsSignalPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(string chatMessage, string nameOfUserWhoTyped) { if (!Plugin.IsEnabled) { return true; } if (!string.IsNullOrEmpty(nameOfUserWhoTyped)) { return true; } if (AdminOpsClient.TryHandleWarnWhisper(chatMessage)) { return false; } if (AdminOpsClient.TryHandleSystemMessage(chatMessage)) { return false; } return true; } } [HarmonyPatch(typeof(SoundManager), "SetPlayerVoiceFilters")] internal static class MuteVoiceFilterPatch { [HarmonyPrefix] private static void Prefix() { if (Plugin.IsEnabled) { AdminOpsClient.ApplyVoiceMuteState(); } } } [HarmonyPatch] internal static class AutoOnlineLaunchPatches { private static bool _chose; private static bool _settingsLoaded; [HarmonyPatch(typeof(IngamePlayerSettings), "LoadSettingsFromPrefs")] [HarmonyPostfix] private static void LoadSettingsFromPrefs_Postfix(IngamePlayerSettings __instance) { if (!Plugin.IsEnabled || !Plugin.Config.AutoSelectOnlineMode.Value) { return; } _settingsLoaded = true; try { if (__instance.unsavedSettings != null && __instance.settings != null) { __instance.unsavedSettings.CopySettings(__instance.settings); } } catch { } TrySafeOnline("LoadSettingsFromPrefs"); } [HarmonyPatch(typeof(PreInitSceneScript), "Start")] [HarmonyPostfix] private static void Start_Postfix(PreInitSceneScript __instance) { if (Plugin.IsEnabled && Plugin.Config.AutoSelectOnlineMode.Value) { HideLaunchOptionUi(__instance); TrySafeOnline("Start"); } } [HarmonyPatch(typeof(PreInitSceneScript), "SkipToFinalSetting")] [HarmonyPostfix] private static void SkipToFinalSetting_Postfix(PreInitSceneScript __instance) { if (Plugin.IsEnabled && Plugin.Config.AutoSelectOnlineMode.Value) { TrySafeOnline("SkipToFinalSetting"); } } [HarmonyPatch(typeof(PreInitSceneScript), "PressContinueButton")] [HarmonyPostfix] private static void PressContinue_Postfix(PreInitSceneScript __instance) { if (Plugin.IsEnabled && Plugin.Config.AutoSelectOnlineMode.Value) { TrySafeOnline("PressContinue"); } } [HarmonyPatch(typeof(PreInitSceneScript), "ChooseLaunchOption")] [HarmonyPrefix] private static bool ChooseLaunchOption_Prefix(PreInitSceneScript __instance, bool online) { if (!Plugin.IsEnabled) { return true; } return !TryChooseLaunchWithoutSavingSettings(__instance, online, "vanilla-click"); } private static void TrySafeOnline(string reason) { if (_chose) { return; } PreInitSceneScript val = Object.FindObjectOfType(); if (!((Object)(object)val == (Object)null)) { HideLaunchOptionUi(val); if (_settingsLoaded && TryChooseLaunchWithoutSavingSettings(val, online: true, reason)) { _chose = true; } } } private static bool TryChooseLaunchWithoutSavingSettings(PreInitSceneScript pre, bool online, string reason) { if ((Object)(object)pre == (Object)null || pre.choseLaunchOption) { return false; } try { IngamePlayerSettings instance = IngamePlayerSettings.Instance; if ((Object)(object)instance != (Object)null) { if (_settingsLoaded && instance.unsavedSettings != null && instance.settings != null) { instance.unsavedSettings.CopySettings(instance.settings); } try { instance.SetLaunchInOnlineMode(online); } catch { } try { instance.SetPlayerFinishedLaunchOptions(); } catch { } } pre.choseLaunchOption = true; try { if ((Object)(object)pre.mainAudio != (Object)null && (Object)(object)pre.selectSFX != (Object)null) { pre.mainAudio.PlayOneShot(pre.selectSFX); } } catch { } Plugin.Log.LogInfo((object)("UEXP_Dedicated_Client: online launch without SaveChangedSettings (" + reason + ").")); if ((Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(LoadSceneDelayed(online)); } else { SceneManager.LoadScene(online ? "InitScene" : "InitSceneLANMode"); } HideLaunchOptionUi(pre); return true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Safe online launch failed: " + ex.Message)); return false; } } private static IEnumerator LoadSceneDelayed(bool online) { yield return (object)new WaitForSecondsRealtime(0.2f); SceneManager.LoadScene(online ? "InitScene" : "InitSceneLANMode"); } private static void HideLaunchOptionUi(PreInitSceneScript pre) { try { if ((Object)(object)pre.OnlineModeButton != (Object)null) { pre.OnlineModeButton.SetActive(false); } if (pre.LaunchSettingsPanels != null) { GameObject[] launchSettingsPanels = pre.LaunchSettingsPanels; foreach (GameObject val in launchSettingsPanels) { if ((Object)(object)val != (Object)null) { val.SetActive(false); } } } if ((Object)(object)pre.launchSettingsPanelsContainer != (Object)null) { pre.launchSettingsPanelsContainer.SetActive(false); } } catch { } } } internal static class ChatCommandHide { public static bool ShouldHidePlayerMessage(string? chatMessage) { if (string.IsNullOrWhiteSpace(chatMessage)) { return false; } string text = chatMessage.Trim(); if (text.Length == 0 || text[0] != '/') { return false; } string text2 = text.ToLowerInvariant(); if (text2 == "/login" || text2.StartsWith("/login ")) { return true; } bool flag; switch (text2) { case "/help": case "/commands": case "/?": flag = true; break; default: flag = false; break; } if (flag) { return true; } if (text2 == "/logout" || text2 == "/admin" || text2.StartsWith("/admin ")) { return true; } if (text2 == "/kick" || text2.StartsWith("/kick ")) { return true; } if (text2 == "/ban" || text2.StartsWith("/ban ")) { return true; } if (text2 == "/unban" || text2.StartsWith("/unban ")) { return true; } switch (text2) { case "/list": case "/bans": case "/mods": return true; default: if (!text2.StartsWith("/reset ")) { if (text2 == "/save" || text2.StartsWith("/save ")) { return true; } switch (text2) { case "/motd": case "/rules": case "/ping": case "/pong": return true; case "/when": return true; default: if (!text2.StartsWith("/report ")) { if (text2 == "/announce" || text2.StartsWith("/announce ")) { return true; } if (text2 == "/door" || text2.StartsWith("/door ")) { return true; } if (text2 == "/id" || text2.StartsWith("/id ") || text2 == "/ids" || text2.StartsWith("/ids ")) { return true; } if (text2 == "/tp" || text2.StartsWith("/tp ") || text2 == "/bring" || text2.StartsWith("/bring ")) { return true; } if (text2 == "/heal" || text2.StartsWith("/heal ") || text2 == "/healall") { return true; } if (text2 == "/credits" || text2.StartsWith("/credits ") || text2 == "/setquota" || text2.StartsWith("/setquota ") || text2 == "/quota" || text2.StartsWith("/quota ")) { return true; } if (text2 == "/weather" || text2.StartsWith("/weather ")) { return true; } if (text2 == "/mute" || text2.StartsWith("/mute ") || text2 == "/unmute" || text2.StartsWith("/unmute ")) { return true; } if (text2 == "/warn" || text2.StartsWith("/warn ") || text2 == "/warns" || text2.StartsWith("/warns ") || text2 == "/clearwarns" || text2.StartsWith("/clearwarns ")) { return true; } if (text2 == "/mod" || text2.StartsWith("/mod ") || text2 == "/unmod" || text2.StartsWith("/unmod ")) { return true; } if (text2 == "/vote" || text2.StartsWith("/vote ")) { return true; } if (text2 == "/votekick" || text2.StartsWith("/votekick ") || text2 == "/vk" || text2.StartsWith("/vk ")) { return true; } switch (text2) { case "/yes": case "/y": case "/no": case "/n": flag = true; break; default: flag = false; break; } if (flag) { return true; } if (text2 == "/dev" || text2.StartsWith("/dev")) { return true; } return false; } goto case "/report"; case "/report": return true; } } goto case "/reset"; case "/reset": return true; } } } [HarmonyPatch(typeof(HUDManager), "AddChatMessage")] internal static class HideSlashCommandLocalEchoPatch { [HarmonyPrefix] private static bool Prefix(string chatMessage, string nameOfUserWhoTyped) { if (!Plugin.IsEnabled) { return true; } if (string.IsNullOrEmpty(nameOfUserWhoTyped)) { return true; } if (ChatCommandHide.ShouldHidePlayerMessage(chatMessage)) { return false; } return true; } } [HarmonyPatch(typeof(HUDManager), "AddPlayerChatMessageClientRpc")] internal static class HideSlashCommandClientRpcPatch { [HarmonyPrefix] private static bool Prefix(string chatMessage) { if (!Plugin.IsEnabled) { return true; } if (ChatCommandHide.ShouldHidePlayerMessage(chatMessage)) { return false; } return true; } } [HarmonyPatch(typeof(GameNetworkManager), "SetConnectionDataBeforeConnecting")] internal static class ConnectionDataHandshakePatch { public const string Token = "uexpC1"; public const string VersionPrefix = "uexpCv"; [HarmonyPostfix] private static void Postfix() { if (!Plugin.IsEnabled) { return; } try { NetworkManager singleton = NetworkManager.Singleton; if (singleton?.NetworkConfig == null) { return; } byte[] connectionData = singleton.NetworkConfig.ConnectionData; if (connectionData == null || connectionData.Length == 0) { return; } string text = Encoding.ASCII.GetString(connectionData); string[] array = text.Split(','); bool flag = false; bool flag2 = false; for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (string.Equals(text2, "uexpC1", StringComparison.Ordinal)) { flag = true; } if (text2.StartsWith("uexpCv", StringComparison.Ordinal)) { flag2 = true; } } string text3 = text; if (!flag) { text3 += ",uexpC1"; } if (!flag2) { text3 += ",uexpCv1.0.3"; } if (!string.Equals(text3, text, StringComparison.Ordinal)) { singleton.NetworkConfig.ConnectionData = Encoding.ASCII.GetBytes(text3); Plugin.DebugLog("ConnectionData handshake appended (uexpC1, uexpCv1.0.3)."); } LogConfigHash(singleton); } catch (Exception ex) { Plugin.DebugLog("ConnectionData handshake failed: " + ex.Message); } } private static void LogConfigHash(NetworkManager nm) { try { ulong config = nm.NetworkConfig.GetConfig(false); int num = nm.NetworkConfig.Prefabs?.NetworkPrefabOverrideLinks?.Count ?? (-1); Plugin.DebugLog($"NGO config hash for this join: {config} prefabLinks={num}."); } catch (Exception ex) { Plugin.DebugLog("Config hash log failed: " + ex.Message); } } } internal static class DedicatedLobbySoftRefresh { private const float IntervalSeconds = 3f; private static Coroutine? _loop; private static SteamLobbyManager? _slm; private static bool _hookedDataChanged; public static void EnsureStarted(SteamLobbyManager slm) { if (Plugin.Config.DedicatedBrowserOnly.Value) { _slm = slm; EnsureDataChangedHook(); if (_loop == null && !((Object)(object)Plugin.Instance == (Object)null)) { _loop = ((MonoBehaviour)Plugin.Instance).StartCoroutine(Loop()); Plugin.DebugLog("Dedicated lobby soft-refresh started (3s)."); } } } public static void Stop() { if (_loop != null && (Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StopCoroutine(_loop); } _loop = null; _slm = null; } private static void EnsureDataChangedHook() { if (_hookedDataChanged) { return; } try { SteamMatchmaking.OnLobbyDataChanged += OnLobbyDataChanged; _hookedDataChanged = true; } catch (Exception ex) { Plugin.DebugLog("OnLobbyDataChanged hook failed: " + ex.Message); } } private static void OnLobbyDataChanged(Lobby lobby) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) try { if (!Plugin.IsEnabled || !Plugin.Config.DedicatedBrowserOnly.Value || !DedicatedLobby.IsDedicatedLobby(lobby)) { return; } SteamLobbyManager val = _slm ?? Object.FindObjectOfType(); if ((Object)(object)val?.levelListContainer == (Object)null) { return; } LobbySlot[] componentsInChildren = ((Component)val.levelListContainer).GetComponentsInChildren(true); foreach (LobbySlot val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null) { continue; } try { if (SteamId.op_Implicit(((Lobby)(ref val2.thisLobby)).Id) == SteamId.op_Implicit(((Lobby)(ref lobby)).Id)) { val2.thisLobby = lobby; if ((Object)(object)val2.LobbyName != (Object)null) { ((TMP_Text)val2.LobbyName).text = ""; } } } catch { } } } catch (Exception ex) { Plugin.DebugLog("OnLobbyDataChanged: " + ex.Message); } } private static IEnumerator Loop() { WaitForSecondsRealtime wait = new WaitForSecondsRealtime(3f); while (true) { yield return wait; if (!Plugin.Config.DedicatedBrowserOnly.Value || !MenuOverlayLifecycle.MenuUiAllowed) { break; } SteamLobbyManager val = _slm; if ((Object)(object)val == (Object)null) { val = Object.FindObjectOfType(); } if (!((Object)(object)val == (Object)null) && !((Object)(object)val.levelListContainer == (Object)null) && ((Component)val.levelListContainer).gameObject.activeInHierarchy) { try { RefreshVisibleSlots(val); } catch (Exception ex) { Plugin.DebugLog("Soft refresh: " + ex.Message); } } } _loop = null; } private static void RefreshVisibleSlots(SteamLobbyManager slm) { //IL_0027: 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_002e: 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) LobbySlot[] componentsInChildren = ((Component)slm.levelListContainer).GetComponentsInChildren(true); int num = 0; int num2 = 0; LobbySlot[] array = componentsInChildren; foreach (LobbySlot val in array) { if ((Object)(object)val == (Object)null) { continue; } try { Lobby thisLobby = val.thisLobby; if (!DedicatedLobby.IsDedicatedLobby(thisLobby)) { continue; } ((Lobby)(ref thisLobby)).Refresh(); num++; if (DedicatedLobby.IsJoinableListing(thisLobby)) { continue; } try { GameObject gameObject = ((Component)val).gameObject; if ((Object)(object)gameObject != (Object)null) { gameObject.SetActive(false); Object.Destroy((Object)(object)gameObject); num2++; } } catch { } } catch { } } if (num > 0) { Plugin.DebugLog($"Soft-refreshed {num} dedicated lobby card(s); dropped {num2}."); } if (num2 > 0) { try { DedicatedServerListReplacePatch.FitListContentHeight(slm); } catch { } } } } [HarmonyPatch(typeof(SteamLobbyManager), "LoadServerList")] internal static class DedicatedSoftRefreshOnLoadPatch { [HarmonyPostfix] private static void Postfix(SteamLobbyManager __instance) { if (Plugin.Config.DedicatedBrowserOnly.Value) { DedicatedLobbySoftRefresh.EnsureStarted(__instance); } } } [HarmonyPatch(typeof(MenuManager), "ClickJoinButton")] internal static class DedicatedSoftRefreshOnOpenPatch { [HarmonyPostfix] private static void Postfix() { if (Plugin.Config.DedicatedBrowserOnly.Value) { SteamLobbyManager val = Object.FindObjectOfType(); if ((Object)(object)val != (Object)null) { DedicatedLobbySoftRefresh.EnsureStarted(val); } } } } internal static class DedicatedModsModal { private sealed class ModsModalStatusPump : MonoBehaviour { private void Update() { PumpPendingStatus(); } } [CompilerGenerated] private static class <>O { public static UnityAction <0>__ForceClose; public static UnityAction <1>__CopyProfileCode; public static UnityAction <2>__DownloadModList; } private static GameObject? _root; private static TextMeshProUGUI? _title; private static TextMeshProUGUI? _status; private static RectTransform? _content; private static ScrollRect? _scroll; private static TMP_FontAsset? _font; private static string _serverName = ""; private static string _modsCsv = ""; private static string _profileCode = ""; private static string? _pendingStatus; private static readonly Color PanelBg = new Color(0.07f, 0.075f, 0.08f, 0.98f); private static readonly Color Accent = new Color(0.91f, 0.62f, 0.12f, 1f); private static readonly Color Text = new Color(0.95f, 0.93f, 0.86f, 1f); private static readonly Color Muted = new Color(0.72f, 0.74f, 0.7f, 1f); private static readonly Color RowBg = new Color(0.1f, 0.105f, 0.11f, 1f); private static readonly Color BtnBg = new Color(0.16f, 0.14f, 0.09f, 1f); private static readonly Color ScrollBg = new Color(0.04f, 0.04f, 0.045f, 1f); public static void Show(string serverName, string modsCsv, string profileCode) { if (!MenuOverlayLifecycle.MenuUiAllowed) { Plugin.Log.LogWarning((object)"Mods modal blocked — menu UI not active."); return; } JoinPasswordPrompt.ForceClose(); ForceClose(); _serverName = serverName ?? ""; _modsCsv = modsCsv ?? ""; _profileCode = (profileCode ?? "").Trim(); Build(); if ((Object)(object)_root == (Object)null || (Object)(object)_title == (Object)null || (Object)(object)_content == (Object)null || (Object)(object)_scroll == (Object)null) { return; } ((TMP_Text)_title).text = (string.IsNullOrWhiteSpace(serverName) ? "SERVER MODS" : serverName); ClearContent(); List list = new List(); if (!string.IsNullOrWhiteSpace(modsCsv)) { string[] array = modsCsv.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { list.Add(text); } } } if (!string.IsNullOrEmpty(_profileCode)) { AddRow("r2modman: Import/Update → From code → paste the profile code.", isEmpty: true); AddRow("Code: " + _profileCode, isEmpty: false); } else { AddRow("No profile code yet — host may still be exporting.", isEmpty: true); AddRow("Install the same mods manually, or ask the host for an r2modman code.", isEmpty: true); } if (list.Count == 0) { AddRow("No display mod names published by this host.", isEmpty: true); } else { AddRow($"Installed packages ({list.Count}):", isEmpty: true); for (int j = 0; j < list.Count; j++) { AddRow($"{j + 1}. {list[j]}", isEmpty: false); } } LayoutRebuilder.ForceRebuildLayoutImmediate(_content); Canvas.ForceUpdateCanvases(); _scroll.verticalNormalizedPosition = 1f; _root.SetActive(true); SetStatus(string.IsNullOrEmpty(_profileCode) ? "Download saves a JSON checklist. Prefer a profile code when available." : "Copy code → r2modman Import/Update → From code. Or download .r2z."); Plugin.DebugLog($"Mods modal shown ({list.Count} mods, code={!string.IsNullOrEmpty(_profileCode)})."); } public static void ForceClose() { _title = null; _status = null; _content = null; _scroll = null; _font = null; _serverName = ""; _modsCsv = ""; _profileCode = ""; if (!((Object)(object)_root != (Object)null)) { return; } GameObject root = _root; _root = null; try { GraphicRaycaster[] componentsInChildren = root.GetComponentsInChildren(true); foreach (GraphicRaycaster val in componentsInChildren) { if ((Object)(object)val != (Object)null) { ((Behaviour)val).enabled = false; } } root.SetActive(false); } catch { } Object.Destroy((Object)(object)root); } public static void DestroyIfAny() { ForceClose(); } private static void ClearContent() { if (!((Object)(object)_content == (Object)null)) { for (int num = ((Transform)_content).childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)((Transform)_content).GetChild(num)).gameObject); } } } private static void AddRow(string text, bool isEmpty) { //IL_0040: 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_0056: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_content == (Object)null)) { GameObject val = new GameObject("ModRow", new Type[3] { typeof(RectTransform), typeof(Image), typeof(LayoutElement) }); val.transform.SetParent((Transform)(object)_content, false); ((Graphic)val.GetComponent()).color = (isEmpty ? ScrollBg : RowBg); ((Graphic)val.GetComponent()).raycastTarget = false; LayoutElement component = val.GetComponent(); component.minHeight = 34f; component.preferredHeight = 34f; component.flexibleWidth = 1f; TextMeshProUGUI obj = CreateTmp(val.transform, "Label", text, 16f, isEmpty ? Muted : Text, _font, (FontStyles)0); ((TMP_Text)obj).enableWordWrapping = false; ((TMP_Text)obj).overflowMode = (TextOverflowModes)1; ((TMP_Text)obj).alignment = (TextAlignmentOptions)4097; RectTransform rectTransform = ((TMP_Text)obj).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = new Vector2(12f, 2f); rectTransform.offsetMax = new Vector2(-12f, -2f); } } private static void Build() { //IL_0046: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: 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_0129: 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_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0167: 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_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Expected O, but got Unknown //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Expected O, but got Unknown //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Expected O, but got Unknown //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03fa: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0424: Unknown result type (might be due to invalid IL or missing references) //IL_0438: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Unknown result type (might be due to invalid IL or missing references) //IL_047a: Expected O, but got Unknown //IL_04a7: Unknown result type (might be due to invalid IL or missing references) //IL_04f4: Unknown result type (might be due to invalid IL or missing references) //IL_04f9: Unknown result type (might be due to invalid IL or missing references) //IL_050b: Unknown result type (might be due to invalid IL or missing references) //IL_0525: Unknown result type (might be due to invalid IL or missing references) //IL_053e: Unknown result type (might be due to invalid IL or missing references) //IL_0557: Unknown result type (might be due to invalid IL or missing references) //IL_0566: Unknown result type (might be due to invalid IL or missing references) //IL_057f: Unknown result type (might be due to invalid IL or missing references) //IL_0589: Unknown result type (might be due to invalid IL or missing references) //IL_05c1: Unknown result type (might be due to invalid IL or missing references) //IL_05cb: Expected O, but got Unknown //IL_060f: Unknown result type (might be due to invalid IL or missing references) //IL_0615: Expected O, but got Unknown //IL_0641: Unknown result type (might be due to invalid IL or missing references) //IL_065c: Unknown result type (might be due to invalid IL or missing references) //IL_0671: Unknown result type (might be due to invalid IL or missing references) //IL_0686: Unknown result type (might be due to invalid IL or missing references) //IL_069b: Unknown result type (might be due to invalid IL or missing references) //IL_06af: Unknown result type (might be due to invalid IL or missing references) //IL_06d1: Unknown result type (might be due to invalid IL or missing references) //IL_06d8: Expected O, but got Unknown //IL_0708: Unknown result type (might be due to invalid IL or missing references) //IL_0723: Unknown result type (might be due to invalid IL or missing references) //IL_0752: Unknown result type (might be due to invalid IL or missing references) //IL_0759: Expected O, but got Unknown //IL_0774: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Expected O, but got Unknown _font = FindMenuFont(); _root = ((Component)MenuOverlayLifecycle.CreateOverlayCanvas("UEXP_ModsModal", 6100)).gameObject; Image obj = CreateImage(_root.transform, "Dim", new Color(0.01f, 0.01f, 0.015f, 0.82f)); Stretch(((Graphic)obj).rectTransform); Button obj2 = ((Component)obj).gameObject.AddComponent