Due to update 2.4.3, some mods may no longer function. FixedConfig may be necessary.
Decompiled source of TestMoreBopl v1.0.3
MoreMultiPlayer.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using Steamworks; using Steamworks.Data; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")] [assembly: AssemblyCompany("MoreMultiPlayer")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Allows 8 players to join a lobby!")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("MoreMultiPlayer")] [assembly: AssemblyTitle("MoreMultiPlayer")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.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] [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 MoreMultiPlayer { [HarmonyPatch(typeof(CharacterSelectHandler_online))] [HarmonyPatch("ForceStartGame")] public static class CharacterSelecterHandler_online_ForceStartGamePatch { [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] [HarmonyPatch(typeof(CharacterSelectHandler_online), "InitPlayer")] public static Player InitPlayer(int id, byte color, byte team, byte ability1, byte ability2, byte ability3, int nrOfAbilities, PlayerColors playerColors) { throw new NotImplementedException("It's a stub"); } public static bool Prefix([CanBeNull] PlayerColors pcs) { //IL_0043: 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_01e4: Unknown result type (might be due to invalid IL or missing references) CharacterSelectHandler_online val = AccessTools.StaticFieldRefAccess<CharacterSelectHandler_online, CharacterSelectHandler_online>("selfRef"); if ((Object)(object)pcs == (Object)null) { pcs = val.playerColors; } MultiStartRequestPacket startParameters = SteamManagerExtended.startParameters; Updater.ReInit(); List<Player> list = new List<Player>(); Updater.InitSeed(startParameters.seed); Main.Log.LogInfo((object)$"SteamID: {SteamClient.SteamId}"); for (int i = 0; i < startParameters.nrOfPlayers; i++) { Main.Log.LogInfo((object)$"Initializing player {i}: [id: {startParameters.p_ids[i]}, color: {startParameters.p_colors[i]}, team: {startParameters.p_teams[i]}, ability1: {startParameters.p_ability1s[i]}, ability2: {startParameters.p_ability2s[i]}, ability3: {startParameters.p_ability3s[i]}]"); list.Add(InitPlayer(i + 1, startParameters.p_colors[i], startParameters.p_teams[i], startParameters.p_ability1s[i], startParameters.p_ability2s[i], startParameters.p_ability3s[i], startParameters.nrOfAbilites, pcs)); } Player val2 = null; if (GameLobby.isPlayingAReplay) { for (int j = 0; j < list.Count; j++) { if (list[j].Id == 1) { val2 = list[j]; break; } } } else { int num = Array.IndexOf(startParameters.p_ids, SteamId.op_Implicit(SteamClient.SteamId)); Main.Log.LogInfo((object)("SteamIdIndex: " + num)); if (num != -1) { val2 = list[num]; } } if (val2 == null) { Main.Log.LogError((object)"Failed to find local player on ForceStart."); return false; } for (int k = 0; k < list.Count; k++) { list[k].steamId = SteamId.op_Implicit(startParameters.p_ids[k]); } val2.IsLocalPlayer = true; val2.inputDevice = CharacterSelectHandler_online.localPlayerInit.inputDevice; val2.UsesKeyboardAndMouse = CharacterSelectHandler_online.localPlayerInit.usesKeyboardMouse; val2.CustomKeyBinding = CharacterSelectHandler_online.localPlayerInit.keybindOverride; CharacterSelectHandler_online.startButtonAvailable = false; PlayerHandler.Get().SetPlayerList(list); SteamManager.instance.StartHostedGame(); AudioManager obj = AudioManager.Get(); if (obj != null) { obj.Play("startGame"); } GameSession.Init(); if (GameLobby.isPlayingAReplay) { SceneManager.LoadScene(startParameters.currentLevel + 6); } else { SceneManager.LoadScene("Level1"); } if (!WinnerTriangleCanvas.HasBeenSpawned) { SceneManager.LoadScene("winnerTriangle", (LoadSceneMode)1); } return false; } } [HarmonyPatch(typeof(GameSessionHandler))] [HarmonyPatch("LoadNextLevelScene")] public class GameSessionHandlerPatch_LoadNextLevelScene { [HarmonyTranspiler] public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { Main.Log.LogInfo((object)"Patching GameSessionHandler.LoadNextLevelScene"); FieldInfo fromA = AccessTools.Field(typeof(SteamManager), "startParameters"); FieldInfo toA = AccessTools.Field(typeof(SteamManagerExtended), "startParameters"); FieldInfo fromB = AccessTools.Field(typeof(StartRequestPacket), "seed"); FieldInfo toB = AccessTools.Field(typeof(MultiStartRequestPacket), "seed"); return Main.PatchFieldLoad(fromA, fromB, toA, toB, instructions); } } [HarmonyPatch(typeof(GameSessionHandler))] [HarmonyPatch("SpawnPlayers")] public class GameSessionHandlerPatch_SpawnPlayers { private static void Prefix() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) List<Player> list = PlayerHandler.Get().PlayerList(); Main.Log.LogInfo((object)$"Spawning {list.Count} players:"); foreach (Player item in list) { Main.Log.LogInfo((object)$"Player {item.Id} ({item.steamId})"); } } } public class HostPatch { public static Queue<MultiInputPacket> InputBuffer = new Queue<MultiInputPacket>(); public static MultiInputPacket previousInputPacket; public static uint GetMaxSeqNumber(MultiInputPacket packet) { if (packet.inputPackets.Count != 0) { return packet.inputPackets.Max((KeyValuePair<int, InputPacket> p) => p.Value.seqNumber); } return 0u; } public static int GetMaxPreviousTargetDelayBufferSize() { if (previousInputPacket.inputPackets.Count != 0) { return previousInputPacket.inputPackets.Max((KeyValuePair<int, InputPacket> p) => p.Value.targetDelayBufferSize); } return 0; } } [HarmonyPatch(typeof(Host))] [HarmonyPatch("Start")] public class HostPatch_Start { public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { Main.Log.LogInfo((object)"Patching Host.Start"); FieldInfo fromA = AccessTools.Field(typeof(SteamManager), "startParameters"); FieldInfo toA = AccessTools.Field(typeof(SteamManagerExtended), "startParameters"); FieldInfo fromB = AccessTools.Field(typeof(StartRequestPacket), "nrOfAbilites"); FieldInfo toB = AccessTools.Field(typeof(MultiStartRequestPacket), "nrOfAbilites"); return Main.PatchFieldLoad(fromA, fromB, toA, toB, instructions); } } [HarmonyPatch(typeof(Host))] [HarmonyPatch("ReInit")] public class HostPatch_ReInit { public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { Main.Log.LogInfo((object)"Patching Host.ReInit"); FieldInfo fromA = AccessTools.Field(typeof(SteamManager), "startParameters"); FieldInfo toA = AccessTools.Field(typeof(SteamManagerExtended), "startParameters"); FieldInfo fromB = AccessTools.Field(typeof(StartRequestPacket), "frameBufferSize"); FieldInfo toB = AccessTools.Field(typeof(MultiStartRequestPacket), "frameBufferSize"); return Main.PatchFieldLoad(fromA, fromB, toA, toB, instructions); } } [HarmonyPatch(typeof(Host))] [HarmonyPatch("Init")] public class HostPatch_Init { public static void Prefix() { Main.Log.LogInfo((object)"Host::Init::Prefix"); HostPatch.previousInputPacket = new MultiInputPacket(); } } [HarmonyPatch(typeof(Host))] [HarmonyPatch("ProcessNetworkPackets")] public class HostPatch_ProcessNetworkPackets { [CompilerGenerated] private sealed class <>c__DisplayClass4_0 { public FieldInfo delayBufferSizeFieldInfo; public FieldInfo updatesPlacedInDelayBufferFieldInfo; public Func<CodeInstruction, bool> <>9__0; public Func<CodeInstruction, bool> <>9__1; internal bool <Transpiler>b__0(CodeInstruction i) { return CodeInstructionExtensions.LoadsField(i, delayBufferSizeFieldInfo, false); } internal bool <Transpiler>b__1(CodeInstruction i) { return CodeInstructionExtensions.LoadsField(i, updatesPlacedInDelayBufferFieldInfo, false); } } [CompilerGenerated] private sealed class <DebugLogInstructions>d__2 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private string message; public string <>3__message; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DebugLogInstructions>d__2(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldstr, (object)message); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(HostPatch_ProcessNetworkPackets), "LogText", (Type[])null, (Type[])null)); <>1__state = 2; return true; case 2: <>1__state = -1; 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() { <DebugLogInstructions>d__2 <DebugLogInstructions>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <DebugLogInstructions>d__ = this; } else { <DebugLogInstructions>d__ = new <DebugLogInstructions>d__2(0); } <DebugLogInstructions>d__.message = <>3__message; return <DebugLogInstructions>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } [CompilerGenerated] private sealed class <Transpiler>d__4 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private <>c__DisplayClass4_0 <>8__1; private ILGenerator generator; public ILGenerator <>3__generator; private IEnumerator<CodeInstruction> <enumerator>5__2; private Label? <last_br>5__3; private List<CodeInstruction> <instructionsSkipped>5__4; private Label <label>5__5; private object <local_i>5__6; private object <local_m>5__7; private int <i>5__8; private List<CodeInstruction>.Enumerator <>7__wrap8; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Transpiler>d__4(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { switch (<>1__state) { case -3: case 32: try { } finally { <>m__Finally1(); } break; case -4: case 33: try { } finally { <>m__Finally2(); } break; } <>8__1 = null; <enumerator>5__2 = null; <instructionsSkipped>5__4 = null; <local_i>5__6 = null; <local_m>5__7 = null; <>7__wrap8 = default(List<CodeInstruction>.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Expected O, but got Unknown //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Expected O, but got Unknown //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_03b7: Expected O, but got Unknown //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03dd: Expected O, but got Unknown //IL_03f9: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Expected O, but got Unknown //IL_044f: Unknown result type (might be due to invalid IL or missing references) //IL_0459: Expected O, but got Unknown //IL_0480: Unknown result type (might be due to invalid IL or missing references) //IL_048a: Expected O, but got Unknown //IL_05d8: Unknown result type (might be due to invalid IL or missing references) //IL_05e2: Expected O, but got Unknown //IL_05ff: Unknown result type (might be due to invalid IL or missing references) //IL_0609: Expected O, but got Unknown //IL_0639: Unknown result type (might be due to invalid IL or missing references) //IL_0643: Expected O, but got Unknown //IL_0660: Unknown result type (might be due to invalid IL or missing references) //IL_066a: Expected O, but got Unknown //IL_069a: Unknown result type (might be due to invalid IL or missing references) //IL_06a4: Expected O, but got Unknown //IL_06f3: Unknown result type (might be due to invalid IL or missing references) //IL_06fd: Expected O, but got Unknown //IL_071a: Unknown result type (might be due to invalid IL or missing references) //IL_0724: Expected O, but got Unknown //IL_0754: Unknown result type (might be due to invalid IL or missing references) //IL_075e: Expected O, but got Unknown //IL_077b: Unknown result type (might be due to invalid IL or missing references) //IL_0785: Expected O, but got Unknown //IL_07a2: Unknown result type (might be due to invalid IL or missing references) //IL_07ac: Expected O, but got Unknown //IL_07dc: Unknown result type (might be due to invalid IL or missing references) //IL_07e6: Expected O, but got Unknown //IL_0808: Unknown result type (might be due to invalid IL or missing references) //IL_0812: Expected O, but got Unknown //IL_082f: Unknown result type (might be due to invalid IL or missing references) //IL_0839: Expected O, but got Unknown //IL_0856: Unknown result type (might be due to invalid IL or missing references) //IL_0860: Expected O, but got Unknown //IL_0882: Unknown result type (might be due to invalid IL or missing references) //IL_088c: Expected O, but got Unknown //IL_08ae: Unknown result type (might be due to invalid IL or missing references) //IL_08d0: Expected O, but got Unknown //IL_08f7: Unknown result type (might be due to invalid IL or missing references) //IL_0901: Expected O, but got Unknown //IL_0928: Unknown result type (might be due to invalid IL or missing references) //IL_0932: Expected O, but got Unknown //IL_0586: Unknown result type (might be due to invalid IL or missing references) //IL_05a3: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass4_0(); Main.Log.LogInfo((object)"Patching Host.ProcessNetworkPackets"); <>8__1.delayBufferSizeFieldInfo = AccessTools.Field(typeof(Host), "delayBufferSize"); <>8__1.updatesPlacedInDelayBufferFieldInfo = AccessTools.Field(typeof(Host), "UpdatesPlacedInDelayBuffer"); <enumerator>5__2 = instructions.GetEnumerator(); <last_br>5__3 = null; goto IL_0ae9; case 1: <>1__state = -1; goto IL_0ae9; case 2: <>1__state = -1; return false; case 3: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldloc_3, (object)null); <>1__state = 4; return true; case 4: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldc_I4_1, (object)null); <>1__state = 5; return true; case 5: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Add, (object)null); <>1__state = 6; return true; case 6: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Stloc_3, (object)null); <>1__state = 7; return true; case 7: <>1__state = -1; <>2__current = CodeInstructionExtensions.WithLabels(new CodeInstruction(OpCodes.Ldloc_3, (object)null), new Label[1] { <last_br>5__3.Value }); <>1__state = 8; return true; case 8: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(Host), "delayBufferSize")); <>1__state = 9; return true; case 9: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Blt_S, (object)<label>5__5); <>1__state = 10; return true; case 10: <>1__state = -1; goto IL_0ae9; case 11: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(Host), "clients")); <>1__state = 12; return true; case 12: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldarg_0, (object)null); <>1__state = 13; return true; case 13: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(Host), "sentPacketHistory")); <>1__state = 14; return true; case 14: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldarg_0, (object)null); <>1__state = 15; return true; case 15: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(Host), "localPlayerId")); <>1__state = 16; return true; case 16: <>1__state = -1; <>2__current = CodeInstruction.Call(typeof(HostPatch_ProcessNetworkPackets), "AddInputPacket", (Type[])null, (Type[])null); <>1__state = 17; return true; case 17: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldarg_0, (object)null); <>1__state = 18; return true; case 18: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldarg_0, (object)null); <>1__state = 19; return true; case 19: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(Host), "UpdatesPlacedInDelayBuffer")); <>1__state = 20; return true; case 20: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldc_I4_1, (object)null); <>1__state = 21; return true; case 21: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Add, (object)null); <>1__state = 22; return true; case 22: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Stfld, (object)AccessTools.Field(typeof(Host), "UpdatesPlacedInDelayBuffer")); <>1__state = 23; return true; case 23: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldloc_S, <local_i>5__6); <>1__state = 24; return true; case 24: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldc_I4_1, (object)null); <>1__state = 25; return true; case 25: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Add, (object)null); <>1__state = 26; return true; case 26: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Stloc_S, <local_i>5__6); <>1__state = 27; return true; case 27: <>1__state = -1; <>2__current = CodeInstructionExtensions.WithLabels(new CodeInstruction(OpCodes.Ldloc_S, <local_i>5__6), new Label[1] { <last_br>5__3.Value }); <>1__state = 28; return true; case 28: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldloc_S, <local_m>5__7); <>1__state = 29; return true; case 29: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Blt_S, (object)<label>5__5); <>1__state = 30; return true; case 30: <>1__state = -1; goto IL_0ae9; case 31: <>1__state = -1; <i>5__8++; goto IL_09e5; case 32: <>1__state = -3; goto IL_0a44; case 33: <>1__state = -4; goto IL_0aae; case 34: { <>1__state = -1; goto IL_0ae9; } IL_0ae9: if (<enumerator>5__2.MoveNext()) { CodeInstruction current = <enumerator>5__2.Current; Label? label = default(Label?); if (CodeInstructionExtensions.Branches(current, ref label)) { <last_br>5__3 = label; } if (current.opcode == OpCodes.Ldloca_S) { CodeInstruction val = current; List<Label> list = CodeInstructionExtensions.ExtractLabels(val); <instructionsSkipped>5__4 = new List<CodeInstruction>(); <instructionsSkipped>5__4.Add(val); if (list.Count == 0) { <>2__current = val; <>1__state = 1; return true; } if (!<enumerator>5__2.MoveNext()) { Main.Log.LogError((object)"Expected to find next instruction after Ldloca_S"); <>2__current = val; <>1__state = 2; return true; } CodeInstruction current2 = <enumerator>5__2.Current; <instructionsSkipped>5__4.Add(current2); if (CodeInstructionExtensions.Is(current2, OpCodes.Initobj, (MemberInfo)typeof(InputPacketQuad))) { Main.Log.LogInfo((object)"Found possible start of loop. Searching for end..."); bool flag = false; while (<enumerator>5__2.MoveNext()) { CodeInstruction current3 = <enumerator>5__2.Current; <instructionsSkipped>5__4.Add(current3); if (current3.opcode == OpCodes.Blt && list.Contains((Label)current3.operand)) { Main.Log.LogInfo((object)"Found End of loop"); flag = true; break; } } if (flag) { if (!<last_br>5__3.HasValue) { Main.Log.LogError((object)"What this shouldn't be null?!"); } if (<instructionsSkipped>5__4.Any((CodeInstruction i) => CodeInstructionExtensions.LoadsField(i, <>8__1.delayBufferSizeFieldInfo, false))) { Main.Log.LogInfo((object)"Found 'fill InputBuffer with default InputPacket' loop"); <label>5__5 = generator.DefineLabel(); <>2__current = CodeInstructionExtensions.WithLabels(CodeInstruction.Call(typeof(HostPatch_ProcessNetworkPackets), "AddDefaultPacket", (Type[])null, (Type[])null), new Label[1] { <label>5__5 }); <>1__state = 3; return true; } if (<instructionsSkipped>5__4.Any((CodeInstruction i) => CodeInstructionExtensions.LoadsField(i, <>8__1.updatesPlacedInDelayBufferFieldInfo, false))) { <local_i>5__6 = <instructionsSkipped>5__4[<instructionsSkipped>5__4.Count - 3].operand; <local_m>5__7 = <instructionsSkipped>5__4[<instructionsSkipped>5__4.Count - 2].operand; Main.Log.LogInfo((object)$"Local_i: {<local_i>5__6}"); Main.Log.LogInfo((object)$"Local_m: {<local_m>5__7}"); Main.Log.LogInfo((object)"Found InputPacket creation loop"); <label>5__5 = generator.DefineLabel(); <>2__current = CodeInstructionExtensions.WithLabels(new CodeInstruction(OpCodes.Ldarg_0, (object)null), new Label[1] { <label>5__5 }); <>1__state = 11; return true; } <instructionsSkipped>5__4[<instructionsSkipped>5__4.Count - 7].labels.Add((Label)<instructionsSkipped>5__4[<instructionsSkipped>5__4.Count - 1].operand); <i>5__8 = <instructionsSkipped>5__4.Count - 7; goto IL_09e5; } <>7__wrap8 = <instructionsSkipped>5__4.GetEnumerator(); <>1__state = -3; goto IL_0a44; } <>7__wrap8 = <instructionsSkipped>5__4.GetEnumerator(); <>1__state = -4; goto IL_0aae; } <>2__current = current; <>1__state = 34; return true; } <enumerator>5__2.Dispose(); return false; IL_09e5: if (<i>5__8 < <instructionsSkipped>5__4.Count) { <>2__current = <instructionsSkipped>5__4[<i>5__8]; <>1__state = 31; return true; } goto IL_0ae9; IL_0a44: if (<>7__wrap8.MoveNext()) { CodeInstruction current4 = <>7__wrap8.Current; <>2__current = current4; <>1__state = 32; return true; } <>m__Finally1(); <>7__wrap8 = default(List<CodeInstruction>.Enumerator); return false; IL_0aae: if (<>7__wrap8.MoveNext()) { CodeInstruction current5 = <>7__wrap8.Current; <>2__current = current5; <>1__state = 33; return true; } <>m__Finally2(); <>7__wrap8 = default(List<CodeInstruction>.Enumerator); goto IL_0ae9; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap8).Dispose(); } private void <>m__Finally2() { <>1__state = -1; ((IDisposable)<>7__wrap8).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <Transpiler>d__4 <Transpiler>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <Transpiler>d__ = this; } else { <Transpiler>d__ = new <Transpiler>d__4(0); } <Transpiler>d__.instructions = <>3__instructions; <Transpiler>d__.generator = <>3__generator; return <Transpiler>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } private static void AddDefaultPacket() { Main.Log.LogInfo((object)"Adding default packet"); HostPatch.InputBuffer.Enqueue(new MultiInputPacket()); } private static void AddInputPacket(List<Client> clients, Queue<InputPacket> sentPacketHistory, int localPlayerId) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) MultiInputPacket item = new MultiInputPacket(); foreach (Client client in clients) { InputPacket value = client.inputHistory.Dequeue(); item.inputPackets.Add(client.PlayerId, value); } item.inputPackets.Add(localPlayerId, sentPacketHistory.Dequeue()); HostPatch.InputBuffer.Enqueue(item); } [IteratorStateMachine(typeof(<DebugLogInstructions>d__2))] private static IEnumerable<CodeInstruction> DebugLogInstructions(string message) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DebugLogInstructions>d__2(-2) { <>3__message = message }; } private static void LogText(string message) { Main.Log.LogInfo((object)message); } [IteratorStateMachine(typeof(<Transpiler>d__4))] [HarmonyDebug] public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Transpiler>d__4(-2) { <>3__instructions = instructions, <>3__generator = generator }; } } [HarmonyPatch(typeof(Host))] [HarmonyPatch("Update")] public class HostPatch_Update { [CompilerGenerated] private sealed class <Transpiler>d__4 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private ILGenerator generator; public ILGenerator <>3__generator; private FieldInfo <inputBufferFieldInfo>5__2; private MethodInfo <getCountMethodInfo>5__3; private MethodInfo <dequeueMethodInfo>5__4; private IEnumerator<CodeInstruction> <enumerator>5__5; private LocalBuilder <mipl>5__6; private bool <foundInputBuffer>5__7; private CodeInstruction <instruction>5__8; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Transpiler>d__4(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <inputBufferFieldInfo>5__2 = null; <getCountMethodInfo>5__3 = null; <dequeueMethodInfo>5__4 = null; <enumerator>5__5 = null; <mipl>5__6 = null; <instruction>5__8 = null; <>1__state = -2; } private bool MoveNext() { //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Expected O, but got Unknown //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Expected O, but got Unknown //IL_04b6: Unknown result type (might be due to invalid IL or missing references) //IL_04c0: Expected O, but got Unknown //IL_04d8: Unknown result type (might be due to invalid IL or missing references) //IL_04e2: Expected O, but got Unknown //IL_050d: Unknown result type (might be due to invalid IL or missing references) //IL_0517: Expected O, but got Unknown //IL_0544: Unknown result type (might be due to invalid IL or missing references) //IL_054e: Expected O, but got Unknown //IL_0579: Unknown result type (might be due to invalid IL or missing references) //IL_0583: Expected O, but got Unknown //IL_0691: Unknown result type (might be due to invalid IL or missing references) //IL_069b: Expected O, but got Unknown //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Expected O, but got Unknown //IL_048f: Unknown result type (might be due to invalid IL or missing references) //IL_0499: Expected O, but got Unknown //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Expected O, but got Unknown //IL_03a0: Unknown result type (might be due to invalid IL or missing references) //IL_03aa: Expected O, but got Unknown //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Expected O, but got Unknown //IL_065a: Unknown result type (might be due to invalid IL or missing references) //IL_0664: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; Main.Log.LogInfo((object)"Patching Host.Update"); <inputBufferFieldInfo>5__2 = AccessTools.Field(typeof(Host), "InputBuffer"); <getCountMethodInfo>5__3 = AccessTools.Method(<inputBufferFieldInfo>5__2.FieldType, "get_Count", (Type[])null, (Type[])null); <dequeueMethodInfo>5__4 = AccessTools.Method(<inputBufferFieldInfo>5__2.FieldType, "Dequeue", (Type[])null, (Type[])null); <enumerator>5__5 = instructions.GetEnumerator(); <mipl>5__6 = generator.DeclareLocal(typeof(MultiInputPacket)); <foundInputBuffer>5__7 = false; break; case 1: <>1__state = -1; break; case 2: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(HostPatch_Update), "GetCount", (Type[])null, (Type[])null)); <>1__state = 3; return true; case 3: <>1__state = -1; break; case 4: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(HostPatch_Update), "Dequeue", (Type[])null, (Type[])null)); <>1__state = 5; return true; case 5: <>1__state = -1; if (!<enumerator>5__5.MoveNext() && <enumerator>5__5.Current.opcode == OpCodes.Stloc_S) { Main.Log.LogError((object)"Expected a store local instruction."); return false; } <>2__current = new CodeInstruction(OpCodes.Stloc, (object)<mipl>5__6); <>1__state = 6; return true; case 6: <>1__state = -1; goto IL_0599; case 7: <>1__state = -1; goto IL_0599; case 8: <>1__state = -1; <>2__current = <instruction>5__8; <>1__state = 9; return true; case 9: <>1__state = -1; if (!<enumerator>5__5.MoveNext()) { Main.Log.LogError((object)"Invalid input instruction stream."); goto IL_0599; } <instruction>5__8 = <enumerator>5__5.Current; <>2__current = <instruction>5__8; <>1__state = 10; return true; case 10: { <>1__state = -1; Label? label = default(Label?); if (!CodeInstructionExtensions.Branches(<instruction>5__8, ref label)) { Main.Log.LogError((object)"Assumption about branch after AdaptiveInputDelayBuffer was incorrect."); goto IL_0599; } while (<enumerator>5__5.MoveNext()) { <instruction>5__8 = <enumerator>5__5.Current; if (CodeInstructionExtensions.StoresField(<instruction>5__8, AccessTools.Field(typeof(Host), "targetDelayBufferSize"))) { break; } } <>2__current = new CodeInstruction(OpCodes.Ldarg_0, (object)null); <>1__state = 11; return true; } case 11: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldloc, (object)<mipl>5__6); <>1__state = 12; return true; case 12: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldarg_0, (object)null); <>1__state = 13; return true; case 13: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(Host), "targetDelayBufferSize")); <>1__state = 14; return true; case 14: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(HostPatch_Update), "GetTargetDelayBufferSize", (Type[])null, (Type[])null)); <>1__state = 15; return true; case 15: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Stfld, (object)AccessTools.Field(typeof(Host), "targetDelayBufferSize")); <>1__state = 16; return true; case 16: <>1__state = -1; break; case 17: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(HostPatch_Update), "OverrideInputWithNetworkInput", (Type[])null, (Type[])null)); <>1__state = 18; return true; case 18: <>1__state = -1; break; case 19: { <>1__state = -1; <instruction>5__8 = null; break; } IL_0599: while (<enumerator>5__5.MoveNext()) { <instruction>5__8 = <enumerator>5__5.Current; if (<instruction>5__8.opcode == OpCodes.Ldarg_0) { if (!<enumerator>5__5.MoveNext()) { Main.Log.LogError((object)"Expected to find next instruction after Ldarg_0"); <>2__current = <instruction>5__8; <>1__state = 7; return true; } <instruction>5__8 = <enumerator>5__5.Current; if (CodeInstructionExtensions.LoadsField(<instruction>5__8, AccessTools.Field(typeof(Host), "AdaptiveInputDelayBuffer"), false)) { Main.Log.LogInfo((object)"Found AdaptiveInputDelayBuffer check"); <>2__current = new CodeInstruction(OpCodes.Ldarg_0, (object)null); <>1__state = 8; return true; } } } break; } if (<enumerator>5__5.MoveNext()) { <instruction>5__8 = <enumerator>5__5.Current; if (CodeInstructionExtensions.LoadsField(<instruction>5__8, <inputBufferFieldInfo>5__2, false)) { Main.Log.LogInfo((object)"Found InputBuffer field load instruction"); <foundInputBuffer>5__7 = true; if (!<enumerator>5__5.MoveNext()) { Main.Log.LogError((object)"Expected to find next instruction after InputBuffer field load instruction"); <>2__current = <instruction>5__8; <>1__state = 1; return true; } <instruction>5__8 = <enumerator>5__5.Current; if (CodeInstructionExtensions.Calls(<instruction>5__8, <getCountMethodInfo>5__3)) { Main.Log.LogInfo((object)"Patching InputBuffer.getCount"); <>2__current = new CodeInstruction(OpCodes.Pop, (object)null); <>1__state = 2; return true; } if (CodeInstructionExtensions.Calls(<instruction>5__8, <dequeueMethodInfo>5__4)) { Main.Log.LogInfo((object)"Patching InputBuffer.Dequeue"); <>2__current = new CodeInstruction(OpCodes.Pop, (object)null); <>1__state = 4; return true; } Main.Log.LogError((object)"Failed to patch InputBuffer reference out."); } if (<foundInputBuffer>5__7 && CodeInstructionExtensions.Calls(<instruction>5__8, AccessTools.Method(typeof(PlayerHandler), "Get", (Type[])null, (Type[])null))) { Main.Log.LogInfo((object)"Patching PlayerHandler.Get calls"); while (<enumerator>5__5.MoveNext() && !CodeInstructionExtensions.StoresField(<enumerator>5__5.Current, AccessTools.Field(typeof(Host), "previousInputQuad"))) { } if (<enumerator>5__5.Current == null) { Main.Log.LogError((object)"Failed to find previousInputQuad store"); return false; } <>2__current = new CodeInstruction(OpCodes.Ldloc, (object)<mipl>5__6); <>1__state = 17; return true; } <>2__current = <instruction>5__8; <>1__state = 19; 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() { <Transpiler>d__4 <Transpiler>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <Transpiler>d__ = this; } else { <Transpiler>d__ = new <Transpiler>d__4(0); } <Transpiler>d__.instructions = <>3__instructions; <Transpiler>d__.generator = <>3__generator; return <Transpiler>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } public static int GetCount() { return HostPatch.InputBuffer.Count; } public static MultiInputPacket Dequeue() { return HostPatch.InputBuffer.Dequeue(); } public static int GetTargetDelayBufferSize(MultiInputPacket packet, int currentTargetDelayBufferSize) { if (HostPatch.GetMaxSeqNumber(packet) % 32 == 0) { int maxPreviousTargetDelayBufferSize = HostPatch.GetMaxPreviousTargetDelayBufferSize(); if (maxPreviousTargetDelayBufferSize > 0) { return maxPreviousTargetDelayBufferSize; } } return currentTargetDelayBufferSize; } public static void OverrideInputWithNetworkInput(MultiInputPacket packet) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) List<Player> list = PlayerHandler.Get().PlayerList(); for (int i = 0; i < list.Count; i++) { if (packet.inputPackets.TryGetValue(list[i].Id, out var value)) { list[i].OverrideInputWithNetworkInput(value); } } HostPatch.previousInputPacket = packet; } [IteratorStateMachine(typeof(<Transpiler>d__4))] public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Transpiler>d__4(-2) { <>3__instructions = instructions, <>3__generator = generator }; } } [BepInPlugin("com.MoreMultiPlayerTeam.MoreMultiPlayer", "MoreMultiPlayer", "1.0.0")] public class Main : BaseUnityPlugin { [CompilerGenerated] private sealed class <PatchFieldLoad>d__5 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private FieldInfo fromA; public FieldInfo <>3__fromA; private FieldInfo fromB; public FieldInfo <>3__fromB; private FieldInfo toA; public FieldInfo <>3__toA; private FieldInfo toB; public FieldInfo <>3__toB; private bool <patched>5__2; private IEnumerator<CodeInstruction> <enumerator>5__3; private CodeInstruction <instruction>5__4; private CodeInstruction <nextInstruction>5__5; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PatchFieldLoad>d__5(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <enumerator>5__3 = null; <instruction>5__4 = null; <nextInstruction>5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Expected O, but got Unknown //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <patched>5__2 = false; <enumerator>5__3 = instructions.GetEnumerator(); goto IL_01fc; case 1: <>1__state = -1; goto IL_00ba; case 2: <>1__state = -1; <>2__current = <nextInstruction>5__5; <>1__state = 3; return true; case 3: <>1__state = -1; goto IL_01fc; case 4: <>1__state = -1; <>2__current = new CodeInstruction(<nextInstruction>5__5.opcode, (object)toB); <>1__state = 5; return true; case 5: <>1__state = -1; <patched>5__2 = true; <nextInstruction>5__5 = null; goto IL_01f5; case 6: { <>1__state = -1; goto IL_01f5; } IL_01f5: <instruction>5__4 = null; goto IL_01fc; IL_01fc: if (<enumerator>5__3.MoveNext()) { <instruction>5__4 = <enumerator>5__3.Current; if (CodeInstructionExtensions.LoadsField(<instruction>5__4, fromA, true)) { if (!<enumerator>5__3.MoveNext()) { Log.LogError((object)$"Expected to find next instruction after {fromA} load instruction"); <>2__current = <instruction>5__4; <>1__state = 1; return true; } goto IL_00ba; } <>2__current = <instruction>5__4; <>1__state = 6; return true; } if (!<patched>5__2) { Log.LogError((object)"Failed to patch GameSessionHandler.LoadNextLevelScene"); } return false; IL_00ba: <nextInstruction>5__5 = <enumerator>5__3.Current; if (!CodeInstructionExtensions.LoadsField(<nextInstruction>5__5, fromB, false)) { Log.LogInfo((object)$"Candidate patch instruction is not loading {fromB} field: {<nextInstruction>5__5.opcode}:{<nextInstruction>5__5.operand}"); <>2__current = <instruction>5__4; <>1__state = 2; return true; } Log.LogInfo((object)$"Found {fromA} and {fromB} field load instructions to patch"); <>2__current = new CodeInstruction(<instruction>5__4.opcode, (object)toA); <>1__state = 4; 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(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <PatchFieldLoad>d__5 <PatchFieldLoad>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <PatchFieldLoad>d__ = this; } else { <PatchFieldLoad>d__ = new <PatchFieldLoad>d__5(0); } <PatchFieldLoad>d__.fromA = <>3__fromA; <PatchFieldLoad>d__.fromB = <>3__fromB; <PatchFieldLoad>d__.toA = <>3__toA; <PatchFieldLoad>d__.toB = <>3__toB; <PatchFieldLoad>d__.instructions = <>3__instructions; return <PatchFieldLoad>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } [CompilerGenerated] private sealed class <SteamManagerCreateFriendLobbyPatch>d__4 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private IEnumerator<CodeInstruction> <>7__wrap1; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SteamManagerCreateFriendLobbyPatch>d__4(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>7__wrap1 = instructions.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; case 2: <>1__state = -3; break; } if (<>7__wrap1.MoveNext()) { CodeInstruction current = <>7__wrap1.Current; if (CodeInstructionExtensions.LoadsConstant(current, 4L)) { Log.LogMessage((object)$"Found create lobby instruction to patch from 4 to {Constants.MAX_PLAYERS}"); <>2__current = new CodeInstruction(OpCodes.Ldc_I4, (object)Constants.MAX_PLAYERS); <>1__state = 1; return true; } <>2__current = current; <>1__state = 2; return true; } <>m__Finally1(); <>7__wrap1 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap1 != null) { <>7__wrap1.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <SteamManagerCreateFriendLobbyPatch>d__4 <SteamManagerCreateFriendLobbyPatch>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <SteamManagerCreateFriendLobbyPatch>d__ = this; } else { <SteamManagerCreateFriendLobbyPatch>d__ = new <SteamManagerCreateFriendLobbyPatch>d__4(0); } <SteamManagerCreateFriendLobbyPatch>d__.instructions = <>3__instructions; return <SteamManagerCreateFriendLobbyPatch>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } internal static ManualLogSource Log; private Harmony harmony; private bool isVisible = true; private ConfigEntry<int> maxPlayers; [IteratorStateMachine(typeof(<SteamManagerCreateFriendLobbyPatch>d__4))] private static IEnumerable<CodeInstruction> SteamManagerCreateFriendLobbyPatch(IEnumerable<CodeInstruction> instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SteamManagerCreateFriendLobbyPatch>d__4(-2) { <>3__instructions = instructions }; } [IteratorStateMachine(typeof(<PatchFieldLoad>d__5))] public static IEnumerable<CodeInstruction> PatchFieldLoad(FieldInfo fromA, FieldInfo fromB, FieldInfo toA, FieldInfo toB, IEnumerable<CodeInstruction> instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PatchFieldLoad>d__5(-2) { <>3__fromA = fromA, <>3__fromB = fromB, <>3__toA = toA, <>3__toB = toB, <>3__instructions = instructions }; } private void OnGUI() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_016e: 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_0185: Expected O, but got Unknown //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021a: 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) int num = PlayerHandler.Get().NumberOfPlayers(); List<Player> list = PlayerHandler.Get().PlayerList(); GUI.color = new Color(0f, 0f, 0f, 0.7f); GUIStyle val = new GUIStyle(); val.fontSize = 20; val.normal.textColor = Color.white; val.alignment = (TextAnchor)3; val.padding = new RectOffset(10, 10, 5, 5); if (GUI.Button(new Rect(50f, (float)(135 + list.Count * 30), 150f, 40f), "Toggle Visibility")) { isVisible = !isVisible; } GUI.color = Color.white; foreach (SteamConnection connectedPlayer in SteamManager.instance.connectedPlayers) { if (connectedPlayer.hasAvatar) { float num2 = 10f; float num3 = 82f; float num4 = 82f; float num5 = 50f; GUI.DrawTexture(new Rect(90f, num2, num3, num4), (Texture)(object)connectedPlayer.avatar); } else { Log.LogWarning((object)(connectedPlayer.steamName + ", does not have an avatar, this can cause issues. Please set an avatar ASAP.")); } } if (!isVisible) { return; } GUI.Box(new Rect(20f, 90f, 640f, (float)(40 + list.Count * 30)), GUIContent.none); GUIStyle val2 = new GUIStyle(val); val2.fontStyle = (FontStyle)1; GUI.Label(new Rect(25f, 95f, 300f, 30f), $"MoreBopl Leaderboard \n{num} Player(s)", val2); for (int i = 0; i < list.Count; i++) { string text = ((object)list[i].Color).ToString().Replace("Slime (UnityEngine.Material)", ""); string text2 = char.ToUpper(text[0]) + text.Substring(1); CauseOfDeath causeOfDeath = list[i].CauseOfDeath; string text3 = ((object)(CauseOfDeath)(ref causeOfDeath)).ToString(); if (text3 == "NotDeadYet") { text3 = "Alive"; } float num6 = 130 + i * 30; GUI.Label(new Rect(70f, num6, 600f, 30f), $"{text2}: Kills: {list[i].Kills}, Deaths: {list[i].Deaths}, Cause of Death: {text3}", val); } } private Sprite ConvertTexture2DToSprite(Texture2D texture) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) return Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f)); } private Texture2D MakeTex(int width, int height, Color col) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown Color[] array = (Color[])(object)new Color[width * height]; for (int i = 0; i < array.Length; i++) { array[i] = col; } Texture2D val = new Texture2D(width, height); val.SetPixels(array); val.Apply(); return val; } private void Awake() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"Logger Loaded"); maxPlayers = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxPlayers", 8, "The maximum number of players allowed in a lobby."); Constants.MAX_PLAYERS = maxPlayers.Value; Host.recordReplay = false; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Disabled replay recording"); harmony = new Harmony("com.MoreMultiPlayerTeam.MoreMultiPlayer"); harmony.PatchAll(); MethodInfo method = typeof(SteamManager).GetMethod("CreateFriendLobby", BindingFlags.Instance | BindingFlags.Public); if (method == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Failed to find SteamManager::CreateFriendLobby!"); return; } MethodInfo method2 = method.GetCustomAttribute<AsyncStateMachineAttribute>().StateMachineType.GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic); MethodInfo method3 = typeof(Main).GetMethod("SteamManagerCreateFriendLobbyPatch", BindingFlags.Static | BindingFlags.NonPublic); PatchProcessor obj = harmony.CreateProcessor((MethodBase)method2); obj.AddTranspiler(method3); obj.Patch(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"More players acquired! Max players: {Constants.MAX_PLAYERS}"); } private void OnDestroy() { harmony.UnpatchSelf(); } private void Update() { if (SteamClient.Name == "Noob" || !SteamClient.IsValid) { Log.LogFatal((object)"PIRATED GAME DETECTED, PLEASE INSTALL THE FULL GAME! MODS WILL NOT WORK WITHOUT IT AND YOU WILL SUPPORT THE DEVELOPER!"); Application.OpenURL("https://store.steampowered.com/app/1686940/Bopl_Battle/"); Application.Quit(); } } } [HarmonyPatch(typeof(printText))] [HarmonyPatch("Awake")] public static class PatchVersion { public static void Prefix() { Main.Log.LogInfo((object)("Found version " + Constants.version)); Constants.version += " -More Players Modded"; Main.Log.LogInfo((object)("Patched to version " + Constants.version)); } } public struct MultiInputPacket { public Dictionary<int, InputPacket> inputPackets; public MultiInputPacket() { inputPackets = new Dictionary<int, InputPacket>(); } public void Log() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) Main.Log.LogInfo((object)$"MultiInputPacket: {inputPackets.Count} input packets"); foreach (KeyValuePair<int, InputPacket> inputPacket in inputPackets) { Main.Log.LogInfo((object)$"Player {inputPacket.Key}:"); Main.Log.LogInfo((object)$"seqNumber: {inputPacket.Value.seqNumber}"); Main.Log.LogInfo((object)$"joystickAngle: {inputPacket.Value.joystickAngle}"); Main.Log.LogInfo((object)$"jump: {inputPacket.Value.jump}"); Main.Log.LogInfo((object)$"ab1: {inputPacket.Value.ab1}"); Main.Log.LogInfo((object)$"ab2: {inputPacket.Value.ab2}"); Main.Log.LogInfo((object)$"ab3: {inputPacket.Value.ab3}"); Main.Log.LogInfo((object)$"start: {inputPacket.Value.start}"); Main.Log.LogInfo((object)$"select: {inputPacket.Value.select}"); Main.Log.LogInfo((object)$"w: {inputPacket.Value.w}"); Main.Log.LogInfo((object)$"a: {inputPacket.Value.a}"); Main.Log.LogInfo((object)$"s: {inputPacket.Value.s}"); Main.Log.LogInfo((object)$"d: {inputPacket.Value.d}"); Main.Log.LogInfo((object)$"targetDelayBufferSize: {inputPacket.Value.targetDelayBufferSize}"); } } } public struct MultiStartRequestPacket { public ushort seqNum; public uint seed; public byte nrOfPlayers; public byte nrOfAbilites; public byte currentLevel; public byte frameBufferSize; public byte isDemoMask; public ulong[] p_ids; public byte[] p_colors; public byte[] p_teams; public byte[] p_ability1s; public byte[] p_ability2s; public byte[] p_ability3s; public void Initialize(int count) { p_ids = new ulong[count]; p_colors = new byte[count]; p_teams = new byte[count]; p_ability1s = new byte[count]; p_ability2s = new byte[count]; p_ability3s = new byte[count]; } public override string ToString() { return string.Format("seqNum: {0}, seed: {1}, nrOfPlayers: {2}, nrOfAbilites: {3}, currentLevel: {4}, frameBufferSize: {5}, isDemoMask: {6}, p_ids: {7}, p_colors: {8}, p_teams: {9}, p_ability1s: {10}, p_ability2s: {11}, p_ability3s: {12}", seqNum, seed, nrOfPlayers, nrOfAbilites, currentLevel, frameBufferSize, isDemoMask, string.Join(", ", p_ids), string.Join(", ", p_colors), string.Join(", ", p_teams), string.Join(", ", p_ability1s), string.Join(", ", p_ability2s), string.Join(", ", p_ability3s)); } } public static class NetworkToolsExtensions { public static MultiStartRequestPacket ReadMultiStartRequest(byte[] data, ref byte[] uintConversionHelperArray, ref byte[] ulongConversionHelperArray, ref byte[] ushortConversionHelperArray) { Main.Log.LogInfo((object)$"Decoding MultiStartRequestPacket, size of array: {data.Length}"); MultiStartRequestPacket result = default(MultiStartRequestPacket); int num = 0; ushortConversionHelperArray[0] = data[num++]; ushortConversionHelperArray[1] = data[num++]; result.seqNum = NetworkTools.SwapBytesIfLittleEndian(BitConverter.ToUInt16(ushortConversionHelperArray, 0)); Main.Log.LogInfo((object)$"Decoded seqNum: {result.seqNum} (byte: {num})"); uintConversionHelperArray[0] = data[num++]; uintConversionHelperArray[1] = data[num++]; uintConversionHelperArray[2] = data[num++]; uintConversionHelperArray[3] = data[num++]; result.seed = NetworkTools.SwapBytesIfLittleEndian(BitConverter.ToUInt32(uintConversionHelperArray, 0)); Main.Log.LogInfo((object)$"Decoded seed: {result.seed} (byte: {num})"); result.nrOfPlayers = data[num++]; result.nrOfAbilites = data[num++]; result.currentLevel = data[num++]; result.frameBufferSize = data[num++]; result.isDemoMask = data[num++]; Main.Log.LogInfo((object)$"Decoded nrOfPlayers: {result.nrOfPlayers}, nrOfAbilities: {result.nrOfAbilites}, currentLevel: {result.currentLevel}, frameBufferSize: {result.frameBufferSize}, isDemoMask: {result.isDemoMask} (byte: {num})"); result.Initialize(result.nrOfPlayers); for (int i = 0; i < result.nrOfPlayers; i++) { ulongConversionHelperArray[0] = data[num++]; ulongConversionHelperArray[1] = data[num++]; ulongConversionHelperArray[2] = data[num++]; ulongConversionHelperArray[3] = data[num++]; ulongConversionHelperArray[4] = data[num++]; ulongConversionHelperArray[5] = data[num++]; ulongConversionHelperArray[6] = data[num++]; ulongConversionHelperArray[7] = data[num++]; result.p_ids[i] = NetworkTools.SwapBytesIfLittleEndian(BitConverter.ToUInt64(ulongConversionHelperArray, 0)); Main.Log.LogInfo((object)$"Decoded p_ids[{i}]: {result.p_ids[i]} (byte: {num})"); } for (int j = 0; j < result.nrOfPlayers; j++) { result.p_colors[j] = data[num++]; Main.Log.LogInfo((object)$"Decoded p_colors[{j}]: {result.p_colors[j]} (byte: {num})"); } for (int k = 0; k < result.nrOfPlayers; k++) { result.p_teams[k] = data[num++]; Main.Log.LogInfo((object)$"Decoded p_teams[{k}]: {result.p_teams[k]} (byte: {num})"); } for (int l = 0; l < result.nrOfPlayers; l++) { result.p_ability1s[l] = data[num++]; Main.Log.LogInfo((object)$"Decoded p_ability1s[{l}]: {result.p_ability1s[l]} (byte: {num})"); } for (int m = 0; m < result.nrOfPlayers; m++) { result.p_ability2s[m] = data[num++]; Main.Log.LogInfo((object)$"Decoded p_ability2s[{m}]: {result.p_ability2s[m]} (byte: {num})"); } for (int n = 0; n < result.nrOfPlayers; n++) { result.p_ability3s[n] = data[num++]; Main.Log.LogInfo((object)$"Decoded p_ability3s[{n}]: {result.p_ability3s[n]} (byte: {num})"); } return result; } public static void EncodeMultiStartRequest(ref byte[] data, MultiStartRequestPacket p) { Main.Log.LogInfo((object)$"Encoding MultiStartRequestPacket, size of array: {data.Length}"); int num = 0; Main.Log.LogInfo((object)$"Encoding seqNum: {p.seqNum} (byte: {num})"); p.seqNum = NetworkTools.SwapBytesIfLittleEndian(p.seqNum); byte[] bytes = BitConverter.GetBytes(p.seqNum); data[num++] = bytes[0]; data[num++] = bytes[1]; Main.Log.LogInfo((object)$"Encoding seed: {p.seed} (byte: {num})"); p.seed = NetworkTools.SwapBytesIfLittleEndian(p.seed); bytes = BitConverter.GetBytes(p.seed); data[num++] = bytes[0]; data[num++] = bytes[1]; data[num++] = bytes[2]; data[num++] = bytes[3]; data[num++] = p.nrOfPlayers; data[num++] = p.nrOfAbilites; data[num++] = p.currentLevel; data[num++] = p.frameBufferSize; data[num++] = p.isDemoMask; Main.Log.LogInfo((object)$"Encoded nrOfPlayers: {p.nrOfPlayers}, nrOfAbilities: {p.nrOfAbilites}, currentLevel: {p.currentLevel}, frameBufferSize: {p.frameBufferSize}, isDemoMask: {p.isDemoMask} (byte: {num})"); for (int i = 0; i < p.nrOfPlayers; i++) { Main.Log.LogInfo((object)$"Encoding p_ids[{i}]: {p.p_ids[i]} (byte: {num})"); bytes = BitConverter.GetBytes(NetworkTools.SwapBytesIfLittleEndian(p.p_ids[i])); data[num++] = bytes[0]; data[num++] = bytes[1]; data[num++] = bytes[2]; data[num++] = bytes[3]; data[num++] = bytes[4]; data[num++] = bytes[5]; data[num++] = bytes[6]; data[num++] = bytes[7]; } for (int j = 0; j < p.nrOfPlayers; j++) { data[num++] = p.p_colors[j]; Main.Log.LogInfo((object)$"Encoded p_colors[{j}]: {p.p_colors[j]} (byte: {num})"); } for (int k = 0; k < p.nrOfPlayers; k++) { data[num++] = p.p_teams[k]; Main.Log.LogInfo((object)$"Encoded p_teams[{k}]: {p.p_teams[k]} (byte: {num})"); } for (int l = 0; l < p.nrOfPlayers; l++) { data[num++] = p.p_ability1s[l]; Main.Log.LogInfo((object)$"Encoded p_ability1s[{l}]: {p.p_ability1s[l]} (byte: {num})"); } for (int m = 0; m < p.nrOfPlayers; m++) { data[num++] = p.p_ability2s[m]; Main.Log.LogInfo((object)$"Encoded p_ability2s[{m}]: {p.p_ability2s[m]} (byte: {num})"); } for (int n = 0; n < p.nrOfPlayers; n++) { data[num++] = p.p_ability3s[n]; Main.Log.LogInfo((object)$"Encoded p_ability3s[{n}]: {p.p_ability3s[n]} (byte: {num})"); } } public static int GetMultiStartRequestSize(MultiStartRequestPacket startParameters) { return 11 + startParameters.nrOfPlayers * 13; } } [HarmonyPatch(typeof(NetworkTools))] [HarmonyPatch("ReadLobbyReadyPacket")] public static class NetworkTools_ReadLobbyReadyPacket { private static void Postfix(ref LobbyReadyPacket __result) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) Debug.Log((object)"ReadLobbyReadyPacket"); Debug.Log((object)__result.steamId); Debug.Log((object)__result.ability1); Debug.Log((object)__result.ability2); Debug.Log((object)__result.ability3); Debug.Log((object)__result.color); Debug.Log((object)__result.team); Debug.Log((object)__result.ownsFullGame); Debug.Log((object)__result.usesKeyboardAndMouse); Debug.Log((object)"Connected Players"); foreach (SteamConnection connectedPlayer in SteamManager.instance.connectedPlayers) { Debug.Log((object)connectedPlayer.id); } } } internal class SteamManagerExtended { public static MultiStartRequestPacket startParameters; } [HarmonyPatch(typeof(SteamManager))] [HarmonyPatch("HostGame")] internal static class SteamManagerPatch_HostGame { private static FieldRef<SteamManager, ushort> nextStartGameSeqAccess = AccessTools.FieldRefAccess<SteamManager, ushort>("nextStartGameSeq"); public static bool Prefix(SteamManager __instance, PlayerInit hostPlayer) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_015d: 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_0324: Unknown result type (might be due to invalid IL or missing references) Main.Log.LogInfo((object)"Running custom HostGame patch"); ((Lobby)(ref __instance.currentLobby)).SetData("LFM", "0"); ((Lobby)(ref __instance.currentLobby)).SetFriendsOnly(); ((Lobby)(ref __instance.currentLobby)).SetJoinable(false); SteamManagerExtended.startParameters = default(MultiStartRequestPacket); SteamManagerExtended.startParameters.seqNum = nextStartGameSeqAccess.Invoke(__instance)++; SteamManagerExtended.startParameters.nrOfPlayers = (byte)(__instance.connectedPlayers.Count + 1); SteamManagerExtended.startParameters.nrOfAbilites = (byte)Settings.Get().NumberOfAbilities; SteamManagerExtended.startParameters.currentLevel = GameSession.CurrentLevel(); SteamManagerExtended.startParameters.seed = (uint)Environment.TickCount; SteamManagerExtended.startParameters.Initialize(__instance.connectedPlayers.Count + 1); ManualLogSource log = Main.Log; SteamId steamId = SteamClient.SteamId; log.LogInfo((object)("My SteamID: " + ((object)(SteamId)(ref steamId)).ToString())); SteamManagerExtended.startParameters.p_ids[0] = SteamId.op_Implicit(SteamClient.SteamId); SteamManagerExtended.startParameters.p_teams[0] = (byte)hostPlayer.team; SteamManagerExtended.startParameters.p_colors[0] = (byte)hostPlayer.color; SteamManagerExtended.startParameters.p_ability1s[0] = (byte)hostPlayer.ability0; SteamManagerExtended.startParameters.p_ability2s[0] = (byte)hostPlayer.ability1; SteamManagerExtended.startParameters.p_ability3s[0] = (byte)hostPlayer.ability2; for (int i = 1; i < SteamManagerExtended.startParameters.nrOfPlayers; i++) { Main.Log.LogInfo((object)$"{i} <? {__instance.connectedPlayers.Count}"); SteamManagerExtended.startParameters.p_ids[i] = SteamId.op_Implicit(__instance.connectedPlayers[i - 1].id); SteamManagerExtended.startParameters.p_teams[i] = __instance.connectedPlayers[i - 1].lobby_team; SteamManagerExtended.startParameters.p_colors[i] = (byte)__instance.connectedPlayers[i - 1].lobby_color; SteamManagerExtended.startParameters.p_ability1s[i] = __instance.connectedPlayers[i - 1].lobby_ability1; SteamManagerExtended.startParameters.p_ability2s[i] = __instance.connectedPlayers[i - 1].lobby_ability2; SteamManagerExtended.startParameters.p_ability3s[i] = __instance.connectedPlayers[i - 1].lobby_ability3; } byte b = (SteamManager.instance.dlc.HasDLC() ? ((byte)1) : ((byte)0)); for (int j = 0; j < __instance.connectedPlayers.Count; j++) { if (__instance.connectedPlayers[j].ownsFullGame) { b = (byte)(b | (1 << j + 1)); } } SteamManagerExtended.startParameters.isDemoMask = b; byte[] data = new byte[NetworkToolsExtensions.GetMultiStartRequestSize(SteamManagerExtended.startParameters)]; Main.Log.LogInfo((object)SteamManagerExtended.startParameters.ToString()); NetworkToolsExtensions.EncodeMultiStartRequest(ref data, SteamManagerExtended.startParameters); for (int k = 0; k < __instance.connectedPlayers.Count; k++) { ((Connection)(ref ((ConnectionManager)__instance.connectedPlayers[k]).Connection)).SendMessage(data, (SendType)8); } return false; } } [HarmonyPatch(typeof(SteamManager))] [HarmonyPatch("ForceLoadNextLevel")] internal static class SteamManagerPatch_ForceLoadNextLevel { [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] [HarmonyPatch(typeof(SteamManager), "ChangePlayerAbilites")] public static void ChangePlayerAbilities(Player player, byte ability1, byte ability2, byte ability3, int nrOfAbilities, NamedSpriteList abilityIcons) { throw new NotImplementedException("It's a stub"); } public static bool Prefix() { Main.Log.LogInfo((object)"Running custom ForceLoadNextLevel patch"); SteamManager.networkClientHandle.DeInit(); MultiStartRequestPacket startParameters = SteamManagerExtended.startParameters; List<Player> list = PlayerHandler.Get().PlayerList(); if (startParameters.nrOfPlayers <= 1) { GameSessionHandler.LeaveGame(true, false); return false; } int num; for (num = list.Count - 1; num >= 0; num--) { if (!list[num].IsLocalPlayer && !SteamManager.instance.connectedPlayers.Any((SteamConnection player) => SteamId.op_Implicit(player.id) == SteamId.op_Implicit(list[num].steamId))) { list.RemoveAt(num); Debug.Log((object)"dropping player because they were disconnected"); } } for (int i = 0; i < list.Count; i++) { ChangePlayerAbilities(list[i], startParameters.p_ability1s[i], startParameters.p_ability2s[i], startParameters.p_ability3s[i], startParameters.nrOfAbilites, SteamManager.instance.abilityIcons); } GameSession.SetCurrentLevel(startParameters.currentLevel); if (!GameSessionHandler.GameIsPaused) { CharacterStatsList.ForceNextLevelImmediately(); } else { CharacterStatsList.ForceNextLevelLoad(); } return false; } } [HarmonyPatch(typeof(SteamManager))] [HarmonyPatch("InitNetworkClient")] internal static class SteamManagerPatch_InitNetworkClient { private static bool Prefix(SteamManager __instance) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown Main.Log.LogInfo((object)"Running custom InitNetworkClient patch"); int num = Array.IndexOf(SteamManagerExtended.startParameters.p_ids, SteamClient.SteamId.Value) + 1; List<Client> list = new List<Client>(); foreach (SteamConnection connectedPlayer in __instance.connectedPlayers) { ulong value = connectedPlayer.id.Value; int num2 = Array.IndexOf(SteamManagerExtended.startParameters.p_ids, value) + 1; list.Add(new Client(num2, connectedPlayer)); } __instance.networkClient.Init(list, num, SteamManagerExtended.startParameters.currentLevel, __instance.startFrameBuffer, __instance.checkForDesyncs); SteamManager.networkClientHandle = __instance.networkClient; return false; } } [HarmonyPatch(typeof(SteamManager))] [HarmonyPatch("HostNextLevel")] internal static class SteamManagerPatch_HostNextLevel { [HarmonyPatch(typeof(SteamManager))] [HarmonyPatch("KickPlayer")] private static class SteamManagerPatch_KickPlayer { private static void Prefix(ref int connectedPlayerIndex, SteamManager __instance) { connectedPlayerIndex = Mathf.Clamp(connectedPlayerIndex, 0, __instance.connectedPlayers.Count - 1); } } private static bool Prefix(SteamManager __instance, Player hostPlayer, NamedSpriteList abilityIcons) { //IL_0187: Unknown result type (might be due to invalid IL or missing references) Main.Log.LogInfo((object)"Running custom HostNextLevel patch"); GameSession.CurrentLevel(); SteamManagerExtended.startParameters.frameBufferSize = (byte)Host.CurrentDelayBufferSize; SteamManagerExtended.startParameters.seed = (uint)Environment.TickCount; SteamManagerExtended.startParameters.nrOfPlayers = (byte)(__instance.connectedPlayers.Count + 1); SteamManagerExtended.startParameters.currentLevel = GameSession.CurrentLevel(); SteamManagerExtended.startParameters.p_ability1s[0] = (byte)abilityIcons.IndexOf(((Object)hostPlayer.Abilities[0]).name); if (Settings.Get().NumberOfAbilities > 1) { SteamManagerExtended.startParameters.p_ability2s[0] = (byte)abilityIcons.IndexOf(((Object)hostPlayer.Abilities[1]).name); } if (Settings.Get().NumberOfAbilities > 2) { SteamManagerExtended.startParameters.p_ability3s[0] = (byte)abilityIcons.IndexOf(((Object)hostPlayer.Abilities[2]).name); } for (int i = 0; i < __instance.connectedPlayers.Count; i++) { SteamManagerExtended.startParameters.p_ability1s[i + 1] = __instance.connectedPlayers[i].lobby_ability1; SteamManagerExtended.startParameters.p_ability2s[i + 1] = __instance.connectedPlayers[i].lobby_ability2; SteamManagerExtended.startParameters.p_ability3s[i + 1] = __instance.connectedPlayers[i].lobby_ability3; } byte[] data = new byte[NetworkToolsExtensions.GetMultiStartRequestSize(SteamManagerExtended.startParameters)]; NetworkToolsExtensions.EncodeMultiStartRequest(ref data, SteamManagerExtended.startParameters); for (int j = 0; j < __instance.connectedPlayers.Count; j++) { ((Connection)(ref ((ConnectionManager)__instance.connectedPlayers[j]).Connection)).SendMessage(data, (SendType)8); } return false; } } [HarmonyPatch(typeof(SteamSocket))] [HarmonyPatch("OnMessage")] public static class SteamSocketPatch_OnMessage { [CompilerGenerated] private sealed class <Transpiler>d__4 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private IEnumerator<CodeInstruction> <enumerator>5__2; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Transpiler>d__4(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <enumerator>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; Main.Log.LogInfo((object)"Patching SteamSocket.OnMessage()"); <enumerator>5__2 = instructions.GetEnumerator(); break; case 1: { <>1__state = -1; if (!<enumerator>5__2.MoveNext()) { Main.Log.LogError((object)"Expected to find next instruction after Ack.get_PacketTypeAsEnum() call"); return false; } CodeInstruction current = <enumerator>5__2.Current; if (CodeInstructionExtensions.LoadsConstant(current, 5L)) { <>2__current = Log(new CodeInstruction(OpCodes.Ldc_I4, (object)254)); <>1__state = 2; return true; } if (CodeInstructionExtensions.LoadsConstant(current, 6L)) { <>2__current = new CodeInstruction(OpCodes.Ldc_I4, (object)255); <>1__state = 3; return true; } <>2__current = current; <>1__state = 4; return true; } case 2: <>1__state = -1; break; case 3: <>1__state = -1; break; case 4: <>1__state = -1; break; case 5: <>1__state = -1; break; } if (<enumerator>5__2.MoveNext()) { CodeInstruction current = <enumerator>5__2.Current; if (CodeInstructionExtensions.Calls(current, AccessTools.Method(typeof(Ack), "get_PacketTypeAsEnum", (Type[])null, (Type[])null))) { <>2__current = current; <>1__state = 1; return true; } <>2__current = current; <>1__state = 5; 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() { <Transpiler>d__4 <Transpiler>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <Transpiler>d__ = this; } else { <Transpiler>d__ = new <Transpiler>d__4(0); } <Transpiler>d__.instructions = <>3__instructions; return <Transpiler>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } private static byte[] ulongConversionArray = new byte[8]; private static byte[] uintConversionArray = new byte[4]; private static byte[] ushortConversionArray = new byte[2]; private static CodeInstruction Log(CodeInstruction i) { Main.Log.LogInfo((object)i); return i; } [IteratorStateMachine(typeof(<Transpiler>d__4))] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Transpiler>d__4(-2) { <>3__instructions = instructions }; } private static bool Prefix(SteamSocket __instance, Connection connection, NetIdentity identity, IntPtr data, int size, long messageNum, long recvTime, int channel) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) if (size >= 24 && size != 67 && size != 83) { SteamId steamId = ((NetIdentity)(ref identity)).SteamId; if (!((SteamId)(ref steamId)).IsValid) { Main.Log.LogWarning((object)"got message from invalid steamId"); return false; } Friend val = new Friend(((NetIdentity)(ref identity)).SteamId); if (!((Friend)(ref val)).IsIn(((Lobby)(ref SteamManager.instance.currentLobby)).Id)) { ManualLogSource log = Main.Log; steamId = ((NetIdentity)(ref identity)).SteamId; log.LogWarning((object)("Ignored a msg from " + ((object)(SteamId)(ref steamId)).ToString())); return false; } byte[] array = new byte[size]; Marshal.Copy(data, array, 0, size); if (((Lobby)(ref SteamManager.instance.currentLobby)).IsOwnedBy(((NetIdentity)(ref identity)).SteamId)) { SteamManagerExtended.startParameters = NetworkToolsExtensions.ReadMultiStartRequest(array, ref uintConversionArray, ref ulongConversionArray, ref ushortConversionArray); if (GameSession.inMenus) { CharacterSelectHandler_online.ForceStartGame((PlayerColors)null); } else { SteamManager.ForceLoadNextLevel(); } } return false; } return true; } } public static class PluginInfo { public const string PLUGIN_GUID = "MoreMultiPlayer"; public const string PLUGIN_NAME = "MoreMultiPlayer"; public const string PLUGIN_VERSION = "1.0.0"; } }