Decompiled source of LateJoinAllInOne v1.0.0

LateJoinAllInOne.dll

Decompiled a week ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("LateJoinAllInOne")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LateJoinAllInOne")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("75abf0df-7027-478f-b1e9-00480d84523b")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HoppinHauler.LateJoinAllInOne;

internal static class Configs
{
	internal static ConfigEntry<bool> Enabled;

	internal static ConfigEntry<bool> AllowLateJoinAlways;

	internal static ConfigEntry<bool> KeepLobbyJoinableAlways;

	internal static ConfigEntry<Key> UiHotkey;

	internal static void Bind(ConfigFile cfg)
	{
		Enabled = cfg.Bind<bool>("General", "Enabled", true, "Master switch. If false, mod does nothing.");
		AllowLateJoinAlways = cfg.Bind<bool>("LateJoin", "AllowLateJoinAlways", true, "Allow joining even after 'Game has already started!' (host-only).");
		KeepLobbyJoinableAlways = cfg.Bind<bool>("Lobby", "KeepLobbyJoinableAlways", true, "If true, keep lobby joinable whenever there is a free slot (even mid-round). If false, lobby joinable only in ship phase.");
		UiHotkey = cfg.Bind<Key>("UI", "Hotkey", (Key)99, "Hotkey to toggle the in-game config window.");
	}
}
internal static class Patches
{
	[HarmonyPatch(typeof(GameNetworkManager), "LeaveLobbyAtGameStart")]
	private static class LeaveLobbyAtGameStart_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			if (!Configs.Enabled.Value)
			{
				return true;
			}
			return false;
		}
	}

	[HarmonyPatch(typeof(GameNetworkManager), "ConnectionApproval")]
	private static class ConnectionApproval_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(ref ConnectionApprovalRequest request, ref ConnectionApprovalResponse response)
		{
			if (IsHostSafe())
			{
				NetworkManager singleton = NetworkManager.Singleton;
				if ((!((Object)(object)singleton != (Object)null) || request.ClientNetworkId != singleton.LocalClientId) && !response.Approved && Configs.AllowLateJoinAlways.Value && string.Equals(response.Reason, "Game has already started!", StringComparison.Ordinal))
				{
					response.Reason = "";
					response.Approved = true;
				}
			}
		}
	}

	[HarmonyPatch(typeof(QuickMenuManager), "DisableInviteFriendsButton")]
	private static class DisableInviteFriendsButton_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			if (!Configs.Enabled.Value)
			{
				return true;
			}
			return false;
		}
	}

	[HarmonyPatch(typeof(QuickMenuManager), "InviteFriendsButton")]
	private static class InviteFriendsButton_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			if (!Configs.Enabled.Value)
			{
				return true;
			}
			try
			{
				GameNetworkManager instance = GameNetworkManager.Instance;
				if ((Object)instance == (Object)null)
				{
					return false;
				}
				if (!IsHostSafe())
				{
					return false;
				}
				if (instance.disableSteam)
				{
					return false;
				}
				RefreshLobbyJoinable();
				instance.InviteFriendsUI();
			}
			catch
			{
			}
			return false;
		}
	}

	[HarmonyPatch(typeof(StartOfRound), "StartGame")]
	private static class StartGame_Patch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			if (IsHostSafe())
			{
				RefreshLobbyJoinable();
				LateJoinAllInOneUI.Ensure();
			}
		}
	}

	[HarmonyPatch(typeof(StartOfRound), "SetShipReadyToLand")]
	private static class SetShipReadyToLand_Patch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			if (IsHostSafe())
			{
				RefreshLobbyJoinable();
			}
		}
	}

	[HarmonyPatch(typeof(StartOfRound), "OnPlayerDC")]
	private static class OnPlayerDC_Patch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			if (IsHostSafe())
			{
				RefreshLobbyJoinable();
			}
		}
	}

	[HarmonyPatch(typeof(StartOfRound), "OnPlayerConnectedClientRpc")]
	private static class OnPlayerConnectedClientRpc_Patch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			if (IsHostSafe())
			{
				RefreshLobbyJoinable();
			}
		}
	}

	[HarmonyPatch(typeof(GameNetworkManager), "Start")]
	private static class GameNetworkManagerStart_Patch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			try
			{
				LateJoinAllInOneUI.Ensure();
			}
			catch
			{
			}
		}
	}

	internal static bool IsHostSafe()
	{
		try
		{
			if (!Configs.Enabled.Value)
			{
				return false;
			}
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null)
			{
				return false;
			}
			return singleton.IsHost;
		}
		catch
		{
		}
		return false;
	}

	internal static void RefreshLobbyJoinable()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Expected O, but got Unknown
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Expected O, but got Unknown
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Expected O, but got Unknown
		if (!IsHostSafe())
		{
			return;
		}
		GameNetworkManager instance = GameNetworkManager.Instance;
		if ((Object)instance == (Object)null)
		{
			return;
		}
		StartOfRound instance2 = StartOfRound.Instance;
		if ((Object)instance2 == (Object)null)
		{
			return;
		}
		bool flag = instance2.allPlayerScripts != null && instance2.connectedPlayersAmount + 1 < instance2.allPlayerScripts.Length;
		bool flag2 = false;
		if (Configs.AllowLateJoinAlways.Value && flag)
		{
			flag2 = Configs.KeepLobbyJoinableAlways.Value || instance2.inShipPhase;
		}
		try
		{
			instance.SetLobbyJoinable(flag2);
		}
		catch
		{
		}
		try
		{
			QuickMenuManager val = Object.FindObjectOfType<QuickMenuManager>();
			if ((Object)val != (Object)null)
			{
				val.inviteFriendsTextAlpha.alpha = (flag2 ? 1f : 0.2f);
			}
		}
		catch
		{
		}
	}
}
[BepInPlugin("HoppinHauler.LateJoinAllInOne", "LateJoinAllInOne", "1.0.0")]
public sealed class LateJoinAllInOnePlugin : BaseUnityPlugin
{
	internal static ManualLogSource Log;

