using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using HarmonyLib.Public.Patching;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using LobbyCompatibility.Enums;
using LobbyCompatibility.Features;
using LobbyControl.API;
using LobbyControl.Dependency;
using LobbyControl.Networking;
using LobbyControl.Patches;
using LobbyControl.PopUp;
using LobbyControl.TerminalCommands;
using LobbyControl.Utils;
using LobbyControl.Utils.IL;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using MonoMod.RuntimeDetour;
using MonoMod.Utils;
using Steamworks;
using Steamworks.Data;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using UnityEngine;
using UnityEngine.Pool;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("EasyTextEffects")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: AssemblyCompany("mattymatty")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.5.11")]
[assembly: AssemblyInformationalVersion("2.5.11+80e4358ced3bae058de4469cf96090d2bdfc3202")]
[assembly: AssemblyProduct("LobbyControl")]
[assembly: AssemblyTitle("LobbyControl - Plugin")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.5.11.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class IsUnmanagedAttribute : Attribute
{
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace LobbyControl
{
[BepInPlugin("mattymatty.LobbyControl", "LobbyControl", "2.5.11")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal class LobbyControl : BaseUnityPlugin
{
public const string GUID = "mattymatty.LobbyControl";
public const string NAME = "LobbyControl";
public const string VERSION = "2.5.11";
public static LobbyControl Instance;
internal static ManualLogSource Log;
internal static readonly Harmony Harmony = new Harmony("mattymatty.LobbyControl");
public static bool CanModifyLobby = true;
public static bool CanSave = true;
public static bool AutoSaveEnabled = true;
public static readonly List<Hook> Hooks = new List<Hook>();
private static readonly string[] IncompatibleGUIDs = new string[4] { "com.github.tinyhoot.ShipLobby", "twig.latecompany", "McBowie.VeryLateCompany", "com.potatoepet.AdvancedCompany" };
internal static readonly List<PluginInfo> FoundIncompatibilities = new List<PluginInfo>();
private void Awake()
{
Log = ((BaseUnityPlugin)this).Logger;
Instance = this;
try
{
PluginInfo[] array = Chainloader.PluginInfos.Values.Where((PluginInfo p) => IncompatibleGUIDs.Contains(p.Metadata.GUID)).ToArray();
if (array.Length != 0)
{
StringBuilder stringBuilder = new StringBuilder("LOBBY CONTROL was DISABLED!\nIncompatible:");
FoundIncompatibilities.AddRange(array);
PluginInfo[] array2 = array;
foreach (PluginInfo val in array2)
{
Log.LogWarning((object)(val.Metadata.Name + " is incompatible!"));
stringBuilder.Append("\n").Append(val.Metadata.Name);
}
Log.LogError((object)$"{array.Length} incompatible mods found! Disabling!");
PopUpPatch.PopUps.Add(("LC_Incompatibility", stringBuilder.ToString()));
Harmony.PatchAll(typeof(PopUpPatch));
return;
}
if (LobbyCompatibilityChecker.Enabled)
{
LobbyCompatibilityChecker.Init("mattymatty.LobbyControl", Version.Parse("2.5.11"), 1, 2);
}
Log.LogInfo((object)"Initializing Configs");
PluginConfig.Init((BaseUnityPlugin)(object)this);
CommandManager.Initialize();
LobbyCommand.Init();
Log.LogInfo((object)"Patching Methods");
Harmony.PatchAll(typeof(PopUpPatch));
Harmony.PatchAll(typeof(JoinQueuePatches));
JoinQueuePatches.Init();
Harmony.PatchAll(typeof(LateJoinPatches));
Harmony.PatchAll(typeof(LimitPatcher));
Harmony.PatchAll(typeof(LobbyPatcher));
Harmony.PatchAll(typeof(LogSpamPatches));
Harmony.PatchAll(typeof(NetworkManagerPatch));
Harmony.PatchAll(typeof(SavePatches));
Harmony.PatchAll(typeof(TerminalPatch));
Log.LogInfo((object)"LobbyControl v2.5.11 Loaded!");
}
catch (Exception ex)
{
Log.LogError((object)("Exception while initializing: \n" + ex));
}
}
}
internal static class PluginConfig
{
internal static class SteamLobby
{
internal static ConfigEntry<bool> AutoLobby;
}
internal static class SaveLimit
{
internal static ConfigEntry<bool> Enabled;
}
internal static class LogSpam
{
internal static ConfigEntry<bool> Enabled;
internal static ConfigEntry<bool> CalculatePolygonPath;
}
internal static class JoinQueue
{
internal static ConfigEntry<bool> Enabled;
internal static ConfigEntry<int> MaxSize;
internal static ConfigEntry<int> ConnectionTimeout;
internal static ConfigEntry<int> ConnectionDelay;
internal static ConfigEntry<bool> TimeoutPopup;
internal static ConfigEntry<bool> ConnectionPopup;
}
internal static class Networking
{
internal static ConfigEntry<bool> Enabled;
internal static ConfigEntry<bool> SyncRadarNames;
internal static ConfigEntry<bool> ResetPlayerValues;
}
internal static void Init(BaseUnityPlugin plugin)
{
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Expected O, but got Unknown
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Expected O, but got Unknown
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: Expected O, but got Unknown
ConfigFile config = plugin.Config;
config.SaveOnConfigSet = false;
SaveLimit.Enabled = config.Bind<bool>("SaveLimit", "enabled", true, "remove the limit to the amount of items that can be saved");
SteamLobby.AutoLobby = config.Bind<bool>("SteamLobby", "auto_lobby", false, "automatically reopen the lobby as soon as you reach orbit");
LogSpam.Enabled = config.Bind<bool>("LogSpam", "enabled", true, "prevent some annoying log spam");
LogSpam.CalculatePolygonPath = config.Bind<bool>("LogSpam", "CalculatePolygonPath", true, "stop pathfinding for dead Enemies");
JoinQueue.Enabled = config.Bind<bool>("JoinQueue", "enabled", true, "handle joining players as a queue instead of at the same time");
JoinQueue.MaxSize = config.Bind<int>("JoinQueue", "max_size", 3, new ConfigDescription("max number of players in queue ( if queue is full extra connections will be refused )", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-1, 10), Array.Empty<object>()));
JoinQueue.ConnectionTimeout = config.Bind<int>("JoinQueue", "connection_timeout_ms", 40000, new ConfigDescription("After how much time discard a hanging connection", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10000, int.MaxValue), Array.Empty<object>()));
JoinQueue.ConnectionDelay = config.Bind<int>("JoinQueue", "connection_delay_ms", 2000, new ConfigDescription("Delay between each successful connection", (AcceptableValueBase)(object)new AcceptableValueRange<int>(100, int.MaxValue), Array.Empty<object>()));
JoinQueue.TimeoutPopup = config.Bind<bool>("JoinQueue", "timeout_notification", true, "show a popup when a client fails to join before the timeout");
JoinQueue.ConnectionPopup = config.Bind<bool>("JoinQueue", "connection_notification", false, "show a popup when a client tries to join");
Networking.Enabled = config.Bind<bool>("Networking", "enabled", true, "handle extra actions requested by host");
Networking.SyncRadarNames = config.Bind<bool>("Networking", "sync_radar_names", false, "allow host to reorder radar names to align clients\nWARNING: all clients need to have the mod installed or desyncs might will happen");
Networking.ResetPlayerValues = config.Bind<bool>("Networking", "reset_player_values", true, "allow host to force clients to reset most fields of a playerObject ( fix for invisible players )");
JoinQueue.ConnectionTimeout.SettingChanged += delegate
{
NetworkManager singleton = NetworkManager.Singleton;
if (singleton != null)
{
singleton.NetworkConfig.ClientConnectionBufferTimeout = JoinQueue.ConnectionTimeout.Value / 1000 * 4;
}
};
if (LethalConfigProxy.Enabled)
{
LethalConfigProxy.AddConfig(SaveLimit.Enabled);
LethalConfigProxy.AddConfig(SteamLobby.AutoLobby);
LethalConfigProxy.AddConfig(LogSpam.Enabled);
LethalConfigProxy.AddConfig(LogSpam.CalculatePolygonPath);
LethalConfigProxy.AddConfig(JoinQueue.Enabled);
LethalConfigProxy.AddConfig(JoinQueue.MaxSize);
LethalConfigProxy.AddConfig(JoinQueue.ConnectionTimeout);
LethalConfigProxy.AddConfig(JoinQueue.ConnectionDelay);
LethalConfigProxy.AddConfig(JoinQueue.TimeoutPopup);
LethalConfigProxy.AddConfig(JoinQueue.ConnectionPopup);
LethalConfigProxy.AddConfig(Networking.Enabled);
LethalConfigProxy.AddConfig(Networking.SyncRadarNames);
LethalConfigProxy.AddConfig(Networking.ResetPlayerValues);
}
PropertyInfo property = ((object)config).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic);
Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(config, null);
dictionary.Clear();
config.Save();
config.SaveOnConfigSet = true;
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "mattymatty.LobbyControl";
public const string PLUGIN_NAME = "LobbyControl";
public const string PLUGIN_VERSION = "2.5.11";
}
}
namespace LobbyControl.Utils
{
public static class HudUtils
{
[CompilerGenerated]
private sealed class <ShowMessageAfterDelay>d__1 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public float delay;
public string title;
public string text;
public bool isWarning;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <ShowMessageAfterDelay>d__1(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
if (delay > 0f)
{
<>2__current = (object)new WaitForSeconds(delay);
<>1__state = 1;
return true;
}
goto IL_0050;
case 1:
<>1__state = -1;
goto IL_0050;
case 2:
{
<>1__state = -1;
HUDManager.Instance.DisplayTip(title, text, isWarning, false, "LC_Tip1");
return false;
}
IL_0050:
<>2__current = WaitForAnimation;
<>1__state = 2;
return true;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <ShowTipAfterDelay>d__2 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public float delay;
public string title;
public string text;
public string saveKey;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <ShowTipAfterDelay>d__2(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
if (delay > 0f)
{
<>2__current = (object)new WaitForSeconds(delay);
<>1__state = 1;
return true;
}
goto IL_0050;
case 1:
<>1__state = -1;
goto IL_0050;
case 2:
{
<>1__state = -1;
HUDManager.Instance.DisplayTip(title, text, false, true, saveKey);
return false;
}
IL_0050:
<>2__current = WaitForAnimation;
<>1__state = 2;
return true;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private static readonly WaitUntil WaitForAnimation = new WaitUntil((Func<bool>)delegate
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
AnimatorStateInfo currentAnimatorStateInfo = HUDManager.Instance.tipsPanelAnimator.GetCurrentAnimatorStateInfo(0);
return ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime >= 1f;
});
[IteratorStateMachine(typeof(<ShowMessageAfterDelay>d__1))]
internal static IEnumerator ShowMessageAfterDelay(string title, string text, float delay = 0f, bool isWarning = false)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <ShowMessageAfterDelay>d__1(0)
{
title = title,
text = text,
delay = delay,
isWarning = isWarning
};
}
[IteratorStateMachine(typeof(<ShowTipAfterDelay>d__2))]
internal static IEnumerator ShowTipAfterDelay(string title, string text, float delay, string saveKey)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <ShowTipAfterDelay>d__2(0)
{
title = title,
text = text,
delay = delay,
saveKey = saveKey
};
}
}
public static class RPCUtils
{
private static readonly MethodInfo BeginSendClientRpc = AccessTools.Method(typeof(NetworkBehaviour), "__beginSendClientRpc", (Type[])null, (Type[])null);
private static readonly MethodInfo BeginSendServerRpc = AccessTools.Method(typeof(NetworkBehaviour), "__beginSendServerRpc", (Type[])null, (Type[])null);
internal static bool TryGetRpcID(MethodInfo methodInfo, out uint rpcID)
{
//IL_002c: 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_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_0046: 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)
Collection<Instruction> instructions = PatchManager.GetMethodPatcher((MethodBase)methodInfo).CopyOriginal().Definition.Body.Instructions;
rpcID = 0u;
for (int i = 0; i < instructions.Count; i++)
{
if (instructions[i].OpCode == OpCodes.Ldc_I4 && instructions[i - 1].OpCode == OpCodes.Ldarg_0)
{
rpcID = (uint)(int)instructions[i].Operand;
}
if (!(instructions[i].OpCode != OpCodes.Call))
{
object operand = instructions[i].Operand;
MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null);
if (val != null && (Extensions.Is((MemberReference)(object)val, (MemberInfo)BeginSendClientRpc) || Extensions.Is((MemberReference)(object)val, (MemberInfo)BeginSendServerRpc)))
{
LobbyControl.Log.LogDebug((object)$"Rpc Id found for {methodInfo.Name}: {rpcID}U");
return true;
}
}
}
LobbyControl.Log.LogFatal((object)("Cannot find Rpc ID for " + methodInfo.Name));
return false;
}
}
}
namespace LobbyControl.Utils.IL
{
internal class ILInjector
{
[CompilerGenerated]
private sealed class <GetRelativeInstructions>d__34 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable
{
private int <>1__state;
private CodeInstruction <>2__current;
private int <>l__initialThreadId;
public ILInjector <>4__this;
private int offset;
public int <>3__offset;
private int size;
public int <>3__size;
private int <i>5__2;
CodeInstruction IEnumerator<CodeInstruction>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <GetRelativeInstructions>d__34(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
int num = <>1__state;
ILInjector iLInjector = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
<i>5__2 = 0;
break;
case 1:
<>1__state = -1;
<i>5__2++;
break;
}
if (<i>5__2 < size)
{
<>2__current = iLInjector.instructions[iLInjector.index + offset + <i>5__2];
<>1__state = 1;
return true;
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
{
<GetRelativeInstructions>d__34 <GetRelativeInstructions>d__;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
<GetRelativeInstructions>d__ = this;
}
else
{
<GetRelativeInstructions>d__ = new <GetRelativeInstructions>d__34(0)
{
<>4__this = <>4__this
};
}
<GetRelativeInstructions>d__.offset = <>3__offset;
<GetRelativeInstructions>d__.size = <>3__size;
return <GetRelativeInstructions>d__;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
}
}
private const string INVALID = "Injector is invalid";
private List<CodeInstruction> instructions = instructions.ToList();
private ILGenerator generator;
private int index;
private int matchEnd;
public int Index
{
get
{
return index;
}
set
{
index = value;
}
}
public bool IsValid
{
get
{
if (instructions != null)
{
return IsIndexValid(index);
}
return false;
}
}
public CodeInstruction Instruction
{
get
{
if (!IsIndexInRange(index))
{
return null;
}
return instructions[index];
}
set
{
if (!IsIndexInRange(index))
{
throw new InvalidOperationException($"Current index {index} is out of range of instruction count {instructions.Count}");
}
instructions[index] = value;
}
}
public CodeInstruction LastMatchedInstruction
{
get
{
int num = matchEnd - 1;
if (!IsIndexInRange(num))
{
return null;
}
return instructions[num];
}
set
{
int num = matchEnd - 1;
if (!IsIndexInRange(num))
{
throw new InvalidOperationException($"Last matched index {index} is out of range of instruction count {instructions.Count}");
}
instructions[num] = value;
}
}
public ICollection<CodeInstruction> Instructions => instructions.AsReadOnly();
public ILInjector(IEnumerable<CodeInstruction> instructions, ILGenerator generator = null)
{
this.generator = generator;
matchEnd = -1;
base..ctor();
}
public ILInjector GoToStart()
{
matchEnd = index;
index = 0;
return this;
}
public ILInjector GoToEnd()
{
matchEnd = index;
index = instructions.Count;
return this;
}
public ILInjector Forward(int offset)
{
if (!IsValid)
{
return this;
}
matchEnd = index;
index = Math.Clamp(index + offset, -1, instructions.Count);
return this;
}
public ILInjector Back(int offset)
{
return Forward(-offset);
}
private void MarkInvalid()
{
index = -1;
matchEnd = -1;
}
private void Search(bool forward, ILMatcher[] predicates)
{
if (!IsValid)
{
return;
}
int num = 1;
if (!forward)
{
num = -1;
index--;
}
while (forward ? (index < instructions.Count) : (index >= 0))
{
if (forward && index + predicates.Length > instructions.Count)
{
index = instructions.Count;
break;
}
int i;
for (i = 0; i < predicates.Length && predicates[i].Matches(instructions[index + i]); i++)
{
}
if (i == predicates.Length)
{
matchEnd = index + i;
return;
}
index += num;
}
MarkInvalid();
}
public ILInjector Find(params ILMatcher[] predicates)
{
Search(forward: true, predicates);
return this;
}
public ILInjector ReverseFind(params ILMatcher[] predicates)
{
Search(forward: false, predicates);
return this;
}
public ILInjector GoToPush(int popIndex)
{
if (!IsValid)
{
return this;
}
matchEnd = index;
index--;
int num = 0;
while (index >= 0)
{
CodeInstruction instruction = instructions[index];
num += instruction.PushCount();
num -= instruction.PopCount();
if (num >= popIndex)
{
return this;
}
index--;
}
return this;
}
public ILInjector SkipBranch()
{
if (Instruction == null)
{
return this;
}
if (!(Instruction.operand is Label label))
{
throw new InvalidOperationException($"Current instruction is not a branch: {Instruction}");
}
return FindLabel(label);
}
public ILInjector FindLabel(Label label)
{
if (label == default(Label))
{
return this;
}
matchEnd = index;
for (index = 0; index < instructions.Count; index++)
{
if (instructions[index].labels.Contains(label))
{
return this;
}
}
MarkInvalid();
return this;
}
public ILInjector GoToMatchEnd()
{
index = matchEnd;
return this;
}
public ILInjector GoToLastMatchedInstruction()
{
if (!IsIndexValid(matchEnd))
{
return this;
}
index = matchEnd - 1;
return this;
}
private bool IsIndexValid(int index)
{
return index != -1;
}
private bool IsIndexInRange(int index)
{
if (index >= 0)
{
return index < instructions.Count;
}
return false;
}
public CodeInstruction GetRelativeInstruction(int offset)
{
if (!IsValid)
{
throw new InvalidOperationException("Injector is invalid");
}
int num = index + offset;
if (!IsIndexInRange(num))
{
throw new IndexOutOfRangeException($"Offset {offset} would read out of bounds at index {num}");
}
return instructions[num];
}
public ILInjector SetRelativeInstruction(int offset, CodeInstruction instruction)
{
if (!IsValid)
{
throw new InvalidOperationException("Injector is invalid");
}
int num = index + offset;
if (!IsIndexInRange(num))
{
throw new IndexOutOfRangeException($"Offset {offset} would write out of bounds at index {num}");
}
instructions[num] = instruction;
return this;
}
[IteratorStateMachine(typeof(<GetRelativeInstructions>d__34))]
public IEnumerable<CodeInstruction> GetRelativeInstructions(int offset, int size)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <GetRelativeInstructions>d__34(-2)
{
<>4__this = this,
<>3__offset = offset,
<>3__size = size
};
}
public IEnumerable<CodeInstruction> GetRelativeInstructions(int size)
{
return GetRelativeInstructions(0, size);
}
private void GetLastMatchRangeAbsolute(out int start, out int end)
{
start = index;
end = matchEnd;
if (start > end)
{
int num = end;
int num2 = start;
start = num;
end = num2;
}
}
private void GetLastMatchRange(out int start, out int size)
{
GetLastMatchRangeAbsolute(out start, out var end);
if (start < 0 || start >= instructions.Count)
{
throw new InvalidOperationException($"Last match range starts at invalid index {start}");
}
if (end < 0 || end > instructions.Count)
{
throw new InvalidOperationException($"Last match range ends at invalid index {end}");
}
size = end - start;
}
public List<CodeInstruction> GetLastMatch()
{
GetLastMatchRange(out var start, out var size);
return instructions.GetRange(start, size);
}
public ILInjector DefineLabel(out Label label)
{
if (generator == null)
{
throw new InvalidOperationException("No ILGenerator was provided");
}
label = generator.DefineLabel();
return this;
}
public ILInjector AddLabel(out Label label)
{
DefineLabel(out label);
return AddLabel(label);
}
public ILInjector AddLabel(Label label)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
Instruction = new CodeInstruction(Instruction);
Instruction.labels.Add(label);
return this;
}
public ILInjector InsertInPlace(params CodeInstruction[] instructions)
{
if (!IsValid)
{
throw new InvalidOperationException("Injector is invalid");
}
this.instructions.InsertRange(index, instructions);
if (matchEnd >= index)
{
matchEnd += instructions.Length;
}
return this;
}
public ILInjector Insert(params CodeInstruction[] instructions)
{
InsertInPlace(instructions);
index += instructions.Length;
return this;
}
public ILInjector InsertInPlaceAfterBranch(params CodeInstruction[] instructions)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
if (!IsValid)
{
throw new InvalidOperationException("Injector is invalid");
}
List<Label> labels = Instruction.labels;
Instruction = new CodeInstruction(Instruction);
Instruction.labels.Clear();
this.instructions.InsertRange(index, instructions);
Instruction.labels.AddRange(labels);
if (matchEnd >= index)
{
matchEnd += instructions.Length;
}
return this;
}
public ILInjector InsertAfterBranch(params CodeInstruction[] instructions)
{
InsertInPlaceAfterBranch(instructions);
index += instructions.Length;
return this;
}
public ILInjector RemoveAllPreviousInstructions()
{
if (!IsValid)
{
throw new InvalidOperationException("Injector is invalid");
}
instructions.RemoveRange(0, index);
matchEnd -= index;
if (matchEnd < 0)
{
matchEnd = 0;
}
index = 0;
return this;
}
public ILInjector Remove(int count = 1)
{
if (!IsValid)
{
throw new InvalidOperationException("Injector is invalid");
}
instructions.RemoveRange(index, count);
if (matchEnd > index)
{
matchEnd = Math.Max(index, matchEnd - count);
}
return this;
}
public ILInjector RemoveLastMatch()
{
GetLastMatchRange(out var start, out var size);
List<Label> labels = instructions[start].labels;
instructions.RemoveRange(start, size);
index = start;
matchEnd = start;
instructions[start].labels.AddRange(labels);
return this;
}
public ILInjector ReplaceLastMatch(params CodeInstruction[] replacementInstructions)
{
if (replacementInstructions.Length == 0)
{
throw new ArgumentException("Cannot replace a match with an empty array.");
}
GetLastMatchRange(out var start, out var size);
List<Label> labels = instructions[start].labels;
instructions.RemoveRange(start, size);
instructions.InsertRange(start, replacementInstructions);
index = start;
matchEnd = start + replacementInstructions.Length;
instructions[start].labels.AddRange(labels);
return this;
}
public List<CodeInstruction> ReleaseInstructions()
{
List<CodeInstruction> result = instructions;
instructions = null;
return result;
}
public ILInjector PrintContext(int context, string header = "")
{
if (!IsValid)
{
throw new InvalidOperationException("Injector is invalid (" + header + ")");
}
StringBuilder stringBuilder = new StringBuilder(header);
if (header.Length > 0)
{
stringBuilder.Append(':');
}
stringBuilder.AppendLine();
GetLastMatchRangeAbsolute(out var start, out var end);
int num = Math.Min(end + 1 + context, instructions.Count);
for (int i = Math.Max(start - context, 0); i < num; i++)
{
if (end == -1 && i == index)
{
stringBuilder.Append("╶> ");
}
else
{
if (i >= start && i < end)
{
stringBuilder.Append("│");
}
else
{
stringBuilder.Append(" ");
}
if (i == index)
{
stringBuilder.Append("╶> ");
}
else
{
stringBuilder.Append(" ");
}
}
stringBuilder.AppendLine($"{i}: {instructions[i]}");
}
LobbyControl.Log.LogFatal((object)stringBuilder);
return this;
}
public ILInjector PrintContext(string header = "")
{
return PrintContext(4, header);
}
}
internal interface ILMatcher
{
bool Matches(CodeInstruction instruction);
ILMatcher CaptureAs(out CodeInstruction variable)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
variable = new CodeInstruction(OpCodes.Nop, (object)null);
return new InstructionCapturingMatcher(this, variable);
}
unsafe ILMatcher CaptureOperandAs<T>(out T operand) where T : unmanaged
{
operand = default(T);
fixed (T* operand2 = &operand)
{
return new OperandCapturingMatcher<T>(this, operand2);
}
}
static ILMatcher Not(ILMatcher matcher)
{
return new NotMatcher(matcher);
}
static ILMatcher Opcode(OpCode opcode)
{
return new OpcodeMatcher(opcode);
}
static ILMatcher Opcodes(params OpCode[] opcodes)
{
return new OpcodesMatcher(opcodes);
}
static ILMatcher OpcodeOperand(OpCode opcode, object operand)
{
return new OpcodeOperandMatcher(opcode, operand);
}
static ILMatcher Instruction(CodeInstruction instruction)
{
return new InstructionMatcher(instruction);
}
static ILMatcher Ldarg(int? arg = null)
{
return new LdargMatcher(arg);
}
static ILMatcher Ldloc(int? loc = null)
{
return new LdlocMatcher(loc);
}
static ILMatcher Stloc(int? loc = null)
{
return new StlocMatcher(loc);
}
static ILMatcher Ldc(int? value = null)
{
return new LdcI32Matcher(value);
}
static ILMatcher Branch()
{
return new BranchMatcher();
}
static ILMatcher Ldfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
if (field == null)
{
LobbyControl.Log.LogWarning((object)$"Field passed to ILMatcher.Ldfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})");
}
return new OpcodeOperandMatcher(OpCodes.Ldfld, field);
}
static ILMatcher Ldsfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
if (field == null)
{
LobbyControl.Log.LogWarning((object)$"Field passed to ILMatcher.Ldsfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})");
}
return new OpcodeOperandMatcher(OpCodes.Ldsfld, field);
}
static ILMatcher Stfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
if (field == null)
{
LobbyControl.Log.LogWarning((object)$"Field passed to ILMatcher.Stfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})");
}
return new OpcodeOperandMatcher(OpCodes.Stfld, field);
}
static ILMatcher Stsfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
if (field == null)
{
LobbyControl.Log.LogWarning((object)$"Field passed to ILMatcher.Stsfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})");
}
return new OpcodeOperandMatcher(OpCodes.Stsfld, field);
}
static ILMatcher Callvirt(MethodBase method, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
if (method == null)
{
LobbyControl.Log.LogWarning((object)$"Method passed to ILMatcher.Callvirt() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})");
}
return OpcodeOperand(OpCodes.Callvirt, method);
}
static ILMatcher Call(MethodBase method, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
if (method == null)
{
LobbyControl.Log.LogWarning((object)$"Method passed to ILMatcher.Call() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})");
}
return OpcodeOperand(OpCodes.Call, method);
}
static ILMatcher Predicate(Func<CodeInstruction, bool> predicate)
{
return new PredicateMatcher(predicate);
}
static ILMatcher Predicate(Func<FieldInfo, bool> predicate)
{
return new PredicateMatcher((CodeInstruction insn) => insn.operand is FieldInfo arg && predicate(arg));
}
}
internal class NotMatcher : ILMatcher
{
private readonly ILMatcher matcher;
public NotMatcher(ILMatcher matcher)
{
this.matcher = matcher;
base..ctor();
}
public bool Matches(CodeInstruction instruction)
{
return !matcher.Matches(instruction);
}
}
internal class OpcodeMatcher : ILMatcher
{
private readonly OpCode opcode;
public OpcodeMatcher(OpCode opcode)
{
this.opcode = opcode;
base..ctor();
}
public bool Matches(CodeInstruction instruction)
{
return instruction.opcode == opcode;
}
}
internal class OpcodesMatcher : ILMatcher
{
private readonly OpCode[] opcodes;
public OpcodesMatcher(OpCode[] opcodes)
{
this.opcodes = opcodes;
base..ctor();
}
public bool Matches(CodeInstruction instruction)
{
return opcodes.Contains(instruction.opcode);
}
}
internal class OpcodeOperandMatcher : ILMatcher
{
private readonly OpCode opcode;
private readonly object operand;
public OpcodeOperandMatcher(OpCode opcode, object operand)
{
this.opcode = opcode;
this.operand = operand;
base..ctor();
}
public bool Matches(CodeInstruction instruction)
{
if (instruction.opcode == opcode)
{
return instruction.operand == operand;
}
return false;
}
}
internal class InstructionMatcher : ILMatcher
{
private readonly OpCode opcode = instruction.opcode;
private readonly object operand = instruction.operand;
private readonly Label[] labels = instruction.labels.ToArray();
public InstructionMatcher(CodeInstruction instruction)
{
}
public bool Matches(CodeInstruction instruction)
{
if (instruction.opcode != opcode)
{
return false;
}
if (instruction.operand != operand)
{
return false;
}
if (instruction.labels.Count != labels.Length)
{
return false;
}
for (int i = 0; i < labels.Length; i++)
{
if (labels[i] != instruction.labels[i])
{
return false;
}
}
return true;
}
}
internal class LdargMatcher : ILMatcher
{
private readonly int? arg;
public LdargMatcher(int? arg)
{
this.arg = arg;
base..ctor();
}
public bool Matches(CodeInstruction instruction)
{
if (!arg.HasValue)
{
return instruction.GetLdargIndex().HasValue;
}
return instruction.GetLdargIndex() == arg;
}
}
internal class LdlocMatcher : ILMatcher
{
private readonly int? loc;
public LdlocMatcher(int? loc)
{
this.loc = loc;
base..ctor();
}
public bool Matches(CodeInstruction instruction)
{
if (!loc.HasValue)
{
return instruction.GetLdlocIndex().HasValue;
}
return instruction.GetLdlocIndex() == loc;
}
}
internal class StlocMatcher : ILMatcher
{
private readonly int? loc;
public StlocMatcher(int? loc)
{
this.loc = loc;
base..ctor();
}
public bool Matches(CodeInstruction instruction)
{
if (!loc.HasValue)
{
return instruction.GetStlocIndex().HasValue;
}
return instruction.GetStlocIndex() == loc;
}
}
internal class LdcI32Matcher : ILMatcher
{
private readonly int? value;
public LdcI32Matcher(int? value)
{
this.value = value;
base..ctor();
}
public bool Matches(CodeInstruction instruction)
{
if (!value.HasValue)
{
return instruction.GetLdcI32().HasValue;
}
return instruction.GetLdcI32() == value;
}
}
internal class BranchMatcher : ILMatcher
{
public bool Matches(CodeInstruction instruction)
{
Label? label = default(Label?);
return CodeInstructionExtensions.Branches(instruction, ref label);
}
}
internal class PredicateMatcher : ILMatcher
{
private readonly Func<CodeInstruction, bool> predicate;
public PredicateMatcher(Func<CodeInstruction, bool> predicate)
{
this.predicate = predicate;
base..ctor();
}
public bool Matches(CodeInstruction instruction)
{
return predicate(instruction);
}
}
internal class InstructionCapturingMatcher : ILMatcher
{
private readonly ILMatcher matcher;
private readonly CodeInstruction variable;
public InstructionCapturingMatcher(ILMatcher matcher, CodeInstruction variable)
{
this.matcher = matcher;
this.variable = variable;
base..ctor();
}
public bool Matches(CodeInstruction instruction)
{
bool flag = matcher.Matches(instruction);
if (flag)
{
variable.opcode = instruction.opcode;
variable.operand = instruction.operand;
variable.blocks = instruction.blocks.ToList();
variable.labels = instruction.labels.ToList();
}
return flag;
}
}
internal class OperandCapturingMatcher<T> : ILMatcher where T : unmanaged
{
private readonly ILMatcher matcher;
private unsafe readonly T* operand;
public unsafe OperandCapturingMatcher(ILMatcher matcher, T* operand)
{
this.matcher = matcher;
this.operand = operand;
base..ctor();
}
public unsafe bool Matches(CodeInstruction instruction)
{
bool flag = matcher.Matches(instruction);
if (flag)
{
*operand = (T)instruction.operand;
}
return flag;
}
}
internal static class InstructionUtilities
{
public static CodeInstruction MakeLdarg(int index)
{
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Expected O, but got Unknown
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Expected O, but got Unknown
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Expected O, but got Unknown
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Expected O, but got Unknown
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Expected O, but got Unknown
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
if (index < 256)
{
return (CodeInstruction)(index switch
{
0 => (object)new CodeInstruction(OpCodes.Ldarg_0, (object)null),
1 => (object)new CodeInstruction(OpCodes.Ldarg_1, (object)null),
2 => (object)new CodeInstruction(OpCodes.Ldarg_2, (object)null),
3 => (object)new CodeInstruction(OpCodes.Ldarg_3, (object)null),
_ => (object)new CodeInstruction(OpCodes.Ldarg_S, (object)index),
});
}
return new CodeInstruction(OpCodes.Ldarg, (object)index);
}
public static int PopCount(this CodeInstruction instruction)
{
if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt || instruction.opcode == OpCodes.Newobj)
{
MethodBase methodBase = (MethodBase)instruction.operand;
int num = methodBase.GetParameters().Length;
if (!methodBase.IsStatic)
{
num++;
}
return num;
}
if (instruction.opcode == OpCodes.Ret)
{
return 1;
}
return instruction.opcode.StackBehaviourPop switch
{
StackBehaviour.Pop0 => 0,
StackBehaviour.Pop1 => 1,
StackBehaviour.Pop1_pop1 => 2,
StackBehaviour.Popi => 1,
StackBehaviour.Popi_pop1 => 2,
StackBehaviour.Popi_popi => 2,
StackBehaviour.Popi_popi8 => 2,
StackBehaviour.Popi_popi_popi => 3,
StackBehaviour.Popi_popr4 => 2,
StackBehaviour.Popi_popr8 => 2,
StackBehaviour.Popref => 1,
StackBehaviour.Popref_pop1 => 2,
StackBehaviour.Popref_popi => 2,
StackBehaviour.Popref_popi_popi => 3,
StackBehaviour.Popref_popi_popi8 => 3,
StackBehaviour.Popref_popi_popr4 => 3,
StackBehaviour.Popref_popi_popr8 => 3,
StackBehaviour.Popref_popi_popref => 3,
StackBehaviour.Varpop => throw new NotImplementedException($"Variable pop on non-call instruction '{instruction}'"),
StackBehaviour.Popref_popi_pop1 => 3,
_ => throw new NotSupportedException($"StackBehaviourPop of {instruction.opcode.StackBehaviourPop} was not a pop for instruction '{instruction}'"),
};
}
public static int PushCount(this CodeInstruction instruction)
{
if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt || instruction.opcode == OpCodes.Newobj)
{
if (instruction.operand is MethodInfo methodInfo && methodInfo.ReturnType == typeof(void))
{
return 0;
}
return 1;
}
return instruction.opcode.StackBehaviourPush switch
{
StackBehaviour.Push0 => 0,
StackBehaviour.Push1 => 1,
StackBehaviour.Push1_push1 => 2,
StackBehaviour.Pushi => 1,
StackBehaviour.Pushi8 => 1,
StackBehaviour.Pushr4 => 1,
StackBehaviour.Pushr8 => 1,
StackBehaviour.Pushref => 1,
StackBehaviour.Varpush => throw new NotImplementedException($"Variable push on non-call instruction '{instruction}'"),
_ => throw new NotSupportedException($"StackBehaviourPush of {instruction.opcode.StackBehaviourPush} was not a push for instruction '{instruction}'"),
};
}
public static int? GetLdargIndex(this CodeInstruction instruction)
{
OpCode opcode = instruction.opcode;
if (opcode == OpCodes.Ldarg_0)
{
return 0;
}
if (opcode == OpCodes.Ldarg_1)
{
return 1;
}
if (opcode == OpCodes.Ldarg_2)
{
return 2;
}
if (opcode == OpCodes.Ldarg_3)
{
return 3;
}
if (opcode == OpCodes.Ldarg || opcode == OpCodes.Ldarg_S)
{
return instruction.operand as int?;
}
return null;
}
public static int? GetLdlocIndex(this CodeInstruction instruction)
{
OpCode opcode = instruction.opcode;
if (opcode == OpCodes.Ldloc_0)
{
return 0;
}
if (opcode == OpCodes.Ldloc_1)
{
return 1;
}
if (opcode == OpCodes.Ldloc_2)
{
return 2;
}
if (opcode == OpCodes.Ldloc_3)
{
return 3;
}
if (opcode == OpCodes.Ldloc || opcode == OpCodes.Ldloc_S)
{
return (instruction.operand as LocalBuilder)?.LocalIndex;
}
return null;
}
public static int? GetStlocIndex(this CodeInstruction instruction)
{
OpCode opcode = instruction.opcode;
if (opcode == OpCodes.Stloc_0)
{
return 0;
}
if (opcode == OpCodes.Stloc_1)
{
return 1;
}
if (opcode == OpCodes.Stloc_2)
{
return 2;
}
if (opcode == OpCodes.Stloc_3)
{
return 3;
}
if (opcode == OpCodes.Stloc || opcode == OpCodes.Stloc_S)
{
return (instruction.operand as LocalBuilder)?.LocalIndex;
}
return null;
}
public static CodeInstruction LdlocToStloc(this CodeInstruction instruction)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected O, but got Unknown
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Expected O, but got Unknown
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Expected O, but got Unknown
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Expected O, but got Unknown
OpCode opcode = instruction.opcode;
if (opcode == OpCodes.Ldloc_0)
{
return new CodeInstruction(OpCodes.Stloc_0, (object)null);
}
if (opcode == OpCodes.Ldloc_1)
{
return new CodeInstruction(OpCodes.Stloc_1, (object)null);
}
if (opcode == OpCodes.Ldloc_2)
{
return new CodeInstruction(OpCodes.Stloc_2, (object)null);
}
if (opcode == OpCodes.Ldloc_3)
{
return new CodeInstruction(OpCodes.Stloc_3, (object)null);
}
if (opcode == OpCodes.Ldloc || opcode == OpCodes.Ldloc_S)
{
return new CodeInstruction(OpCodes.Stloc, instruction.operand);
}
return null;
}
public static CodeInstruction StlocToLdloc(this CodeInstruction instruction)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected O, but got Unknown
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Expected O, but got Unknown
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Expected O, but got Unknown
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Expected O, but got Unknown
OpCode opcode = instruction.opcode;
if (opcode == OpCodes.Stloc_0)
{
return new CodeInstruction(OpCodes.Ldloc_0, (object)null);
}
if (opcode == OpCodes.Stloc_1)
{
return new CodeInstruction(OpCodes.Ldloc_1, (object)null);
}
if (opcode == OpCodes.Stloc_2)
{
return new CodeInstruction(OpCodes.Ldloc_2, (object)null);
}
if (opcode == OpCodes.Stloc_3)
{
return new CodeInstruction(OpCodes.Ldloc_3, (object)null);
}
if (opcode == OpCodes.Stloc || opcode == OpCodes.Stloc_S)
{
return new CodeInstruction(OpCodes.Ldloc, instruction.operand);
}
return null;
}
public static int? GetLdcI32(this CodeInstruction instruction)
{
OpCode opcode = instruction.opcode;
if (opcode == OpCodes.Ldc_I4_M1)
{
return -1;
}
if (opcode == OpCodes.Ldc_I4_0)
{
return 0;
}
if (opcode == OpCodes.Ldc_I4_1)
{
return 1;
}
if (opcode == OpCodes.Ldc_I4_2)
{
return 2;
}
if (opcode == OpCodes.Ldc_I4_3)
{
return 3;
}
if (opcode == OpCodes.Ldc_I4_4)
{
return 4;
}
if (opcode == OpCodes.Ldc_I4_5)
{
return 5;
}
if (opcode == OpCodes.Ldc_I4_6)
{
return 6;
}
if (opcode == OpCodes.Ldc_I4_7)
{
return 7;
}
if (opcode == OpCodes.Ldc_I4_8)
{
return 8;
}
if (opcode == OpCodes.Ldc_I4_S)
{
return instruction.operand as sbyte?;
}
if (opcode == OpCodes.Ldc_I4)
{
return instruction.operand as int?;
}
return null;
}
}
public static class ReflectionExtensions
{
public static MethodInfo GetGenericMethod(this Type type, string name, Type[] parameters, Type[] genericArgs)
{
MethodInfo[] methods = type.GetMethods();
MethodInfo[] array = methods;
foreach (MethodInfo methodInfo in array)
{
if (!(methodInfo.Name != name) && methodInfo.IsGenericMethodDefinition)
{
return methodInfo.MakeGenericMethod(genericArgs);
}
}
return null;
}
}
}
namespace LobbyControl.TerminalCommands
{
public class Command
{
public TerminalNode previousTerminalNode;
public bool awaitingConfirmation
{
get
{
return CommandManager.awaitingConfirmationCommand == this;
}
set
{
CommandManager.awaitingConfirmationCommand = (value ? this : null);
}
}
public virtual bool IsCommand(string[] args)
{
return false;
}
public virtual TerminalNode Execute(string[] args)
{
return TerminalPatch.CreateTerminalNode("Execute override was not found.\n\n");
}
public virtual TerminalNode ExecuteConfirmation(string[] args)
{
string text = args[0].ToLower();
if ("confirm".Contains(text) && text.Length > 0)
{
return OnConfirm(args);
}
if ("deny".Contains(text) && text.Length > 0)
{
return OnDeny(args);
}
return OnInvalidInput(args);
}
protected virtual TerminalNode OnConfirm(string[] args)
{
return TerminalPatch.CreateTerminalNode("OnConfirm override was not found.\n\n");
}
protected virtual TerminalNode OnDeny(string[] args)
{
return TerminalPatch.CreateTerminalNode("OnDeny override was not found.\n\n");
}
protected virtual TerminalNode OnInvalidInput(string[] args)
{
return previousTerminalNode;
}
}
internal class CommandManager
{
private static List<Command> commands = new List<Command>();
public static Command awaitingConfirmationCommand;
public static void Initialize()
{
commands = new List<Command>
{
new LobbyCommand()
};
awaitingConfirmationCommand = null;
}
public static bool TryExecuteCommand(string[] array, out TerminalNode terminalNode)
{
terminalNode = null;
if (awaitingConfirmationCommand != null)
{
Command command = awaitingConfirmationCommand;
terminalNode = command.ExecuteConfirmation(array);
command.previousTerminalNode = terminalNode;
return true;
}
Command command2 = GetCommand(array);
if (command2 == null)
{
return false;
}
terminalNode = command2.Execute(array);
command2.previousTerminalNode = terminalNode;
return true;
}
public static void OnLocalDisconnect()
{
awaitingConfirmationCommand = null;
}
public static void OnTerminalQuit()
{
awaitingConfirmationCommand = null;
}
private static Command GetCommand(string[] args)
{
Command result = null;
commands.ForEach(delegate(Command command)
{
if (result == null && command.IsCommand(args))
{
result = command;
}
});
return result;
}
}
public class LobbyCommand : Command
{
[CompilerGenerated]
private sealed class <LoadLobbyCoroutine>d__19 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
private StartOfRound <startOfRound>5__2;
private Terminal <terminal>5__3;
private bool <mem>5__4;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <LoadLobbyCoroutine>d__19(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<startOfRound>5__2 = null;
<terminal>5__3 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
//IL_01fa: Expected O, but got Unknown
//IL_021b: Unknown result type (might be due to invalid IL or missing references)
//IL_0225: Expected O, but got Unknown
//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
//IL_01cf: Expected O, but got Unknown
//IL_016c: Unknown result type (might be due to invalid IL or missing references)
//IL_0176: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
{
<>1__state = -1;
<startOfRound>5__2 = StartOfRound.Instance;
<terminal>5__3 = Object.FindObjectOfType<Terminal>();
<startOfRound>5__2.ResetShip();
VehicleController[] array = Object.FindObjectsOfType<VehicleController>();
VehicleController[] array2 = array;
foreach (VehicleController val in array2)
{
if ((Object)(object)((NetworkBehaviour)val).NetworkObject != (Object)null)
{
((NetworkBehaviour)val).NetworkObject.Despawn(false);
}
}
<mem>5__4 = GameNetworkManager.Instance.gameHasStarted;
GameNetworkManager.Instance.gameHasStarted = false;
foreach (KeyValuePair<int, GameObject> item in StartOfRound.Instance.SpawnedShipUnlockables.ToList())
{
UnlockableItem val2 = <startOfRound>5__2.unlockablesList.unlockables[item.Key];
if (val2.alreadyUnlocked && val2.spawnPrefab && !((Object)(object)item.Value == (Object)null))
{
NetworkObject component = item.Value.GetComponent<NetworkObject>();
if ((Object)(object)component != (Object)null && component.IsSpawned)
{
component.Despawn(true);
}
}
}
<startOfRound>5__2.SpawnedShipUnlockables.Clear();
<startOfRound>5__2.suitsPlaced = 0;
GameNetworkManager.Instance.ResetUnlockablesListValues(false);
<>2__current = (object)new WaitForSeconds(0.2f);
<>1__state = 1;
return true;
}
case 1:
<>1__state = -1;
<startOfRound>5__2.SetTimeAndPlanetToSavedSettings();
<startOfRound>5__2.SetMapScreenInfoToCurrentLevel();
<terminal>5__3.Start();
if (<startOfRound>5__2.connectedPlayersAmount >= 1)
{
RefreshLobby();
}
ReloadUnlockables();
<>2__current = (object)new WaitForSeconds(0.2f);
<>1__state = 2;
return true;
case 2:
<>1__state = -1;
<startOfRound>5__2.LoadAttachedVehicle();
<>2__current = (object)new WaitForSeconds(0.1f);
<>1__state = 3;
return true;
case 3:
<>1__state = -1;
<startOfRound>5__2.LoadShipGrabbableItems();
<>2__current = (object)new WaitForSeconds(0.1f);
<>1__state = 4;
return true;
case 4:
<>1__state = -1;
if (<startOfRound>5__2.connectedPlayersAmount >= 1)
{
<startOfRound>5__2.SyncShipUnlockablesServerRpc();
}
GameNetworkManager.Instance.gameHasStarted = <mem>5__4;
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private const string DefaultText = "- status : prints the current lobby status\r\n\r\nSteam:\r\n- open : open the lobby\r\n- close : close the lobby\r\n- private : set lobby to Invite Only\r\n- friend : set lobby to Friends Only\r\n- public : set lobby to Public\r\n- rename [name] : change the name of the lobby\r\n\r\nSaving:\r\n- autosave : toggle autosave for the savefile\r\n- save (name) : save the lobby\r\n- load (name) : load a savefile\r\n- switch (name) : swap savefile without loading it\r\n- clear : reset the current lobby to empty\r\n\r\nExtra:\r\n- dropall : drop all items to the ground\r\n";
private const string DefaultTextLAN = "- status : prints the current lobby status\r\n\r\nLAN:\r\n- open : set the lobby to be discoverable\r\n- close : set the lobby to be non-discoverable\r\n- rename [name] : change the name of the lobby\r\n\r\nSaving:\r\n- autosave : toggle autosave for the savefile\r\n- save (name) : save the lobby\r\n- load (name) : load a savefile\r\n- switch (name) : swap savefile without loading it\r\n- clear : reset the current lobby to empty\r\n\r\nExtra:\r\n- dropall : drop all items to the ground\r\n";
private static uint? _returnUnlockableFromStorageServerRpcID;
private static uint? _onPlayerConnectedClientRpcID;
public override bool IsCommand(string[] args)
{
if (GameNetworkManager.Instance.isHostingGame)
{
return args[0].Trim().ToLower() == "lobby";
}
return false;
}
public override TerminalNode Execute(string[] args)
{
TerminalNode node = ScriptableObject.CreateInstance<TerminalNode>();
try
{
if (Utility.IsNullOrWhiteSpace(args[1]))
{
return HelpNode();
}
switch (args[1])
{
case "status":
StatusCommand(ref node, args);
break;
case "open":
{
if (PerformOrbitCheck(node, out var errorText10))
{
return errorText10;
}
if (!LobbyControl.CanModifyLobby)
{
node.displayText = "Lobby cannot be changed at the moment\n\n";
}
else
{
OpenCommand(ref node, args);
}
break;
}
case "close":
{
if (PerformOrbitCheck(node, out var errorText7))
{
return errorText7;
}
if (!LobbyControl.CanModifyLobby)
{
node.displayText = "Lobby cannot be changed at the moment\n\n";
}
else
{
CloseCommand(ref node, args);
}
break;
}
case "private":
{
if (PerformOrbitCheck(node, out var errorText3))
{
return errorText3;
}
if (!LobbyControl.CanModifyLobby)
{
node.displayText = "Lobby cannot be changed at the moment\n\n";
}
else
{
PrivateCommand(ref node, args);
}
break;
}
case "friend":
{
if (PerformOrbitCheck(node, out var errorText11))
{
return errorText11;
}
if (!LobbyControl.CanModifyLobby)
{
node.displayText = "Lobby cannot be changed at the moment\n\n";
}
else
{
FriendCommand(ref node, args);
}
break;
}
case "public":
{
if (PerformOrbitCheck(node, out var errorText2))
{
return errorText2;
}
if (!LobbyControl.CanModifyLobby)
{
node.displayText = "Lobby cannot be changed at the moment\n\n";
}
else
{
PublicCommand(ref node, args);
}
break;
}
case "rename":
{
if (PerformOrbitCheck(node, out var errorText6))
{
return errorText6;
}
if (!LobbyControl.CanModifyLobby)
{
node.displayText = "Lobby cannot be changed at the moment\n\n";
}
else
{
RenameCommand(ref node, args);
}
break;
}
case "autosave":
AutoSaveCommand(ref node, args);
break;
case "save":
{
if (PerformOrbitCheck(node, out var errorText8))
{
return errorText8;
}
if (!LobbyControl.CanModifyLobby)
{
node.displayText = "Lobby cannot be changed at the moment\n\n";
}
else
{
SaveCommand(ref node, args);
}
break;
}
case "load":
{
if (PerformOrbitCheck(node, out var errorText4))
{
return errorText4;
}
if (!LobbyControl.CanModifyLobby)
{
node.displayText = "Lobby cannot be changed at the moment\n\n";
}
else
{
LoadCommand(ref node, args);
}
break;
}
case "switch":
{
if (PerformOrbitCheck(node, out var errorText9))
{
return errorText9;
}
if (!LobbyControl.CanModifyLobby)
{
node.displayText = "Lobby cannot be changed at the moment\n\n";
}
else
{
SwitchCommand(ref node, args);
}
break;
}
case "clear":
{
if (PerformOrbitCheck(node, out var errorText5))
{
return errorText5;
}
if (!LobbyControl.CanModifyLobby)
{
node.displayText = "Lobby cannot be changed at the moment\n\n";
}
else
{
ClearCommand(ref node, args);
}
break;
}
case "dropall":
{
if (PerformOrbitCheck(node, out var errorText))
{
return errorText;
}
if (!LobbyControl.CanModifyLobby)
{
node.displayText = "Lobby cannot be changed at the moment\n\n";
}
else
{
DropAllCommand(ref node, args);
}
break;
}
case "help":
node = HelpNode();
break;
default:
node = HelpNode();
node.displayText = "Invalid Command, options:\n" + node.displayText;
break;
}
}
catch (Exception ex)
{
LobbyControl.Log.LogError((object)("Exception:\n\n" + ex));
node.displayText = "Exception!\n\n";
}
return node;
}
private static bool StatusCommand(ref TerminalNode node, string[] args)
{
//IL_0073: 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_007a: 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_0084: 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)
GameNetworkManager instance = GameNetworkManager.Instance;
bool flag = false;
string value = instance.steamLobbyName;
string value2;
if (instance.disableSteam)
{
UnityTransport component = ((Component)NetworkManager.Singleton).GetComponent<UnityTransport>();
value2 = ((component.ConnectionData.ServerListenAddress == "0.0.0.0") ? "Public" : "Private");
}
else
{
if (!instance.currentLobby.HasValue)
{
node.displayText = "Failed to fetch lobby ( was null )\n\n";
return false;
}
Lobby value3 = instance.currentLobby.Value;
flag = LobbyPatcher.IsOpen(value3);
LobbyType visibility = LobbyPatcher.GetVisibility(value3);
value2 = ((object)(LobbyType)(ref visibility)).ToString();
value = ((Lobby)(ref value3)).GetData("name");
}
bool canSave = LobbyControl.CanSave;
StringBuilder stringBuilder = new StringBuilder("Lobby Status:");
stringBuilder.Append("\n- File is '").Append(instance.currentSaveFileName).Append("'");
stringBuilder.Append("\n- Name is '").Append(value).Append("'");
if (!instance.disableSteam)
{
stringBuilder.Append("\n- Status is ").Append(flag ? "Open" : "Closed");
}
stringBuilder.Append("\n- Visibility is ").Append(value2);
stringBuilder.Append("\n- Saving is ").Append(canSave ? "Automatic" : "Manual");
stringBuilder.Append("\n\n");
node.displayText = stringBuilder.ToString();
node.maxCharactersToType = node.displayText.Length + 2;
return true;
}
private static bool OpenCommand(ref TerminalNode node, string[] args)
{
LobbyControl.Log.LogDebug((object)"Reopening lobby, setting to joinable.");
GameNetworkManager instance = GameNetworkManager.Instance;
if (instance.disableSteam)
{
UnityTransport component = ((Component)NetworkManager.Singleton).GetComponent<UnityTransport>();
if (component.ConnectionData.ServerListenAddress != "0.0.0.0")
{
node.displayText = "Server is limited to local connections\n\n";
return false;
}
instance.lobbyHostSettings.isLobbyPublic = true;
ES3.Save<bool>("HostSettings_Public", instance.lobbyHostSettings.isLobbyPublic, "LCGeneralSaveData");
}
else if (!instance.currentLobby.HasValue)
{
node.displayText = "Failed to fetch lobby ( was null )\n\n";
return false;
}
instance.SetLobbyJoinable(true);
Object.FindObjectOfType<QuickMenuManager>().inviteFriendsTextAlpha.alpha = 1f;
string text = "Lobby is now Open";
LobbyControl.Log.LogInfo((object)text);
node.displayText = text + "\n\n";
node.maxCharactersToType = node.displayText.Length + 2;
return true;
}
private static bool CloseCommand(ref TerminalNode node, string[] args)
{
LobbyControl.Log.LogDebug((object)"Closing lobby, setting to not joinable.");
GameNetworkManager instance = GameNetworkManager.Instance;
if (instance.disableSteam)
{
UnityTransport component = ((Component)NetworkManager.Singleton).GetComponent<UnityTransport>();
if (component.ConnectionData.ServerListenAddress != "0.0.0.0")
{
node.displayText = "Server is limited to local connections\n\n";
return false;
}
instance.lobbyHostSettings.isLobbyPublic = false;
ES3.Save<bool>("HostSettings_Public", instance.lobbyHostSettings.isLobbyPublic, "LCGeneralSaveData");
}
else if (!instance.currentLobby.HasValue)
{
node.displayText = "Failed to fetch lobby ( was null )\n\n";
return false;
}
instance.SetLobbyJoinable(false);
Object.FindObjectOfType<QuickMenuManager>().inviteFriendsTextAlpha.alpha = 0f;
string text = "Lobby is now Closed";
LobbyControl.Log.LogInfo((object)text);
node.displayText = text + "\n\n";
node.maxCharactersToType = node.displayText.Length + 2;
return true;
}
private static bool PrivateCommand(ref TerminalNode node, string[] args)
{
//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)
LobbyControl.Log.LogDebug((object)"Locking lobby, setting to Private.");
GameNetworkManager instance = GameNetworkManager.Instance;
if (!instance.currentLobby.HasValue)
{
node.displayText = "Failed to fetch lobby ( was null )\n\n";
return false;
}
ES3.Save<bool>("HostSettings_Public", false, "LCGeneralSaveData");
Lobby value = instance.currentLobby.Value;
((Lobby)(ref value)).SetPrivate();
string text = "Lobby is now Private";
LobbyControl.Log.LogInfo((object)text);
node.displayText = text + "\n\n";
node.maxCharactersToType = node.displayText.Length + 2;
return true;
}
private static bool FriendCommand(ref TerminalNode node, string[] args)
{
//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)
LobbyControl.Log.LogDebug((object)"Locking lobby, setting to Friends Only.");
GameNetworkManager instance = GameNetworkManager.Instance;
if (!instance.currentLobby.HasValue)
{
node.displayText = "Failed to fetch lobby ( was null )\n\n";
return false;
}
ES3.Save<bool>("HostSettings_Public", false, "LCGeneralSaveData");
Lobby value = instance.currentLobby.Value;
((Lobby)(ref value)).SetFriendsOnly();
string text = "Lobby is now Friends Only";
LobbyControl.Log.LogInfo((object)text);
node.displayText = text + "\n\n";
node.maxCharactersToType = node.displayText.Length + 2;
return true;
}
private static bool PublicCommand(ref TerminalNode node, string[] args)
{
//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)
LobbyControl.Log.LogDebug((object)"Unlocking lobby, setting to Public.");
GameNetworkManager instance = GameNetworkManager.Instance;
if (!instance.currentLobby.HasValue)
{
node.displayText = "Failed to fetch lobby ( was null )\n\n";
return false;
}
ES3.Save<bool>("HostSettings_Public", true, "LCGeneralSaveData");
Lobby value = instance.currentLobby.Value;
((Lobby)(ref value)).SetPublic();
string text = "Lobby is now Public";
LobbyControl.Log.LogInfo((object)text);
node.displayText = text + "\n\n";
node.maxCharactersToType = node.displayText.Length + 2;
return true;
}
private static bool RenameCommand(ref TerminalNode node, string[] args)
{
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
if (Utility.IsNullOrWhiteSpace(args[2]))
{
node.displayText = "Lobby name cannot be null\n\n";
return false;
}
string text = args[2];
if (text.Length > 40)
{
text = text.Substring(0, 40);
}
LobbyControl.Log.LogDebug((object)("Renaming lobby: \"" + text + "\""));
GameNetworkManager instance = GameNetworkManager.Instance;
if (!instance.disableSteam && !instance.currentLobby.HasValue)
{
node.displayText = "Failed to fetch lobby ( was null )\n\n";
return false;
}
instance.lobbyHostSettings.lobbyName = text;
instance.steamLobbyName = instance.lobbyHostSettings.lobbyName;
if (instance.currentLobby.HasValue)
{
Lobby value = instance.currentLobby.Value;
((Lobby)(ref value)).SetData("name", instance.steamLobbyName);
}
ES3.Save<string>("HostSettings_Name", instance.steamLobbyName, "LCGeneralSaveData");
string text2 = "Lobby renamed to \"" + text + "\"";
LobbyControl.Log.LogInfo((object)text2);
node.displayText = text2 + "\n\n";
node.maxCharactersToType = node.displayText.Length + 2;
return true;
}
private static bool AutoSaveCommand(ref TerminalNode node, string[] args)
{
LobbyControl.Log.LogDebug((object)"Toggling AutoSave");
LobbyControl.CanSave = (LobbyControl.AutoSaveEnabled = !LobbyControl.AutoSaveEnabled);
string text = "AutoSaving is now " + (LobbyControl.CanSave ? "On" : "Off");
LobbyControl.Log.LogInfo((object)text);
node.displayText = text + "\n\n";
node.maxCharactersToType = node.displayText.Length + 2;
return true;
}
private static bool SaveCommand(ref TerminalNode node, string[] args)
{
if (StartOfRound.Instance.isChallengeFile)
{
node.displayText = "Cannot Edit Challenge Save\n\n";
return false;
}
LobbyControl.Log.LogDebug((object)"Saving Lobby");
GameNetworkManager instance = GameNetworkManager.Instance;
string currentSaveFileName = instance.currentSaveFileName;
if (!Utility.IsNullOrWhiteSpace(args[2]))
{
string text = args[2];
if (text.Length > 20)
{
text = text.Substring(0, 20);
}
instance.currentSaveFileName = text;
}
if (currentSaveFileName != instance.currentSaveFileName)
{
ES3.CopyFile(currentSaveFileName, instance.currentSaveFileName);
}
LobbyControl.CanSave = true;
HUDManager.Instance.saveDataIconAnimatorB.SetTrigger("save");
instance.SaveGameValues();
string text2 = "Lobby Saved to " + instance.currentSaveFileName;
LobbyControl.CanSave = LobbyControl.AutoSaveEnabled;
instance.currentSaveFileName = currentSaveFileName;
LobbyControl.Log.LogInfo((object)text2);
node.displayText = text2 + "\n\n";
node.maxCharactersToType = node.displayText.Length + 2;
return true;
}
private static bool LoadCommand(ref TerminalNode node, string[] args)
{
if (StartOfRound.Instance.isChallengeFile)
{
node.displayText = "Cannot Edit Challenge Save\n\n";
return false;
}
LobbyControl.Log.LogDebug((object)"Reloading Lobby");
GameNetworkManager instance = GameNetworkManager.Instance;
if (!Utility.IsNullOrWhiteSpace(args[2]))
{
string text = args[2];
if (text.Length > 20)
{
text = text.Substring(0, 20);
}
instance.currentSaveFileName = text;
}
string text2 = "Lobby '" + instance.currentSaveFileName + "' loaded";
((MonoBehaviour)StartOfRound.Instance).StartCoroutine(LoadLobbyCoroutine());
LobbyControl.AutoSaveEnabled = (LobbyControl.CanSave = ES3.Load<bool>("LC_SavingMethod", GameNetworkManager.Instance.currentSaveFileName, true));
LobbyControl.Log.LogInfo((object)text2);
node.displayText = text2 + "\n\n";
node.maxCharactersToType = node.displayText.Length + 2;
return true;
}
private static bool SwitchCommand(ref TerminalNode node, string[] args)
{
if (StartOfRound.Instance.isChallengeFile)
{
node.displayText = "Cannot Edit Challenge Save\n\n";
return false;
}
LobbyControl.Log.LogDebug((object)"Switching Lobby");
GameNetworkManager instance = GameNetworkManager.Instance;
if (Utility.IsNullOrWhiteSpace(args[2]))
{
node.displayText = "You need to specify a destination for the swap!";
return false;
}
string text = args[2];
if (text.Length > 20)
{
text = text.Substring(0, 20);
}
instance.currentSaveFileName = text;
string text2 = "Lobby is now saving to '" + instance.currentSaveFileName + "'";
node.displayText = text2 + "\n\n";
node.maxCharactersToType = node.displayText.Length + 2;
return true;
}
private static bool ClearCommand(ref TerminalNode node, string[] args)
{
if (StartOfRound.Instance.isChallengeFile)
{
node.displayText = "Cannot Edit Challenge Save\n\n";
return false;
}
LobbyControl.Log.LogDebug((object)"Clearing Lobby");
LobbyControl.CanSave = true;
GameNetworkManager.Instance.ResetSavedGameValues();
ES3.DeleteFile(GameNetworkManager.Instance.currentSaveFileName);
LobbyControl.CanSave = LobbyControl.AutoSaveEnabled;
bool flag = LoadCommand(ref node, new string[3]);
if (flag)
{
node.displayText = "Lobby is now Empty!";
}
return flag;
}
private static bool DropAllCommand(ref TerminalNode node, string[] args)
{
LobbyControl.Log.LogDebug((object)"Dropping all Items");
string text = "All Items Dropped";
PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
foreach (PlayerControllerB val in allPlayerScripts)
{
val.DropAllHeldItemsAndSync();
}
node.displayText = text + "\n\n";
node.maxCharactersToType = node.displayText.Length + 2;
return true;
}
private static bool PerformOrbitCheck(TerminalNode terminalNode, out TerminalNode errorText)
{
if (!StartOfRound.Instance.inShipPhase)
{
terminalNode.displayText = "Can only be used while in Orbit\n\n";
errorText = terminalNode;
return true;
}
errorText = null;
return false;
}
private static TerminalNode HelpNode()
{
TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
val.displayText = (GameNetworkManager.Instance.disableSteam ? "- status : prints the current lobby status\r\n\r\nLAN:\r\n- open : set the lobby to be discoverable\r\n- close : set the lobby to be non-discoverable\r\n- rename [name] : change the name of the lobby\r\n\r\nSaving:\r\n- autosave : toggle autosave for the savefile\r\n- save (name) : save the lobby\r\n- load (name) : load a savefile\r\n- switch (name) : swap savefile without loading it\r\n- clear : reset the current lobby to empty\r\n\r\nExtra:\r\n- dropall : drop all items to the ground\r\n" : "- status : prints the current lobby status\r\n\r\nSteam:\r\n- open : open the lobby\r\n- close : close the lobby\r\n- private : set lobby to Invite Only\r\n- friend : set lobby to Friends Only\r\n- public : set lobby to Public\r\n- rename [name] : change the name of the lobby\r\n\r\nSaving:\r\n- autosave : toggle autosave for the savefile\r\n- save (name) : save the lobby\r\n- load (name) : load a savefile\r\n- switch (name) : swap savefile without loading it\r\n- clear : reset the current lobby to empty\r\n\r\nExtra:\r\n- dropall : drop all items to the ground\r\n");
val.clearPreviousText = true;
val.maxCharactersToType = val.displayText.Length + 2;
return val;
}
[IteratorStateMachine(typeof(<LoadLobbyCoroutine>d__19))]
private static IEnumerator LoadLobbyCoroutine()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <LoadLobbyCoroutine>d__19(0);
}
private static void ReloadUnlockables()
{
//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
//IL_02c5: 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_02cc: Unknown result type (might be due to invalid IL or missing references)
//IL_019c: 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_01a6: Unknown result type (might be due to invalid IL or missing references)
//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
//IL_01c5: 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_01cc: Unknown result type (might be due to invalid IL or missing references)
//IL_01ce: 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_01d5: Unknown result type (might be due to invalid IL or missing references)
//IL_01da: Unknown result type (might be due to invalid IL or missing references)
//IL_01dd: 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_01e1: Unknown result type (might be due to invalid IL or missing references)
//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
//IL_01ea: 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_01ff: Unknown result type (might be due to invalid IL or missing references)
//IL_020f: Unknown result type (might be due to invalid IL or missing references)
//IL_0214: Unknown result type (might be due to invalid IL or missing references)
//IL_0219: Unknown result type (might be due to invalid IL or missing references)
//IL_0226: Unknown result type (might be due to invalid IL or missing references)
//IL_0236: Unknown result type (might be due to invalid IL or missing references)
//IL_023b: Unknown result type (might be due to invalid IL or missing references)
//IL_0240: Unknown result type (might be due to invalid IL or missing references)
//IL_0253: Unknown result type (might be due to invalid IL or missing references)
//IL_0258: Unknown result type (might be due to invalid IL or missing references)
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_025f: Unknown result type (might be due to invalid IL or missing references)
//IL_0264: Unknown result type (might be due to invalid IL or missing references)
//IL_0266: Unknown result type (might be due to invalid IL or missing references)
//IL_026b: 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_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: 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_010b: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: 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_012b: Unknown result type (might be due to invalid IL or missing references)
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: 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_0152: Unknown result type (might be due to invalid IL or missing references)
//IL_015f: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: 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_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: Unknown result type (might be due to invalid IL or missing references)
//IL_0180: 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_0187: 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_0314: Unknown result type (might be due to invalid IL or missing references)
//IL_0317: Unknown result type (might be due to invalid IL or missing references)
//IL_031c: Unknown result type (might be due to invalid IL or missing references)
//IL_031e: Unknown result type (might be due to invalid IL or missing references)
//IL_032c: Unknown result type (might be due to invalid IL or missing references)
StartOfRound instance = StartOfRound.Instance;
instance.LoadUnlockables();
try
{
for (int i = 0; i < instance.unlockablesList.unlockables.Count; i++)
{
UnlockableItem val = instance.unlockablesList.unlockables[i];
if (val.unlockableType == 0 || !val.alreadyUnlocked)
{
continue;
}
LobbyControl.Log.LogDebug((object)(val.unlockableName + " starting"));
if (!instance.SpawnedShipUnlockables.ContainsKey(i))
{
instance.SpawnUnlockable(i, true);
}
PlaceableShipObject val2 = instance.SpawnedShipUnlockables[i].GetComponent<PlaceableShipObject>();
if (val2 == null)
{
val2 = instance.SpawnedShipUnlockables[i].GetComponentInChildren<PlaceableShipObject>();
}
if (val2 != null)
{
LobbyControl.Log.LogDebug((object)(val.unlockableName + " continuing"));
Quaternion val4;
if (Object.op_Implicit((Object)(object)val2.parentObjectSecondary))
{
Quaternion rotation = ((Component)val2.parentObjectSecondary).transform.rotation;
Quaternion rotation2 = ((Component)val2.parentObjectSecondary).transform.rotation;
Quaternion rotation3 = ((Component)val2.mainMesh).transform.rotation;
Quaternion val3 = rotation * Quaternion.Inverse(rotation2);
val4 = val3 * rotation3;
val.placedRotation = ((Quaternion)(ref val4)).eulerAngles;
Vector3 position = val2.parentObjectSecondary.position;
Vector3 val5 = ((Component)val2.parentObjectSecondary).transform.position - ((Component)val2.mainMesh).transform.position;
Vector3 val6 = ((Component)val2.mainMesh).transform.position - ((Component)val2.placeObjectCollider).transform.position;
val.placedPosition = position - val5 - val6;
}
else
{
Quaternion val7 = Quaternion.Euler(val2.parentObject.rotationOffset);
Quaternion rotation4 = ((Component)val2.parentObject).transform.rotation;
Quaternion rotation5 = ((Component)val2.mainMesh).transform.rotation;
Quaternion val8 = val7 * Quaternion.Inverse(rotation4);
val4 = val8 * rotation5;
val.placedRotation = ((Quaternion)(ref val4)).eulerAngles;
Vector3 val9 = ((Component)val2.parentObject).transform.position - ((Component)val2.mainMesh).transform.position;
Vector3 val10 = ((Component)val2.mainMesh).transform.position - ((Component)val2.placeObjectCollider).transform.position;
val.placedPosition = StartOfRound.Instance.elevatorTransform.TransformPoint(val2.parentObject.positionOffset) - val9 - val10;
}
}
}
if (instance.connectedPlayersAmount < 1)
{
return;
}
List<ulong> targetClientIds = instance.ClientPlayerList.Keys.ToList();
ClientRpcParams val11 = default(ClientRpcParams);
val11.Send = new ClientRpcSendParams
{
TargetClientIds = targetClientIds
};
ClientRpcParams val12 = val11;
for (int j = 0; j < instance.unlockablesList.unlockables.Count; j++)
{
UnlockableItem val13 = instance.unlockablesList.unlockables[j];
if (val13.alreadyUnlocked && !val13.inStorage && _returnUnlockableFromStorageServerRpcID.HasValue)
{
uint value = _returnUnlockableFromStorageServerRpcID.Value;
FastBufferWriter val14 = ((NetworkBehaviour)instance).__beginSendClientRpc(value, val12, (RpcDelivery)0);
BytePacker.WriteValueBitPacked(val14, j);
((NetworkBehaviour)instance).__endSendClientRpc(ref val14, value, val12, (RpcDelivery)0);
}
}
instance.SyncShipUnlockablesServerRpc();
}
catch (Exception ex)
{
LobbyControl.Log.LogError((object)ex);
}
}
private static void RefreshLobby()
{
//IL_0082: 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_009a: 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_00a1: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_0108: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: 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_014b: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_0181: 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_0193: Unknown result type (might be due to invalid IL or missing references)
//IL_019c: Unknown result type (might be due to invalid IL or missing references)
//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
StartOfRound instance = StartOfRound.Instance;
List<ulong> list = new List<ulong>();
List<ulong> list2 = new List<ulong>();
for (int i = 0; i < instance.allPlayerObjects.Length; i++)
{
NetworkObject component = instance.allPlayerObjects[i].GetComponent<NetworkObject>();
if (!component.IsOwnedByServer)
{
list.Add(component.OwnerClientId);
list2.Add(component.OwnerClientId);
}
else if (i == 0)
{
list.Add(NetworkManager.Singleton.LocalClientId);
}
else
{
list.Add(999uL);
}
}
ClientRpcParams val = default(ClientRpcParams);
val.Send = new ClientRpcSendParams
{
TargetClientIds = list2
};
ClientRpcParams val2 = val;
int groupCredits = Object.FindObjectOfType<Terminal>().groupCredits;
int profitQuota = TimeOfDay.Instance.profitQuota;
int quotaFulfilled = TimeOfDay.Instance.quotaFulfilled;
int num = (int)TimeOfDay.Instance.timeUntilDeadline;
PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController;
if (_onPlayerConnectedClientRpcID.HasValue)
{
uint value = _onPlayerConnectedClientRpcID.Value;
FastBufferWriter val3 = ((NetworkBehaviour)instance).__beginSendClientRpc(value, val2, (RpcDelivery)0);
BytePacker.WriteValueBitPacked(val3, localPlayerController.actualClientId);
BytePacker.WriteValueBitPacked(val3, instance.connectedPlayersAmount - 1);
bool flag = true;
((FastBufferWriter)(ref val3)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
((FastBufferWriter)(ref val3)).WriteValueSafe<ulong>(list.ToArray(), default(ForPrimitives));
BytePacker.WriteValueBitPacked(val3, instance.ClientPlayerList[localPlayerController.actualClientId]);
BytePacker.WriteValueBitPacked(val3, groupCredits);
BytePacker.WriteValueBitPacked(val3, instance.currentLevelID);
BytePacker.WriteValueBitPacked(val3, profitQuota);
BytePacker.WriteValueBitPacked(val3, num);
BytePacker.WriteValueBitPacked(val3, quotaFulfilled);
BytePacker.WriteValueBitPacked(val3, instance.randomMapSeed);
((FastBufferWriter)(ref val3)).WriteValueSafe<bool>(ref instance.isChallengeFile, default(ForPrimitives));
((NetworkBehaviour)instance).__endSendClientRpc(ref val3, value, val2, (RpcDelivery)0);
}
}
internal static void Init()
{
MethodInfo methodInfo = AccessTools.Method(typeof(StartOfRound), "ReturnUnlockableFromStorageClientRpc", (Type[])null, (Type[])null);
if (RPCUtils.TryGetRpcID(methodInfo, out var rpcID))
{
_returnUnlockableFromStorageServerRpcID = rpcID;
}
MethodInfo methodInfo2 = AccessTools.Method(typeof(StartOfRound), "OnPlayerConnectedClientRpc", (Type[])null, (Type[])null);
if (RPCUtils.TryGetRpcID(methodInfo2, out var rpcID2))
{
_onPlayerConnectedClientRpcID = rpcID2;
}
}
}
}
namespace LobbyControl.PopUp
{
[HarmonyPatch]
public class PopUpPatch
{
public static readonly List<(string objectName, string text)> PopUps = new List<(string, string)>();
[HarmonyPrefix]
[HarmonyPatch(typeof(MenuManager), "Awake")]
private static void AddPopups(MenuManager __instance)
{
foreach (var (objectName, text) in PopUps)
{
AppendPopup(objectName, text);
}
}
private static void AppendPopup(string objectName, string text)
{
GameObject val = GameObject.Find("/Canvas/MenuContainer/");
GameObject val2 = GameObject.Find("Canvas/MenuContainer/LANWarning/");
if (!((Object)(object)val2 == (Object)null))
{
GameObject val3 = Object.Instantiate<GameObject>(val2, val.transform);
((Object)val3).name = objectName;
val3.SetActive(true);
Transform val4 = val3.transform.Find("Panel/NotificationText");
TextMeshProUGUI component = ((Component)val4).GetComponent<TextMeshProUGUI>();
((TMP_Text)component).text = text;
}
}
}
}
namespace LobbyControl.Patches
{
[HarmonyPatch]
internal class JoinQueuePatches
{
private static bool _checkpointsInitialized;
private static ConnectionCheckpoint _syncAlreadyHeldObjectsCheckpoint;
private static ConnectionCheckpoint _sendNewPlayerValuesCheckpoint;
private static ConnectionCheckpoint _syncAllPlayerLevelsCheckpoint;
private static readonly ConcurrentQueue<(ConnectionApprovalRequest request, ConnectionApprovalResponse response, ulong? steamId)> ConnectionQueue = new ConcurrentQueue<(ConnectionApprovalRequest, ConnectionApprovalResponse, ulong?)>();
private static readonly Timer ConnectionTimer = new Timer
{
AutoReset = false
};
internal static ConcurrentDictionary<ulong, bool> DroppedConnections = new ConcurrentDictionary<ulong, bool>();
private static readonly Stopwatch ConnectionStopwatch = new Stopwatch();
private static int QueuedClients => ConnectionQueue.Count + (ConnectionEvents.ConnectingClientId.HasValue ? 1 : 0);
internal static void Init()
{
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Expected O, but got Unknown
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Expected O, but got Unknown
//IL_018f: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: Expected O, but got Unknown
//IL_020f: Unknown result type (might be due to invalid IL or missing references)
//IL_0221: Unknown result type (might be due to invalid IL or missing references)
//IL_0223: Unknown result type (might be due to invalid IL or missing references)
//IL_022d: Expected O, but got Unknown
MethodInfo methodInfo = AccessTools.Method(typeof(StartOfRound), "SyncAlreadyHeldObjectsServerRpc", (Type[])null, (Type[])null);
if (RPCUtils.TryGetRpcID(methodInfo, out var rpcID))
{
MethodInfo methodInfo2 = AccessTools.Method(typeof(StartOfRound), $"__rpc_handler_{rpcID}", (Type[])null, (Type[])null);
MethodInfo methodInfo3 = AccessTools.Method(typeof(JoinQueuePatches), "OnSyncAlreadyHeldObjectsServerRpc", (Type[])null, (Type[])null);
LobbyControl.Harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo3), (HarmonyMethod)null);
}
else
{
LobbyControl.Log.LogFatal((object)"Could not find RPC id for SyncAlreadyHeldObjectsServerRpc");
}
methodInfo = AccessTools.Method(typeof(PlayerControllerB), "SendNewPlayerValuesServerRpc", (Type[])null, (Type[])null);
if (RPCUtils.TryGetRpcID(methodInfo, out rpcID))
{
MethodInfo methodInfo4 = AccessTools.Method(typeof(PlayerControllerB), $"__rpc_handler_{rpcID}", (Type[])null, (Type[])null);
MethodInfo methodInfo5 = AccessTools.Method(typeof(JoinQueuePatches), "OnSendNewPlayerValuesServerRpc", (Type[])null, (Type[])null);
LobbyControl.Harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo5), (HarmonyMethod)null);
}
else
{
LobbyControl.Log.LogFatal((object)"Could not find RPC id for SendNewPlayerValuesServerRpc");
}
methodInfo = AccessTools.Method(typeof(HUDManager), "SyncAllPlayerLevelsServerRpc", new Type[2]
{
typeof(int),
typeof(int)
}, (Type[])null);
if (RPCUtils.TryGetRpcID(methodInfo, out rpcID))
{
MethodInfo methodInfo6 = AccessTools.Method(typeof(HUDManager), $"__rpc_handler_{rpcID}", (Type[])null, (Type[])null);
MethodInfo methodInfo7 = AccessTools.Method(typeof(JoinQueuePatches), "OnSyncAllPlayerLevelsServerRpc", (Type[])null, (Type[])null);
LobbyControl.Harmony.Patch((MethodBase)methodInfo6, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo7), (HarmonyMethod)null);
}
else
{
LobbyControl.Log.LogFatal((object)"Could not find RPC id for SyncAllPlayerLevelsServerRpc");
}
ConnectionEvents.OnConnectionCompletedServer += OnConnectionCompletedServer;
MethodInfo methodInfo8 = AccessTools.Method(typeof(StartOfRound), "StartGame", (Type[])null, (Type[])null);
if (methodInfo8 != null)
{
LobbyControl.Hooks.Add(new Hook((MethodBase)methodInfo8, (Delegate)new Action<Action<StartOfRound>, StartOfRound>(CheckValidStart), new HookConfig
{
Priority = 999
}));
}
else
{
LobbyControl.Log.LogFatal((object)"Cannot apply patch to StartGame");
}
}