using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using Features.MultiplayerSessionServices.Scripts; using Features.SessionManagementModule.Gate; using Features.SessionManagementModule.Models; using Features.SessionManagementModule.Networked; using Fusion; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LobbyExpansionFix")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LobbyExpansionFix")] [assembly: AssemblyTitle("LobbyExpansionFix")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LastPirates.LobbyExpansionFix { [BepInPlugin("com.bwadd.lastpirates.lobbyexpansionfix", "Last Pirates Lobby Expansion Fix", "1.2.1")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.bwadd.lastpirates.lobbyexpansionfix"; public const string PluginName = "Last Pirates Lobby Expansion Fix"; public const string PluginVersion = "1.2.1"; internal static ConfigEntry MaxPlayers; internal static ConfigEntry EnableLateJoin; internal static ConfigEntry RecoverMissingBellCountdown; internal static ConfigEntry FixExpandedShopVote; private Rect _windowRect = new Rect(30f, 80f, 500f, 340f); private bool _showWindow; private int _editedMaxPlayers; private bool _editedLateJoin; private bool _editedBellRecovery; private bool _editedShopVoteFix; private CursorLockMode _previousCursorLockMode; private bool _previousCursorVisible; private Texture2D _windowTexture; private Texture2D _controlTexture; private Texture2D _highlightTexture; private GUIStyle _windowStyle; private GUIStyle _labelStyle; private GUIStyle _headerStyle; private GUIStyle _toggleStyle; private GUIStyle _buttonStyle; private GUIStyle _sliderStyle; private GUIStyle _sliderThumbStyle; private void Awake() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) MaxPlayers = ((BaseUnityPlugin)this).Config.Bind("Lobby", "MaxPlayers", 16, new ConfigDescription("Maximum number of players in a Photon Fusion room created by this host.", (AcceptableValueBase)(object)new AcceptableValueRange(2, 32), Array.Empty())); EnableLateJoin = ((BaseUnityPlugin)this).Config.Bind("Lobby", "EnableLateJoin", true, "Allow unmodded clients to join after the host has started the run."); RecoverMissingBellCountdown = ((BaseUnityPlugin)this).Config.Bind("Progression", "RecoverMissingBellCountdown", true, "Complete a level when quota and bell activation replicated but the bell countdown tick is missing."); FixExpandedShopVote = ((BaseUnityPlugin)this).Config.Bind("Progression", "FixExpandedShopVote", true, "Allow an expanded lobby to leave the four-seat purchase screen after four distinct players vote."); new Harmony("com.bwadd.lastpirates.lobbyexpansionfix").PatchAll(typeof(Plugin).Assembly); LoadEditedValues(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Compatibility fixes enabled: capacity={MaxPlayers.Value}, lateJoin={EnableLateJoin.Value}, bellRecovery={RecoverMissingBellCountdown.Value}, shopVoteFix={FixExpandedShopVote.Value}."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Press F1 to open the Lobby Expansion Fix host settings."); } private void Update() { if (Input.GetKeyDown((KeyCode)282)) { SetWindowVisible(!_showWindow); } } private void OnGUI() { //IL_0016: 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_0037: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (_showWindow) { EnsureStyles(); _windowRect = GUI.Window(819204, _windowRect, new WindowFunction(DrawSettingsWindow), "Lobby Expansion Fix 1.2.1", _windowStyle); GUI.BringWindowToFront(819204); } } private void DrawSettingsWindow(int windowId) { //IL_01c3: Unknown result type (might be due to invalid IL or missing references) GUILayout.Label("HOST SETTINGS", _headerStyle, Array.Empty()); GUILayout.Label("Press F1 at any time to close this window.", _labelStyle, Array.Empty()); GUILayout.Space(12f); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Maximum players", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(360f) }); GUILayout.Label(_editedMaxPlayers.ToString(), _headerStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }); GUILayout.EndHorizontal(); _editedMaxPlayers = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)_editedMaxPlayers, 2f, 32f, _sliderStyle, _sliderThumbStyle, Array.Empty())); GUILayout.Label("The new cap applies when the host creates the next room.", _labelStyle, Array.Empty()); GUILayout.Space(14f); _editedLateJoin = GUILayout.Toggle(_editedLateJoin, "Allow players to join after the run starts", _toggleStyle, Array.Empty()); _editedBellRecovery = GUILayout.Toggle(_editedBellRecovery, "Recover a missing bell countdown", _toggleStyle, Array.Empty()); _editedShopVoteFix = GUILayout.Toggle(_editedShopVoteFix, "Let four shop votes advance expanded lobbies", _toggleStyle, Array.Empty()); GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button("Save settings", _buttonStyle, Array.Empty())) { SaveEditedValues(); } if (GUILayout.Button("Reset changes", _buttonStyle, Array.Empty())) { LoadEditedValues(); } if (GUILayout.Button("Close", _buttonStyle, Array.Empty())) { SetWindowVisible(visible: false); } GUILayout.EndHorizontal(); GUI.DragWindow(new Rect(0f, 0f, 10000f, 24f)); } private void EnsureStyles() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00b3: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_0102: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected O, but got Unknown //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: 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_019c: Expected O, but got Unknown //IL_01a7: 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_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Expected O, but got Unknown //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Expected O, but got Unknown //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Expected O, but got Unknown if (_windowStyle == null) { _windowTexture = MakeTexture(new Color(0.035f, 0.055f, 0.085f, 0.98f)); _controlTexture = MakeTexture(new Color(0.12f, 0.19f, 0.27f, 1f)); _highlightTexture = MakeTexture(new Color(0.15f, 0.82f, 0.72f, 1f)); _windowStyle = new GUIStyle(GUI.skin.window) { fontSize = 17, fontStyle = (FontStyle)1, alignment = (TextAnchor)1, padding = new RectOffset(22, 22, 34, 18) }; _windowStyle.normal.background = _windowTexture; _windowStyle.normal.textColor = Color.white; _labelStyle = new GUIStyle(GUI.skin.label) { fontSize = 15, wordWrap = true }; _labelStyle.normal.textColor = new Color(0.94f, 0.97f, 1f, 1f); _headerStyle = new GUIStyle(_labelStyle) { fontSize = 17, fontStyle = (FontStyle)1 }; _headerStyle.normal.textColor = new Color(0.25f, 1f, 0.88f, 1f); _toggleStyle = new GUIStyle(GUI.skin.toggle) { fontSize = 15, fixedHeight = 28f }; _toggleStyle.normal.textColor = Color.white; _toggleStyle.onNormal.textColor = new Color(0.25f, 1f, 0.88f, 1f); _toggleStyle.hover.textColor = new Color(0.25f, 1f, 0.88f, 1f); _toggleStyle.onHover.textColor = new Color(0.25f, 1f, 0.88f, 1f); _buttonStyle = new GUIStyle(GUI.skin.button) { fontSize = 14, fontStyle = (FontStyle)1, fixedHeight = 34f }; _buttonStyle.normal.background = _controlTexture; _buttonStyle.normal.textColor = Color.white; _buttonStyle.hover.background = _highlightTexture; _buttonStyle.hover.textColor = new Color(0.02f, 0.08f, 0.1f, 1f); _sliderStyle = new GUIStyle(GUI.skin.horizontalSlider) { fixedHeight = 12f }; _sliderStyle.normal.background = _controlTexture; _sliderThumbStyle = new GUIStyle(GUI.skin.horizontalSliderThumb) { fixedWidth = 20f, fixedHeight = 22f }; _sliderThumbStyle.normal.background = _highlightTexture; _sliderThumbStyle.hover.background = _highlightTexture; } } private static Texture2D MakeTexture(Color color) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false); val.SetPixel(0, 0, color); val.Apply(); return val; } private void LoadEditedValues() { _editedMaxPlayers = MaxPlayers.Value; _editedLateJoin = EnableLateJoin.Value; _editedBellRecovery = RecoverMissingBellCountdown.Value; _editedShopVoteFix = FixExpandedShopVote.Value; } private void SaveEditedValues() { MaxPlayers.Value = Mathf.Clamp(_editedMaxPlayers, 2, 32); EnableLateJoin.Value = _editedLateJoin; RecoverMissingBellCountdown.Value = _editedBellRecovery; FixExpandedShopVote.Value = _editedShopVoteFix; ((BaseUnityPlugin)this).Config.Save(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Settings saved: capacity={MaxPlayers.Value}, lateJoin={EnableLateJoin.Value}, bellRecovery={RecoverMissingBellCountdown.Value}, shopVoteFix={FixExpandedShopVote.Value}."); } private void SetWindowVisible(bool visible) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (visible != _showWindow) { _showWindow = visible; if (visible) { LoadEditedValues(); _previousCursorLockMode = Cursor.lockState; _previousCursorVisible = Cursor.visible; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } else { Cursor.lockState = _previousCursorLockMode; Cursor.visible = _previousCursorVisible; } } } private void OnDisable() { if (_showWindow) { SetWindowVisible(visible: false); } } private void OnDestroy() { if ((Object)(object)_windowTexture != (Object)null) { Object.Destroy((Object)(object)_windowTexture); } if ((Object)(object)_controlTexture != (Object)null) { Object.Destroy((Object)(object)_controlTexture); } if ((Object)(object)_highlightTexture != (Object)null) { Object.Destroy((Object)(object)_highlightTexture); } } } [HarmonyPatch(typeof(ShopLeaveVoteObservation), "HasEveryPresentPlayerVotedToLeave")] internal static class ExpandedShopVotePatch { private const int ShopInteractionCapacity = 4; private static void Postfix(MultiplayerModel ____multiplayerModel, ref bool __result) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) if (__result || !Plugin.FixExpandedShopVote.Value) { return; } NetworkRunner val = ((____multiplayerModel != null) ? ____multiplayerModel.NetworkRunner : null); if ((Object)(object)val == (Object)null || !val.IsRunning) { return; } int num = 0; foreach (PlayerRef activePlayer in val.ActivePlayers) { _ = activePlayer; num++; } if (num <= 4) { return; } HashSet hashSet = new HashSet(); ShopVoteNetworkObject[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (ShopVoteNetworkObject val2 in array) { if ((Object)(object)((SimulationBehaviour)val2).Runner == (Object)(object)val && val2.HasVotedToLeave) { hashSet.Add(((SimulationBehaviour)val2).Object.StateAuthority); } } __result = hashSet.Count >= 4; } } [HarmonyPatch(typeof(MultiplayerSessionConfig), "get_MaxPlayersInRoom")] internal static class MaxPlayersInRoomPatch { private static void Postfix(ref int __result) { __result = Plugin.MaxPlayers.Value; } } [HarmonyPatch(typeof(NetworkRunnerRoomPropertyExtensions), "TrySetRoomCustomProperty")] internal static class LateJoinAdvertisementPatch { private static void Prefix(string propertyKey, ref object propertyValue) { if (Plugin.EnableLateJoin.Value && propertyKey == "IsSessionStarted" && propertyValue is bool) { propertyValue = false; } } } [HarmonyPatch(typeof(LevelCompletionResolver), "IsComplete")] internal static class MissingBellCountdownRecoveryPatch { private static void Postfix(bool isQuotaCompleted, bool isBellActivated, int countdownStartTick, ref bool __result) { if (!__result && Plugin.RecoverMissingBellCountdown.Value && isQuotaCompleted && isBellActivated && countdownStartTick == 0) { __result = true; } } } }