Decompiled source of Level Requirements v1.1.0

plugins/MinimumLevel.dll

Decompiled 3 weeks ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppSystem;
using InnerNet;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
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: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("MinimumLevel")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+a47fb94306ff588579317c6839e99a05fc55813a")]
[assembly: AssemblyProduct("MinimumLevel")]
[assembly: AssemblyTitle("MinimumLevel")]
[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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace MinimumLevel
{
	[BepInPlugin("com.atomic.minimumlevel", "Minimum Level", "1.1.0")]
	[BepInProcess("Among Us.exe")]
	public class MinimumLevelPlugin : BasePlugin
	{
		public static MinimumLevelPlugin Instance;

		public static ConfigEntry<int> MinimumLevel;

		public static ConfigEntry<int> MaximumLevel;

		public static ConfigEntry<bool> banInsteadOfKick;

		public static ConfigEntry<bool> customUiInGame;

		public Scroller scroller = null;

		public Transform sliderInner = null;

		public GameObject banInsteadOfKickSetting = null;

		public GameObject MinimumLevelSetting = null;

		public GameOptionButton IncreaseMinLevelButton = null;

		public GameOptionButton DecreaseMinLevelButton = null;

		public GameObject MaximumLevelSetting = null;

		public GameOptionButton IncreaseMaxLevelButton = null;

		public GameOptionButton DecreaseMaxLevelButton = null;

		public GameOptionButton BigIncreaseMinLevelButton = null;

		public GameOptionButton BigDecreaseMinLevelButton = null;

		public GameOptionButton BigIncreaseMaxLevelButton = null;

		public GameOptionButton BigDecreaseMaxLevelButton = null;

		public GameObject kickPlayersNotAtRequirementsButton = null;

		public float inputHeldTime = 0f;

		public float nextRepeatTime = 0f;

		private const float SettingSpacing = -0.45f;

		public event Action recheckLevelRequirements;

		public override void Load()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			Instance = this;
			Harmony val = new Harmony("com.atomic.minimumlevel");
			val.PatchAll();
			MinimumLevel = ((BasePlugin)this).Config.Bind<int>("General", "MinimumLevel", 10, "The minimum player level required to join the game.");
			MaximumLevel = ((BasePlugin)this).Config.Bind<int>("General", "MaximumLevel", 300, "The maximum player level allowed to join the game.");
			banInsteadOfKick = ((BasePlugin)this).Config.Bind<bool>("General", "BanInsteadOfKick", false, "Whether to ban players instead of kicking them if they don't meet level requirements.");
			customUiInGame = ((BasePlugin)this).Config.Bind<bool>("General", "CustomUiInGame", true, "Whether to show custom UI in-game for the settings, this lets values be editted live.");
		}

		public void SyncSettingsUI()
		{
			if (!((Object)(object)sliderInner == (Object)null))
			{
				if ((Object)(object)banInsteadOfKickSetting != (Object)null)
				{
					((Renderer)((Component)((Component)banInsteadOfKickSetting.transform.Find("Toggle")).transform.Find("Check")).GetComponent<SpriteRenderer>()).enabled = banInsteadOfKick.Value;
				}
				if ((Object)(object)MinimumLevelSetting != (Object)null)
				{
					((TMP_Text)((Component)MinimumLevelSetting.transform.Find("Value_TMP")).GetComponent<TextMeshPro>()).text = MinimumLevel.Value.ToString();
				}
				if ((Object)(object)MaximumLevelSetting != (Object)null)
				{
					((TMP_Text)((Component)MaximumLevelSetting.transform.Find("Value_TMP")).GetComponent<TextMeshPro>()).text = MaximumLevel.Value.ToString();
				}
			}
		}

		public GameObject CreateBoolSetting(string name, string title, Vector3 localPos, GameObject boolTemplate, Transform parent, ConfigEntry<bool> config)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<bool> config2 = config;
			GameObject val = Object.Instantiate<GameObject>(boolTemplate, parent);
			((Object)val).name = name;
			val.transform.position = boolTemplate.transform.position;
			val.transform.localPosition = localPos;
			Object.Destroy((Object)(object)val.GetComponent<ToggleOption>());
			Object.Destroy((Object)(object)val.GetComponent<UIScrollbarHelper>());
			((TMP_Text)((Component)val.transform.Find("Title Text")).GetComponent<TextMeshPro>()).text = title;
			PassiveButton component = ((Component)val.transform.Find("Toggle")).GetComponent<PassiveButton>();
			((UnityEvent)component.OnClick).AddListener(UnityAction.op_Implicit((Action)delegate
			{
				config2.Value = !config2.Value;
				SyncSettingsUI();
			}));
			return val;
		}

		public GameObject CreateNumberSetting(string name, string title, Vector3 localPos, GameObject numberTemplate, Transform parent, out GameOptionButton increaseButton, out GameOptionButton decreaseButton, out GameOptionButton bigIncreaseButton, out GameOptionButton bigDecreaseButton, int min, int max, Func<int> getter, Action<int> setter)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: 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_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			Func<int> getter2 = getter;
			Action<int> setter2 = setter;
			GameObject val = Object.Instantiate<GameObject>(numberTemplate, parent);
			((Object)val).name = name;
			val.transform.position = numberTemplate.transform.position;
			val.transform.localPosition = localPos;
			((TMP_Text)((Component)val.transform.Find("Title Text")).GetComponent<TextMeshPro>()).text = title;
			Object.Destroy((Object)(object)val.GetComponent<NumberOption>());
			Object.Destroy((Object)(object)val.GetComponent<UIScrollbarHelper>());
			decreaseButton = ((Component)val.transform.Find("MinusButton")).GetComponent<GameOptionButton>();
			increaseButton = ((Component)val.transform.Find("PlusButton")).GetComponent<GameOptionButton>();
			Transform transform = ((Component)decreaseButton).transform;
			transform.localPosition += new Vector3(0.6f, 0f, 0f);
			Transform transform2 = ((Component)increaseButton).transform;
			transform2.localPosition += new Vector3(0.6f, 0f, 0f);
			Transform transform3 = ((Component)val.transform.Find("ValueBox")).transform;
			transform3.localPosition += new Vector3(0.6f, 0f, 0f);
			Transform transform4 = ((Component)val.transform.Find("Value_TMP")).transform;
			transform4.localPosition += new Vector3(0.6f, 0f, 0f);
			((UnityEvent)((PassiveButton)decreaseButton).OnClick).AddListener(UnityAction.op_Implicit((Action)delegate
			{
				int obj4 = Math.Max(min, getter2() - 1);
				setter2(obj4);
				SyncSettingsUI();
			}));
			((UnityEvent)((PassiveButton)increaseButton).OnClick).AddListener(UnityAction.op_Implicit((Action)delegate
			{
				int obj3 = Math.Min(max, getter2() + 1);
				setter2(obj3);
				SyncSettingsUI();
			}));
			bigDecreaseButton = Object.Instantiate<GameOptionButton>(decreaseButton, val.transform);
			((Object)bigDecreaseButton).name = "BigMinusButton";
			((Component)bigDecreaseButton).transform.localPosition = ((Component)decreaseButton).transform.localPosition + new Vector3(-0.6f, 0f, 0f);
			((Component)bigDecreaseButton).transform.localScale = new Vector3(1.25f, 1.25f, 1.25f);
			bigIncreaseButton = Object.Instantiate<GameOptionButton>(increaseButton, val.transform);
			((Object)bigIncreaseButton).name = "BigPlusButton";
			((Component)bigIncreaseButton).transform.localPosition = ((Component)increaseButton).transform.localPosition + new Vector3(0.6f, 0f, 0f);
			((Component)bigIncreaseButton).transform.localScale = new Vector3(1.25f, 1.25f, 1.25f);
			((UnityEvent)((PassiveButton)bigDecreaseButton).OnClick).AddListener(UnityAction.op_Implicit((Action)delegate
			{
				int obj2 = Math.Max(min, getter2() - 10);
				setter2(obj2);
				SyncSettingsUI();
			}));
			((UnityEvent)((PassiveButton)bigIncreaseButton).OnClick).AddListener(UnityAction.op_Implicit((Action)delegate
			{
				int obj = Math.Min(max, getter2() + 10);
				setter2(obj);
				SyncSettingsUI();
			}));
			return val;
		}

		public GameObject CreateButtonSetting(string name, string title, Vector3 localPos, GameObject numberTemplate, Transform parent, out GameObject button, Func<int> getter, Action<int> setter)
		{
			//IL_002e: 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)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: 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_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			Action<int> setter2 = setter;
			GameObject val = Object.Instantiate<GameObject>(numberTemplate, parent);
			((Object)val).name = name;
			val.transform.position = numberTemplate.transform.position;
			val.transform.localPosition = localPos;
			((TMP_Text)((Component)val.transform.Find("Title Text")).GetComponent<TextMeshPro>()).text = title;
			Object.Destroy((Object)(object)val.GetComponent<NumberOption>());
			Object.Destroy((Object)(object)val.GetComponent<UIScrollbarHelper>());
			button = ((Component)val.transform.Find("PlusButton")).gameObject;
			Object.Destroy((Object)(object)((Component)val.transform.Find("MinusButton")).gameObject);
			((Component)val.transform.Find("Value_TMP")).gameObject.SetActive(false);
			Transform transform = button.transform;
			transform.localScale += new Vector3(8.3f, 0.3f, 0.02f);
			Transform transform2 = button.transform;
			transform2.localPosition += new Vector3(-0.6f, 0f, 0f);
			((Component)button.transform.Find("ButtonSprite")).gameObject.SetActive(false);
			TextMeshPro component = ((Component)button.transform.Find("Text_TMP")).GetComponent<TextMeshPro>();
			((TMP_Text)component).text = "Kick Players Now";
			((Graphic)component).color = Color.white;
			Transform transform3 = ((Component)component).gameObject.transform;
			transform3.localScale += new Vector3(-0.8855f, -0.3f, 0.3f);
			Transform transform4 = ((Component)val.transform.Find("ValueBox")).transform;
			transform4.localScale += new Vector3(0.55f, 0f, 0f);
			Transform transform5 = ((Component)val.transform.Find("ValueBox")).transform;
			transform5.localPosition += new Vector3(0.65f, 0f, 0f);
			((UnityEvent)((PassiveButton)button.GetComponent<GameOptionButton>()).OnClick).AddListener(UnityAction.op_Implicit((Action)delegate
			{
				setter2(0);
			}));
			return val;
		}

		public void CreateSettingsUI(GameObject GameOptionsMenu)
		{
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: 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_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0396: Unknown result type (might be due to invalid IL or missing references)
			//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			if (!customUiInGame.Value)
			{
				return;
			}
			scroller = ((Component)GameOptionsMenu.transform.Find("Scroller")).GetComponent<Scroller>();
			if ((Object)(object)scroller == (Object)null)
			{
				Debug.LogError(Object.op_Implicit("[MinimumLevel] Failed to find Scroller component."));
				return;
			}
			sliderInner = ((Component)scroller).transform.Find("SliderInner");
			if ((Object)(object)sliderInner == (Object)null)
			{
				Debug.LogError(Object.op_Implicit("[MinimumLevel] Failed to find SliderInner transform."));
			}
			else
			{
				if (Object.op_Implicit((Object)(object)sliderInner.Find("Header_Joining")))
				{
					return;
				}
				FloatRange contentYBounds = scroller.ContentYBounds;
				contentYBounds.max += 2.3f;
				Transform val = sliderInner.Find("CategoryHeaderMasked(Clone)");
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogError(Object.op_Implicit("[MinimumLevel] Failed to find CategoryHeaderMasked template, even with (Clone) suffix."));
					return;
				}
				GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, sliderInner);
				((Object)val2).name = "Header_Joining";
				val2.transform.position = val.position;
				val2.transform.localPosition = new Vector3(-0.8828f, -9.5f);
				((TMP_Text)val2.GetComponentInChildren<TextMeshPro>()).text = "Join requirements";
				Transform val3 = sliderInner.Find("GameOption_Checkbox(Clone)");
				if ((Object)(object)val3 == (Object)null)
				{
					Debug.LogError(Object.op_Implicit("[MinimumLevel] Failed to find GameOption_Checkbox template."));
					return;
				}
				banInsteadOfKickSetting = CreateBoolSetting("Setting_BanInsteadOfKick", "Ban instead of kick", new Vector3(0.9228f, -10.1314f, -1.5f), ((Component)val3).gameObject, sliderInner, banInsteadOfKick);
				Transform val4 = sliderInner.Find("GameOption_Number(Clone)");
				if ((Object)(object)val4 == (Object)null)
				{
					Debug.LogError(Object.op_Implicit("[MinimumLevel] Failed to find GameOption_Number template."));
					return;
				}
				MinimumLevelSetting = CreateNumberSetting("Setting_MinimumLevel", "Minimum Level", banInsteadOfKickSetting.transform.localPosition + new Vector3(0f, -0.45f, 0f), ((Component)val4).gameObject, sliderInner, out GameOptionButton increaseButton, out GameOptionButton decreaseButton, out GameOptionButton bigIncreaseButton, out GameOptionButton bigDecreaseButton, 0, 1000, () => MinimumLevel.Value, delegate(int v)
				{
					MinimumLevel.Value = v;
				});
				IncreaseMinLevelButton = increaseButton;
				DecreaseMinLevelButton = decreaseButton;
				BigIncreaseMinLevelButton = bigIncreaseButton;
				BigDecreaseMinLevelButton = bigDecreaseButton;
				MaximumLevelSetting = CreateNumberSetting("Setting_MaximumLevel", "Maximum Level", MinimumLevelSetting.transform.localPosition + new Vector3(0f, -0.45f, 0f), ((Component)val4).gameObject, sliderInner, out GameOptionButton increaseButton2, out GameOptionButton decreaseButton2, out GameOptionButton bigIncreaseButton2, out GameOptionButton bigDecreaseButton2, 0, 1001, () => MaximumLevel.Value, delegate(int v)
				{
					MaximumLevel.Value = v;
				});
				IncreaseMaxLevelButton = increaseButton2;
				DecreaseMaxLevelButton = decreaseButton2;
				BigIncreaseMaxLevelButton = bigIncreaseButton2;
				BigDecreaseMaxLevelButton = bigDecreaseButton2;
				kickPlayersNotAtRequirementsButton = CreateButtonSetting("Setting_KickPlayersNotAtRequirements", "Kick players not at requirements", MaximumLevelSetting.transform.localPosition + new Vector3(0f, -0.45f, 0f), ((Component)val4).gameObject, sliderInner, out GameObject _, () => 0, delegate
				{
					this.recheckLevelRequirements?.Invoke();
				});
				SyncSettingsUI();
			}
		}
	}
	[HarmonyPatch]
	public static class MinimumLevelPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameOptionsMenu), "OnEnable")]
		public static void GameOptionsMenu_Awake_Postfix(GameOptionsMenu __instance)
		{
			if (MinimumLevelPlugin.customUiInGame.Value)
			{
				MinimumLevelPlugin.Instance.CreateSettingsUI(((Component)__instance).gameObject);
				MinimumLevelPlugin.Instance.SyncSettingsUI();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(NetworkedPlayerInfo), "UpdateLevel")]
		public static void UpdateLevel_Postfix(NetworkedPlayerInfo __instance)
		{
			NetworkedPlayerInfo __instance2 = __instance;
			MinimumLevelPlugin.Instance.recheckLevelRequirements += delegate
			{
				CheckPlayerLevel(__instance2);
			};
			CheckPlayerLevel(__instance2);
		}

		public static void CheckPlayerLevel(NetworkedPlayerInfo __instance)
		{
			if (__instance.ClientId == ((InnerNetClient)AmongUsClient.Instance).ClientId)
			{
				return;
			}
			int num = (int)(__instance.PlayerLevel + 1);
			string playerName = __instance.PlayerName;
			if ((Object)(object)GameData.Instance.GetHost() == (Object)(object)PlayerControl.LocalPlayer.Data)
			{
				Debug.Log(Object.op_Implicit(playerName + " has joined and we are host."));
				if (num < MinimumLevelPlugin.MinimumLevel.Value || num > MinimumLevelPlugin.MaximumLevel.Value)
				{
					Debug.Log(Object.op_Implicit($"Kicking player {playerName} for not meeting level requirements. Level: {num}"));
					((InnerNetClient)AmongUsClient.Instance).KickPlayer(__instance.ClientId, MinimumLevelPlugin.banInsteadOfKick.Value);
				}
				else
				{
					Debug.Log(Object.op_Implicit($"Player {playerName} meets level requirements. Level: {num}"));
				}
			}
			else
			{
				Debug.Log(Object.op_Implicit("We are not host, not checking level for " + playerName + "."));
				Debug.Log(Object.op_Implicit($"{GameData.Instance.GetHost()} is the host, and we are {PlayerControl.LocalPlayer.Data}"));
			}
		}
	}
}