Decompiled source of LobbyExpansionFix v1.2.1

plugins\LobbyExpansionFix\LobbyExpansionFix.dll

Decompiled 11 minutes ago
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;
			}
		}
	}
}