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<int> MaxPlayers;
internal static ConfigEntry<bool> EnableLateJoin;
internal static ConfigEntry<bool> RecoverMissingBellCountdown;
internal static ConfigEntry<bool> 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<int>("Lobby", "MaxPlayers", 16, new ConfigDescription("Maximum number of players in a Photon Fusion room created by this host.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 32), Array.Empty<object>()));
EnableLateJoin = ((BaseUnityPlugin)this).Config.Bind<bool>("Lobby", "EnableLateJoin", true, "Allow unmodded clients to join after the host has started the run.");
RecoverMissingBellCountdown = ((BaseUnityPlugin)this).Config.Bind<bool>("Progression", "RecoverMissingBellCountdown", true, "Complete a level when quota and bell activation replicated but the bell countdown tick is missing.");
FixExpandedShopVote = ((BaseUnityPlugin)this).Config.Bind<bool>("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<GUILayoutOption>());
GUILayout.Label("Press F1 at any time to close this window.", _labelStyle, Array.Empty<GUILayoutOption>());
GUILayout.Space(12f);
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
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<GUILayoutOption>()));
GUILayout.Label("The new cap applies when the host creates the next room.", _labelStyle, Array.Empty<GUILayoutOption>());
GUILayout.Space(14f);
_editedLateJoin = GUILayout.Toggle(_editedLateJoin, "Allow players to join after the run starts", _toggleStyle, Array.Empty<GUILayoutOption>());
_editedBellRecovery = GUILayout.Toggle(_editedBellRecovery, "Recover a missing bell countdown", _toggleStyle, Array.Empty<GUILayoutOption>());
_editedShopVoteFix = GUILayout.Toggle(_editedShopVoteFix, "Let four shop votes advance expanded lobbies", _toggleStyle, Array.Empty<GUILayoutOption>());
GUILayout.FlexibleSpace();
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
if (GUILayout.Button("Save settings", _buttonStyle, Array.Empty<GUILayoutOption>()))
{
SaveEditedValues();
}
if (GUILayout.Button("Reset changes", _buttonStyle, Array.Empty<GUILayoutOption>()))
{
LoadEditedValues();
}
if (GUILayout.Button("Close", _buttonStyle, Array.Empty<GUILayoutOption>()))
{
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<PlayerRef> hashSet = new HashSet<PlayerRef>();
ShopVoteNetworkObject[] array = Object.FindObjectsByType<ShopVoteNetworkObject>((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;
}
}
}
}