Decompiled source of MorePlayersLateJoin fixed v1.0.0

BepInEx/plugins/MorePlayersLateJoin_fixed/MorePlayersLateJoin_fixed.dll

Decompiled 5 hours ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MorePlayersLateJoin.Patches;
using Photon.Pun;
using Photon.Realtime;
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("MorePlayersLateJoin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Combined MorePlayers + LateJoin for R.E.P.O.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MorePlayersLateJoin")]
[assembly: AssemblyTitle("MorePlayersLateJoin")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace MorePlayersLateJoin
{
	internal static class LobbyCoordinator
	{
		internal enum LobbyStateReason
		{
			LevelChangeJoinablePhase,
			LevelChangeClosedPhase
		}

		internal struct DesiredLobbyState
		{
			public bool PhotonIsOpen;

			public bool PhotonIsVisible;

			public bool SteamUnlockAsPublic;

			public bool SteamLocked;

			public LobbyStateReason Reason;
		}

		internal struct RoomCreationOptions
		{
			public int MaxPlayers;

			public bool IsVisible;

			public bool IsOpen;

			public string? DisplayName;
		}

		private static readonly FieldInfo? LobbyTypeField = AccessTools.Field(typeof(GameManager), "lobbyType");

		internal static RoomCreationOptions ForPublicHost(string serverDisplayName)
		{
			RoomCreationOptions result = default(RoomCreationOptions);
			result.MaxPlayers = ModConfig.EffectiveMaxPlayers();
			result.IsVisible = ModConfig.PublicLobbySupport.Value;
			result.IsOpen = true;
			result.DisplayName = (ModConfig.PublicLobbySupport.Value ? ("[Modded] " + serverDisplayName) : serverDisplayName);
			return result;
		}

		internal static RoomCreationOptions ForClientJoin()
		{
			RoomCreationOptions result = default(RoomCreationOptions);
			result.MaxPlayers = ModConfig.EffectiveMaxPlayers();
			result.IsVisible = false;
			result.IsOpen = true;
			return result;
		}

		internal static DesiredLobbyState ForRunPhase(bool isLobbyMenu, bool isLobby, bool isShop, LobbyTypes lobbyType)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Invalid comparison between Unknown and I4
			if (!ModConfig.AllowLateJoin.Value)
			{
				return ClosedPhase(LobbyStateReason.LevelChangeClosedPhase);
			}
			if (!(isLobbyMenu || isLobby) && (!isShop || !ModConfig.AllowJoinInShop.Value))
			{
				return ClosedPhase(LobbyStateReason.LevelChangeClosedPhase);
			}
			bool flag = (int)lobbyType == 1;
			bool photonIsVisible = ModConfig.PublicLobbySupport.Value && flag;
			DesiredLobbyState result = default(DesiredLobbyState);
			result.PhotonIsOpen = true;
			result.PhotonIsVisible = photonIsVisible;
			result.SteamUnlockAsPublic = flag;
			result.SteamLocked = false;
			result.Reason = LobbyStateReason.LevelChangeJoinablePhase;
			return result;
		}

		private static DesiredLobbyState ClosedPhase(LobbyStateReason reason)
		{
			DesiredLobbyState result = default(DesiredLobbyState);
			result.PhotonIsOpen = false;
			result.PhotonIsVisible = false;
			result.SteamUnlockAsPublic = false;
			result.SteamLocked = true;
			result.Reason = reason;
			return result;
		}

		internal static void Apply(DesiredLobbyState state)
		{
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			Room currentRoom = PhotonNetwork.CurrentRoom;
			if (currentRoom != null)
			{
				currentRoom.IsOpen = state.PhotonIsOpen;
				currentRoom.IsVisible = state.PhotonIsVisible;
			}
			SteamManager instance = SteamManager.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				if (state.SteamLocked)
				{
					instance.LockLobby();
				}
				else
				{
					instance.UnlockLobby(state.SteamUnlockAsPublic);
				}
				Plugin.Log.LogInfo((object)($"[LobbyCoordinator] {state.Reason} photonOpen={state.PhotonIsOpen} photonVisible={state.PhotonIsVisible} " + $"steamLocked={state.SteamLocked} steamPublic={state.SteamUnlockAsPublic}"));
			}
		}

		internal static RoomOptions BuildRoomOptions(RoomCreationOptions options)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			return new RoomOptions
			{
				MaxPlayers = options.MaxPlayers,
				IsOpen = options.IsOpen,
				IsVisible = options.IsVisible
			};
		}

		internal static LobbyTypes GetLobbyType(GameManager gameManager)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (LobbyTypeField == null)
			{
				Plugin.Log.LogWarning((object)"[LobbyCoordinator] GameManager.lobbyType field not found.");
				return (LobbyTypes)0;
			}
			object value = LobbyTypeField.GetValue(gameManager);
			if (value is LobbyTypes)
			{
				return (LobbyTypes)value;
			}
			return (LobbyTypes)0;
		}

		internal static void ApplyMaxPlayersToGame(GameManager gameManager)
		{
			gameManager.SetMaxPlayers(gameManager.maxPlayersPhoton = ModConfig.EffectiveMaxPlayers());
		}
	}
	internal static class ModConfig
	{
		public const int DefaultMaxPlayers = 10;

		public const int HardMaxPlayersCap = 20;

		public const int MinMaxPlayers = 2;

		internal static ConfigEntry<int> MaxPlayers => Plugin.MaxPlayers;

		internal static ConfigEntry<bool> PublicLobbySupport => Plugin.PublicLobbySupport;

		internal static ConfigEntry<bool> AllowLateJoin => Plugin.AllowLateJoin;

		internal static ConfigEntry<bool> AllowJoinInShop => Plugin.AllowJoinInShop;

		internal static void Bind(ConfigFile config)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			Plugin.MaxPlayers = config.Bind<int>("General", "Max Players", 10, new ConfigDescription("Maximum players in a lobby.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 20), Array.Empty<object>()));
			Plugin.PublicLobbySupport = config.Bind<bool>("General", "Public Lobby Support", true, "Show the host lobby in the server browser when rules allow.");
			Plugin.AllowLateJoin = config.Bind<bool>("General", "Allow Late Join", true, "Allow players to join while a run is in progress (subject to phase rules).");
			Plugin.AllowJoinInShop = config.Bind<bool>("General", "Allow Join In Shop", true, "When late join is enabled, also allow joining during the shop phase.");
		}

		internal static int EffectiveMaxPlayers()
		{
			int value = MaxPlayers.Value;
			if (value < 2)
			{
				return 2;
			}
			if (value > 20)
			{
				return 20;
			}
			return value;
		}
	}
	[BepInPlugin("ozoka.moreplayerslatejoin", "MorePlayersLateJoin", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "ozoka.moreplayerslatejoin";

		public const string PluginName = "MorePlayersLateJoin";

		public const string PluginVersion = "1.0.0";

		private Harmony? _harmony;

		public static ConfigEntry<int> MaxPlayers { get; internal set; }

		public static ConfigEntry<bool> PublicLobbySupport { get; internal set; }

		public static ConfigEntry<bool> AllowLateJoin { get; internal set; }

		public static ConfigEntry<bool> AllowJoinInShop { get; internal set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("ozoka.moreplayerslatejoin");
			_harmony.PatchAll(typeof(GameManagerAwakePatch).Assembly);
			Log.LogInfo((object)"MorePlayersLateJoin v1.0.0 loaded.");
			Log.LogInfo((object)($"Config: MaxPlayers={MaxPlayers.Value}, " + $"PublicLobby={PublicLobbySupport.Value}, " + $"LateJoin={AllowLateJoin.Value}, " + $"JoinInShop={AllowJoinInShop.Value}"));
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace MorePlayersLateJoin.Patches
{
	[HarmonyPatch(typeof(RunManager), "ChangeLevel", new Type[]
	{
		typeof(bool),
		typeof(bool),
		typeof(ChangeLevelType)
	})]
	internal static class LateJoinPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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)
			if (PhotonNetwork.IsMasterClient)
			{
				if ((Object)(object)GameManager.instance == (Object)null)
				{
					Plugin.Log.LogWarning((object)"[LateJoinPatch] ChangeLevel: GameManager.instance is null.");
					return;
				}
				LobbyTypes lobbyType = LobbyCoordinator.GetLobbyType(GameManager.instance);
				LobbyCoordinator.Apply(LobbyCoordinator.ForRunPhase(SemiFunc.RunIsLobbyMenu(), SemiFunc.RunIsLobby(), SemiFunc.RunIsShop(), lobbyType));
			}
		}
	}
	[HarmonyPatch(typeof(GameManager), "Awake")]
	internal static class GameManagerAwakePatch
	{
		[HarmonyPostfix]
		private static void Postfix(GameManager __instance)
		{
			LobbyCoordinator.ApplyMaxPlayersToGame(__instance);
			Plugin.Log.LogInfo((object)$"[LobbyPatch] GameManager.Awake maxPlayers={ModConfig.EffectiveMaxPlayers()}");
		}
	}
	[HarmonyPatch(typeof(NetworkConnect), "TryJoiningRoom")]
	internal static class NetworkConnectTryJoiningRoomPatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			if (!((Object)(object)GameManager.instance == (Object)null))
			{
				LobbyCoordinator.ApplyMaxPlayersToGame(GameManager.instance);
			}
		}
	}
	[HarmonyPatch(typeof(NetworkConnect), "OnConnectedToMaster")]
	internal static class NetworkConnectOnConnectedToMasterPatch
	{
		private static readonly FieldInfo? ConnectRandomField = AccessTools.Field(typeof(GameManager), "connectRandom");

		[HarmonyPrefix]
		private static void Prefix()
		{
			if ((Object)(object)GameManager.instance == (Object)null)
			{
				return;
			}
			LobbyCoordinator.ApplyMaxPlayersToGame(GameManager.instance);
			if (ModConfig.PublicLobbySupport.Value)
			{
				object obj = ConnectRandomField?.GetValue(GameManager.instance);
				if (obj is bool && (bool)obj)
				{
					Plugin.Log.LogDebug((object)"[LobbyPatch] OnConnectedToMaster: max players applied for open lobby paths.");
				}
			}
		}
	}
	[HarmonyPatch(typeof(SteamManager), "HostLobby", new Type[] { typeof(bool) })]
	internal static class SteamLobbyPatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			if (!((Object)(object)GameManager.instance == (Object)null))
			{
				LobbyCoordinator.ApplyMaxPlayersToGame(GameManager.instance);
				Plugin.Log.LogDebug((object)($"[SteamLobbyPatch] HostLobby: maxPlayers={GameManager.instance.maxPlayers} " + "(steam CreateLobbyAsync uses this value)"));
			}
		}
	}
}