Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MorePlayersLateJoin fixed v1.0.0
BepInEx/plugins/MorePlayersLateJoin_fixed/MorePlayersLateJoin_fixed.dll
Decompiled 5 hours agousing 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)")); } } } }