	private Harmony _harmony;

	private void Awake()
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Configs.Bind(((BaseUnityPlugin)this).Config);
		_harmony = new Harmony("HoppinHauler.LateJoinAllInOne");
		_harmony.PatchAll(typeof(LateJoinAllInOnePlugin).Assembly);
		Log.LogInfo((object)"[LateJoinAllInOne] Loaded.");
	}

	private void OnDestroy()
	{
		try
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
		catch
		{
		}
	}
}
internal static class MyPluginInfo
{
	internal const string PLUGIN_GUID = "HoppinHauler.LateJoinAllInOne";

	internal const string PLUGIN_NAME = "LateJoinAllInOne";

	internal const string PLUGIN_VERSION = "1.0.0";
}
internal sealed class LateJoinAllInOneUI : MonoBehaviour
{
	private static LateJoinAllInOneUI _instance;

	private static bool _visible;

	private Rect _windowRect = new Rect(980f, 20f, 360f, 220f);

	private string _status = "";

	internal static void Ensure()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		if (!((Object)_instance != (Object)null))
		{
			GameObject val = new GameObject("LateJoinAllInOne_UI");
			Object.DontDestroyOnLoad((Object)(object)val);
			_instance = val.AddComponent<LateJoinAllInOneUI>();
		}
	}

	private void Update()
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!Configs.Enabled.Value || IsTypingInInputField())
			{
				return;
			}
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				return;
			}
			Key value = Configs.UiHotkey.Value;
			if (IsKeyPressedThisFrame(current, value))
			{
				_visible = !_visible;
				if (_visible)
				{
					_status = "";
				}
			}
		}
		catch
		{
		}
	}

	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_0036: Expected O, but got Unknown
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		if (_visible)
		{
			_windowRect = GUILayout.Window(128773, _windowRect, new WindowFunction(DrawWindow), "LateJoinAllInOne", Array.Empty<GUILayoutOption>());
		}
	}

	private void DrawWindow(int windowId)
	{
		GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
		GUILayout.Label("Host-only behavior. If you're not host, nothing should happen.", Array.Empty<GUILayoutOption>());
		bool flag = GUILayout.Toggle(Configs.Enabled.Value, "Enabled", Array.Empty<GUILayoutOption>());
		if (flag != Configs.Enabled.Value)
		{
			Configs.Enabled.Value = flag;
			_status = "Saved.";
		}
		bool flag2 = GUILayout.Toggle(Configs.AllowLateJoinAlways.Value, "Allow late join (always)", Array.Empty<GUILayoutOption>());
		if (flag2 != Configs.AllowLateJoinAlways.Value)
		{
			Configs.AllowLateJoinAlways.Value = flag2;
			_status = "Saved.";
		}
		bool flag3 = GUILayout.Toggle(Configs.KeepLobbyJoinableAlways.Value, "Keep lobby joinable always (if slots)", Array.Empty<GUILayoutOption>());
		if (flag3 != Configs.KeepLobbyJoinableAlways.Value)
		{
			Configs.KeepLobbyJoinableAlways.Value = flag3;
			_status = "Saved.";
		}
		GUILayout.Space(8f);
		if (GUILayout.Button("Apply / Refresh lobby joinable", Array.Empty<GUILayoutOption>()))
		{
			try
			{
				Patches.RefreshLobbyJoinable();
				_status = "Refreshed.";
			}
			catch (Exception ex)
			{
				_status = "Refresh failed: " + ex.GetType().Name;
			}
		}
		GUILayout.Space(8f);
		if (!string.IsNullOrEmpty(_status))
		{
			GUILayout.Label(_status, Array.Empty<GUILayoutOption>());
		}
		GUI.DragWindow();
		GUILayout.EndVertical();
	}

	private static bool IsTypingInInputField()
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Expected O, but got Unknown
		try
		{
			EventSystem current = EventSystem.current;
			if ((Object)(object)current == (Object)null)
			{
				return false;
			}
			GameObject currentSelectedGameObject = current.currentSelectedGameObject;
			if ((Object)currentSelectedGameObject == (Object)null)
			{
				return false;
			}
			if ((Object)(object)currentSelectedGameObject.GetComponent<TMP_InputField>() != (Object)null)
			{
				return true;
			}
			if ((Object)(object)currentSelectedGameObject.GetComponent<InputField>() != (Object)null)
			{
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	private static bool IsKeyPressedThisFrame(Keyboard kb, Key key)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			KeyControl val = kb[key];
			return val != null && ((ButtonControl)val).wasPressedThisFrame;
		}
		catch
		{
		}
		return false;
	}
}