Decompiled source of BetterLobby v1.2.2

BetterLobby.dll

Decompiled 8 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[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("sonodima")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.2.0")]
[assembly: AssemblyInformationalVersion("1.2.2")]
[assembly: AssemblyProduct("BetterLobby")]
[assembly: AssemblyTitle("BetterLobby")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 BetterLobby
{
	internal static class LobbyHelpers
	{
		private static readonly int s_dNumPlayers = 1;

		private static readonly int s_dMaxPlayers = 4;

		internal static bool IsFull => (NumPlayers ?? s_dNumPlayers) >= (MaxPlayers ?? s_dMaxPlayers);

		internal static int? NumPlayers => PlayerHandler.instance?.players.Count;

		internal static int? MaxPlayers => Traverse.Create((object)MainMenuHandler.SteamLobbyHandler).Field("m_MaxPlayers").GetValue<int>();

		internal static CSteamID? CurrentID => Traverse.Create((object)MainMenuHandler.SteamLobbyHandler).Field("m_CurrentLobby").GetValue<CSteamID>();

		internal static bool SetPublic(bool value)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (!RunChecks(out var id) || !id.HasValue)
			{
				return false;
			}
			ManualLogSource curLogger = Plugin.CurLogger;
			if (curLogger != null)
			{
				curLogger.LogInfo((object)("Changing Steam lobby type to " + (value ? "PUBLIC" : "FRIENDS ONLY")));
			}
			SteamMatchmaking.SetLobbyType(id.Value, (ELobbyType)((!value) ? 1 : 2));
			return true;
		}

		internal static bool SetJoinable(bool value)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (!RunChecks(out var id) || !id.HasValue)
			{
				return false;
			}
			ManualLogSource curLogger = Plugin.CurLogger;
			if (curLogger != null)
			{
				curLogger.LogInfo((object)("Changing the current lobby to " + (value ? "JOINABLE" : "NOT JOINABLE")));
			}
			SteamMatchmaking.SetLobbyJoinable(id.Value, value);
			if (PhotonNetwork.CurrentRoom != null)
			{
				PhotonNetwork.CurrentRoom.IsOpen = value;
				PhotonNetwork.CurrentRoom.IsVisible = value;
			}
			return true;
		}

		private static bool RunChecks(out CSteamID? id)
		{
			id = CurrentID;
			if (!id.HasValue)
			{
				ManualLogSource curLogger = Plugin.CurLogger;
				if (curLogger != null)
				{
					curLogger.LogWarning((object)"Failed to get the current lobby's CSteamID value.");
				}
				return false;
			}
			if (!PhotonNetwork.IsMasterClient)
			{
				ManualLogSource curLogger2 = Plugin.CurLogger;
				if (curLogger2 != null)
				{
					curLogger2.LogWarning((object)"You can't perform this operation because you are not the master client!");
				}
				return false;
			}
			return true;
		}
	}
	internal sealed class PauseMenu : MonoBehaviour
	{
		private static GameObject UIMenu
		{
			get
			{
				Transform? obj2 = ((IEnumerable<Transform>)Resources.FindObjectsOfTypeAll<Transform>()).FirstOrDefault((Func<Transform, bool>)((Transform obj) => ((Object)obj).name == "EscapeMenu"));
				if (obj2 == null)
				{
					return null;
				}
				Transform obj3 = obj2.Find("MainPage");
				if (obj3 == null)
				{
					return null;
				}
				return ((Component)obj3).gameObject;
			}
		}

		private static GameObject UIButtonList
		{
			get
			{
				GameObject uIMenu = UIMenu;
				if (uIMenu == null)
				{
					return null;
				}
				Transform obj = uIMenu.transform.Find("LIST");
				if (obj == null)
				{
					return null;
				}
				return ((Component)obj).gameObject;
			}
		}

		internal static bool AddButton(string name, string text, UnityAction action, int? index = null)
		{
			GameObject uIButtonList = UIButtonList;
			if ((Object)(object)uIButtonList == (Object)null)
			{
				ManualLogSource curLogger = Plugin.CurLogger;
				if (curLogger != null)
				{
					curLogger.LogError((object)"Failed to find the EscapeMenu control list!");
				}
				return false;
			}
			Transform obj = uIButtonList.transform.Find("RESUME");
			GameObject val = ((obj != null) ? ((Component)obj).gameObject : null);
			if ((Object)(object)val == (Object)null)
			{
				ManualLogSource curLogger2 = Plugin.CurLogger;
				if (curLogger2 != null)
				{
					curLogger2.LogError((object)"Failed to find the 'RESUME' button to use as a template!");
				}
				return false;
			}
			GameObject val2 = Object.Instantiate<GameObject>(val, uIButtonList.transform);
			((Object)val2).name = name;
			if (index.HasValue)
			{
				val2.transform.SetSiblingIndex(index.Value);
			}
			Button componentInChildren = val2.GetComponentInChildren<Button>();
			if ((Object)(object)componentInChildren == (Object)null)
			{
				ManualLogSource curLogger3 = Plugin.CurLogger;
				if (curLogger3 != null)
				{
					curLogger3.LogError((object)"Failed to find the Button component!");
				}
				Object.Destroy((Object)(object)val2);
				return false;
			}
			TextMeshProUGUI componentInChildren2 = val2.GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren2 == (Object)null)
			{
				ManualLogSource curLogger4 = Plugin.CurLogger;
				if (curLogger4 != null)
				{
					curLogger4.LogError((object)"Failed to find the TextMeshProUGUI component!");
				}
				Object.Destroy((Object)(object)val2);
				return false;
			}
			((UnityEvent)componentInChildren.onClick).AddListener(action);
			((TMP_Text)componentInChildren2).SetCharArray(text.ToCharArray());
			((Graphic)componentInChildren2).SetAllDirty();
			return true;
		}
	}
	[ContentWarningPlugin("BetterLobby", "1.2.2", true)]
	[BepInPlugin("BetterLobby", "BetterLobby", "1.2.2")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private ConfigEntry<bool> _incompatibleAck;

		public static ManualLogSource CurLogger { get; private set; }

		private void Awake()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			_incompatibleAck = ((BaseUnityPlugin)this).Config.Bind<bool>("Never Show Again", "Vanilla Compatible", false, "Whether the warning dialog shown when non vanilla-compatible plugins are found is hidden");
			CurLogger = ((BaseUnityPlugin)this).Logger;
			new Harmony("sonodima.BetterLobby").PatchAll();
		}

		private void OnEnable()
		{
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			if (!PhotonGameLobbyHandler.IsSurface || !PhotonNetwork.IsMasterClient)
			{
				return;
			}
			if ((Object)(object)PlayerHandler.instance != (Object)null)
			{
				PlayerHandler instance = PlayerHandler.instance;
				instance.OnPlayerJoined = (Action<Player>)Delegate.Combine(instance.OnPlayerJoined, (Action<Player>)delegate(Player player)
				{
					((MonoBehaviour)this).StartCoroutine(OnPlayerJoined(player));
				});
			}
			PauseMenu.AddButton("FILL", "FILL LOBBY", new UnityAction(OnFillPress), 1);
		}

		private IEnumerator OnPlayerJoined(Player player)
		{
			if (LobbyHelpers.IsFull && SurfaceNetworkHandler.HasStarted)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Maximum number of players reached, closing lobby to the public...");
				LobbyHelpers.SetPublic(value: false);
			}
			yield return (object)new WaitForSeconds(2f);
			if (PhotonGameLobbyHandler.CurrentObjective != null)
			{
				PhotonGameLobbyHandler.Instance.SetCurrentObjective(PhotonGameLobbyHandler.CurrentObjective);
			}
			yield return (object)new WaitForSeconds(1f);
			PhotonView view = player.refs.view;
			Player val = ((view != null) ? view.Owner : null);
			if (val != null && (Object)(object)SurfaceNetworkHandler.Instance != (Object)null && SurfaceNetworkHandler.HasStarted)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Game has already started, sending RPCA_OpenDoor to the late-joiner...");
				((MonoBehaviourPun)SurfaceNetworkHandler.Instance).photonView.RPC("RPCA_OpenDoor", val, new object[0]);
			}
		}

		private void OnFillPress()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			if (GameHandler.GetPluginHash() != "none" && !_incompatibleAck.Value)
			{
				ModalOption[] array = (ModalOption[])(object)new ModalOption[2]
				{
					new ModalOption("Never Show Again", (Action)delegate
					{
						_incompatibleAck.Value = true;
					}),
					new ModalOption("Ok", (Action)null)
				};
				Modal.Show("NON-VANILLA PLUGINS", "You have installed plugins that are marked as non vanilla-compatible.\r\nThis restricts the matchmaking to people with those same exact\r\nplugins, and BetterLobby may not be able to fill the lobby!", array, (Action)null);
			}
			if (LobbyHelpers.IsFull)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Lobby is already full, will not make it public.");
				Modal.ShowError("LOBBY IS FULL", "Wait for a player to disconnect before making it public again!");
			}
			else if (!PhotonGameLobbyHandler.IsSurface)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Attempted to make the lobby public while not on suface!");
				Modal.ShowError("NOT READY", "You need to be on surface to make the lobby public!");
			}
			else
			{
				LobbyHelpers.SetPublic(value: true);
				LobbyHelpers.SetJoinable(value: true);
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "BetterLobby";

		public const string PLUGIN_NAME = "BetterLobby";

		public const string PLUGIN_VERSION = "1.2.2";
	}
}
namespace BetterLobby.Patches
{
	[HarmonyPatch]
	internal static class InviteFriends
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(SteamLobbyHandler), "InviteScreen")]
		private static bool InviteScreenPatch()
		{
			if (LobbyHelpers.IsFull)
			{
				ManualLogSource curLogger = Plugin.CurLogger;
				if (curLogger != null)
				{
					curLogger.LogWarning((object)"Lobby is already full, will not show the invite screen.");
				}
				return false;
			}
			LobbyHelpers.SetPublic(value: false);
			LobbyHelpers.SetJoinable(value: true);
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static bool InviteTerminalPatch(ref bool __result)
		{
			__result = false;
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(EscapeMenuMainPage), "Update")]
		private static bool InviteButtonPatch(EscapeMenuMainPage __instance)
		{
			Button inviteButton = __instance.inviteButton;
			if (inviteButton != null)
			{
				GameObject gameObject = ((Component)inviteButton).gameObject;
				if (gameObject != null)
				{
					gameObject.SetActive(true);
				}
			}
			return false;
		}
	}
	[HarmonyPatch]
	public static class LobbyHandler
	{
		private static bool? s_wasHostPrivate;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(SteamLobbyHandler), "HostMatch")]
		private static bool OnHostMatch(ref bool privateMatch)
		{
			ManualLogSource curLogger = Plugin.CurLogger;
			if (curLogger != null)
			{
				curLogger.LogInfo((object)("Requested " + (privateMatch ? "PRIVATE" : "PUBLIC") + " match. Creating a PUBLIC lobby..."));
			}
			s_wasHostPrivate = privateMatch;
			privateMatch = false;
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(SteamLobbyHandler), "OpenLobby")]
		private static void OpenLobby()
		{
			if (!s_wasHostPrivate.HasValue)
			{
				ManualLogSource curLogger = Plugin.CurLogger;
				if (curLogger != null)
				{
					curLogger.LogWarning((object)"OpenLobby called, but we didn't store a lobby type target! Check this routine again!");
				}
				return;
			}
			ManualLogSource curLogger2 = Plugin.CurLogger;
			if (curLogger2 != null)
			{
				curLogger2.LogInfo((object)("Making the created lobby " + (s_wasHostPrivate.Value ? "PRIVATE" : "PUBLIC") + " as specified in HostMatch..."));
			}
			LobbyHelpers.SetPublic(!s_wasHostPrivate.Value);
			s_wasHostPrivate = null;
		}
	}
}