Decompiled source of DeadliestCompany v1.1.0

plugins/EladsHUD.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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.Bootstrap;
using BepInEx.Configuration;
using CustomHUD;
using GameNetcodeStuff;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("EladsHUD")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Custom HUD for lethal company :]")]
[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: AssemblyInformationalVersion("1.3.0")]
[assembly: AssemblyProduct("EladsHUD")]
[assembly: AssemblyTitle("EladsHUD")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.0.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;
		}
	}
}
public enum PocketFlashlightOptions
{
	Disabled,
	Vanilla,
	Separate
}
public enum StaminaTextOptions
{
	Disabled,
	PercentageOnly,
	Full
}
internal class CustomHUD_Mono : MonoBehaviour
{
	public static CustomHUD_Mono instance;

	[Header("Health")]
	public CanvasGroup healthGroup;

	public Image healthBar;

	public TextMeshProUGUI healthText;

	public TextMeshProUGUI healthText2;

	[Header("Stamina")]
	public CanvasGroup staminaGroup;

	public Image staminaBar;

	public Image staminaBarChangeFG;

	public TextMeshProUGUI staminaText;

	public TextMeshProUGUI carryText;

	[Header("Battery")]
	public CanvasGroup batteryGroup;

	public Image batteryBar;

	public TextMeshProUGUI batteryText;

	[Header("Flashlight")]
	public CanvasGroup flashlightGroup;

	public Image flashlightBar;

	public TextMeshProUGUI flashlightText;

	private Color staminaColor;

	private Color staminaWarnColor = new Color(255f, 0f, 0f);

	private float colorLerp;

	private int lastHealth = 100;

	private float lastHealthChange = 0f;

	private void Awake()
	{
		if ((Object)(object)instance != (Object)null)
		{
			throw new Exception("2 instances of CustomHUD_Mono!");
		}
		instance = this;
	}

	private void Start()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		staminaColor = ((Graphic)staminaBar).color;
	}

	public void UpdateFromPlayer(PlayerControllerB player)
	{
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: 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_0210: Unknown result type (might be due to invalid IL or missing references)
		lastHealthChange += Time.deltaTime;
		if (player.health < lastHealth)
		{
			Debug.Log((object)"o shit");
			Debug.Log((object)player.health);
			Debug.Log((object)lastHealth);
			lastHealthChange = 0f;
		}
		lastHealth = player.health;
		int health = player.health;
		float sprintMeter = player.sprintMeter;
		float sprintTime = player.sprintTime;
		if ((double)sprintMeter < 0.3)
		{
			colorLerp = Mathf.Clamp01(colorLerp + Time.deltaTime * 8f);
		}
		else
		{
			colorLerp = Mathf.Clamp01(colorLerp - Time.deltaTime * 8f);
		}
		((Graphic)staminaBar).color = Color.Lerp(staminaColor, staminaWarnColor, colorLerp);
		int num = Mathf.FloorToInt(sprintMeter * 100f);
		float num2 = CalculateStaminaOverTime(player);
		float num3 = num2 * 100f;
		if (Plugin.detailedStamina.Value != 0)
		{
			((TMP_Text)staminaText).text = $"{num}<size=75%><voffset=1>%</voffset></size>";
		}
		else
		{
			((TMP_Text)staminaText).text = "";
		}
		float num4 = Mathf.Sign(num2);
		float num5 = num4;
		if (num5 != -1f)
		{
			if (num5 != 0f)
			{
				if (num5 != 1f)
				{
				}
				staminaBar.fillAmount = sprintMeter;
				staminaBarChangeFG.fillAmount = 0f;
				if (Plugin.detailedStamina.Value == StaminaTextOptions.Full)
				{
					TextMeshProUGUI obj = staminaText;
					((TMP_Text)obj).text = ((TMP_Text)obj).text + " | +" + num3.ToString("0.0") + "<size=75%>/sec</size>";
				}
			}
			else
			{
				staminaBar.fillAmount = sprintMeter;
				staminaBarChangeFG.fillAmount = 0f;
				if (Plugin.detailedStamina.Value == StaminaTextOptions.Full)
				{
					TextMeshProUGUI obj2 = staminaText;
					((TMP_Text)obj2).text = ((TMP_Text)obj2).text + " | +0.0<size=75%>/sec</size>";
				}
			}
		}
		else
		{
			staminaBar.fillAmount = sprintMeter - Mathf.Abs(num2);
			((Graphic)staminaBarChangeFG).color = Color.Lerp(Color.white, staminaWarnColor, colorLerp);
			staminaBarChangeFG.fillAmount = Mathf.Min(sprintMeter, Mathf.Abs(num2));
			((Transform)((Graphic)staminaBarChangeFG).rectTransform).localPosition = new Vector3(1f + 276f * Mathf.Max(0f, sprintMeter - Mathf.Abs(num2)) + 0.05f, 0f);
			if (Plugin.detailedStamina.Value == StaminaTextOptions.Full)
			{
				TextMeshProUGUI obj3 = staminaText;
				((TMP_Text)obj3).text = ((TMP_Text)obj3).text + " | " + num3.ToString("0.0") + "<size=75%>/sec</size>";
			}
		}
		float num6 = Mathf.RoundToInt(Mathf.Clamp(player.carryWeight - 1f, 0f, 100f) * 105f);
		if (Plugin.shouldDoKGConversion)
		{
			num6 *= 0.453592f;
			((TMP_Text)carryText).text = $"{num6}<size=60%>kg</size>";
		}
		else
		{
			((TMP_Text)carryText).text = $"{num6}<size=60%>lb</size>";
		}
		healthBar.fillAmount = (float)health / 100f;
		((TMP_Text)healthText).text = health.ToString();
		if ((Object)(object)healthText2 != (Object)null)
		{
			((TMP_Text)healthText2).text = health.ToString();
		}
		float value = Plugin.healthbarHideDelay.Value;
		healthGroup.alpha = (Plugin.autoHideHealthbar.Value ? Mathf.InverseLerp(value + 1f, value, lastHealthChange) : 1f);
		((Component)flashlightGroup).gameObject.SetActive(UpdateFlashlight(player));
		((Component)batteryGroup).gameObject.SetActive(UpdateBattery(player));
	}

	private bool UpdateFlashlight(PlayerControllerB player)
	{
		if (Plugin.pocketedFlashlightDisplayMode.Value != PocketFlashlightOptions.Separate)
		{
			return false;
		}
		if (!((Behaviour)player.helmetLight).enabled)
		{
			return false;
		}
		GrabbableObject pocketedFlashlight = player.pocketedFlashlight;
		if ((Object)(object)pocketedFlashlight == (Object)null)
		{
			return false;
		}
		if (!pocketedFlashlight.itemProperties.requiresBattery)
		{
			return false;
		}
		flashlightBar.fillAmount = pocketedFlashlight.insertedBattery.charge;
		int num = Mathf.CeilToInt(pocketedFlashlight.insertedBattery.charge * pocketedFlashlight.itemProperties.batteryUsage);
		((TMP_Text)flashlightText).text = $"{Mathf.CeilToInt(pocketedFlashlight.insertedBattery.charge * 100f)}%";
		if (!Plugin.displayTimeLeft.Value)
		{
			return true;
		}
		TextMeshProUGUI obj = flashlightText;
		((TMP_Text)obj).text = ((TMP_Text)obj).text + string.Format(" <size=60%>{0}:{1}", num / 60, (num % 60).ToString("D2"));
		return true;
	}

	private bool UpdateBattery(PlayerControllerB player)
	{
		GrabbableObject val = player.currentlyHeldObjectServer;
		if ((Object)(object)val == (Object)null && Plugin.pocketedFlashlightDisplayMode.Value == PocketFlashlightOptions.Vanilla)
		{
			val = player.pocketedFlashlight;
		}
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		if (!val.itemProperties.requiresBattery)
		{
			return false;
		}
		batteryBar.fillAmount = val.insertedBattery.charge;
		int num = (int)(val.insertedBattery.charge / val.itemProperties.batteryUsage);
		int num2 = Mathf.CeilToInt(val.insertedBattery.charge * val.itemProperties.batteryUsage);
		((TMP_Text)batteryText).text = $"{Mathf.CeilToInt(val.insertedBattery.charge * 100f)}%";
		if (!Plugin.displayTimeLeft.Value)
		{
			return true;
		}
		if (val.itemProperties.itemIsTrigger)
		{
			TextMeshProUGUI obj = batteryText;
			((TMP_Text)obj).text = ((TMP_Text)obj).text + $" ({num} uses remaining)";
		}
		else
		{
			TextMeshProUGUI obj2 = batteryText;
			((TMP_Text)obj2).text = ((TMP_Text)obj2).text + string.Format(" ({0}:{1} remaining)", num2 / 60, (num2 % 60).ToString("D2"));
		}
		return true;
	}

	private float CalculateStaminaOverTime(PlayerControllerB player)
	{
		if (player.sprintMeter == 1f)
		{
			return 0f;
		}
		bool privateField = player.GetPrivateField<bool>("isWalking");
		float sprintTime = player.sprintTime;
		float num = 1f;
		if ((double)player.drunkness > 0.019999999552965164)
		{
			num *= Mathf.Abs(StartOfRound.Instance.drunknessSpeedEffect.Evaluate(player.drunkness) - 1.25f);
		}
		return player.isSprinting ? (-1f / sprintTime * player.carryWeight * num) : ((player.isMovementHindered > 0 && privateField) ? (-1f / sprintTime * num * 0.5f) : ((!privateField) ? (1f / (sprintTime + 4f) * num) : (1f / (sprintTime + 9f) * num)));
	}
}
namespace EladsHUD
{
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "EladsHUD";

		public const string PLUGIN_NAME = "EladsHUD";

		public const string PLUGIN_VERSION = "1.3.0";
	}
}
namespace CustomHUD
{
	[BepInPlugin("me.eladnlg.customhud", "Elads HUD", "1.2.3")]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin instance;

		public AssetBundle assets;

		public GameObject HUD;

		public static bool shouldDoKGConversion;

		internal static ConfigEntry<PocketFlashlightOptions> pocketedFlashlightDisplayMode;

		internal static ConfigEntry<StaminaTextOptions> detailedStamina;

		internal static ConfigEntry<bool> displayTimeLeft;

		internal static ConfigEntry<float> hudScale;

		internal static ConfigEntry<bool> autoHideHealthbar;

		internal static ConfigEntry<float> healthbarHideDelay;

		internal static ConfigEntry<bool> hidePlanetInfo;

		private void Awake()
		{
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Expected O, but got Unknown
			if ((Object)(object)instance != (Object)null)
			{
				throw new Exception("what the cuck??? more than 1 plugin instance.");
			}
			instance = this;
			hudScale = ((BaseUnityPlugin)this).Config.Bind<float>("General", "HUDScale", 1f, "The size of the HUD.");
			autoHideHealthbar = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HideHealthbarAutomatically", true, "Should the healthbar be hidden after not taking damage for a while.");
			healthbarHideDelay = ((BaseUnityPlugin)this).Config.Bind<float>("General", "HealthbarHideDelay", 4f, "The amount of time before the healthbar starts fading away.");
			pocketedFlashlightDisplayMode = ((BaseUnityPlugin)this).Config.Bind<PocketFlashlightOptions>("General", "FlashlightBattery", PocketFlashlightOptions.Separate, "How the flashlight battery is displayed whilst unequipped.\r\nDisabled - Flashlight battery will not be displayed.\r\nVanilla - Flashlight battery will be displayed when you don't have a battery-using item equipped.\r\nSeparate - Flashlight battery will be displayed using a dedicated panel. (recommended)");
			detailedStamina = ((BaseUnityPlugin)this).Config.Bind<StaminaTextOptions>("General", "DetailedStamina", StaminaTextOptions.PercentageOnly, "What the stamina text should display.\r\nDisabled - The stamina text will be hidden.\r\nPercentageOnly - Only the percentage will be displayed. (recommended)\r\nFull - Both percentage and rate of gain/loss will be displayed.");
			displayTimeLeft = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DisplayTimeLeft", true, "Should the uses/time left for a battery-using item be displayed.");
			hidePlanetInfo = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HidePlanetInfo", false, "Should planet info be hidden. If modifying from an in-game menu, this requires you to rejoin the game.");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Elad's HUD is loaded!");
			assets = AssetUtils.LoadAssetBundleFromResources("customhud", typeof(PlayerPatches).Assembly);
			HUD = assets.LoadAsset<GameObject>("PlayerInfo");
			Harmony val = new Harmony("me.eladnlg.customhud");
			val.PatchAll(Assembly.GetExecutingAssembly());
		}

		private void Start()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)(Chainloader.PluginInfos.Count + " plugins loaded"));
			foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Plugin GUID: " + pluginInfo.Value.Metadata.GUID));
			}
			shouldDoKGConversion = Chainloader.PluginInfos.Any((KeyValuePair<string, PluginInfo> pair) => pair.Value.Metadata.GUID == "com.zduniusz.lethalcompany.lbtokg");
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	public class HUDPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(HUDManager __instance)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			HUDElement[] privateField = __instance.GetPrivateField<HUDElement[]>("HUDElements");
			HUDElement val = privateField[2];
			GameObject val2 = Object.Instantiate<GameObject>(Plugin.instance.HUD, ((Component)val.canvasGroup).transform.parent);
			val2.transform.localScale = Vector3.one * 0.75f * Plugin.hudScale.Value;
			val.canvasGroup.alpha = 0f;
			Transform val3 = ((Component)val.canvasGroup).transform.Find("CinematicGraphics");
			if ((Object)(object)val3 != (Object)null && !Plugin.hidePlanetInfo.Value)
			{
				val3.SetParent(val2.transform.parent);
			}
			privateField[2].canvasGroup = val2.GetComponent<CanvasGroup>();
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	public static class PlayerPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("LateUpdate")]
		private static void LateUpdate_Prefix(PlayerControllerB __instance)
		{
			if (((NetworkBehaviour)__instance).IsOwner && (!((NetworkBehaviour)__instance).IsServer || __instance.isHostPlayerObject) && !((Object)(object)CustomHUD_Mono.instance == (Object)null))
			{
				CustomHUD_Mono.instance.UpdateFromPlayer(__instance);
			}
		}
	}
	internal static class ReflectionUtils
	{
		public static T GetPrivateField<T>(this object obj, string field)
		{
			return (T)obj.GetType().GetField(field, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
		}
	}
}
namespace Jotunn.Utils
{
	public static class AssetUtils
	{
		public const char AssetBundlePathSeparator = '$';

		public static Texture2D LoadTexture(string texturePath, bool relativePath = true)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			string text = texturePath;
			if (relativePath)
			{
				text = Path.Combine(Paths.PluginPath, texturePath);
			}
			if (!File.Exists(text))
			{
				return null;
			}
			if (!text.EndsWith(".png") && !text.EndsWith(".jpg"))
			{
				throw new Exception("LoadTexture can only load png or jpg textures");
			}
			byte[] array = File.ReadAllBytes(text);
			Texture2D val = new Texture2D(2, 2);
			val.LoadRawTextureData(array);
			return val;
		}

		public static Sprite LoadSpriteFromFile(string spritePath)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = LoadTexture(spritePath);
			if ((Object)(object)val != (Object)null)
			{
				return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), default(Vector2), 100f);
			}
			return null;
		}

		public static AssetBundle LoadAssetBundle(string bundlePath)
		{
			string text = Path.Combine(Paths.PluginPath, bundlePath);
			if (!File.Exists(text))
			{
				return null;
			}
			return AssetBundle.LoadFromFile(text);
		}

		public static AssetBundle LoadAssetBundleFromResources(string bundleName, Assembly resourceAssembly)
		{
			if (resourceAssembly == null)
			{
				throw new ArgumentNullException("Parameter resourceAssembly can not be null.");
			}
			string text = null;
			try
			{
				text = resourceAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(bundleName));
			}
			catch (Exception)
			{
			}
			if (text == null)
			{
				Debug.LogError((object)("AssetBundle " + bundleName + " not found in assembly manifest"));
				return null;
			}
			AssetBundle result;
			using (Stream stream = resourceAssembly.GetManifestResourceStream(text))
			{
				result = AssetBundle.LoadFromStream(stream);
			}
			return result;
		}

		public static string LoadText(string path)
		{
			string text = Path.Combine(Paths.PluginPath, path);
			if (!File.Exists(text))
			{
				Debug.LogError((object)("Error, failed to load contents from non-existant path: $" + text));
				return null;
			}
			return File.ReadAllText(text);
		}

		public static Sprite LoadSprite(string assetPath)
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			string text = Path.Combine(Paths.PluginPath, assetPath);
			if (!File.Exists(text))
			{
				return null;
			}
			if (text.Contains('$'.ToString()))
			{
				string[] array = text.Split('$');
				string text2 = array[0];
				string text3 = array[1];
				AssetBundle val = AssetBundle.LoadFromFile(text2);
				Sprite result = val.LoadAsset<Sprite>(text3);
				val.Unload(false);
				return result;
			}
			Texture2D val2 = LoadTexture(text, relativePath: false);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				return null;
			}
			return Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), Vector2.zero);
		}
	}
}

plugins/FasterItemDropship.dll

Decompiled 2 months ago
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("FasterItemDropship")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("Mod made by flipf17")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FasterItemDropship")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("a5a250fd-b706-48b9-9be9-da360fd939dc")]
[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 FasterItemDropship
{
	public static class ConfigSettings
	{
		public static ConfigEntry<int> dropshipDeliveryTime;

		public static ConfigEntry<int> dropshipMaxStayDuration;

		public static ConfigEntry<int> dropshipLeaveAfterSecondsOpenDoors;

		public static ConfigEntry<bool> addItemsToDropshipDuringDelivery;

		public static ConfigEntry<bool> startDeliveryBeforePlayerShipLanded;

		public static Dictionary<string, ConfigEntryBase> currentConfigEntries = new Dictionary<string, ConfigEntryBase>();

		public static void BindConfigSettings()
		{
			Plugin.Log("BindingConfigs");
			dropshipDeliveryTime = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("General", "DeliveryTime", 10, "[Host only] How long it takes (in seconds) for the item dropship to arrive."));
			dropshipMaxStayDuration = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("General", "MaxLandDuration", 40, "[Host only] The max duration (in seconds) the item dropship will stay."));
			dropshipLeaveAfterSecondsOpenDoors = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("General", "LeaveAfterSecondsOpenDoors", 3, "[Host only] How long (in seconds) the item dropship will stay for after opening its doors."));
			addItemsToDropshipDuringDelivery = AddConfigEntry<bool>(((BaseUnityPlugin)Plugin.instance).Config.Bind<bool>("General", "AddItemsToDropshipDuringDelivery", true, "[Host only] If true, items purchased while a delivery is in progress, but before the item dropship has fully landed, will be added immediately."));
			startDeliveryBeforePlayerShipLanded = AddConfigEntry<bool>(((BaseUnityPlugin)Plugin.instance).Config.Bind<bool>("General", "StartDeliveryBeforePlayerShipLanded", true, "[Host only] If true, the dropship timer will start incrementing when the players start landing on the moon rather than after they finishing landing on the moon.\nDisable this if this causes any mod conflicts of any kind."));
		}

		public static ConfigEntry<T> AddConfigEntry<T>(ConfigEntry<T> configEntry)
		{
			currentConfigEntries.Add(((ConfigEntryBase)configEntry).Definition.Key, (ConfigEntryBase)(object)configEntry);
			return configEntry;
		}

		public static void TryRemoveOldConfigSettings()
		{
			HashSet<string> hashSet = new HashSet<string>();
			HashSet<string> hashSet2 = new HashSet<string>();
			foreach (ConfigEntryBase value in currentConfigEntries.Values)
			{
				hashSet.Add(value.Definition.Section);
				hashSet2.Add(value.Definition.Key);
			}
			try
			{
				ConfigFile config = ((BaseUnityPlugin)Plugin.instance).Config;
				string configFilePath = config.ConfigFilePath;
				if (!File.Exists(configFilePath))
				{
					return;
				}
				string text = File.ReadAllText(configFilePath);
				string[] array = File.ReadAllLines(configFilePath);
				string text2 = "";
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = array[i].Replace("\n", "");
					if (array[i].Length <= 0)
					{
						continue;
					}
					if (array[i].StartsWith("["))
					{
						if (text2 != "" && !hashSet.Contains(text2))
						{
							text2 = "[" + text2 + "]";
							int num = text.IndexOf(text2);
							int num2 = text.IndexOf(array[i]);
							text = text.Remove(num, num2 - num);
						}
						text2 = array[i].Replace("[", "").Replace("]", "").Trim();
					}
					else
					{
						if (!(text2 != ""))
						{
							continue;
						}
						if (i <= array.Length - 4 && array[i].StartsWith("##"))
						{
							int j;
							for (j = 1; i + j < array.Length && array[i + j].Length > 3; j++)
							{
							}
							if (hashSet.Contains(text2))
							{
								int num3 = array[i + j - 1].IndexOf("=");
								string item = array[i + j - 1].Substring(0, num3 - 1);
								if (!hashSet2.Contains(item))
								{
									int num4 = text.IndexOf(array[i]);
									int num5 = text.IndexOf(array[i + j - 1]) + array[i + j - 1].Length;
									text = text.Remove(num4, num5 - num4);
								}
							}
							i += j - 1;
						}
						else if (array[i].Length > 3)
						{
							text = text.Replace(array[i], "");
						}
					}
				}
				if (!hashSet.Contains(text2))
				{
					text2 = "[" + text2 + "]";
					int num6 = text.IndexOf(text2);
					text = text.Remove(num6, text.Length - num6);
				}
				while (text.Contains("\n\n\n"))
				{
					text = text.Replace("\n\n\n", "\n\n");
				}
				File.WriteAllText(configFilePath, text);
				config.Reload();
			}
			catch
			{
			}
		}
	}
	[BepInPlugin("FlipMods.FasterItemDropship", "FasterItemDropship", "1.3.1")]
	public class Plugin : BaseUnityPlugin
	{
		private Harmony _harmony;

		public static Plugin instance;

		private void Awake()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			instance = this;
			ConfigSettings.BindConfigSettings();
			_harmony = new Harmony("FasterItemDropship");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"FasterItemDropship loaded");
		}

		internal static void Log(string message)
		{
			((BaseUnityPlugin)instance).Logger.LogInfo((object)message);
		}

		internal static void LogWarning(string message)
		{
			((BaseUnityPlugin)instance).Logger.LogWarning((object)message);
		}

		internal static void LogError(string message)
		{
			((BaseUnityPlugin)instance).Logger.LogError((object)message);
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "FlipMods.FasterItemDropship";

		public const string PLUGIN_NAME = "FasterItemDropship";

		public const string PLUGIN_VERSION = "1.3.1";
	}
}
namespace FasterItemDropship.Patches
{
	[HarmonyPatch]
	internal static class FasterItemDropshipPatcher
	{
		private static Terminal terminalScript;

		private static List<int> itemsToDeliver;

		private static float previousShipTimer = 0f;

		private static bool previousFirstOrder = true;

		[HarmonyPatch(typeof(ItemDropship), "Start")]
		[HarmonyPrefix]
		private static void InitializeDropship(ItemDropship __instance)
		{
			itemsToDeliver = (List<int>)Traverse.Create((object)__instance).Field("itemsToDeliver").GetValue();
		}

		[HarmonyPatch(typeof(Terminal), "Start")]
		[HarmonyPrefix]
		private static void InitializeTerminal(Terminal __instance)
		{
			terminalScript = __instance;
		}

		[HarmonyPatch(typeof(ItemDropship), "Update")]
		[HarmonyPrefix]
		private static void DropshipUpdatePrefix(ItemDropship __instance)
		{
			if (NetworkManager.Singleton.IsServer)
			{
				previousShipTimer = __instance.shipTimer;
				previousFirstOrder = __instance.playersFirstOrder;
				if (!__instance.deliveringOrder && (terminalScript.orderedItemsFromTerminal.Count > 0 || terminalScript.orderedVehicleFromTerminal != -1) && !StartOfRound.Instance.shipHasLanded && ConfigSettings.startDeliveryBeforePlayerShipLanded.Value)
				{
					__instance.shipTimer += Time.deltaTime;
				}
			}
		}

		[HarmonyPatch(typeof(ItemDropship), "Update")]
		[HarmonyPostfix]
		private static void DropshipUpdatePostfix(ItemDropship __instance)
		{
			if (NetworkManager.Singleton.IsServer && !__instance.deliveringOrder && (__instance.shipTimer < previousShipTimer || (previousFirstOrder && !__instance.playersFirstOrder)) && (terminalScript.orderedItemsFromTerminal.Count > 0 || terminalScript.orderedVehicleFromTerminal != -1))
			{
				__instance.shipTimer = 40 - ConfigSettings.dropshipDeliveryTime.Value;
			}
		}

		[HarmonyPatch(typeof(ItemDropship), "OpenShipDoorsOnServer")]
		[HarmonyPostfix]
		private static void OnOpenShipDoors(ItemDropship __instance)
		{
			if (NetworkManager.Singleton.IsServer)
			{
				__instance.shipTimer = Mathf.Max(__instance.shipTimer, (float)(30 - ConfigSettings.dropshipLeaveAfterSecondsOpenDoors.Value));
			}
		}

		[HarmonyPatch(typeof(ItemDropship), "ShipLandedAnimationEvent")]
		[HarmonyPostfix]
		private static void OnLandShipFinished(ItemDropship __instance)
		{
			if (!NetworkManager.Singleton.IsServer)
			{
				return;
			}
			__instance.shipTimer = 30 - ConfigSettings.dropshipMaxStayDuration.Value;
			if (ConfigSettings.addItemsToDropshipDuringDelivery.Value)
			{
				while (terminalScript.orderedItemsFromTerminal.Count > 0 && itemsToDeliver.Count < 12)
				{
					itemsToDeliver.Add(terminalScript.orderedItemsFromTerminal[0]);
					terminalScript.orderedItemsFromTerminal.RemoveAt(0);
				}
			}
		}

		[HarmonyPatch(typeof(ItemDropship), "ShipLeave")]
		[HarmonyPatch(typeof(ItemDropship), "FinishDeliveringVehicleOnServer")]
		[HarmonyPostfix]
		private static void OnShipLeave(ItemDropship __instance)
		{
			__instance.shipTimer = 40 - ConfigSettings.dropshipDeliveryTime.Value;
		}
	}
}

plugins/freejester/JesterFree.dll

Decompiled 2 months ago
using System;
using System.Diagnostics;
using System.IO;
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 LCSoundTool;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("JesterFree")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("JesterFree")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("E5A9D456-B06D-4FBC-A40E-190441538DF6")]
[assembly: AssemblyFileVersion("2.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("2.0.0.0")]
namespace JesterFree;

[HarmonyPatch(typeof(JesterAI))]
public static class JesterAiPatch
{
	[HarmonyPatch("Start")]
	[HarmonyPrefix]
	public static void JesterFreePatch(ref AudioClip ___popGoesTheWeaselTheme, ref AudioClip ___screamingSFX, ref AudioSource ___farAudio, ref AudioSource ___creatureVoice)
	{
		if (JesterFreeBase.Instance.IntroEnabled.Value)
		{
			___popGoesTheWeaselTheme = JesterFreeBase.Instance.Intro;
			___farAudio.volume = (float)JesterFreeBase.Instance.IntroVolume.Value / 100f;
		}
		if (JesterFreeBase.Instance.SoloEnabled.Value)
		{
			___screamingSFX = JesterFreeBase.Instance.Solo;
			___creatureVoice.volume = (float)JesterFreeBase.Instance.SoloVolume.Value / 100f;
		}
	}
}
[BepInPlugin("AriDev.JesterFree", "Jester Free", "2.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class JesterFreeBase : BaseUnityPlugin
{
	private const string ModGuid = "AriDev.JesterFree";

	private readonly Harmony _harmony = new Harmony("AriDev.JesterFree");

	public static JesterFreeBase Instance { get; private set; }

	public AudioClip Intro { get; private set; }

	public AudioClip Solo { get; private set; }

	public ConfigEntry<bool> IntroEnabled { get; private set; }

	public ConfigEntry<int> IntroVolume { get; private set; }

	public ConfigEntry<bool> SoloEnabled { get; private set; }

	public ConfigEntry<int> SoloVolume { get; private set; }

	private void Awake()
	{
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Expected O, but got Unknown
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Expected O, but got Unknown
		if ((Object)(object)Instance != (Object)null)
		{
			((BaseUnityPlugin)this).Logger.Log((LogLevel)16, (object)"Jester Free instance already running");
			return;
		}
		Instance = this;
		ConfigEntry<bool> obj = ((BaseUnityPlugin)this).Config.Bind<bool>("Mod", "EnableMod", true, "Enables the mod, otherwise doesn't load it");
		IntroEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Sound", "EnableCrankingIntro", true, "Enables the cranking to be replaced by Free Bird intro");
		IntroVolume = ((BaseUnityPlugin)this).Config.Bind<int>("Sound", "IntroVolume", 50, new ConfigDescription("Sets the volume of the cranking intro (in %)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>()));
		SoloEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Sound", "EnableScreamSolo", true, "Enables the scream to be replaced by Free Bird solo");
		SoloVolume = ((BaseUnityPlugin)this).Config.Bind<int>("Sound", "SoloVolume", 100, new ConfigDescription("Sets the volume of the screaming solo (in %)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>()));
		if (!obj.Value)
		{
			((BaseUnityPlugin)this).Logger.Log((LogLevel)16, (object)"Jester Free disabled in config");
			return;
		}
		((BaseUnityPlugin)this).Logger.Log((LogLevel)16, (object)"Starting Jester Free");
		Intro = SoundTool.GetAudioClip(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "intro.wav");
		Solo = SoundTool.GetAudioClip(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "solo.wav");
		_harmony.PatchAll(typeof(JesterAiPatch));
		_harmony.PatchAll(typeof(JesterFreeBase));
		((BaseUnityPlugin)this).Logger.Log((LogLevel)16, (object)"Jester Free is loaded");
	}
}

plugins/HelmetCamera.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("HelmetCamera")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HelmetCamera")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("b99c4d46-5f13-47b3-a5af-5e3f37772e77")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HelmetCamera
{
	[BepInPlugin("RickArg.lethalcompany.helmetcameras", "Helmet_Cameras", "2.1.5")]
	public class PluginInit : BaseUnityPlugin
	{
		public static Harmony _harmony;

		public static ConfigEntry<int> config_isHighQuality;

		public static ConfigEntry<int> config_renderDistance;

		public static ConfigEntry<int> config_cameraFps;

		private void Awake()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			config_isHighQuality = ((BaseUnityPlugin)this).Config.Bind<int>("MONITOR QUALITY", "monitorResolution", 0, "Low FPS affection. High Quality mode. 0 - vanilla (48x48), 1 - vanilla+ (128x128), 2 - mid quality (256x256), 3 - high quality (512x512), 4 - Very High Quality (1024x1024)");
			config_renderDistance = ((BaseUnityPlugin)this).Config.Bind<int>("MONITOR QUALITY", "renderDistance", 20, "Low FPS affection. Render distance for helmet camera.");
			config_cameraFps = ((BaseUnityPlugin)this).Config.Bind<int>("MONITOR QUALITY", "cameraFps", 30, "Very high FPS affection. FPS for helmet camera. To increase YOUR fps, you should low cameraFps value.");
			_harmony = new Harmony("HelmetCamera");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Helmet_Cameras is loaded with version 2.1.5!");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"--------Helmet camera patch done.---------");
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "RickArg.lethalcompany.helmetcameras";

		public const string PLUGIN_NAME = "Helmet_Cameras";

		public const string PLUGIN_VERSION = "2.1.5";
	}
	public class Plugin : MonoBehaviour
	{
		private RenderTexture renderTexture;

		private bool isMonitorChanged = false;

		private GameObject helmetCameraNew;

		private bool isSceneLoaded = false;

		private bool isCoroutineStarted = false;

		private int currentTransformIndex;

		private int resolution = 0;

		private int renderDistance = 50;

		private float cameraFps = 30f;

		private float elapsed;

		private void Awake()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			resolution = PluginInit.config_isHighQuality.Value;
			renderDistance = PluginInit.config_renderDistance.Value;
			cameraFps = PluginInit.config_cameraFps.Value;
			switch (resolution)
			{
			case 0:
				renderTexture = new RenderTexture(48, 48, 24);
				break;
			case 1:
				renderTexture = new RenderTexture(128, 128, 24);
				break;
			case 2:
				renderTexture = new RenderTexture(256, 256, 24);
				break;
			case 3:
				renderTexture = new RenderTexture(512, 512, 24);
				break;
			case 4:
				renderTexture = new RenderTexture(1024, 1024, 24);
				break;
			}
		}

		public void Start()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			isCoroutineStarted = false;
			while ((Object)(object)helmetCameraNew == (Object)null)
			{
				helmetCameraNew = new GameObject("HelmetCamera");
			}
			Scene activeScene = SceneManager.GetActiveScene();
			if (((Scene)(ref activeScene)).name != "MainMenu")
			{
				activeScene = SceneManager.GetActiveScene();
				if (((Scene)(ref activeScene)).name != "InitScene")
				{
					activeScene = SceneManager.GetActiveScene();
					if (((Scene)(ref activeScene)).name != "InitSceneLaunchOptions")
					{
						isSceneLoaded = true;
						Debug.Log((object)"[HELMET_CAMERAS] Starting coroutine...");
						((MonoBehaviour)this).StartCoroutine(LoadSceneEnter());
						return;
					}
				}
			}
			isSceneLoaded = false;
			isMonitorChanged = false;
		}

		private IEnumerator LoadSceneEnter()
		{
			Debug.Log((object)"[HELMET_CAMERAS] 5 seconds for init mode... Please wait...");
			yield return (object)new WaitForSeconds(5f);
			isCoroutineStarted = true;
			if ((Object)(object)GameObject.Find("Environment/HangarShip/Cameras/ShipCamera") != (Object)null)
			{
				Debug.Log((object)"[HELMET_CAMERAS] Ship camera founded...");
				if (!isMonitorChanged)
				{
					((Renderer)GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/Cube").GetComponent<MeshRenderer>()).materials[2].mainTexture = ((Renderer)GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/Cube.001").GetComponent<MeshRenderer>()).materials[2].mainTexture;
					((Renderer)GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/Cube.001").GetComponent<MeshRenderer>()).materials[2].mainTexture = (Texture)(object)renderTexture;
					helmetCameraNew.AddComponent<Camera>();
					((Behaviour)helmetCameraNew.GetComponent<Camera>()).enabled = false;
					helmetCameraNew.GetComponent<Camera>().targetTexture = renderTexture;
					helmetCameraNew.GetComponent<Camera>().cullingMask = 20649983;
					helmetCameraNew.GetComponent<Camera>().farClipPlane = renderDistance;
					helmetCameraNew.GetComponent<Camera>().nearClipPlane = 0.55f;
					isMonitorChanged = true;
					Debug.Log((object)"[HELMET_CAMERAS] Monitors were changed...");
					Debug.Log((object)"[HELMET_CAMERAS] Turning off vanilla internal ship camera");
					((Behaviour)GameObject.Find("Environment/HangarShip/Cameras/ShipCamera").GetComponent<Camera>()).enabled = false;
				}
			}
		}

		public void Update()
		{
			//IL_022b: 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_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			bool flag = isSceneLoaded && isCoroutineStarted;
			if (flag && StartOfRound.Instance.localPlayerController.isInHangarShipRoom)
			{
				helmetCameraNew.SetActive(true);
				elapsed += Time.deltaTime;
				if (elapsed > 1f / cameraFps)
				{
					elapsed = 0f;
					((Behaviour)helmetCameraNew.GetComponent<Camera>()).enabled = true;
				}
				else
				{
					((Behaviour)helmetCameraNew.GetComponent<Camera>()).enabled = false;
				}
				GameObject val = GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/Cube.001/CameraMonitorScript");
				currentTransformIndex = val.GetComponent<ManualCameraRenderer>().targetTransformIndex;
				TransformAndName val2 = val.GetComponent<ManualCameraRenderer>().radarTargets[currentTransformIndex];
				if (!val2.isNonPlayer)
				{
					try
					{
						helmetCameraNew.transform.SetPositionAndRotation(val2.transform.Find("ScavengerModel/metarig/CameraContainer/MainCamera/HelmetLights").position + new Vector3(0f, 0f, 0f), val2.transform.Find("ScavengerModel/metarig/CameraContainer/MainCamera/HelmetLights").rotation * Quaternion.Euler(0f, 0f, 0f));
						DeadBodyInfo[] array = Object.FindObjectsOfType<DeadBodyInfo>();
						for (int i = 0; i < array.Length; i++)
						{
							if (array[i].playerScript.playerUsername == val2.name)
							{
								helmetCameraNew.transform.SetPositionAndRotation(((Component)array[i]).gameObject.transform.Find("spine.001/spine.002/spine.003").position, ((Component)array[i]).gameObject.transform.Find("spine.001/spine.002/spine.003").rotation * Quaternion.Euler(0f, 0f, 0f));
							}
						}
						return;
					}
					catch (NullReferenceException)
					{
						Debug.Log((object)"[HELMET_CAMERAS] ERROR NULL REFERENCE");
						return;
					}
				}
				helmetCameraNew.transform.SetPositionAndRotation(val2.transform.position + new Vector3(0f, 1.6f, 0f), val2.transform.rotation * Quaternion.Euler(0f, -90f, 0f));
			}
			else if (flag && !StartOfRound.Instance.localPlayerController.isInHangarShipRoom)
			{
				helmetCameraNew.SetActive(false);
			}
		}
	}
}
namespace HelmetCamera.Patches
{
	[HarmonyPatch]
	internal class HelmetCamera
	{
		public static void InitCameras()
		{
			GameObject val = GameObject.Find("Environment/HangarShip/Cameras/ShipCamera");
			val.AddComponent<Plugin>();
		}

		[HarmonyPatch(typeof(StartOfRound), "Start")]
		[HarmonyPostfix]
		public static void InitCamera(ref ManualCameraRenderer __instance)
		{
			InitCameras();
		}
	}
}

plugins/LateCompanyV1.0.17.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
[assembly: AssemblyCompany("LateCompany")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+394f6e913ae93b8bc416d40547f3b1a710f49a92")]
[assembly: AssemblyProduct("LateCompany")]
[assembly: AssemblyTitle("LateCompany")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 LateCompany
{
	public static class PluginInfo
	{
		public const string GUID = "twig.latecompany";

		public const string PrintName = "Late Company";

		public const string Version = "1.0.17";
	}
	[BepInPlugin("twig.latecompany", "Late Company", "1.0.17")]
	internal class Plugin : BaseUnityPlugin
	{
		public static bool LobbyJoinable = true;

		public void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			Harmony val = new Harmony("twig.latecompany");
			val.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.Log((LogLevel)16, (object)"Late Company loaded!");
		}

		public static void SetLobbyJoinable(bool joinable)
		{
			LobbyJoinable = joinable;
			GameNetworkManager.Instance.SetLobbyJoinable(joinable);
			QuickMenuManager val = Object.FindObjectOfType<QuickMenuManager>();
			if (Object.op_Implicit((Object)(object)val))
			{
				val.inviteFriendsTextAlpha.alpha = (joinable ? 1f : 0.2f);
			}
		}
	}
}
namespace LateCompany.Patches
{
	[HarmonyPatch(typeof(GameNetworkManager), "LeaveLobbyAtGameStart")]
	[HarmonyWrapSafe]
	internal static class LeaveLobbyAtGameStart_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			return false;
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager), "ConnectionApproval")]
	[HarmonyWrapSafe]
	internal static class ConnectionApproval_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(ref ConnectionApprovalRequest request, ref ConnectionApprovalResponse response)
		{
			if (request.ClientNetworkId != NetworkManager.Singleton.LocalClientId && Plugin.LobbyJoinable && response.Reason == "Game has already started!")
			{
				response.Reason = "";
				response.Approved = true;
			}
		}
	}
	[HarmonyPatch(typeof(QuickMenuManager), "DisableInviteFriendsButton")]
	internal static class DisableInviteFriendsButton_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			return false;
		}
	}
	[HarmonyPatch(typeof(QuickMenuManager), "InviteFriendsButton")]
	internal static class InviteFriendsButton_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			if (Plugin.LobbyJoinable && !GameNetworkManager.Instance.disableSteam)
			{
				GameNetworkManager.Instance.InviteFriendsUI();
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "OnPlayerConnectedClientRpc")]
	[HarmonyWrapSafe]
	internal static class OnPlayerConnectedClientRpc_Patch
	{
		internal static void UpdateControlledState()
		{
			for (int i = 0; i < StartOfRound.Instance.connectedPlayersAmount + 1; i++)
			{
				if ((i == 0 || !((NetworkBehaviour)StartOfRound.Instance.allPlayerScripts[i]).IsOwnedByServer) && !StartOfRound.Instance.allPlayerScripts[i].isPlayerDead)
				{
					StartOfRound.Instance.allPlayerScripts[i].isPlayerControlled = true;
				}
			}
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			bool flag = false;
			bool flag2 = false;
			bool flag3 = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (!flag3)
				{
					if (!flag && instruction.opcode == OpCodes.Call && instruction.operand != null && instruction.operand.ToString() == "System.Collections.IEnumerator setPlayerToSpawnPosition(UnityEngine.Transform, UnityEngine.Vector3)")
					{
						flag = true;
					}
					else
					{
						if (flag && instruction.opcode == OpCodes.Ldc_I4_0)
						{
							flag2 = true;
							continue;
						}
						if (flag2 && instruction.opcode == OpCodes.Ldloc_0)
						{
							flag2 = false;
							flag3 = true;
							list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(OnPlayerConnectedClientRpc_Patch), "UpdateControlledState", new Type[0], (Type[])null)));
						}
					}
				}
				if (!flag2)
				{
					list.Add(instruction);
				}
			}
			if (!flag3)
			{
				Debug.LogError((object)"Failed to transpile StartOfRound::OnPlayerConnectedClientRpc");
			}
			return list.AsEnumerable();
		}

		[HarmonyPostfix]
		private static void Postfix()
		{
			if (StartOfRound.Instance.connectedPlayersAmount + 1 >= StartOfRound.Instance.allPlayerScripts.Length)
			{
				Plugin.SetLobbyJoinable(joinable: false);
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "OnPlayerDC")]
	[HarmonyWrapSafe]
	internal static class OnPlayerDC_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(int playerObjectNumber)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			if (StartOfRound.Instance.inShipPhase)
			{
				Plugin.SetLobbyJoinable(joinable: true);
			}
			PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerObjectNumber];
			val.activatingItem = false;
			val.bleedingHeavily = false;
			val.clampLooking = false;
			val.criticallyInjured = false;
			val.Crouch(false);
			val.disableInteract = false;
			val.DisableJetpackControlsLocally();
			val.disableLookInput = false;
			val.disableMoveInput = false;
			val.DisablePlayerModel(((Component)val).gameObject, true, true);
			val.disableSyncInAnimation = false;
			val.externalForceAutoFade = Vector3.zero;
			val.freeRotationInInteractAnimation = false;
			val.hasBeenCriticallyInjured = false;
			val.health = 100;
			((Behaviour)val.helmetLight).enabled = false;
			val.holdingWalkieTalkie = false;
			val.inAnimationWithEnemy = null;
			val.inShockingMinigame = false;
			val.inSpecialInteractAnimation = false;
			val.inVehicleAnimation = false;
			val.isClimbingLadder = false;
			val.isSinking = false;
			val.isUnderwater = false;
			Animator mapRadarDotAnimator = val.mapRadarDotAnimator;
			if (mapRadarDotAnimator != null)
			{
				mapRadarDotAnimator.SetBool("dead", false);
			}
			Animator playerBodyAnimator = val.playerBodyAnimator;
			if (playerBodyAnimator != null)
			{
				playerBodyAnimator.SetBool("Limp", false);
			}
			val.ResetZAndXRotation();
			val.sinkingValue = 0f;
			val.speakingToWalkieTalkie = false;
			AudioSource statusEffectAudio = val.statusEffectAudio;
			if (statusEffectAudio != null)
			{
				statusEffectAudio.Stop();
			}
			((Collider)val.thisController).enabled = true;
			((Component)val).transform.SetParent(StartOfRound.Instance.playersContainer);
			val.twoHanded = false;
			val.voiceMuffledByEnemy = false;
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "SetShipReadyToLand")]
	internal static class SetShipReadyToLand_Patch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			if (StartOfRound.Instance.connectedPlayersAmount + 1 < StartOfRound.Instance.allPlayerScripts.Length)
			{
				Plugin.SetLobbyJoinable(joinable: true);
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "StartGame")]
	internal static class StartGame_Patch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			Plugin.SetLobbyJoinable(joinable: false);
		}
	}
}

plugins/LC_SoundTool.dll

Decompiled 2 months ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
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 LCSoundTool.Networking;
using LCSoundTool.Patches;
using LCSoundTool.Resources;
using LCSoundTool.Utilities;
using LCSoundToolMod.Properties;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LC_SoundTool")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Various audio related functions. Mainly logs all sounds that are playing and what type of playback they're into the BepInEx console.")]
[assembly: AssemblyFileVersion("1.5.1.0")]
[assembly: AssemblyInformationalVersion("1.5.1+88559329ca22fd77bccf008b2fc220541ba49b23")]
[assembly: AssemblyProduct("LC_SoundTool")]
[assembly: AssemblyTitle("LC_SoundTool")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/no00ob/LCSoundTool")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.5.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
internal class <Module>
{
	static <Module>()
	{
	}
}
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 LCSoundToolMod
{
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "LC_SoundTool";

		public const string PLUGIN_NAME = "LC_SoundTool";

		public const string PLUGIN_VERSION = "1.5.1";
	}
}
namespace LCSoundToolMod.Properties
{
	[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
	[DebuggerNonUserCode]
	[CompilerGenerated]
	internal class Resources
	{
		private static ResourceManager resourceMan;

		private static CultureInfo resourceCulture;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static ResourceManager ResourceManager
		{
			get
			{
				if (resourceMan == null)
				{
					ResourceManager resourceManager = new ResourceManager("LCSoundToolMod.Properties.Resources", typeof(Resources).Assembly);
					resourceMan = resourceManager;
				}
				return resourceMan;
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static CultureInfo Culture
		{
			get
			{
				return resourceCulture;
			}
			set
			{
				resourceCulture = value;
			}
		}

		internal static byte[] soundtool
		{
			get
			{
				object @object = ResourceManager.GetObject("soundtool", resourceCulture);
				return (byte[])@object;
			}
		}

		internal Resources()
		{
		}
	}
}
namespace LCSoundTool
{
	public class AudioSourceExtension : MonoBehaviour
	{
		public AudioSource audioSource;

		public bool playOnAwake = false;

		public bool loop = false;

		private bool updateHasBeenLogged = false;

		private bool hasPlayed = false;

		private void OnEnable()
		{
			if (!((Object)(object)audioSource == (Object)null) && !audioSource.isPlaying)
			{
				if (playOnAwake)
				{
					audioSource.Play();
				}
				if (SoundTool.infoDebugging)
				{
					SoundTool.Instance.logger.LogDebug((object)$"(AudioSourceExtension) Started playback of {audioSource} with clip {audioSource.clip} in OnEnable function!");
				}
				updateHasBeenLogged = false;
				hasPlayed = false;
			}
		}

		private void OnDisable()
		{
			if (!((Object)(object)audioSource == (Object)null) && audioSource.isPlaying)
			{
				if (playOnAwake)
				{
					audioSource.Stop();
				}
				if (SoundTool.infoDebugging)
				{
					SoundTool.Instance.logger.LogDebug((object)$"(AudioSourceExtension) Stopped playback of {audioSource} with clip {audioSource.clip} in OnDisable function!");
				}
				updateHasBeenLogged = false;
				hasPlayed = false;
			}
		}

		private void Update()
		{
			if ((Object)(object)audioSource == (Object)null)
			{
				return;
			}
			if ((Object)(object)audioSource.clip == (Object)null)
			{
				hasPlayed = false;
			}
			if (audioSource.isPlaying)
			{
				updateHasBeenLogged = false;
			}
			else if (!((Behaviour)audioSource).isActiveAndEnabled)
			{
				hasPlayed = false;
			}
			else
			{
				if (!playOnAwake)
				{
					return;
				}
				if ((Object)(object)audioSource.clip != (Object)null && !hasPlayed)
				{
					audioSource.Play();
					if (SoundTool.infoDebugging)
					{
						SoundTool.Instance.logger.LogDebug((object)$"(AudioSourceExtension) Started playback of {audioSource} with clip {audioSource.clip} in Update function!");
					}
					updateHasBeenLogged = false;
					hasPlayed = true;
				}
				else if ((Object)(object)audioSource.clip == (Object)null && !updateHasBeenLogged)
				{
					updateHasBeenLogged = true;
					if (SoundTool.infoDebugging)
					{
						SoundTool.Instance.logger.LogDebug((object)$"(AudioSourceExtension) Can not start playback of {audioSource} with missing clip in Update function!");
					}
				}
			}
		}
	}
	public class RandomAudioClip
	{
		public AudioClip clip;

		[Range(0f, 1f)]
		public float chance = 1f;

		public RandomAudioClip(AudioClip clip, float chance)
		{
			this.clip = clip;
			this.chance = chance;
		}
	}
	public class ReplacementAudioClip
	{
		public List<RandomAudioClip> clips;

		public string source = string.Empty;

		public bool canPlay = true;

		private bool initialized = false;

		public ReplacementAudioClip(AudioClip clip, float chance, string source)
		{
			if (!initialized)
			{
				Initialize();
			}
			RandomAudioClip randomAudioClip = new RandomAudioClip(clip, chance);
			if (!clips.ContainsThisRandomAudioClip(randomAudioClip))
			{
				clips.Add(randomAudioClip);
				this.source = source;
			}
			else if (SoundTool.infoDebugging)
			{
				SoundTool.Instance.logger.LogDebug((object)$"RandomAudioClip {randomAudioClip.clip.GetName()} ({Mathf.RoundToInt(chance * 100f)}%) already exists withing this AudioClipContainer!");
				SoundTool.Instance.logger.LogDebug((object)"- This AudioClipContainer contains the following clip(s):");
				for (int i = 0; i < clips.Count; i++)
				{
					SoundTool.Instance.logger.LogDebug((object)$"-- Clip {i + 1} - {clips[i].clip.GetName()} with a chance of {Mathf.RoundToInt(clips[i].chance * 100f)}%");
				}
			}
		}

		public ReplacementAudioClip(string source)
		{
			Initialize();
			this.source = source;
		}

		public ReplacementAudioClip()
		{
			Initialize();
			source = string.Empty;
		}

		public void AddClip(AudioClip clip, float chance)
		{
			if (!initialized)
			{
				Initialize();
			}
			RandomAudioClip randomAudioClip = new RandomAudioClip(clip, chance);
			if (!clips.ContainsThisRandomAudioClip(randomAudioClip))
			{
				clips.Add(randomAudioClip);
			}
			else if (SoundTool.infoDebugging)
			{
				SoundTool.Instance.logger.LogDebug((object)$"RandomAudioClip {randomAudioClip.clip.GetName()} ({Mathf.RoundToInt(chance * 100f)}%) already exists withing this AudioClipContainer!");
				SoundTool.Instance.logger.LogDebug((object)"- This AudioClipContainer contains the following clip(s):");
				for (int i = 0; i < clips.Count; i++)
				{
					SoundTool.Instance.logger.LogDebug((object)$"-- Clip {i + 1} - {clips[i].clip.GetName()} with a chance of {Mathf.RoundToInt(clips[i].chance * 100f)}%");
				}
			}
		}

		public bool Full()
		{
			if (!initialized)
			{
				Initialize();
			}
			float num = 0f;
			for (int i = 0; i < clips.Count; i++)
			{
				num += clips[i].chance;
			}
			return num >= 1f;
		}

		public bool ContainsClip(AudioClip clip, float chance)
		{
			if (!initialized)
			{
				Initialize();
			}
			RandomAudioClip thisClip = new RandomAudioClip(clip, chance);
			return clips.ContainsThisRandomAudioClip(thisClip);
		}

		public float TotalChance()
		{
			if (!initialized)
			{
				Initialize();
			}
			float num = 0f;
			for (int i = 0; i < clips.Count; i++)
			{
				num += clips[i].chance;
			}
			return num;
		}

		private void Initialize()
		{
			clips = new List<RandomAudioClip>();
			initialized = true;
		}
	}
	[BepInPlugin("LCSoundTool", "LC Sound Tool", "1.5.1")]
	public class SoundTool : BaseUnityPlugin
	{
		public enum AudioType
		{
			wav,
			ogg,
			mp3
		}

		private const string PLUGIN_GUID = "LCSoundTool";

		private const string PLUGIN_NAME = "LC Sound Tool";

		private ConfigEntry<bool> configUseNetworking;

		private ConfigEntry<bool> configSyncRandomSeed;

		private ConfigEntry<float> configPlayOnAwakePatchRepeatDelay;

		private ConfigEntry<bool> configPrintInfoByDefault;

		private readonly Harmony harmony = new Harmony("LCSoundTool");

		public static SoundTool Instance;

		internal ManualLogSource logger;

		public static bool debugAudioSources;

		public static bool indepthDebugging;

		public static bool infoDebugging;

		public static bool networkingInitialized { get; private set; }

		public static bool networkingAvailable { get; private set; }

		public static Dictionary<string, ReplacementAudioClip> replacedClips { get; private set; }

		public static Dictionary<string, AudioClip> networkedClips => NetworkHandler.networkedAudioClips;

		public static event Action ClientNetworkedAudioChanged
		{
			add
			{
				NetworkHandler.ClientNetworkedAudioChanged += value;
			}
			remove
			{
				NetworkHandler.ClientNetworkedAudioChanged -= value;
			}
		}

		public static event Action HostNetworkedAudioChanged
		{
			add
			{
				NetworkHandler.HostNetworkedAudioChanged += value;
			}
			remove
			{
				NetworkHandler.HostNetworkedAudioChanged -= value;
			}
		}

		public static bool IsDebuggingOn()
		{
			if (debugAudioSources || indepthDebugging || infoDebugging)
			{
				return true;
			}
			return false;
		}

		private void Awake()
		{
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			networkingAvailable = true;
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			configUseNetworking = ((BaseUnityPlugin)this).Config.Bind<bool>("Experimental", "EnableNetworking", false, "Whether or not to use the networking built into this plugin. If set to true everyone in the lobby needs LCSoundTool installed and networking enabled to join.");
			configSyncRandomSeed = ((BaseUnityPlugin)this).Config.Bind<bool>("Experimental", "SyncUnityRandomSeed", false, "Whether or not to sync the default Unity randomization seed with all clients. For this feature, networking has to be set to true. Will send the UnityEngine.Random.seed from the host to all clients automatically upon loading a networked scene.");
			configPlayOnAwakePatchRepeatDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Experimental", "NewPlayOnAwakePatchRepeatDelay", 90f, "How long to wait between checks for new playOnAwake AudioSources. Runs the same patching that is done when each scene is loaded with this delay between each run. DO NOT set too low or high. Anything below 10 or above 600 can cause issues. This time is in seconds. Set to 0 to disable rerunning the patch, but be warned that this might break runtime initialized playOnAwake AudioSources.");
			configPrintInfoByDefault = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "PrintInfoByDefault", false, "Whether or not to print additional information logs created by this mod by default. If set to false, informational logs may be toggled on any time with LeftAlt + F5.");
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
			logger = Logger.CreateLogSource("LCSoundTool");
			logger.LogInfo((object)"Plugin LCSoundTool is loaded!");
			InputHelper.Initialize();
			InputHelper.keybinds.Add("toggleAudioSourceDebugLog", new Keybind(new KeyboardShortcut((KeyCode)286, (KeyCode[])(object)new KeyCode[0]), ToggleDebug));
			InputHelper.keybinds.Add("toggleIndepthDebugLog", new Keybind(new KeyboardShortcut((KeyCode)286, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), ToggleIndepthDebug));
			InputHelper.keybinds.Add("toggleInformationalDebugLog", new Keybind(new KeyboardShortcut((KeyCode)286, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), ToggleInfoDebug));
			InputHelper.keybinds.Add("printAllSoundsDebugLog", new Keybind(new KeyboardShortcut((KeyCode)286, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), PrintAllReplacedSounds));
			InputHelper.keybinds.Add("printAllCurrentSoundsDebugLog", new Keybind(new KeyboardShortcut((KeyCode)287, (KeyCode[])(object)new KeyCode[0]), PrintAllCurrentSounds));
			debugAudioSources = false;
			indepthDebugging = false;
			if (configPrintInfoByDefault.Value)
			{
				infoDebugging = true;
			}
			else
			{
				infoDebugging = false;
			}
			replacedClips = new Dictionary<string, ReplacementAudioClip>();
		}

		private void Start()
		{
			if (!configUseNetworking.Value)
			{
				networkingAvailable = false;
				Instance.logger.LogWarning((object)"Networking disabled. Mod in fully client side mode, but no networked actions can take place! You can safely ignore this if you want the mod to run fully client side.");
			}
			else
			{
				networkingAvailable = true;
			}
			if (configUseNetworking.Value)
			{
				logger.LogDebug((object)"Loading SoundTool AssetBundle...");
				Assets.bundle = AssetBundle.LoadFromMemory(LCSoundToolMod.Properties.Resources.soundtool);
				if ((Object)(object)Assets.bundle == (Object)null)
				{
					logger.LogError((object)"Failed to load SoundTool AssetBundle!");
				}
				else
				{
					logger.LogDebug((object)"Finished loading SoundTool AssetBundle!");
				}
			}
			harmony.PatchAll(typeof(AudioSourcePatch));
			if (configUseNetworking.Value)
			{
				harmony.PatchAll(typeof(GameNetworkManagerPatch));
				harmony.PatchAll(typeof(StartOfRoundPatch));
			}
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private void Update()
		{
			if (configUseNetworking.Value)
			{
				if (!networkingInitialized)
				{
					if ((Object)(object)NetworkHandler.Instance != (Object)null)
					{
						networkingInitialized = true;
					}
				}
				else if ((Object)(object)NetworkHandler.Instance == (Object)null)
				{
					networkingInitialized = false;
				}
			}
			else
			{
				networkingInitialized = false;
			}
			if (!InputHelper.CheckInput("printAllCurrentSoundsDebugLog") && !InputHelper.CheckInput("printAllSoundsDebugLog") && !InputHelper.CheckInput("toggleInformationalDebugLog") && !InputHelper.CheckInput("toggleIndepthDebugLog") && !InputHelper.CheckInput("toggleAudioSourceDebugLog"))
			{
			}
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Instance == (Object)null))
			{
				PatchPlayOnAwakeAudio(scene);
				OnSceneLoadedNetworking();
				if (((Scene)(ref scene)).name.ToLower().Contains("level"))
				{
					((MonoBehaviour)this).StopAllCoroutines();
					((MonoBehaviour)this).StartCoroutine(PatchPlayOnAwakeDelayed(scene, 1f));
				}
			}
		}

		private IEnumerator PatchPlayOnAwakeDelayed(Scene scene, float wait)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (infoDebugging)
			{
				logger.LogDebug((object)$"Started playOnAwake patch coroutine with delay of {wait} seconds");
			}
			yield return (object)new WaitForSecondsRealtime(wait);
			if (infoDebugging)
			{
				logger.LogDebug((object)"Running playOnAwake patch coroutine!");
			}
			PatchPlayOnAwakeAudio(scene);
			float repeatWait = configPlayOnAwakePatchRepeatDelay.Value;
			if (repeatWait != 0f)
			{
				if (repeatWait < 10f)
				{
					repeatWait = 10f;
				}
				if (repeatWait > 600f)
				{
					repeatWait = 600f;
				}
				((MonoBehaviour)this).StartCoroutine(PatchPlayOnAwakeDelayed(scene, repeatWait));
			}
		}

		private void PatchPlayOnAwakeAudio(Scene scene)
		{
			if (infoDebugging)
			{
				Instance.logger.LogDebug((object)("Grabbing all playOnAwake AudioSources for loaded scene " + ((Scene)(ref scene)).name));
			}
			AudioSource[] allPlayOnAwakeAudioSources = GetAllPlayOnAwakeAudioSources();
			if (infoDebugging)
			{
				Instance.logger.LogDebug((object)$"Found a total of {allPlayOnAwakeAudioSources.Length} playOnAwake AudioSource(s)!");
				Instance.logger.LogDebug((object)$"Starting setup on {allPlayOnAwakeAudioSources.Length} playOnAwake AudioSource(s)...");
			}
			AudioSource[] array = allPlayOnAwakeAudioSources;
			AudioSourceExtension audioSourceExtension = default(AudioSourceExtension);
			foreach (AudioSource val in array)
			{
				val.Stop();
				if (((Component)((Component)val).transform).TryGetComponent<AudioSourceExtension>(ref audioSourceExtension))
				{
					audioSourceExtension.audioSource = val;
					audioSourceExtension.playOnAwake = true;
					audioSourceExtension.loop = val.loop;
					val.playOnAwake = false;
					if (infoDebugging)
					{
						Instance.logger.LogDebug((object)$"-Set- {Array.IndexOf(allPlayOnAwakeAudioSources, val) + 1} {val} done!");
					}
					continue;
				}
				AudioSourceExtension audioSourceExtension2 = ((Component)val).gameObject.AddComponent<AudioSourceExtension>();
				audioSourceExtension2.audioSource = val;
				audioSourceExtension2.playOnAwake = true;
				audioSourceExtension2.loop = val.loop;
				val.playOnAwake = false;
				if (infoDebugging)
				{
					Instance.logger.LogDebug((object)$"-Add- {Array.IndexOf(allPlayOnAwakeAudioSources, val) + 1} {val} done!");
				}
			}
			if (infoDebugging)
			{
				Instance.logger.LogDebug((object)$"Done setting up {allPlayOnAwakeAudioSources.Length} playOnAwake AudioSources!");
			}
		}

		private void OnSceneLoadedNetworking()
		{
			if (networkingAvailable && networkingInitialized && configSyncRandomSeed.Value)
			{
				int num = (int)DateTime.Now.Ticks;
				Random.InitState(num);
				SendUnityRandomSeed(num);
			}
		}

		public AudioSource[] GetAllPlayOnAwakeAudioSources()
		{
			AudioSource[] array = Object.FindObjectsOfType<AudioSource>(true);
			List<AudioSource> list = new List<AudioSource>();
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i].playOnAwake)
				{
					list.Add(array[i]);
				}
			}
			return list.ToArray();
		}

		public static void ReplaceAudioClip(string originalName, AudioClip newClip)
		{
			if (string.IsNullOrEmpty(originalName))
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without original clip specified! This is not allowed");
			}
			else if ((Object)(object)newClip == (Object)null)
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without new clip specified! This is not allowed");
			}
			else
			{
				ReplaceAudioClipInternal(originalName, newClip, 1f, string.Empty);
			}
		}

		public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip)
		{
			if ((Object)(object)originalClip == (Object)null || string.IsNullOrEmpty(originalClip.GetName()))
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without original clip specified or original clip's name is empty! This is not allowed.");
			}
			else if ((Object)(object)newClip == (Object)null)
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without new clip specified! This is not allowed.");
			}
			else
			{
				ReplaceAudioClipInternal(originalClip.GetName(), newClip, 1f, string.Empty);
			}
		}

		public static void ReplaceAudioClip(string originalName, AudioClip newClip, float chance)
		{
			if (string.IsNullOrEmpty(originalName))
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without original clip specified! This is not allowed");
			}
			else if ((Object)(object)newClip == (Object)null)
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without new clip specified! This is not allowed");
			}
			else if (chance < 0f || chance > 1f)
			{
				Instance.logger.LogWarning((object)$"Trying to replace an audio clip with an invalid chance of {chance}! Chance has to be between 0 - 1.0");
			}
			else
			{
				ReplaceAudioClipInternal(originalName, newClip, chance, string.Empty);
			}
		}

		public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip, float chance)
		{
			if ((Object)(object)originalClip == (Object)null || string.IsNullOrEmpty(originalClip.GetName()))
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without original clip specified or original clip's name is empty! This is not allowed.");
			}
			else if ((Object)(object)newClip == (Object)null)
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without new clip specified! This is not allowed.");
			}
			else if (chance < 0f || chance > 1f)
			{
				Instance.logger.LogWarning((object)$"Trying to replace an audio clip with an invalid chance of {chance}! Chance has to be between 0 - 1.0");
			}
			else
			{
				ReplaceAudioClipInternal(originalClip.GetName(), newClip, chance, string.Empty);
			}
		}

		public static void ReplaceAudioClip(string originalName, AudioClip newClip, string source)
		{
			if (string.IsNullOrEmpty(originalName))
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without original clip specified! This is not allowed");
			}
			else if ((Object)(object)newClip == (Object)null)
			{
				Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed.");
			}
			else
			{
				ReplaceAudioClipInternal(originalName, newClip, 1f, source);
			}
		}

		public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip, string source)
		{
			if ((Object)(object)originalClip == (Object)null || string.IsNullOrEmpty(originalClip.GetName()))
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without original clip specified or original clip's name is empty! This is not allowed.");
			}
			else if ((Object)(object)newClip == (Object)null)
			{
				Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed.");
			}
			else
			{
				ReplaceAudioClipInternal(originalClip.GetName(), newClip, 1f, source);
			}
		}

		public static void ReplaceAudioClip(string originalName, AudioClip newClip, string[] source)
		{
			if (string.IsNullOrEmpty(originalName))
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without original clip specified! This is not allowed");
				return;
			}
			if ((Object)(object)newClip == (Object)null)
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without new clip specified! This is not allowed.");
				return;
			}
			List<string> list = source.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				if (string.IsNullOrEmpty(list[i]))
				{
					list.RemoveAt(i);
					i--;
				}
			}
			ReplaceAudioClipInternal(originalName, newClip, 1f, string.Join(",", list));
		}

		public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip, string[] source)
		{
			if ((Object)(object)originalClip == (Object)null || string.IsNullOrEmpty(originalClip.GetName()))
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without original clip specified or original clip's name is empty! This is not allowed.");
				return;
			}
			if ((Object)(object)newClip == (Object)null)
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without new clip specified! This is not allowed.");
				return;
			}
			List<string> list = source.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				if (string.IsNullOrEmpty(list[i]))
				{
					list.RemoveAt(i);
					i--;
				}
			}
			ReplaceAudioClipInternal(originalClip.GetName(), newClip, 1f, string.Join(",", list));
		}

		public static void ReplaceAudioClip(string originalName, AudioClip newClip, float chance, string source)
		{
			if (string.IsNullOrEmpty(originalName))
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without original clip specified! This is not allowed");
			}
			else if ((Object)(object)newClip == (Object)null)
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without new clip specified! This is not allowed");
			}
			else if (chance < 0f || chance > 1f)
			{
				Instance.logger.LogWarning((object)$"Trying to replace an audio clip with an invalid chance of {chance}! Chance has to be between 0 - 1.0");
			}
			else
			{
				ReplaceAudioClipInternal(originalName, newClip, chance, source);
			}
		}

		public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip, float chance, string source)
		{
			if ((Object)(object)originalClip == (Object)null || string.IsNullOrEmpty(originalClip.GetName()))
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without original clip specified or the specified original clip has no name! This is not allowed");
			}
			else if ((Object)(object)newClip == (Object)null)
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without new clip specified! This is not allowed");
			}
			else if (chance < 0f || chance > 1f)
			{
				Instance.logger.LogWarning((object)$"Trying to replace an audio clip with an invalid chance of {chance}! Chance has to be between 0 - 1.0");
			}
			else
			{
				ReplaceAudioClipInternal(originalClip.GetName(), newClip, chance, source);
			}
		}

		public static void ReplaceAudioClip(string originalName, AudioClip newClip, float chance, string[] source)
		{
			if (string.IsNullOrEmpty(originalName))
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without original clip specified! This is not allowed");
				return;
			}
			if ((Object)(object)newClip == (Object)null)
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without new clip specified! This is not allowed.");
				return;
			}
			if (chance < 0f || chance > 1f)
			{
				Instance.logger.LogWarning((object)$"Trying to replace an audio clip with an invalid chance of {chance}! Chance has to be between 0 - 1.0");
				return;
			}
			List<string> list = source.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				if (string.IsNullOrEmpty(list[i]))
				{
					list.RemoveAt(i);
					i--;
				}
			}
			ReplaceAudioClipInternal(originalName, newClip, chance, string.Join(",", list));
		}

		public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip, float chance, string[] source)
		{
			if ((Object)(object)originalClip == (Object)null || string.IsNullOrEmpty(originalClip.GetName()))
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without original clip specified or original clip's name is empty! This is not allowed.");
				return;
			}
			if ((Object)(object)newClip == (Object)null)
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without new clip specified! This is not allowed.");
				return;
			}
			if (chance < 0f || chance > 1f)
			{
				Instance.logger.LogWarning((object)$"Trying to replace an audio clip with an invalid chance of {chance}! Chance has to be between 0 - 1.0");
				return;
			}
			List<string> list = source.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				if (string.IsNullOrEmpty(list[i]))
				{
					list.RemoveAt(i);
					i--;
				}
			}
			ReplaceAudioClipInternal(originalClip.GetName(), newClip, chance, string.Join(",", list));
		}

		private static void ReplaceAudioClipInternal(string originalName, AudioClip newClip, float chance, string source)
		{
			string text = originalName;
			string name = newClip.GetName();
			if (!string.IsNullOrEmpty(source))
			{
				text = originalName + "#" + source;
			}
			if (replacedClips.ContainsKey(text))
			{
				replacedClips[text].AddClip(newClip, chance);
			}
			else
			{
				replacedClips.Add(text, new ReplacementAudioClip(newClip, chance, source));
			}
			float num = 0f;
			for (int i = 0; i < replacedClips[text].clips.Count(); i++)
			{
				num += replacedClips[text].clips[i].chance;
			}
			int num2 = Mathf.RoundToInt(num * 100f);
			if (infoDebugging)
			{
				Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} does not equal 100%. Currently {num2}% (at least yet?)");
			}
		}

		public static void RemoveRandomAudioClip(string name, float chance)
		{
			if (string.IsNullOrEmpty(name))
			{
				Instance.logger.LogWarning((object)"Trying to restore an audio clip without original clip specified! This is not allowed");
			}
			else if (!replacedClips.ContainsKey(name))
			{
				Instance.logger.LogWarning((object)"Trying to restore an audio clip that does not exist! This is not allowed");
			}
			else if (chance < 0f || chance > 1f)
			{
				Instance.logger.LogWarning((object)$"Trying to restore an audio clip with an invalid chance of {chance}! Chance has to be between 0 - 1.0");
			}
			else
			{
				RemoveRandomAudioClipInternal(name, chance, string.Empty);
			}
		}

		public static void RemoveRandomAudioClip(string name, float chance, string source)
		{
			if (string.IsNullOrEmpty(name))
			{
				Instance.logger.LogWarning((object)"Trying to restore an audio clip without original clip specified! This is not allowed");
			}
			else if (!replacedClips.ContainsKey(name))
			{
				Instance.logger.LogWarning((object)"Trying to restore an audio clip that does not exist! This is not allowed");
			}
			else
			{
				RemoveRandomAudioClipInternal(name, chance, source);
			}
		}

		public static void RemoveRandomAudioClip(string name, float chance, string[] source)
		{
			if (string.IsNullOrEmpty(name))
			{
				Instance.logger.LogWarning((object)"Trying to replace an audio clip without original clip specified! This is not allowed");
				return;
			}
			if (chance < 0f || chance > 1f)
			{
				Instance.logger.LogWarning((object)$"Trying to replace an audio clip with an invalid chance of {chance}! Chance has to be between 0 - 1.0");
				return;
			}
			List<string> list = source.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				if (string.IsNullOrEmpty(list[i]))
				{
					list.RemoveAt(i);
					i--;
				}
			}
			RemoveRandomAudioClipInternal(name, chance, string.Join(",", list));
		}

		private static void RemoveRandomAudioClipInternal(string name, float chance, string source)
		{
			if (!string.IsNullOrEmpty(source))
			{
				name = name + "#" + source;
			}
			if (!(chance > 0f))
			{
				return;
			}
			for (int i = 0; i < replacedClips[name].clips.Count(); i++)
			{
				if (replacedClips[name].clips[i].chance == chance)
				{
					replacedClips[name].clips.RemoveAt(i);
					if (replacedClips[name].clips.Count <= 0)
					{
						Instance.logger.LogDebug((object)("Removed replaced AudioClip " + name + " completely as all of it's random clips have been removed."));
						replacedClips.Remove(name);
					}
					break;
				}
			}
		}

		public static void RestoreAudioClip(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				Instance.logger.LogWarning((object)"Trying to restore an audio clip without original clip specified! This is not allowed");
			}
			else if (!replacedClips.ContainsKey(name))
			{
				Instance.logger.LogWarning((object)"Trying to restore an audio clip that does not exist! This is not allowed");
			}
			else
			{
				RestoreAudioClipInternal(name, string.Empty);
			}
		}

		public static void RestoreAudioClip(string name, string source)
		{
			if (string.IsNullOrEmpty(name))
			{
				Instance.logger.LogWarning((object)"Trying to restore an audio clip without original clip specified! This is not allowed");
			}
			else if (!replacedClips.ContainsKey(name))
			{
				Instance.logger.LogWarning((object)"Trying to restore an audio clip that does not exist! This is not allowed");
			}
			else
			{
				RestoreAudioClipInternal(name, source);
			}
		}

		public static void RestoreAudioClip(string name, string[] source)
		{
			if (string.IsNullOrEmpty(name))
			{
				Instance.logger.LogWarning((object)"Trying to restore an audio clip without original clip specified! This is not allowed");
				return;
			}
			if (!replacedClips.ContainsKey(name))
			{
				Instance.logger.LogWarning((object)"Trying to restore an audio clip that does not exist! This is not allowed");
				return;
			}
			List<string> list = source.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				if (string.IsNullOrEmpty(list[i]))
				{
					list.RemoveAt(i);
					i--;
				}
			}
			RestoreAudioClipInternal(name, string.Join(",", list));
		}

		public static void RestoreAudioClip(AudioClip clip)
		{
			if ((Object)(object)clip == (Object)null || string.IsNullOrEmpty(clip.GetName()))
			{
				Instance.logger.LogWarning((object)"Trying to restore an audio clip without vanilla clip specified or specified clip's name is empty! This is not allowed");
			}
			else
			{
				RestoreAudioClipInternal(clip.GetName(), string.Empty);
			}
		}

		public static void RestoreAudioClip(AudioClip clip, string source)
		{
			if ((Object)(object)clip == (Object)null || string.IsNullOrEmpty(clip.GetName()))
			{
				Instance.logger.LogWarning((object)"Trying to restore an audio clip without vanilla clip specified or specified clip's name is empty! This is not allowed");
			}
			else
			{
				RestoreAudioClipInternal(clip.GetName(), source);
			}
		}

		public static void RestoreAudioClip(AudioClip clip, string[] source)
		{
			if ((Object)(object)clip == (Object)null || string.IsNullOrEmpty(clip.GetName()))
			{
				Instance.logger.LogWarning((object)"Trying to restore an audio clip without vanilla clip specified or specified clip's name is empty! This is not allowed");
				return;
			}
			List<string> list = source.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				if (string.IsNullOrEmpty(list[i]))
				{
					list.RemoveAt(i);
					i--;
				}
			}
			RestoreAudioClipInternal(clip.GetName(), string.Join(",", list));
		}

		private static void RestoreAudioClipInternal(string name, string source)
		{
			if (!string.IsNullOrEmpty(source))
			{
				name = name + "#" + source;
			}
			replacedClips.Remove(name);
		}

		public static AudioClip GetAudioClip(string modFolder, string soundName)
		{
			return GetAudioClip(modFolder, string.Empty, soundName);
		}

		public static AudioClip GetAudioClip(string modFolder, string subFolder, string soundName)
		{
			AudioType audioType = AudioType.wav;
			string[] array = soundName.Split('.');
			if (array[^1].ToLower().Contains("wav"))
			{
				audioType = AudioType.wav;
				if (infoDebugging)
				{
					Instance.logger.LogDebug((object)"File detected as a PCM WAVE file!");
				}
			}
			else if (array[^1].ToLower().Contains("ogg"))
			{
				audioType = AudioType.ogg;
				if (infoDebugging)
				{
					Instance.logger.LogDebug((object)"File detected as an Ogg Vorbis file!");
				}
			}
			else if (array[^1].ToLower().Contains("mp3"))
			{
				audioType = AudioType.mp3;
				if (infoDebugging)
				{
					Instance.logger.LogDebug((object)"File detected as a MPEG MP3 file!");
				}
			}
			else
			{
				audioType = AudioType.wav;
				Instance.logger.LogWarning((object)("Failed to detect file type of a sound file! This may cause issues with other mod functionality. Sound defaulted to WAV. Sound: " + soundName));
			}
			return GetAudioClip(modFolder, subFolder, soundName, audioType);
		}

		public static AudioClip GetAudioClip(string modFolder, string soundName, AudioType audioType)
		{
			return GetAudioClip(modFolder, string.Empty, soundName, audioType);
		}

		public static AudioClip GetAudioClip(string modFolder, string subFolder, string soundName, AudioType audioType)
		{
			bool flag = true;
			bool flag2 = false;
			string text = " ";
			string text2 = Path.Combine(Paths.PluginPath, modFolder, subFolder, soundName);
			string text3 = Path.Combine(Paths.PluginPath, modFolder, soundName);
			string path = Path.Combine(Paths.PluginPath, modFolder, subFolder);
			string text4 = Path.Combine(Paths.PluginPath, subFolder, soundName);
			string path2 = Path.Combine(Paths.PluginPath, subFolder);
			if (!Directory.Exists(path))
			{
				if (!string.IsNullOrEmpty(subFolder))
				{
					Instance.logger.LogWarning((object)("Requested directory at BepInEx/Plugins/" + modFolder + "/" + subFolder + " does not exist!"));
				}
				else
				{
					Instance.logger.LogWarning((object)("Requested directory at BepInEx/Plugins/" + modFolder + " does not exist!"));
					if (!modFolder.Contains("-"))
					{
						Instance.logger.LogWarning((object)"This sound mod might not be compatable with mod managers. You should contact the sound mod's author.");
					}
				}
				flag = false;
			}
			else
			{
				if (infoDebugging)
				{
					Instance.logger.LogDebug((object)"Skipping legacy path check...");
				}
				flag2 = true;
			}
			if (!File.Exists(text2))
			{
				Instance.logger.LogWarning((object)("Requested audio file does not exist at path " + text2 + "!"));
				flag = false;
				Instance.logger.LogDebug((object)("Looking for audio file from mod root instead at " + text3 + "..."));
				if (File.Exists(text3))
				{
					Instance.logger.LogDebug((object)("Found audio file at path " + text3 + "!"));
					text2 = text3;
					flag = true;
					if (infoDebugging)
					{
						Instance.logger.LogDebug((object)"Skipping legacy path check...");
					}
					flag2 = true;
				}
				else
				{
					Instance.logger.LogWarning((object)("Requested audio file does not exist at mod root path " + text3 + "!"));
				}
			}
			else
			{
				if (infoDebugging)
				{
					Instance.logger.LogDebug((object)"Skipping legacy path check...");
				}
				flag2 = true;
			}
			if (Directory.Exists(path2) && !flag2)
			{
				if (!string.IsNullOrEmpty(subFolder))
				{
					Instance.logger.LogWarning((object)("Legacy directory location at BepInEx/Plugins/" + subFolder + " found!"));
				}
				else if (!modFolder.Contains("-"))
				{
					Instance.logger.LogWarning((object)"Legacy directory location at BepInEx/Plugins found!");
				}
			}
			if (File.Exists(text4) && !flag2)
			{
				Instance.logger.LogWarning((object)("Legacy path contains the requested audio file at path " + text4 + "!"));
				text = " legacy ";
				text2 = text4;
				flag = true;
			}
			switch (audioType)
			{
			case AudioType.wav:
				if (infoDebugging)
				{
					Instance.logger.LogDebug((object)"File defined as a WAV file!");
				}
				break;
			case AudioType.ogg:
				if (infoDebugging)
				{
					Instance.logger.LogDebug((object)"File defined as an Ogg Vorbis file!");
				}
				break;
			case AudioType.mp3:
				if (infoDebugging)
				{
					Instance.logger.LogDebug((object)"File defined as a MPEG MP3 file!");
				}
				break;
			default:
				if (infoDebugging)
				{
					Instance.logger.LogDebug((object)"File type not defined and was defaulted to WAV file!");
				}
				break;
			}
			AudioClip val = null;
			if (flag)
			{
				Instance.logger.LogDebug((object)("Loading AudioClip " + soundName + " from" + text + "path: " + text2));
				switch (audioType)
				{
				case AudioType.wav:
					val = AudioUtility.LoadFromDiskToAudioClip(text2, (AudioType)20);
					break;
				case AudioType.ogg:
					val = AudioUtility.LoadFromDiskToAudioClip(text2, (AudioType)14);
					break;
				case AudioType.mp3:
					val = AudioUtility.LoadFromDiskToAudioClip(text2, (AudioType)13);
					break;
				}
				Instance.logger.LogDebug((object)$"Finished loading AudioClip {soundName} with length of {val.length}!");
			}
			else
			{
				Instance.logger.LogWarning((object)("Failed to load AudioClip " + soundName + " from invalid" + text + "path at " + text2 + "!"));
			}
			if (string.IsNullOrEmpty(val.GetName()))
			{
				string empty = string.Empty;
				string[] array = new string[0];
				switch (audioType)
				{
				case AudioType.wav:
					empty = soundName.Replace(".wav", "");
					if (infoDebugging)
					{
						Instance.logger.LogDebug((object)("soundName " + soundName + ", finalName " + empty));
					}
					array = empty.Split('/');
					if (infoDebugging)
					{
						Instance.logger.LogDebug((object)$"nameParts length {array.Length}");
					}
					if (array.Length <= 1)
					{
						array = empty.Split('\\');
					}
					empty = array[^1];
					if (infoDebugging)
					{
						Instance.logger.LogDebug((object)("finalName from nameParts array " + empty));
					}
					((Object)val).name = empty;
					break;
				case AudioType.ogg:
					empty = soundName.Replace(".ogg", "");
					if (infoDebugging)
					{
						Instance.logger.LogDebug((object)("soundName " + soundName + ", finalName " + empty));
					}
					array = empty.Split('/');
					if (infoDebugging)
					{
						Instance.logger.LogDebug((object)$"nameParts length {array.Length}");
					}
					if (array.Length <= 1)
					{
						array = empty.Split('\\');
					}
					empty = array[^1];
					if (infoDebugging)
					{
						Instance.logger.LogDebug((object)("finalName from nameParts array " + empty));
					}
					((Object)val).name = empty;
					break;
				case AudioType.mp3:
					empty = soundName.Replace(".mp3", "");
					if (infoDebugging)
					{
						Instance.logger.LogDebug((object)("soundName " + soundName + ", finalName " + empty));
					}
					array = empty.Split('/');
					if (infoDebugging)
					{
						Instance.logger.LogDebug((object)$"nameParts length {array.Length}");
					}
					if (array.Length <= 1)
					{
						array = empty.Split('\\');
					}
					empty = array[^1];
					if (infoDebugging)
					{
						Instance.logger.LogDebug((object)("finalName from nameParts array " + empty));
					}
					((Object)val).name = empty;
					break;
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				string name = val.GetName();
			}
			return val;
		}

		public static void SendNetworkedAudioClip(AudioClip audioClip)
		{
			if (!Instance.configUseNetworking.Value)
			{
				Instance.logger.LogWarning((object)$"Networking disabled! Failed to send {audioClip}!");
			}
			else if ((Object)(object)audioClip == (Object)null)
			{
				Instance.logger.LogWarning((object)$"audioClip variable of SendAudioClip not assigned! Failed to send {audioClip}!");
			}
			else if ((Object)(object)Instance == (Object)null || (Object)(object)GameNetworkManagerPatch.networkHandlerHost == (Object)null || (Object)(object)NetworkHandler.Instance == (Object)null)
			{
				Instance.logger.LogWarning((object)$"Instance of SoundTool not found or networking has not finished initializing. Failed to send {audioClip}! If you're sending things in Awake or in a scene such as the main menu it might be too early, please try some of the other built-in Unity methods and make sure your networked audio runs only after the player setups a networked connection!");
			}
			else
			{
				NetworkHandler.Instance.SendAudioClipServerRpc(audioClip.GetName(), AudioUtility.AudioClipToByteArray(audioClip, out var _), audioClip.channels, audioClip.frequency);
			}
		}

		public static void RemoveNetworkedAudioClip(AudioClip audioClip)
		{
			RemoveNetworkedAudioClip(audioClip.GetName());
		}

		public static void RemoveNetworkedAudioClip(string audioClip)
		{
			if (!Instance.configUseNetworking.Value)
			{
				Instance.logger.LogWarning((object)("Networking disabled! Failed to remove " + audioClip + "!"));
			}
			else if (string.IsNullOrEmpty(audioClip))
			{
				Instance.logger.LogWarning((object)("audioClip variable of RemoveAudioClip not assigned! Failed to remove " + audioClip + "!"));
			}
			else if ((Object)(object)Instance == (Object)null || (Object)(object)GameNetworkManagerPatch.networkHandlerHost == (Object)null || (Object)(object)NetworkHandler.Instance == (Object)null)
			{
				Instance.logger.LogWarning((object)("Instance of SoundTool not found or networking has not finished initializing. Failed to remove " + audioClip + "! If you're removing things in Awake or in a scene such as the main menu it might be too early, please try some of the other built-in Unity methods and make sure your networked audio runs only after the player setups a networked connection!"));
			}
			else
			{
				NetworkHandler.Instance.RemoveAudioClipServerRpc(audioClip);
			}
		}

		public static void SyncNetworkedAudioClips()
		{
			if (!Instance.configUseNetworking.Value)
			{
				Instance.logger.LogWarning((object)"Networking disabled! Failed to sync audio clips!");
			}
			else if ((Object)(object)Instance == (Object)null || (Object)(object)GameNetworkManagerPatch.networkHandlerHost == (Object)null || (Object)(object)NetworkHandler.Instance == (Object)null)
			{
				Instance.logger.LogWarning((object)"Instance of SoundTool not found or networking has not finished initializing. Failed to sync networked audio! If you're syncing things in Awake or in a scene such as the main menu it might be too early, please try some of the other built-in Unity methods and make sure your networked audio runs only after the player setups a networked connection!");
			}
			else
			{
				NetworkHandler.Instance.SyncAudioClipsServerRpc();
			}
		}

		public static void SendUnityRandomSeed(int seed)
		{
			if (!Instance.configUseNetworking.Value)
			{
				Instance.logger.LogWarning((object)"Networking disabled! Failed to send Unity random seed!");
			}
			else if ((Object)(object)Instance == (Object)null || (Object)(object)GameNetworkManagerPatch.networkHandlerHost == (Object)null || (Object)(object)NetworkHandler.Instance == (Object)null)
			{
				Instance.logger.LogWarning((object)"Instance of SoundTool not found or networking has not finished initializing. Failed to send Unity Random seed! If you're sending the seed in Awake or in a scene such as the main menu it might be too early, please try some of the other built-in Unity methods and make sure your networked methods run only after the player setups a networked connection!");
			}
			else
			{
				NetworkHandler.Instance.SendSeedToClientsServerRpc(seed);
			}
		}

		public void ToggleDebug()
		{
			debugAudioSources = !debugAudioSources;
			if (indepthDebugging && !debugAudioSources)
			{
				indepthDebugging = false;
			}
			Instance.logger.LogDebug((object)$"Toggling AudioSource debug logs {debugAudioSources}!");
		}

		public void ToggleIndepthDebug()
		{
			debugAudioSources = !debugAudioSources;
			indepthDebugging = debugAudioSources;
			infoDebugging = debugAudioSources;
			Instance.logger.LogDebug((object)$"Toggling in-depth AudioSource debug logs {debugAudioSources}!");
		}

		public void ToggleInfoDebug()
		{
			infoDebugging = !infoDebugging;
			Instance.logger.LogDebug((object)$"Toggling informational debug logs {infoDebugging}!");
		}

		public void PrintAllReplacedSounds()
		{
			Instance.logger.LogDebug((object)" ");
			Instance.logger.LogDebug((object)"Printing all currently replaced sounds...");
			Instance.logger.LogDebug((object)" ");
			string[] array = replacedClips.Keys.ToArray();
			for (int i = 0; i < replacedClips.Count; i++)
			{
				ReplacementAudioClip replacementAudioClip = replacedClips[array[i]];
				Instance.logger.LogDebug((object)$"Clip named {array[i]} with {replacementAudioClip.clips.Count} replacement clip(s)");
				Instance.logger.LogDebug((object)$"- Clip can play? {replacementAudioClip.canPlay}");
				Instance.logger.LogDebug((object)("- Clip audio source(s)? " + replacementAudioClip.source));
				Instance.logger.LogDebug((object)$"- All {replacementAudioClip.clips.Count} clip(s):");
				for (int j = 0; j < replacementAudioClip.clips.Count; j++)
				{
					Instance.logger.LogDebug((object)$"-- Clip {j + 1} - {replacementAudioClip.clips[j].clip.GetName()} with chance of {Mathf.RoundToInt(replacementAudioClip.clips[j].chance * 100f)}%");
				}
				Instance.logger.LogDebug((object)$"-- Total - All clips combined chance {Mathf.RoundToInt(replacementAudioClip.TotalChance() * 100f)}%");
			}
			Instance.logger.LogDebug((object)" ");
			Instance.logger.LogDebug((object)"Finished printing all currently replaced sounds!");
			Instance.logger.LogDebug((object)" ");
		}

		private void PrintAllCurrentSounds()
		{
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			Instance.logger.LogDebug((object)" ");
			Instance.logger.LogDebug((object)"Printing all sounds in currently loaded scenes...");
			Instance.logger.LogDebug((object)" ");
			AudioSource[] array = Object.FindObjectsOfType<AudioSource>(true);
			AudioSourceExtension audioSourceExtension = default(AudioSourceExtension);
			for (int i = 0; i < array.Length; i++)
			{
				Instance.logger.LogDebug((object)$"AudioSource {array[i]} with clip {array[i].clip}");
				Instance.logger.LogDebug((object)$"- Volume: {array[i].volume}");
				Instance.logger.LogDebug((object)$"- Priority: {array[i].priority}");
				Instance.logger.LogDebug((object)$"- Plays on awake? {array[i].playOnAwake}");
				Instance.logger.LogDebug((object)$"- Loops? {array[i].loop}");
				Instance.logger.LogDebug((object)$"- Needs custom LCSoundTool component? {array[i].playOnAwake}");
				Instance.logger.LogDebug((object)$"- Contains custom LCSoundTool component? {((Component)((Component)array[i]).transform).TryGetComponent<AudioSourceExtension>(ref audioSourceExtension)}");
				Instance.logger.LogDebug((object)$"- Used by PlayAudioAnimationEvent component? {array[i].UsedByAnimationEventScript()}");
				Instance.logger.LogDebug((object)$"- Located in Scene: {((Component)array[i]).gameObject.scene}");
				Instance.logger.LogDebug((object)"- Located on the following GameObject:");
				Transform val = ((Component)array[i]).transform;
				Instance.logger.LogDebug((object)$"-- (This) {val}");
				while ((Object)(object)val != (Object)(object)((Component)array[i]).transform.root)
				{
					val = val.parent;
					Instance.logger.LogDebug((object)$"-- {val}");
				}
			}
			Instance.logger.LogDebug((object)" ");
			Instance.logger.LogDebug((object)"Finished printing all sounds in currently loaded scenes!");
			Instance.logger.LogDebug((object)" ");
		}
	}
}
namespace LCSoundTool.Utilities
{
	public static class AudioUtility
	{
		public static byte[] AudioClipToByteArray(AudioClip audioClip, out float[] samples)
		{
			samples = new float[audioClip.samples * audioClip.channels];
			audioClip.GetData(samples, 0);
			byte[] array = new byte[samples.Length * 2];
			int num = 32767;
			for (int i = 0; i < samples.Length; i++)
			{
				short value = (short)(samples[i] * (float)num);
				BitConverter.GetBytes(value).CopyTo(array, i * 2);
			}
			return array;
		}

		public static AudioClip LoadFromMemory(byte[] fileData, string clipName)
		{
			int channels = BitConverter.ToInt16(fileData, 22);
			int frequency = BitConverter.ToInt32(fileData, 24);
			int num = BitConverter.ToInt16(fileData, 34);
			byte[] array = new byte[fileData.Length - 44];
			Array.Copy(fileData, 44, array, 0, array.Length);
			return ByteArrayToAudioClip(array, clipName, channels, frequency);
		}

		public static AudioClip ByteArrayToAudioClip(byte[] byteArray, string clipName, int channels, int frequency)
		{
			if (frequency < 1 || frequency > 48000)
			{
				frequency = 44100;
			}
			if (channels < 1 || channels > 2)
			{
				channels = 1;
			}
			int num = 16;
			int num2 = num / 8;
			AudioClip val = AudioClip.Create(clipName, byteArray.Length / num2, channels, frequency, false);
			val.SetData(ConvertByteArrayToFloatArray(byteArray), 0);
			return val;
		}

		private static float[] ConvertByteArrayToFloatArray(byte[] byteArray)
		{
			float[] array = new float[byteArray.Length / 2];
			int num = 32767;
			for (int i = 0; i < array.Length; i++)
			{
				short num2 = BitConverter.ToInt16(byteArray, i * 2);
				array[i] = (float)num2 / (float)num;
			}
			return array;
		}

		public static AudioClip LoadFromDiskToAudioClip(string path, AudioType type)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			AudioClip result = null;
			UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(path, type);
			try
			{
				audioClip.SendWebRequest();
				try
				{
					while (!audioClip.isDone)
					{
					}
					if ((int)audioClip.result != 1)
					{
						SoundTool.Instance.logger.LogError((object)("Failed to load WAV AudioClip from path: " + path + " Full error: " + audioClip.error));
					}
					else
					{
						result = DownloadHandlerAudioClip.GetContent(audioClip);
					}
				}
				catch (Exception ex)
				{
					SoundTool.Instance.logger.LogError((object)(ex.Message + ", " + ex.StackTrace));
				}
			}
			finally
			{
				((IDisposable)audioClip)?.Dispose();
			}
			return result;
		}
	}
	public static class Extensions
	{
		public static bool ContainsThisRandomAudioClip(this List<RandomAudioClip> list, RandomAudioClip thisClip)
		{
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].chance == thisClip.chance && list[i].clip.GetName() == thisClip.clip.GetName())
				{
					return true;
				}
			}
			return false;
		}

		public static bool UsedByAnimationEventScript(this AudioSource source)
		{
			PlayAudioAnimationEvent componentInChildren = ((Component)((Component)source).transform.root).GetComponentInChildren<PlayAudioAnimationEvent>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				return (Object)(object)componentInChildren.audioToPlay == (Object)(object)source || (Object)(object)componentInChildren.audioToPlayB == (Object)(object)source;
			}
			return false;
		}
	}
	public static class InputHelper
	{
		public static Dictionary<string, Keybind> keybinds;

		public static void Initialize()
		{
			keybinds = new Dictionary<string, Keybind>();
		}

		public static bool CheckInput(string keybind)
		{
			if (keybinds.ContainsKey(keybind) && ((KeyboardShortcut)(ref keybinds[keybind].shortcut)).IsDown() && !keybinds[keybind].wasPressed)
			{
				keybinds[keybind].wasPressed = true;
			}
			return CheckInputResult(keybind);
		}

		private static bool CheckInputResult(string keybind)
		{
			if (keybinds.ContainsKey(keybind) && ((KeyboardShortcut)(ref keybinds[keybind].shortcut)).IsUp() && keybinds[keybind].wasPressed)
			{
				keybinds[keybind].wasPressed = false;
				keybinds[keybind].onPress();
				return true;
			}
			return false;
		}
	}
	[Serializable]
	public class Keybind
	{
		public KeyboardShortcut shortcut;

		public Action onPress;

		public bool wasPressed;

		public Keybind(KeyboardShortcut shortcut, Action onPress, bool wasPressed = false)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			this.shortcut = shortcut;
			this.onPress = onPress;
			this.wasPressed = wasPressed;
		}
	}
}
namespace LCSoundTool.Patches
{
	[HarmonyPatch(typeof(AudioSource))]
	internal class AudioSourcePatch
	{
		private static Dictionary<string, AudioClip> originalClips = new Dictionary<string, AudioClip>();

		[HarmonyPatch("Play", new Type[] { })]
		[HarmonyPrefix]
		public static void Play_Patch(AudioSource __instance)
		{
			RunDynamicClipReplacement(__instance);
			DebugPlayMethod(__instance);
		}

		[HarmonyPatch("Play", new Type[] { typeof(ulong) })]
		[HarmonyPrefix]
		public static void Play_UlongPatch(AudioSource __instance)
		{
			RunDynamicClipReplacement(__instance);
			DebugPlayMethod(__instance);
		}

		[HarmonyPatch("Play", new Type[] { typeof(double) })]
		[HarmonyPrefix]
		public static void Play_DoublePatch(AudioSource __instance)
		{
			RunDynamicClipReplacement(__instance);
			DebugPlayMethod(__instance);
		}

		[HarmonyPatch("PlayDelayed", new Type[] { typeof(float) })]
		[HarmonyPrefix]
		public static void PlayDelayed_Patch(AudioSource __instance)
		{
			RunDynamicClipReplacement(__instance);
			DebugPlayDelayedMethod(__instance);
		}

		[HarmonyPatch("PlayClipAtPoint", new Type[]
		{
			typeof(AudioClip),
			typeof(Vector3),
			typeof(float)
		})]
		[HarmonyPrefix]
		public static bool PlayClipAtPoint_Patch(AudioClip clip, Vector3 position, float volume)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject($"ClipAtPoint_{clip}");
			val.transform.position = position;
			AudioSource val2 = val.AddComponent<AudioSource>();
			val2.clip = clip;
			val2.spatialBlend = 1f;
			val2.volume = volume;
			val2.Play();
			DebugPlayClipAtPointMethod(val2, position);
			Object.Destroy((Object)(object)val, clip.length * ((Time.timeScale < 0.01f) ? 0.01f : Time.timeScale));
			return false;
		}

		[HarmonyPatch("PlayOneShotHelper", new Type[]
		{
			typeof(AudioSource),
			typeof(AudioClip),
			typeof(float)
		})]
		[HarmonyPrefix]
		public static void PlayOneShotHelper_Patch(AudioSource source, ref AudioClip clip, float volumeScale)
		{
			clip = ReplaceClipWithNew(clip, source);
			DebugPlayOneShotMethod(source, clip);
		}

		private static void DebugPlayMethod(AudioSource instance)
		{
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			if (SoundTool.debugAudioSources && !SoundTool.indepthDebugging && (Object)(object)instance != (Object)null)
			{
				SoundTool.Instance.logger.LogDebug((object)$"{instance} at {((Component)instance).transform.root} is playing {((Object)instance.clip).name}");
			}
			else if (SoundTool.indepthDebugging && (Object)(object)instance != (Object)null)
			{
				SoundTool.Instance.logger.LogDebug((object)$"{instance} is playing {((Object)instance.clip).name} at");
				Transform val = ((Component)instance).transform;
				while ((Object)(object)val.parent != (Object)null || (Object)(object)val != (Object)(object)((Component)instance).transform.root)
				{
					SoundTool.Instance.logger.LogDebug((object)$"--- {val.parent}");
					val = val.parent;
				}
				if ((Object)(object)val == (Object)(object)((Component)instance).transform.root)
				{
					SoundTool.Instance.logger.LogDebug((object)$"--- {((Component)instance).transform.root}");
				}
			}
		}

		private static void DebugPlayDelayedMethod(AudioSource instance)
		{
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			if (SoundTool.debugAudioSources && !SoundTool.indepthDebugging && (Object)(object)instance != (Object)null)
			{
				SoundTool.Instance.logger.LogDebug((object)$"{instance} at {((Component)instance).transform.root} is playing {((Object)instance.clip).name} with delay");
			}
			else if (SoundTool.indepthDebugging && (Object)(object)instance != (Object)null)
			{
				SoundTool.Instance.logger.LogDebug((object)$"{instance} is playing {((Object)instance.clip).name} with delay at");
				Transform val = ((Component)instance).transform;
				while ((Object)(object)val.parent != (Object)null || (Object)(object)val != (Object)(object)((Component)instance).transform.root)
				{
					SoundTool.Instance.logger.LogDebug((object)$"--- {val.parent}");
					val = val.parent;
				}
				if ((Object)(object)val == (Object)(object)((Component)instance).transform.root)
				{
					SoundTool.Instance.logger.LogDebug((object)$"--- {((Component)instance).transform.root}");
				}
			}
		}

		private static void DebugPlayClipAtPointMethod(AudioSource audioSource, Vector3 position)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)audioSource == (Object)null)
			{
				return;
			}
			if (SoundTool.debugAudioSources && !SoundTool.indepthDebugging && (Object)(object)audioSource != (Object)null)
			{
				SoundTool.Instance.logger.LogDebug((object)$"{audioSource} at {((Component)audioSource).transform.root} is playing {((Object)audioSource.clip).name} at point {position}");
			}
			else if (SoundTool.indepthDebugging && (Object)(object)audioSource != (Object)null)
			{
				SoundTool.Instance.logger.LogDebug((object)$"{audioSource} is playing {((Object)audioSource.clip).name} located at point {position} within ");
				Transform val = ((Component)audioSource).transform;
				while ((Object)(object)val.parent != (Object)null || (Object)(object)val != (Object)(object)((Component)audioSource).transform.root)
				{
					SoundTool.Instance.logger.LogDebug((object)$"--- {val.parent}");
					val = val.parent;
				}
				if ((Object)(object)val == (Object)(object)((Component)audioSource).transform.root)
				{
					SoundTool.Instance.logger.LogDebug((object)$"--- {((Component)audioSource).transform.root}");
				}
			}
		}

		private static void DebugPlayOneShotMethod(AudioSource source, AudioClip clip)
		{
			if ((Object)(object)source == (Object)null || (Object)(object)clip == (Object)null)
			{
				return;
			}
			if (SoundTool.debugAudioSources && !SoundTool.indepthDebugging && (Object)(object)source != (Object)null)
			{
				SoundTool.Instance.logger.LogDebug((object)$"{source} at {((Component)source).transform.root} is playing one shot {((Object)clip).name}");
			}
			else if (SoundTool.indepthDebugging && (Object)(object)source != (Object)null)
			{
				SoundTool.Instance.logger.LogDebug((object)$"{source} is playing one shot {((Object)clip).name} at");
				Transform val = ((Component)source).transform;
				while ((Object)(object)val.parent != (Object)null || (Object)(object)val != (Object)(object)((Component)source).transform.root)
				{
					SoundTool.Instance.logger.LogDebug((object)$"--- {val.parent}");
					val = val.parent;
				}
				if ((Object)(object)val == (Object)(object)((Component)source).transform.root)
				{
					SoundTool.Instance.logger.LogDebug((object)$"--- {((Component)source).transform.root}");
				}
			}
		}

		private static void RunDynamicClipReplacement(AudioSource instance)
		{
			if (SoundTool.infoDebugging)
			{
				SoundTool.Instance.logger.LogDebug((object)$"instance {instance} instance.clip {instance.clip}");
			}
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.clip == (Object)null)
			{
				return;
			}
			string name = ((Object)((Component)instance).gameObject).name;
			bool flag = true;
			string name2 = instance.clip.GetName();
			if (SoundTool.infoDebugging)
			{
				SoundTool.Instance.logger.LogDebug((object)$"sourceName {((Object)((Component)instance).gameObject).name} clipName {name2} replaceClip {flag}");
			}
			string text = name2;
			if (SoundTool.replacedClips.Keys.Count > 0)
			{
				string[] array = SoundTool.replacedClips.Keys.ToArray();
				if (array.Length != 0)
				{
					for (int i = 0; i < array.Length; i++)
					{
						string[] array2 = array[i].Split("#");
						if (array2.Length == 2 && array2[0].Contains(name2) && array2[1].Contains(((Object)((Component)instance).gameObject).name))
						{
							text = name2 + "#" + array2[1];
						}
					}
				}
			}
			if (SoundTool.infoDebugging)
			{
				SoundTool.Instance.logger.LogDebug((object)("finalName after splitName operation " + text));
			}
			if (SoundTool.replacedClips.ContainsKey(text))
			{
				if (SoundTool.infoDebugging)
				{
					SoundTool.Instance.logger.LogDebug((object)"replacedClips contained finalName");
				}
				if (SoundTool.replacedClips[text].canPlay)
				{
					if (!originalClips.ContainsKey(name))
					{
						if (SoundTool.infoDebugging)
						{
							SoundTool.Instance.logger.LogDebug((object)("originalClips did not contain sourceName, adding sourceName " + name));
						}
						originalClips.Add(name, instance.clip);
					}
					if (!string.IsNullOrEmpty(SoundTool.replacedClips[text].source))
					{
						if (SoundTool.infoDebugging)
						{
							SoundTool.Instance.logger.LogDebug((object)("replacedClips[finalName].source " + SoundTool.replacedClips[text].source + " was not null or empty"));
						}
						flag = false;
						string[] array3 = SoundTool.replacedClips[text].source.Split(',');
						if (SoundTool.infoDebugging)
						{
							SoundTool.Instance.logger.LogDebug((object)$"sources array {array3.Length} {array3}");
						}
						if ((Object)(object)instance != (Object)null && ((Object)((Component)instance).gameObject).name != null)
						{
							if (array3.Length > 1)
							{
								for (int j = 0; j < array3.Length; j++)
								{
									if (array3[j] == ((Object)((Component)instance).gameObject).name)
									{
										if (SoundTool.infoDebugging)
										{
											SoundTool.Instance.logger.LogDebug((object)("sources[i] " + array3[j] + " matches instance.gameObject.name " + ((Object)((Component)instance).gameObject).name));
										}
										flag = true;
									}
									else if (SoundTool.infoDebugging)
									{
										SoundTool.Instance.logger.LogDebug((object)("sources[i] " + array3[j] + " does not match instance.gameObject.name " + ((Object)((Component)instance).gameObject).name));
									}
								}
							}
							else if (array3[0] == ((Object)((Component)instance).gameObject).name)
							{
								if (SoundTool.infoDebugging)
								{
									SoundTool.Instance.logger.LogDebug((object)("sources[0] " + array3[0] + " matches instance.gameObject.name " + ((Object)((Component)instance).gameObject).name));
								}
								flag = true;
							}
							else if (SoundTool.infoDebugging)
							{
								SoundTool.Instance.logger.LogDebug((object)("sources[0] " + array3[0] + " does not match instance.gameObject.name " + ((Object)((Component)instance).gameObject).name));
							}
						}
					}
					else if (SoundTool.infoDebugging)
					{
						SoundTool.Instance.logger.LogDebug((object)("replacedClips[finalName].source was empty or null '" + SoundTool.replacedClips[text].source + "'"));
					}
					if (SoundTool.infoDebugging)
					{
						SoundTool.Instance.logger.LogDebug((object)$"replaceClip {flag}");
					}
					List<RandomAudioClip> clips = SoundTool.replacedClips[text].clips;
					float num = 0f;
					foreach (RandomAudioClip item in clips)
					{
						num += item.chance;
					}
					if (SoundTool.infoDebugging)
					{
						SoundTool.Instance.logger.LogDebug((object)$"totalChance {num}");
					}
					float num2 = Random.Range(0f, num);
					{
						foreach (RandomAudioClip item2 in clips)
						{
							if (num2 <= item2.chance)
							{
								if (flag)
								{
									if (SoundTool.infoDebugging)
									{
										SoundTool.Instance.logger.LogDebug((object)$"clip replaced with {item2.clip}");
									}
									instance.clip = item2.clip;
									break;
								}
								if (SoundTool.infoDebugging)
								{
									SoundTool.Instance.logger.LogDebug((object)$"clip was not replaced with {item2.clip}");
								}
								if (originalClips.ContainsKey(name))
								{
									if (SoundTool.infoDebugging)
									{
										SoundTool.Instance.logger.LogDebug((object)$"originalClips.ContainsKey(sourceName), clip was restored to {originalClips[name]}");
									}
									instance.clip = originalClips[name];
									originalClips.Remove(name);
								}
								break;
							}
							num2 -= item2.chance;
						}
						return;
					}
				}
				if (SoundTool.infoDebugging)
				{
					SoundTool.Instance.logger.LogDebug((object)$"replacedClips[finalName].canPlay {SoundTool.replacedClips[text].canPlay}");
				}
			}
			else if (originalClips.ContainsKey(name))
			{
				if (SoundTool.infoDebugging)
				{
					SoundTool.Instance.logger.LogDebug((object)"replacedClips did not contain finalName but originalClips contained sourceName");
				}
				instance.clip = originalClips[name];
				originalClips.Remove(name);
				if (SoundTool.infoDebugging)
				{
					SoundTool.Instance.logger.LogDebug((object)$"clip was restored to {originalClips[name]}");
				}
			}
		}

		private static AudioClip ReplaceClipWithNew(AudioClip original, AudioSource source = null)
		{
			if (SoundTool.infoDebugging)
			{
				SoundTool.Instance.logger.LogDebug((object)$"original {original} source {source}");
			}
			if ((Object)(object)original == (Object)null)
			{
				return original;
			}
			string name = original.GetName();
			bool flag = true;
			string text = name;
			if (SoundTool.infoDebugging)
			{
				SoundTool.Instance.logger.LogDebug((object)$"sourceName {((Object)((Component)source).gameObject).name} clipName {name} replaceClip {flag}");
			}
			if ((Object)(object)source != (Object)null)
			{
				if (SoundTool.replacedClips.Keys.Count > 0)
				{
					string[] array = SoundTool.replacedClips.Keys.ToArray();
					if (array.Length != 0)
					{
						for (int i = 0; i < array.Length; i++)
						{
							string[] array2 = array[i].Split("#");
							if (array2.Length == 2 && array2[0].Contains(name) && array2[1].Contains(((Object)((Component)source).gameObject).name))
							{
								text = name + "#" + array2[1];
							}
						}
					}
				}
			}
			else if (SoundTool.infoDebugging)
			{
				SoundTool.Instance.logger.LogDebug((object)"source was null, this means we can't check for sourceName for this sound!");
			}
			if (SoundTool.infoDebugging)
			{
				SoundTool.Instance.logger.LogDebug((object)("finalName after splitName operation " + text));
			}
			if (SoundTool.replacedClips.ContainsKey(text))
			{
				if (SoundTool.infoDebugging)
				{
					SoundTool.Instance.logger.LogDebug((object)"replacedClips contained finalName");
				}
				if (!SoundTool.replacedClips[text].canPlay)
				{
					if (SoundTool.infoDebugging)
					{
						SoundTool.Instance.logger.LogDebug((object)$"replacedClips[finalName].canPlay {SoundTool.replacedClips[text].canPlay}");
					}
					return original;
				}
				if (!originalClips.ContainsKey(text))
				{
					if (SoundTool.infoDebugging)
					{
						SoundTool.Instance.logger.LogDebug((object)("originalClips did not contain finalName, adding finalName " + text));
					}
					originalClips.Add(text, original);
				}
				if (!string.IsNullOrEmpty(SoundTool.replacedClips[text].source))
				{
					if (SoundTool.infoDebugging)
					{
						SoundTool.Instance.logger.LogDebug((object)("replacedClips[finalName].source " + SoundTool.replacedClips[text].source + " was not null or empty"));
					}
					flag = false;
					string[] array3 = SoundTool.replacedClips[text].source.Split(',');
					if (SoundTool.infoDebugging)
					{
						SoundTool.Instance.logger.LogDebug((object)$"sources array {array3.Length} {array3}");
					}
					if ((Object)(object)source != (Object)null && ((Object)((Component)source).gameObject).name != null)
					{
						if (array3.Length > 1)
						{
							for (int j = 0; j < array3.Length; j++)
							{
								if (array3[j] == ((Object)((Component)source).gameObject).name)
								{
									if (SoundTool.infoDebugging)
									{
										SoundTool.Instance.logger.LogDebug((object)("sources[i] " + array3[j] + " matches instance.gameObject.name " + ((Object)((Component)source).gameObject).name));
									}
									flag = true;
								}
								else if (SoundTool.infoDebugging)
								{
									SoundTool.Instance.logger.LogDebug((object)("sources[i] " + array3[j] + " does not match instance.gameObject.name " + ((Object)((Component)source).gameObject).name));
								}
							}
						}
						else if (array3[0] == ((Object)((Component)source).gameObject).name)
						{
							if (SoundTool.infoDebugging)
							{
								SoundTool.Instance.logger.LogDebug((object)("sources[0] " + array3[0] + " matches instance.gameObject.name " + ((Object)((Component)source).gameObject).name));
							}
							flag = true;
						}
						else if (SoundTool.infoDebugging)
						{
							SoundTool.Instance.logger.LogDebug((object)("sources[0] " + array3[0] + " does not match instance.gameObject.name " + ((Object)((Component)source).gameObject).name));
						}
					}
				}
				else if (SoundTool.infoDebugging)
				{
					SoundTool.Instance.logger.LogDebug((object)("replacedClips[finalName].source was empty or null '" + SoundTool.replacedClips[text].source + "'"));
				}
				if (SoundTool.infoDebugging)
				{
					SoundTool.Instance.logger.LogDebug((object)$"replaceClip {flag}");
				}
				List<RandomAudioClip> clips = SoundTool.replacedClips[text].clips;
				float num = 0f;
				foreach (RandomAudioClip item in clips)
				{
					num += item.chance;
				}
				if (SoundTool.infoDebugging)
				{
					SoundTool.Instance.logger.LogDebug((object)$"totalChance {num}");
				}
				float num2 = Random.Range(0f, num);
				foreach (RandomAudioClip item2 in clips)
				{
					if (num2 <= item2.chance)
					{
						if (flag)
						{
							if (SoundTool.infoDebugging)
							{
								SoundTool.Instance.logger.LogDebug((object)$"clip replaced with {item2.clip}");
							}
							return item2.clip;
						}
						if (SoundTool.infoDebugging)
						{
							SoundTool.Instance.logger.LogDebug((object)$"clip was not replaced with {item2.clip}");
						}
						if (originalClips.ContainsKey(text))
						{
							if (SoundTool.infoDebugging)
							{
								SoundTool.Instance.logger.LogDebug((object)$"originalClips.ContainsKey(finalName), clip was restored to {originalClips[text]}");
							}
							AudioClip result = originalClips[text];
							originalClips.Remove(text);
							return result;
						}
						return original;
					}
					num2 -= item2.chance;
				}
			}
			else if (originalClips.ContainsKey(text))
			{
				if (SoundTool.infoDebugging)
				{
					SoundTool.Instance.logger.LogDebug((object)"replacedClips did not contain finalName but originalClips contained finalName");
				}
				AudioClip result2 = originalClips[text];
				originalClips.Remove(text);
				if (SoundTool.infoDebugging)
				{
					SoundTool.Instance.logger.LogDebug((object)$"clip was restored to {originalClips[text]}");
				}
				return result2;
			}
			return original;
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal class GameNetworkManagerPatch
	{
		public static GameObject networkPrefab;

		public static GameObject networkHandlerHost;

		[HarmonyPatch("Start")]
		[HarmonyPrefix]
		public static void Start_Patch()
		{
			if (!((Object)(object)networkPrefab != (Object)null))
			{
				SoundTool.Instance.logger.LogDebug((object)"Loading NetworkHandler prefab...");
				networkPrefab = Assets.bundle.LoadAsset<GameObject>("SoundToolNetworkHandler.prefab");
				if ((Object)(object)networkPrefab == (Object)null)
				{
					SoundTool.Instance.logger.LogError((object)"Failed to load NetworkHandler prefab!");
				}
				if ((Object)(object)networkPrefab != (Object)null)
				{
					NetworkManager.Singleton.AddNetworkPrefab(networkPrefab);
					SoundTool.Instance.logger.LogDebug((object)"Registered NetworkHandler prefab!");
				}
				else
				{
					SoundTool.Instance.logger.LogWarning((object)"Failed to registered NetworkHandler prefab! No networking can take place.");
				}
			}
		}

		[HarmonyPatch("StartDisconnect")]
		[HarmonyPostfix]
		private static void StartDisconnect_Patch()
		{
			try
			{
				if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer)
				{
					SoundTool.Instance.logger.LogDebug((object)"Destroying NetworkHandler prefab!");
					Object.Destroy((Object)(object)networkHandlerHost);
					networkHandlerHost = null;
				}
			}
			catch
			{
				SoundTool.Instance.logger.LogError((object)"Failed to destroy NetworkHandler prefab!");
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal class StartOfRoundPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void SpawnNetworkHandler()
		{
			//IL_003a: 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)
			try
			{
				if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer)
				{
					SoundTool.Instance.logger.LogDebug((object)"Spawning NetworkHandler prefab!");
					GameNetworkManagerPatch.networkHandlerHost = Object.Instantiate<GameObject>(GameNetworkManagerPatch.networkPrefab, Vector3.zero, Quaternion.identity);
					GameNetworkManagerPatch.networkHandlerHost.GetComponent<NetworkObject>().Spawn(true);
				}
			}
			catch
			{
				SoundTool.Instance.logger.LogError((object)"Failed to spawn NetworkHandler prefab!");
			}
		}
	}
}
namespace LCSoundTool.Networking
{
	public class NetworkHandler : NetworkBehaviour
	{
		public static NetworkHandler Instance { get; private set; }

		public static Dictionary<string, AudioClip> networkedAudioClips { get; private set; }

		public static event Action ClientNetworkedAudioChanged;

		public static event Action HostNetworkedAudioChanged;

		public override void OnNetworkSpawn()
		{
			Debug.Log((object)"LCSoundTool - NetworkHandler created!");
			NetworkHandler.ClientNetworkedAudioChanged = null;
			NetworkHandler.HostNetworkedAudioChanged = null;
			networkedAudioClips = new Dictionary<string, AudioClip>();
			Instance = this;
		}

		[ClientRpc]
		public void ReceiveAudioClipClientRpc(string clipName, byte[] audioData, int channels, int frequency)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(292212293u, val, (RpcDelivery)0);
				bool flag = clipName != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(clipName, false);
				}
				bool flag2 = audioData != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives));
				if (flag2)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe<byte>(audioData, default(ForPrimitives));
				}
				BytePacker.WriteValueBitPacked(val2, channels);
				BytePacker.WriteValueBitPacked(val2, frequency);
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 292212293u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				if (!networkedAudioClips.ContainsKey(clipName))
				{
					AudioClip val3 = null;
					val3 = AudioUtility.ByteArrayToAudioClip(audioData, clipName, channels, frequency);
					networkedAudioClips.Add(clipName, val3);
					NetworkHandler.ClientNetworkedAudioChanged?.Invoke();
				}
				else
				{
					SoundTool.Instance.logger.LogDebug((object)("Sound " + clipName + " already exists for this client! Skipping addition of this sound for this client."));
				}
			}
		}

		[ClientRpc]
		public void RemoveAudioClipClientRpc(string clipName)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1355469546u, val, (RpcDelivery)0);
				bool flag = clipName != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(clipName, false);
				}
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1355469546u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && networkedAudioClips.ContainsKey(clipName))
			{
				networkedAudioClips.Remove(clipName);
				NetworkHandler.ClientNetworkedAudioChanged?.Invoke();
			}
		}

		[ClientRpc]
		public void SyncAudioClipsClientRpc(string clipName)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2611915412u, val, (RpcDelivery)0);
				bool flag = clipName != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(clipName, false);
				}
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2611915412u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !networkedAudioClips.ContainsKey(clipName))
			{
				SendExistingAudioClipServerRpc(clipName);
			}
		}

		[ClientRpc]
		public void ReceiveSeedClientRpc(int seed)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1556253924u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, seed);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1556253924u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
				{
					Random.InitState(seed);
					SoundTool.Instance.logger.LogDebug((object)$"Client received a new Unity Random seed of {seed}!");
				}
			}
		}

		[ServerRpc(RequireOwnership = false)]
		public void SendAudioClipServerRpc(string clipName, byte[] audioData, int channels, int frequency)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				ServerRpcParams val = default(ServerRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(2399630547u, val, (RpcDelivery)0);
				bool flag = clipName != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(clipName, false);
				}
				bool flag2 = audioData != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives));
				if (flag2)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe<byte>(audioData, default(ForPrimitives));
				}
				BytePacker.WriteValueBitPacked(val2, channels);
				BytePacker.WriteValueBitPacked(val2, frequency);
				((NetworkBehaviour)this).__endSendServerRpc(ref val2, 2399630547u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				ReceiveAudioClipClientRpc(clipName, audioData, channels, frequency);
				NetworkHandler.HostNetworkedAudioChanged?.Invoke();
			}
		}

		[ServerRpc(RequireOwnership = false)]
		public void RemoveAudioClipServerRpc(string clipName)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				ServerRpcParams val = default(ServerRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(3103497155u, val, (RpcDelivery)0);
				bool flag = clipName != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(clipName, false);
				}
				((NetworkBehaviour)this).__endSendServerRpc(ref val2, 3103497155u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				RemoveAudioClipClientRpc(clipName);
				NetworkHandler.HostNetworkedAudioChanged?.Invoke();
			}
		}

		[ServerRpc(RequireOwnership = false)]
		public void SyncAudioClipsServerRpc()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				ServerRpcParams val = default(ServerRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(178607916u, val, (RpcDelivery)0);
				((NetworkBehaviour)this).__endSendServerRpc(ref val2, 178607916u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage != 1 || (!networkManager.IsServer && !networkManager.IsHost))
			{
				return;
			}
			string[] array = networkedAudioClips.Keys.ToArray();
			if (array.Length < 1)
			{
				SoundTool.Instance.logger.LogDebug((object)"No sounds found in networkedClips. Syncing process cancelled!");
				return;
			}
			for (int i = 0; i < array.Length; i++)
			{
				SyncAudioClipsClientRpc(array[i]);
			}
		}

		[ServerRpc(RequireOwnership = false)]
		public void SendExistingAudioClipServerRpc(string clipName)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				ServerRpcParams val = default(ServerRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(4006259189u, val, (RpcDelivery)0);
				bool flag = clipName != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(clipName, false);
				}
				((NetworkBehaviour)this).__endSendServerRpc(ref val2, 4006259189u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				if (networkedAudioClips.ContainsKey(clipName))
				{
					byte[] array = null;
					array = AudioUtility.AudioClipToByteArray(networkedAudioClips[clipName], out var _);
					ReceiveAudioClipClientRpc(clipName, array, networkedAudioClips[clipName].channels, networkedAudioClips[clipName].frequency);
				}
				else
				{
					SoundTool.Instance.logger.LogWarning((object)"Trying to obtain and sync a sound from the host that does not exist in the host's game!");
				}
			}
		}

		[ServerRpc(RequireOwnership = false)]
		public void SendSeedToClientsServerRpc(int seed)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val = default(ServerRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(4286510828u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, seed);
					((NetworkBehaviour)this).__endSendServerRpc(ref val2, 4286510828u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost) && ((NetworkBehaviour)this).IsHost)
				{
					ReceiveSeedClientRpc(seed);
					SoundTool.Instance.logger.LogDebug((object)$"Sending a new Unity random seed of {seed} to all clients...");
				}
			}
		}

		protected override void __initializeVariables()
		{
			((NetworkBehaviour)this).__initializeVariables();
		}

		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeRPCS_NetworkHandler()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			NetworkManager.__rpc_func_table.Add(292212293u, new RpcReceiveHandler(__rpc_handler_292212293));
			NetworkManager.__rpc_func_table.Add(1355469546u, new RpcReceiveHandler(__rpc_handler_1355469546));
			NetworkManager.__rpc_func_table.Add(2611915412u, new RpcReceiveHandler(__rpc_handler_2611915412));
			NetworkManager.__rpc_func_table.Add(1556253924u, new RpcReceiveHandler(__rpc_handler_1556253924));
			NetworkManager.__rpc_func_table.Add(2399630547u, new RpcReceiveHandler(__rpc_handler_2399630547));
			NetworkManager.__rpc_func_table.Add(3103497155u, new RpcReceiveHandler(__rpc_handler_3103497155));
			NetworkManager.__rpc_func_table.Add(178607916u, new RpcReceiveHandler(__rpc_handler_178607916));
			NetworkManager.__rpc_func_table.Add(4006259189u, new RpcReceiveHandler(__rpc_handler_4006259189));
			NetworkManager.__rpc_func_table.Add(4286510828u, new RpcReceiveHandler(__rpc_handler_4286510828));
		}

		private static void __rpc_handler_292212293(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				bool flag = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
				string clipName = null;
				if (flag)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe(ref clipName, false);
				}
				bool flag2 = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag2, default(ForPrimitives));
				byte[] audioData = null;
				if (flag2)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref audioData, default(ForPrimitives));
				}
				int channels = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref channels);
				int frequency = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref frequency);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((NetworkHandler)(object)target).ReceiveAudioClipClientRpc(clipName, audioData, channels, frequency);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_1355469546(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && net

plugins/LethalFashion.dll

Decompiled 2 months ago
using System;
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 UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LethalFashion")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Unlocks all base game suits for free to use immediately.")]
[assembly: AssemblyFileVersion("1.0.6.0")]
[assembly: AssemblyInformationalVersion("1.0.6")]
[assembly: AssemblyProduct("LethalFashion")]
[assembly: AssemblyTitle("LethalFashion")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.6.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 LethalFashion
{
	[BepInPlugin("LethalFashion", "LethalFashion", "1.0.6")]
	public class Plugin : BaseUnityPlugin
	{
		public static ManualLogSource Log;

		private static Harmony harmonyInstance;

		public ConfigEntry<string> SuitUnlockConfig;

		public static Plugin Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin LethalFashion is loaded!");
			SuitUnlockConfig = ((BaseUnityPlugin)this).Config.Bind<string>("General", "SuitUnlocks", "Green Suit, Hazard Suit, Pajama Suit, Purple Suit, Bee Suit, Bunny Suit", "Names of the suits to unlock. You can remove them off of this list to ignore unlocking them. This should work for future game updates and can be used to unlock suits from other mods if you know the suit name.");
			InitializeHarmony();
		}

		private void InitializeHarmony()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (harmonyInstance == null)
			{
				harmonyInstance = new Harmony("LethalFashion");
				try
				{
					harmonyInstance.PatchAll(typeof(SuitFashion));
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Patch applied successfully. You are now FASHIONABLE.");
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("Error applying patch: " + ex.Message));
				}
			}
		}
	}
	public class SuitFashion
	{
		private static readonly MethodInfo unlockItem;

		private static bool isHost;

		static SuitFashion()
		{
			unlockItem = typeof(StartOfRound).GetMethod("SpawnUnlockable", BindingFlags.Instance | BindingFlags.NonPublic);
			if (unlockItem == null)
			{
				Plugin.Log.LogError((object)"SpawnUnlockable method not found in StartOfRound. Please check game/plugin version.");
			}
			else
			{
				Plugin.Log.LogInfo((object)"SpawnUnlockable method found successfully.");
			}
		}

		public static void SpawnUnlockableDelegate(StartOfRound instance, int ID)
		{
			if (unlockItem == null)
			{
				Plugin.Log.LogError((object)"SpawnUnlockable method reference is null.");
			}
			else if (!instance.SpawnedShipUnlockables.ContainsKey(ID))
			{
				try
				{
					unlockItem.Invoke(instance, new object[1] { ID });
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)$"Error invoking SpawnUnlockable for ID {ID}: {ex.Message}");
				}
			}
		}

		public static void PositionSuitsOnRack(StartOfRound startOfRoundInstance)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			UnlockableSuit[] array = Object.FindObjectsOfType<UnlockableSuit>();
			for (int i = 0; i < array.Length; i++)
			{
				UnlockableSuit val = array[i];
				AutoParentToShip component = ((Component)val).gameObject.GetComponent<AutoParentToShip>();
				if ((Object)(object)component != (Object)null)
				{
					component.overrideOffset = true;
					component.positionOffset = new Vector3(-2.45f, 2.75f, -8.41f) + startOfRoundInstance.rightmostSuitPosition.forward * 0.18f * (float)i;
					component.rotationOffset = new Vector3(0f, 90f, 0f);
				}
			}
		}

		private static void UnlockAndSpawnSuits(StartOfRound startOfRoundInstance)
		{
			string value = Plugin.Instance.SuitUnlockConfig.Value;
			HashSet<string> hashSet = new HashSet<string>(from s in value.Split(',')
				select s.Trim(), StringComparer.OrdinalIgnoreCase);
			for (int i = 0; i < startOfRoundInstance.unlockablesList.unlockables.Count; i++)
			{
				UnlockableItem val = startOfRoundInstance.unlockablesList.unlockables[i];
				if (val != null && (Object)(object)val.suitMaterial != (Object)null && hashSet.Contains(val.unlockableName))
				{
					Plugin.Log.LogInfo((object)$"Unlocking suit: ID={i}, Name={val.unlockableName}");
					val.alreadyUnlocked = true;
					val.hasBeenUnlockedByPlayer = true;
					val.inStorage = false;
					SpawnUnlockableDelegate(startOfRoundInstance, i);
				}
			}
			Plugin.Log.LogInfo((object)"Finished unlocking and spawning suits.");
		}

		[HarmonyPatch(typeof(StartOfRound), "Start")]
		[HarmonyPostfix]
		public static void StartOfRoundSuitPatch(StartOfRound __instance)
		{
			isHost = GameNetworkManager.Instance.isHostingGame;
			if (isHost)
			{
				UnlockAndSpawnSuits(__instance);
				PositionSuitsOnRack(__instance);
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "ResetShip")]
		[HarmonyPostfix]
		public static void ResetShipSuitPatch(StartOfRound __instance)
		{
			if (isHost)
			{
				StartOfRoundSuitPatch(__instance);
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "LethalFashion";

		public const string PLUGIN_NAME = "LethalFashion";

		public const string PLUGIN_VERSION = "1.0.6";
	}
}

plugins/MaskedEnemyRework.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using MaskedEnemyRework.Patches;
using Microsoft.CodeAnalysis;
using MoreCompany;
using MoreCompany.Cosmetics;
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("MaskedEnemyRework")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Lethal Company Mod")]
[assembly: AssemblyFileVersion("3.3.0.0")]
[assembly: AssemblyInformationalVersion("3.3.0")]
[assembly: AssemblyProduct("MaskedEnemyRework")]
[assembly: AssemblyTitle("MaskedEnemyRework")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("3.3.0.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 MaskedEnemyRework
{
	public class PluginConfig
	{
		public bool RemoveMasks = Cfg("General", "Remove Mask From Masked Enemy", defaultVal: true, "Whether or not the Masked Enemy has a mask on.");

		public bool RevealMasks = Cfg("General", "Reveal Mask When Attacking", defaultVal: false, "The enemy would reveal their mask permanently after trying to attack someone. Mask would be off until the attempt to attack is made");

		public bool RemoveZombieArms = Cfg("General", "Remove Zombie Arms", defaultVal: true, "Remove the animation where the Masked raise arms like a zombie.");

		public bool TriggerMines = Cfg("General", "Masked Trigger Mines", defaultVal: true, "Masked go KABOOM when walking over a mine.");

		public int Health = Cfg("General", "Masked Health", 4, "Number of shovel hits required to kill a Masked.");

		public bool UseVanillaSpawns = Cfg("General", "Use Vanilla Spawns", defaultVal: false, "Disables all spawning rules from this mod. Only uses the above settings from this config. Will not spawn on all moons. will ignore EVERYTHING in the config below this point.");

		public bool DontTouchMimickingPlayer = Cfg("General", "Dont Touch MaskedPlayerEnemy.mimickingPlayer", defaultVal: false, "Experimental. Give control to other mods (like qwbarch-Mirage) to set which players are impersonated.");

		public bool ShowMaskedNames = Cfg("General", "Show Masked Usernames", defaultVal: false, "[UNUSED FOR NOW] Will show username of player being mimicked.");

		public bool UseSpawnRarity = Cfg("Spawns", "Use Spawn Rarity", defaultVal: false, "Use custom spawn rate from config. If this is false, the masked spawns at the same rate as the Bracken. If true, will spawn at whatever rarity is given in Spawn Rarity config option");

		public int SpawnRarity = Cfg("Spawns", "Spawn Rarity", 15, "The rarity for the Masked Enemy to spawn. The higher the number, the more likely to spawn. Can go to 1000000000, any higher will break. Use Spawn Rarity must be set to True");

		public bool CanSpawnOutside = Cfg("Spawns", "Allow Masked To Spawn Outside", defaultVal: false, "Whether the Masked Enemy can spawn outside the building");

		public int MaxSpawnCount = Cfg("Spawns", "Max Number of Masked", 3, "Vents will stop spawning Masked when this limit is hit. Masked can still spawn through other means, like players getting possessed.");

		public float PowerLevel = Cfg("Spawns", "Masked Power Level", 1f, "How much of the moon's Power Level each Masked consumes. Higher = Less entities");

		public bool BoostMoonPowerLevel = Cfg("Spawns", "Boost Moon Power Level", defaultVal: false, "Increase moon indoor max power level by (Max Masked * Masked Power Level). Allows more Masked and other monsters to spawn. Original MEO behavior.");

		public bool ZombieApocalypseMode = Cfg("Zombie Apocalypse Mode", "Always Zombie Apocalypse", defaultVal: false, "Only spawns Masked! Make sure to crank up the Max Spawn Count in this config! Would also recommend bringing a gun (mod), a shovel works fine too though.... This mode does not play nice with other mods that affect spawn rates. Disable those before playing for best results");

		public int ZombieApocalypeRandomChance = Cfg("Zombie Apocalypse Mode", "Random Zombie Apocalypse", -1, "[Must Be Whole Number] The percent chance from 1 to 100 that a day could contain a zombie apocalypse. Put at -1 to never have the chance arise and don't have Only Spawn Masked turned on");

		public int MaxZombies = Cfg("Zombie Apocalypse Mode", "Max Zombies", 6, "Max Masked for Zombie Apocalypse. Vents will stop spawning Masked when this limit is hit.");

		public float ZombiePowerLevel = Cfg("Zombie Apocalypse Mode", "Zombie Power Level", 2f, "Masked power level during Zombie Apocalypse. Higher = Less Zombies. This can limit max zombies by moon difficulty, even if it's lower than what the 'Max Zombies' option allows. Set to 0 to use Max Zombies for all moons. Moon Indoor Power Levels for reference: [Experimentation: 4, Offense: 12, Titan: 18]");

		public bool UseZombieSpawnCurve = Cfg("Zombie Apocalypse Mode", "Use Spawn Curves", defaultVal: false, "[BUGGED: This likely permanently modifies the level spawning options until the game is restarted] Edit level spawn curves during a Zombie Apocalypse; options below. Original MEO behavior.");

		public float InsideEnemySpawnCurve = Cfg("Zombie Apocalypse Mode", "StartOfDay Inside Masked Spawn Curve", 0.1f, "Spawn curve for masked inside, start of the day. Crank this way up for immediate action. More info in the readme");

		public float MiddayInsideEnemySpawnCurve = Cfg("Zombie Apocalypse Mode", "Midday Inside Masked Spawn Curve", 500f, "Spawn curve for masked inside, midday.");

		public float StartOutsideEnemySpawnCurve = Cfg("Zombie Apocalypse Mode", "StartOfDay Masked Outside Spawn Curve", -30f, "Spawn curve for outside masked, start of the day.");

		public float MidOutsideEnemySpawnCurve = Cfg("Zombie Apocalypse Mode", "Midday Outside Masked Spawn Curve", -30f, "Spawn curve for outside masked, midday.");

		public float EndOutsideEnemySpawnCurve = Cfg("Zombie Apocalypse Mode", "EOD Outside Masked Spawn Curve", 10f, "Spawn curve for outside masked, end of day");

		public static List<ConfigEntryBase> entries = new List<ConfigEntryBase>();

		public static T Cfg<T>(string category, string name, T defaultVal, string description)
		{
			ConfigEntry<T> val = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<T>(category, name, defaultVal, description);
			entries.Add((ConfigEntryBase)(object)val);
			return val.Value;
		}
	}
	[BepInPlugin("MaskedEnemyRework", "MaskedEnemyRework", "3.3.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("MaskedEnemyRework");

		public static Plugin Instance;

		public static ManualLogSource logger;

		public static PluginConfig cfg;

		public static List<int> PlayerMimicList;

		public static int PlayerMimicIndex;

		public static int InitialPlayerCount;

		public static SpawnableEnemyWithRarity maskedPrefab;

		public static SpawnableEnemyWithRarity flowerPrefab;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			PlayerMimicList = new List<int>();
			PlayerMimicIndex = 0;
			InitialPlayerCount = 0;
			cfg = new PluginConfig();
			logger = Logger.CreateLogSource("MaskedEnemyRework");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin MaskedEnemyRework is loaded! Woohoo!");
			harmony.PatchAll(typeof(Plugin));
			harmony.PatchAll(typeof(GetMaskedPrefabForLaterUse));
			harmony.PatchAll(typeof(MaskedVisualRework));
			harmony.PatchAll(typeof(MaskedSpawnSettings));
			if (cfg.TriggerMines)
			{
				harmony.PatchAll(typeof(LandmineVsMasked));
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "MaskedEnemyRework";

		public const string PLUGIN_NAME = "MaskedEnemyRework";

		public const string PLUGIN_VERSION = "3.3.0";
	}
}
namespace MaskedEnemyRework.Patches
{
	[HarmonyPatch]
	internal class GetMaskedPrefabForLaterUse
	{
		[HarmonyPatch(typeof(Terminal), "Start")]
		[HarmonyPostfix]
		private static void SavesPrefabForLaterUse(ref SelectableLevel[] ___moonsCatalogueList)
		{
			ManualLogSource val = Logger.CreateLogSource("MaskedEnemyRework");
			SelectableLevel[] array = ___moonsCatalogueList;
			for (int i = 0; i < array.Length; i++)
			{
				foreach (SpawnableEnemyWithRarity enemy in array[i].Enemies)
				{
					if (enemy.enemyType.enemyName == "Masked")
					{
						val.LogInfo((object)"Found Masked!");
						Plugin.maskedPrefab = enemy;
					}
					else if (enemy.enemyType.enemyName == "Flowerman")
					{
						Plugin.flowerPrefab = enemy;
						val.LogInfo((object)"Found Flowerman!");
					}
				}
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "SetHoverTipAndCurrentInteractTrigger")]
		[HarmonyPrefix]
		private static void LookingAtMasked(ref PlayerControllerB __instance)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.cfg.ShowMaskedNames)
			{
				return;
			}
			Ray val = default(Ray);
			((Ray)(ref val))..ctor(((Component)__instance.gameplayCamera).transform.position, ((Component)__instance.gameplayCamera).transform.forward);
			LayerMask val2 = LayerMask.op_Implicit(524288);
			RaycastHit val3 = default(RaycastHit);
			if (!__instance.isFreeCamera && Physics.Raycast(val, ref val3, 5f, LayerMask.op_Implicit(val2)))
			{
				EnemyAICollisionDetect component = ((Component)((RaycastHit)(ref val3)).collider).gameObject.GetComponent<EnemyAICollisionDetect>();
				if (Object.op_Implicit((Object)(object)component))
				{
					((Component)component.mainScript).gameObject.GetComponent<MaskedPlayerEnemy>();
				}
			}
		}
	}
	[HarmonyPatch(typeof(Landmine))]
	internal class LandmineVsMasked
	{
		[HarmonyPatch("OnTriggerEnter")]
		[HarmonyPostfix]
		private static void OnTriggerEnter(Collider other, Landmine __instance, ref bool ___hasExploded, ref float ___pressMineDebounceTimer)
		{
			if (!___hasExploded && !(___pressMineDebounceTimer > 0f) && ((Component)other).CompareTag("Player") && ((Object)other).name.StartsWith("Masked"))
			{
				___pressMineDebounceTimer = 0.5f;
				__instance.PressMineServerRpc();
			}
		}

		[HarmonyPatch("OnTriggerExit")]
		[HarmonyPostfix]
		private static void OnTriggerExit(Collider other, Landmine __instance, ref bool ___hasExploded, ref bool ___mineActivated)
		{
			if (!___hasExploded && ___mineActivated && ((Component)other).CompareTag("Player") && ((Object)other).name.StartsWith("Masked"))
			{
				typeof(Landmine).GetMethod("TriggerMineOnLocalClientByExiting", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, null);
			}
		}
	}
	[HarmonyPatch(typeof(RoundManager))]
	internal class MaskedSpawnSettings
	{
		private static Predicate<SpawnableEnemyWithRarity> isMasked = (SpawnableEnemyWithRarity enemy) => enemy.enemyType.enemyName == "Masked";

		private static Predicate<SpawnableEnemyWithRarity> isFlowerman = (SpawnableEnemyWithRarity enemy) => enemy.enemyType.enemyName == "Flowerman";

		private static FieldInfo powerLevelField = typeof(EnemyType).GetField("PowerLevel");

		private static FieldInfo currentMaxInsidePowerField = typeof(RoundManager).GetField("currentMaxInsidePower");

		public static bool isZombieApocalypse = false;

		public static T StupidGet<T>(object obj, FieldInfo field)
		{
			return (T)Convert.ChangeType(field.GetValue(obj), typeof(T));
		}

		[HarmonyPatch("BeginEnemySpawning")]
		[HarmonyPrefix]
		private static void UpdateSpawnRates(ref SelectableLevel ___currentLevel)
		{
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: 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_0232: Expected O, but got Unknown
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Expected O, but got Unknown
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Expected O, but got Unknown
			PluginConfig cfg = Plugin.cfg;
			if (cfg.UseVanillaSpawns)
			{
				return;
			}
			ManualLogSource logger = Plugin.logger;
			logger.LogInfo((object)"Starting Round Manager");
			SpawnableEnemyWithRarity maskedPrefab = Plugin.maskedPrefab;
			SpawnableEnemyWithRarity val = ___currentLevel.Enemies.Find(isFlowerman) ?? Plugin.flowerPrefab;
			isZombieApocalypse = cfg.ZombieApocalypseMode || StartOfRound.Instance.randomMapSeed % 100 < cfg.ZombieApocalypeRandomChance;
			try
			{
				maskedPrefab.enemyType.enemyPrefab.GetComponent<EnemyAI>().enemyHP = cfg.Health;
				float num = 0f;
				foreach (SpawnableEnemyWithRarity item in ___currentLevel.Enemies.FindAll(isMasked))
				{
					num -= (float)item.enemyType.MaxCount * StupidGet<float>(item.enemyType, powerLevelField);
				}
				___currentLevel.Enemies.RemoveAll(isMasked);
				___currentLevel.Enemies.Add(maskedPrefab);
				if (cfg.CanSpawnOutside)
				{
					___currentLevel.OutsideEnemies.RemoveAll(isMasked);
					___currentLevel.OutsideEnemies.Add(maskedPrefab);
					___currentLevel.DaytimeEnemies.RemoveAll(isMasked);
					___currentLevel.DaytimeEnemies.Add(maskedPrefab);
				}
				float num2 = (isZombieApocalypse ? cfg.ZombiePowerLevel : cfg.PowerLevel);
				powerLevelField.SetValue(maskedPrefab.enemyType, Convert.ChangeType(num2, powerLevelField.FieldType));
				maskedPrefab.enemyType.probabilityCurve = val.enemyType.probabilityCurve;
				maskedPrefab.enemyType.isOutsideEnemy = cfg.CanSpawnOutside;
				if (isZombieApocalypse)
				{
					logger.LogInfo((object)"ZOMBIE APOCALYPSE");
					maskedPrefab.enemyType.MaxCount = cfg.MaxZombies;
					maskedPrefab.rarity = 1000000;
					if (cfg.UseZombieSpawnCurve)
					{
						___currentLevel.enemySpawnChanceThroughoutDay = new AnimationCurve((Keyframe[])(object)new Keyframe[2]
						{
							new Keyframe(0f, cfg.InsideEnemySpawnCurve),
							new Keyframe(0.5f, cfg.MiddayInsideEnemySpawnCurve)
						});
						___currentLevel.daytimeEnemySpawnChanceThroughDay = new AnimationCurve((Keyframe[])(object)new Keyframe[2]
						{
							new Keyframe(0f, 7f),
							new Keyframe(0.5f, 7f)
						});
						___currentLevel.outsideEnemySpawnChanceThroughDay = new AnimationCurve((Keyframe[])(object)new Keyframe[3]
						{
							new Keyframe(0f, cfg.StartOutsideEnemySpawnCurve),
							new Keyframe(20f, cfg.MidOutsideEnemySpawnCurve),
							new Keyframe(21f, cfg.EndOutsideEnemySpawnCurve)
						});
					}
				}
				else
				{
					logger.LogInfo((object)"no zombies :(");
					maskedPrefab.enemyType.MaxCount = cfg.MaxSpawnCount;
					maskedPrefab.rarity = (cfg.UseSpawnRarity ? cfg.SpawnRarity : val.rarity);
				}
				num += (float)maskedPrefab.enemyType.MaxCount * num2;
				if (cfg.BoostMoonPowerLevel)
				{
					logger.LogInfo((object)$"Adjusting power levels: [maxEnemyPowerCount: {___currentLevel.maxEnemyPowerCount}+{num}, maxDaytimeEnemyPowerCount: {___currentLevel.maxDaytimeEnemyPowerCount}+{num}, maxOutsideEnemyPowerCount: {___currentLevel.maxOutsideEnemyPowerCount}+{num}]");
					SelectableLevel obj = ___currentLevel;
					obj.maxEnemyPowerCount += (int)num;
					SelectableLevel obj2 = ___currentLevel;
					obj2.maxDaytimeEnemyPowerCount += (int)num;
					SelectableLevel obj3 = ___currentLevel;
					obj3.maxOutsideEnemyPowerCount += (int)num;
				}
			}
			catch (Exception ex)
			{
				logger.LogInfo((object)ex);
			}
		}

		[HarmonyPatch("AssignRandomEnemyToVent")]
		[HarmonyPrefix]
		private static bool ZombieVent(EnemyVent vent, float spawnTime, ref RoundManager __instance, ref bool __result, ref SelectableLevel ___currentLevel, ref TimeOfDay ___timeScript, ref bool ___cannotSpawnMoreInsideEnemies, ref bool ___firstTimeSpawningEnemies, ref int ___currentEnemyPower, ref int ___currentHour)
		{
			if (Plugin.cfg.UseVanillaSpawns || !isZombieApocalypse)
			{
				return true;
			}
			if (___firstTimeSpawningEnemies)
			{
				foreach (SpawnableEnemyWithRarity enemy in ___currentLevel.Enemies)
				{
					enemy.enemyType.numberSpawned = 0;
				}
			}
			___firstTimeSpawningEnemies = false;
			ManualLogSource logger = Plugin.logger;
			int num = ___currentLevel.Enemies.FindIndex(isMasked);
			SpawnableEnemyWithRarity val = ___currentLevel.Enemies[num];
			if (num == -1)
			{
				logger.LogInfo((object)"No masked found in enemy list?");
				return true;
			}
			if (val.enemyType.numberSpawned >= val.enemyType.MaxCount)
			{
				__result = false;
				___cannotSpawnMoreInsideEnemies = true;
				logger.LogInfo((object)"Max masked spawned");
				return false;
			}
			float num2 = StupidGet<float>(val.enemyType, powerLevelField);
			float num3 = StupidGet<float>(__instance, currentMaxInsidePowerField) - (float)___currentEnemyPower;
			logger.LogInfo((object)("available inside power: " + num3));
			if (num2 > num3)
			{
				__result = false;
				___cannotSpawnMoreInsideEnemies = true;
				logger.LogInfo((object)"Max power");
				return false;
			}
			___currentEnemyPower += (int)num2;
			vent.enemyType = val.enemyType;
			vent.enemyTypeIndex = num;
			vent.occupied = true;
			vent.spawnTime = spawnTime;
			if (___timeScript.hour - ___currentHour > 0)
			{
				logger.LogInfo((object)"Round manager catching up to time yada yada UvU.");
			}
			else
			{
				vent.SyncVentSpawnTimeClientRpc((int)spawnTime, num);
			}
			EnemyType enemyType = val.enemyType;
			enemyType.numberSpawned++;
			logger.LogInfo((object)"Spawned a masked");
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(MaskedPlayerEnemy))]
	internal class MaskedVisualRework
	{
		private static IEnumerator coroutine;

		[HarmonyPatch("Start")]
		[HarmonyBefore(new string[] { "AdvancedCompany" })]
		[HarmonyPostfix]
		private static void ReformVisuals(ref MaskedPlayerEnemy __instance)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			ManualLogSource val = Logger.CreateLogSource("MaskedEnemyRework");
			if (!Plugin.cfg.DontTouchMimickingPlayer)
			{
				PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
				int num = StartOfRound.Instance.ClientPlayerList.Count;
				if (num == 0)
				{
					num = 1;
					val.LogError((object)"Player count was zero");
				}
				if (Plugin.PlayerMimicList.Count <= 1 || Plugin.InitialPlayerCount != num)
				{
					Plugin.InitialPlayerCount = num;
					State state = Random.state;
					Random.InitState(1234);
					for (int i = 0; i < 50; i++)
					{
						Plugin.PlayerMimicList.Add(Random.Range(0, num));
					}
					Random.state = state;
				}
				int num2 = Plugin.PlayerMimicList[Plugin.PlayerMimicIndex % 50] % num;
				Plugin.PlayerMimicIndex++;
				if ((Object)(object)__instance.mimickingPlayer == (Object)null)
				{
					__instance.mimickingPlayer = allPlayerScripts[num2];
				}
				__instance.SetSuit(__instance.mimickingPlayer.currentSuitID);
			}
			if (Plugin.cfg.RemoveMasks || Plugin.cfg.RevealMasks)
			{
				((Component)((Component)__instance).gameObject.transform.Find("ScavengerModel/metarig/spine/spine.001/spine.002/spine.003/spine.004/HeadMaskComedy")).gameObject.SetActive(false);
				((Component)((Component)__instance).gameObject.transform.Find("ScavengerModel/metarig/spine/spine.001/spine.002/spine.003/spine.004/HeadMaskTragedy")).gameObject.SetActive(false);
			}
			if (Chainloader.PluginInfos.ContainsKey("me.swipez.melonloader.morecompany") && !Chainloader.PluginInfos.ContainsKey("com.potatoepet.AdvancedCompany"))
			{
				MoreCompanyPatch.ApplyCosmetics(__instance);
			}
		}

		[HarmonyPatch("SetHandsOutClientRpc")]
		[HarmonyPrefix]
		private static void MaskAndArmsReveal(ref bool setOut, ref MaskedPlayerEnemy __instance)
		{
			GameObject gameObject = ((Component)((Component)__instance).gameObject.transform.Find("ScavengerModel/metarig/spine/spine.001/spine.002/spine.003/spine.004/HeadMaskComedy")).gameObject;
			if (Plugin.cfg.RevealMasks && !gameObject.activeSelf && ((EnemyAI)__instance).currentBehaviourStateIndex == 1)
			{
				Logger.CreateLogSource("MaskedEnemyRework");
				IEnumerator enumerator = FadeInAndOut(gameObject, fadeIn: true, 1f);
				((MonoBehaviour)__instance).StartCoroutine(enumerator);
			}
			if (Plugin.cfg.RemoveZombieArms)
			{
				setOut = false;
			}
		}

		[HarmonyPatch("SetEnemyOutside")]
		[HarmonyPostfix]
		[HarmonyPriority(300)]
		private static void HideCosmeticsIfMarked(ref MaskedPlayerEnemy __instance)
		{
			if (Chainloader.PluginInfos.ContainsKey("me.swipez.melonloader.morecompany") && !Chainloader.PluginInfos.ContainsKey("com.potatoepet.AdvancedCompany"))
			{
				MoreCompanyPatch.ApplyCosmetics(__instance);
			}
		}

		[HarmonyPatch("DoAIInterval")]
		[HarmonyPostfix]
		private static void HideRevealedMask(ref MaskedPlayerEnemy __instance)
		{
			if (Plugin.cfg.RevealMasks && (Object)(object)((EnemyAI)__instance).targetPlayer == (Object)null)
			{
				GameObject gameObject = ((Component)((Component)__instance).gameObject.transform.Find("ScavengerModel/metarig/spine/spine.001/spine.002/spine.003/spine.004/HeadMaskComedy")).gameObject;
				if (gameObject.activeSelf)
				{
					IEnumerator enumerator = FadeInAndOut(gameObject, fadeIn: false, 1f);
					((MonoBehaviour)__instance).StartCoroutine(enumerator);
				}
			}
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void UpdateMaskName(ref MaskedPlayerEnemy __instance)
		{
		}

		private static IEnumerator FadeInAndOut(GameObject mask, bool fadeIn, float duration)
		{
			float counter = 0f;
			mask.SetActive(true);
			float startLoc;
			float endLoc;
			if (fadeIn)
			{
				startLoc = 0.095f;
				endLoc = 0.215f;
			}
			else
			{
				startLoc = 0.215f;
				endLoc = 0.095f;
			}
			while (counter < duration)
			{
				counter += Time.deltaTime;
				float num = Mathf.Lerp(startLoc, endLoc, counter / duration);
				mask.transform.localPosition = new Vector3(-0.009f, 0.143f, num);
				yield return null;
			}
			if (!fadeIn)
			{
				mask.SetActive(false);
			}
		}
	}
	internal class MoreCompanyPatch
	{
		public static void ApplyCosmetics(MaskedPlayerEnemy masked)
		{
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			if (MainClass.playerIdsAndCosmetics.Count == 0)
			{
				return;
			}
			FieldInfo field = typeof(MainClass).GetField("showCosmetics");
			FieldInfo field2 = typeof(MainClass).GetField("cosmeticsSyncOther");
			if (field != null)
			{
				if (!(bool)field.GetValue(null))
				{
					return;
				}
			}
			else if (!(field2 != null) || !((ConfigEntry<bool>)field2.GetValue(null)).Value)
			{
				return;
			}
			Transform val = ((Component)masked).transform.Find("ScavengerModel").Find("metarig");
			CosmeticApplication component = ((Component)val).GetComponent<CosmeticApplication>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.ClearCosmetics();
				Object.Destroy((Object)(object)component);
				((EnemyAI)masked).skinnedMeshRenderers = ((Component)masked).gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();
				((EnemyAI)masked).meshRenderers = ((Component)masked).gameObject.GetComponentsInChildren<MeshRenderer>();
			}
			List<string> list = MainClass.playerIdsAndCosmetics[(int)masked.mimickingPlayer.playerClientId];
			component = ((Component)val).gameObject.AddComponent<CosmeticApplication>();
			foreach (string item in list)
			{
				component.ApplyCosmetic(item, true);
			}
			foreach (CosmeticInstance spawnedCosmetic in component.spawnedCosmetics)
			{
				Transform transform = ((Component)spawnedCosmetic).transform;
				transform.localScale *= 0.38f;
			}
		}
	}
	internal class RemoveZombieArms
	{
		[HarmonyPatch(typeof(MaskedPlayerEnemy), "SetHandsOutClientRpc")]
		[HarmonyPrefix]
		private static void RemoveArms(ref bool setOut)
		{
			if (Plugin.cfg.RemoveZombieArms)
			{
				setOut = false;
			}
		}
	}
}

plugins/Mimics.dll

Decompiled 2 months ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using DunGen;
using GameNetcodeStuff;
using HarmonyLib;
using LethalCompanyMimics.Properties;
using Microsoft.CodeAnalysis;
using Mimics.API;
using Mimics.NetcodePatcher;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;

[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("Mimics")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A mod that adds mimics to Lethal Company")]
[assembly: AssemblyFileVersion("2.6.4.0")]
[assembly: AssemblyInformationalVersion("2.6.4")]
[assembly: AssemblyProduct("Mimics")]
[assembly: AssemblyTitle("Mimics")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.6.4.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
		NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<bool>();
		NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<bool>();
	}
}
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 LethalCompanyMimics.Properties
{
	[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
	[DebuggerNonUserCode]
	[CompilerGenerated]
	internal class Resources
	{
		private static ResourceManager resourceMan;

		private static CultureInfo resourceCulture;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static ResourceManager ResourceManager
		{
			get
			{
				if (resourceMan == null)
				{
					ResourceManager resourceManager = new ResourceManager("LethalCompanyMimics.Properties.Resources", typeof(Resources).Assembly);
					resourceMan = resourceManager;
				}
				return resourceMan;
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static CultureInfo Culture
		{
			get
			{
				return resourceCulture;
			}
			set
			{
				resourceCulture = value;
			}
		}

		internal static byte[] mimicdoor
		{
			get
			{
				object @object = ResourceManager.GetObject("mimicdoor", resourceCulture);
				return (byte[])@object;
			}
		}

		internal Resources()
		{
		}
	}
}
namespace Mimics
{
	[BepInPlugin("x753.Mimics", "Mimics", "2.6.4")]
	public class Mimics : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(GameNetworkManager))]
		internal class GameNetworkManagerPatch
		{
			[HarmonyPatch("Start")]
			[HarmonyPostfix]
			private static void StartPatch()
			{
				((Component)GameNetworkManager.Instance).GetComponent<NetworkManager>().AddNetworkPrefab(MimicNetworkerPrefab);
			}
		}

		[HarmonyPatch(typeof(StartOfRound))]
		internal class StartOfRoundPatch
		{
			[HarmonyPatch("Start")]
			[HarmonyPostfix]
			private static void StartPatch(ref StartOfRound __instance)
			{
				if (((NetworkBehaviour)__instance).IsServer && (Object)(object)MimicNetworker.Instance == (Object)null)
				{
					GameObject val = Object.Instantiate<GameObject>(MimicNetworkerPrefab);
					val.GetComponent<NetworkObject>().Spawn(true);
					MimicNetworker.SpawnWeight0.Value = SpawnRates[0];
					MimicNetworker.SpawnWeight1.Value = SpawnRates[1];
					MimicNetworker.SpawnWeight2.Value = SpawnRates[2];
					MimicNetworker.SpawnWeight3.Value = SpawnRates[3];
					MimicNetworker.SpawnWeight4.Value = SpawnRates[4];
					MimicNetworker.SpawnWeightMax.Value = SpawnRates[5];
					MimicNetworker.SpawnRateDynamic.Value = DynamicSpawnRate;
				}
			}
		}

		[HarmonyPatch(typeof(Terminal))]
		internal class TerminalPatch
		{
			[HarmonyPatch("Start")]
			[HarmonyPostfix]
			private static void StartPatch(ref StartOfRound __instance)
			{
				//IL_0099: Unknown result type (might be due to invalid IL or missing references)
				//IL_009e: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b8: Expected O, but got Unknown
				//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e1: Expected O, but got Unknown
				Terminal val = Object.FindObjectOfType<Terminal>();
				if (!Object.op_Implicit((Object)(object)val.enemyFiles.Find((TerminalNode node) => node.creatureName == "Mimics")))
				{
					MimicCreatureID = val.enemyFiles.Count;
					MimicFile.creatureFileID = MimicCreatureID;
					val.enemyFiles.Add(MimicFile);
					TerminalKeyword val2 = val.terminalNodes.allKeywords.First((TerminalKeyword keyword) => keyword.word == "info");
					TerminalKeyword val3 = new TerminalKeyword
					{
						word = "mimics",
						isVerb = false,
						defaultVerb = val2
					};
					List<CompatibleNoun> list = val2.compatibleNouns.ToList();
					list.Add(new CompatibleNoun
					{
						noun = val3,
						result = MimicFile
					});
					val2.compatibleNouns = list.ToArray();
					List<TerminalKeyword> list2 = val.terminalNodes.allKeywords.ToList();
					list2.Add(val3);
					val.terminalNodes.allKeywords = list2.ToArray();
				}
			}
		}

		[HarmonyPatch(typeof(RoundManager))]
		internal class RoundManagerPatch
		{
			[HarmonyPatch("SetExitIDs")]
			[HarmonyPostfix]
			private static void SetExitIDsPatch(ref RoundManager __instance, Vector3 mainEntrancePosition)
			{
				//IL_058c: Unknown result type (might be due to invalid IL or missing references)
				//IL_059d: Unknown result type (might be due to invalid IL or missing references)
				//IL_05a2: Unknown result type (might be due to invalid IL or missing references)
				//IL_05a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_05ac: Unknown result type (might be due to invalid IL or missing references)
				//IL_027d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0289: Unknown result type (might be due to invalid IL or missing references)
				//IL_029d: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_02de: Unknown result type (might be due to invalid IL or missing references)
				//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
				//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
				//IL_0302: Unknown result type (might be due to invalid IL or missing references)
				//IL_05bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_05c0: Unknown result type (might be due to invalid IL or missing references)
				//IL_05c2: Unknown result type (might be due to invalid IL or missing references)
				//IL_05c4: Unknown result type (might be due to invalid IL or missing references)
				//IL_05f9: Unknown result type (might be due to invalid IL or missing references)
				//IL_063a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0716: Unknown result type (might be due to invalid IL or missing references)
				//IL_071b: Unknown result type (might be due to invalid IL or missing references)
				//IL_071f: Unknown result type (might be due to invalid IL or missing references)
				//IL_072b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0730: Unknown result type (might be due to invalid IL or missing references)
				//IL_0734: Unknown result type (might be due to invalid IL or missing references)
				//IL_0739: Unknown result type (might be due to invalid IL or missing references)
				//IL_06d1: Unknown result type (might be due to invalid IL or missing references)
				//IL_0385: 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_039b: Unknown result type (might be due to invalid IL or missing references)
				//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_03a5: 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)
				//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
				//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_03da: Unknown result type (might be due to invalid IL or missing references)
				//IL_045c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0464: Unknown result type (might be due to invalid IL or missing references)
				//IL_046d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0477: Unknown result type (might be due to invalid IL or missing references)
				//IL_0829: Unknown result type (might be due to invalid IL or missing references)
				//IL_0833: Expected O, but got Unknown
				//IL_0931: Unknown result type (might be due to invalid IL or missing references)
				//IL_0958: Unknown result type (might be due to invalid IL or missing references)
				//IL_08d2: Unknown result type (might be due to invalid IL or missing references)
				//IL_08f9: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a0c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a33: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)MimicNetworker.Instance == (Object)null)
				{
					return;
				}
				MimicsAPI.MainAPI.RefreshMimicEventHandler();
				MimicDoor.allMimics = new List<MimicDoor>();
				int num = 0;
				Dungeon currentDungeon = __instance.dungeonGenerator.Generator.CurrentDungeon;
				if (!InteriorWhitelist.Contains(((Object)currentDungeon.DungeonFlow).name.ToLower().Trim()))
				{
					return;
				}
				int num2 = 0;
				int[] array = new int[6]
				{
					MimicNetworker.SpawnWeight0.Value,
					MimicNetworker.SpawnWeight1.Value,
					MimicNetworker.SpawnWeight2.Value,
					MimicNetworker.SpawnWeight3.Value,
					MimicNetworker.SpawnWeight4.Value,
					MimicNetworker.SpawnWeightMax.Value
				};
				int num3 = 0;
				int[] array2 = array;
				foreach (int num4 in array2)
				{
					num3 += num4;
				}
				Random random = new Random(StartOfRound.Instance.randomMapSeed + 753);
				int num5 = random.Next(0, num3);
				int num6 = 0;
				for (int j = 0; j < array.Length; j++)
				{
					if (num5 < array[j] + num6)
					{
						num2 = j;
						break;
					}
					num6 += array[j];
				}
				if (num2 == 5)
				{
					num2 = 999;
				}
				EntranceTeleport[] array3 = Object.FindObjectsOfType<EntranceTeleport>(false);
				int num7 = (array3.Length - 2) / 2;
				if (MimicNetworker.SpawnRateDynamic.Value && num2 < num7 && num7 > 1)
				{
					num2 += random.Next(0, 2);
				}
				if (MimicNetworker.SpawnRateDynamic.Value && currentDungeon.AllTiles.Count > 100)
				{
					num2 += random.Next(0, 2);
				}
				if (((NetworkBehaviour)RoundManager.Instance).IsOwner)
				{
					Debug.Log((object)("I am the host. Desired mimics: " + num2));
				}
				else
				{
					Debug.Log((object)("I am the client. Desired mimics: " + num2));
				}
				List<Doorway> list = new List<Doorway>();
				Bounds val2 = default(Bounds);
				foreach (Tile allTile in currentDungeon.AllTiles)
				{
					foreach (Doorway unusedDoorway in allTile.UnusedDoorways)
					{
						if (!MimicsAPI.MainAPI.IgnoreDefaultPlacementValidation(unusedDoorway))
						{
							if (unusedDoorway.HasDoorPrefabInstance || (Object)(object)((Component)unusedDoorway).GetComponentInChildren<SpawnSyncedObject>(true) == (Object)null)
							{
								continue;
							}
							GameObject gameObject = ((Component)((Component)((Component)unusedDoorway).GetComponentInChildren<SpawnSyncedObject>(true)).transform.parent).gameObject;
							if (!((Object)gameObject).name.StartsWith("AlleyExitDoorContainer") || gameObject.activeSelf)
							{
								continue;
							}
							bool flag = false;
							Matrix4x4 val = Matrix4x4.TRS(((Component)unusedDoorway).transform.position, ((Component)unusedDoorway).transform.rotation, new Vector3(1f, 1f, 1f));
							((Bounds)(ref val2))..ctor(new Vector3(0f, 1.5f, 5.5f), new Vector3(2f, 6f, 8f));
							((Bounds)(ref val2)).center = ((Matrix4x4)(ref val)).MultiplyPoint3x4(((Bounds)(ref val2)).center);
							Collider[] array4 = Physics.OverlapBox(((Bounds)(ref val2)).center, ((Bounds)(ref val2)).extents, ((Component)unusedDoorway).transform.rotation, LayerMask.GetMask(new string[3] { "Room", "Railing", "MapHazards" }));
							Collider[] array5 = array4;
							int num8 = 0;
							if (num8 < array5.Length)
							{
								Collider val3 = array5[num8];
								flag = true;
							}
							if (flag)
							{
								continue;
							}
							foreach (Tile allTile2 in currentDungeon.AllTiles)
							{
								if (!((Object)(object)allTile == (Object)(object)allTile2))
								{
									Vector3 origin = ((Component)unusedDoorway).transform.position + 5f * ((Component)unusedDoorway).transform.forward;
									Bounds val4 = UnityUtil.CalculateProxyBounds(((Component)allTile2).gameObject, true, Vector3.up);
									Ray val5 = default(Ray);
									((Ray)(ref val5)).origin = origin;
									((Ray)(ref val5)).direction = Vector3.up;
									if (((Bounds)(ref val4)).IntersectRay(val5) && (((Object)allTile2).name.Contains("Catwalk") || ((Object)allTile2).name.Contains("LargeForkTile") || ((Object)allTile2).name.Contains("4x4BigStair") || ((Object)allTile2).name.Contains("ElevatorConnector") || (((Object)allTile2).name.Contains("StartRoom") && !((Object)allTile2).name.Contains("Manor"))))
									{
										flag = true;
									}
									val5 = default(Ray);
									((Ray)(ref val5)).origin = origin;
									((Ray)(ref val5)).direction = Vector3.down;
									if (((Bounds)(ref val4)).IntersectRay(val5) && (((Object)allTile2).name.Contains("MediumRoomHallway1B") || ((Object)allTile2).name.Contains("LargeForkTile") || ((Object)allTile2).name.Contains("4x4BigStair") || ((Object)allTile2).name.Contains("ElevatorConnector") || ((Object)allTile2).name.Contains("StartRoom")))
									{
										flag = true;
									}
								}
							}
							if (flag)
							{
								continue;
							}
						}
						if (MimicsAPI.MainAPI.IsPlacementValid(unusedDoorway))
						{
							list.Add(unusedDoorway);
						}
					}
				}
				Shuffle(list, StartOfRound.Instance.randomMapSeed);
				List<Vector3> list2 = new List<Vector3>();
				foreach (Doorway item in list)
				{
					if (num >= num2)
					{
						break;
					}
					bool flag2 = false;
					Vector3 val6 = ((Component)item).transform.position + 5f * ((Component)item).transform.forward;
					foreach (Vector3 item2 in list2)
					{
						if (Vector3.Distance(val6, item2) < 4f)
						{
							flag2 = true;
							break;
						}
					}
					if (flag2)
					{
						continue;
					}
					list2.Add(val6);
					GameObject gameObject2 = ((Component)((Component)((Component)item).GetComponentInChildren<SpawnSyncedObject>(true)).transform.parent).gameObject;
					GameObject val7 = Object.Instantiate<GameObject>(MimicPrefab, ((Component)item).transform);
					val7.transform.position = gameObject2.transform.position;
					MimicDoor component = val7.GetComponent<MimicDoor>();
					component.scanNode.creatureScanID = MimicCreatureID;
					AudioSource[] componentsInChildren = val7.GetComponentsInChildren<AudioSource>(true);
					foreach (AudioSource val8 in componentsInChildren)
					{
						val8.volume = MimicVolume / 100f;
						val8.outputAudioMixerGroup = StartOfRound.Instance.ship3DAudio.outputAudioMixerGroup;
					}
					if (SpawnRates[5] == 9753 && num == 0)
					{
						val7.transform.position = new Vector3(-7f, 0f, -10f);
					}
					MimicDoor.allMimics.Add(component);
					component.mimicIndex = num;
					num++;
					GameObject gameObject3 = ((Component)((Component)item).transform.GetChild(0)).gameObject;
					gameObject3.SetActive(false);
					Bounds bounds = ((Collider)component.frameBox).bounds;
					Vector3 center = ((Bounds)(ref bounds)).center;
					bounds = ((Collider)component.frameBox).bounds;
					Collider[] array6 = Physics.OverlapBox(center, ((Bounds)(ref bounds)).extents, Quaternion.identity);
					foreach (Collider val9 in array6)
					{
						if (((Object)((Component)val9).gameObject).name.Contains("Shelf"))
						{
							((Component)val9).gameObject.SetActive(false);
						}
					}
					Light componentInChildren = gameObject2.GetComponentInChildren<Light>(true);
					((Component)componentInChildren).transform.parent.SetParent(val7.transform);
					MeshRenderer[] componentsInChildren2 = val7.GetComponentsInChildren<MeshRenderer>();
					MeshRenderer[] array7 = componentsInChildren2;
					foreach (MeshRenderer val10 in array7)
					{
						Material[] materials = ((Renderer)val10).materials;
						foreach (Material val11 in materials)
						{
							val11.shader = ((Renderer)gameObject3.GetComponentInChildren<MeshRenderer>(true)).material.shader;
							val11.renderQueue = ((Renderer)gameObject3.GetComponentInChildren<MeshRenderer>(true)).material.renderQueue;
						}
					}
					component.interactTrigger.onInteract = new InteractEvent();
					((UnityEvent<PlayerControllerB>)(object)component.interactTrigger.onInteract).AddListener((UnityAction<PlayerControllerB>)component.TouchMimic);
					MimicsAPI.MainAPI.OnMimicCreated(component, item);
					if (MimicsAPI.MainAPI.OverrideDefaultImperfectionCreation(component, item))
					{
						MimicsAPI.MainAPI.OnMimicCreateImperfections(component);
						break;
					}
					if (MimicPerfection)
					{
						continue;
					}
					component.interactTrigger.timeToHold = 0.9f;
					if (!ColorBlindMode)
					{
						if ((StartOfRound.Instance.randomMapSeed + num) % 2 == 0)
						{
							((Renderer)val7.GetComponentsInChildren<MeshRenderer>()[0]).material.color = new Color(0.490566f, 0.1226415f, 0.1302275f);
							((Renderer)val7.GetComponentsInChildren<MeshRenderer>()[1]).material.color = new Color(0.4339623f, 0.1043965f, 0.1150277f);
							componentInChildren.colorTemperature = 1250f;
						}
						else
						{
							((Renderer)val7.GetComponentsInChildren<MeshRenderer>()[0]).material.color = new Color(0.5f, 0.1580188f, 0.1657038f);
							((Renderer)val7.GetComponentsInChildren<MeshRenderer>()[1]).material.color = new Color(43f / 106f, 0.1358579f, 0.1393619f);
							componentInChildren.colorTemperature = 1300f;
						}
					}
					else if ((StartOfRound.Instance.randomMapSeed + num) % 2 == 0)
					{
						component.interactTrigger.timeToHold = 1.1f;
					}
					else
					{
						component.interactTrigger.timeToHold = 1f;
					}
					if (!EasyMode)
					{
						continue;
					}
					Random random2 = new Random(StartOfRound.Instance.randomMapSeed + num);
					switch (random2.Next(0, 4))
					{
					case 0:
						if (!ColorBlindMode)
						{
							((Renderer)val7.GetComponentsInChildren<MeshRenderer>()[0]).material.color = new Color(0.489f, 0.2415526f, 0.1479868f);
							((Renderer)val7.GetComponentsInChildren<MeshRenderer>()[1]).material.color = new Color(0.489f, 0.2415526f, 0.1479868f);
						}
						else
						{
							component.interactTrigger.timeToHold = 1.5f;
						}
						break;
					case 1:
						component.interactTrigger.hoverTip = "Feed : [LMB]";
						component.interactTrigger.holdTip = "Feed : [LMB]";
						break;
					case 2:
						component.interactTrigger.hoverIcon = component.LostFingersIcon;
						break;
					case 3:
						component.interactTrigger.holdTip = "DIE : [LMB]";
						component.interactTrigger.timeToHold = 0.5f;
						break;
					default:
						component.interactTrigger.hoverTip = "BUG, REPORT TO DEVELOPER";
						break;
					}
				}
			}
		}

		[HarmonyPatch(typeof(SprayPaintItem))]
		internal class SprayPaintItemPatch
		{
			private static FieldInfo SprayHit = typeof(SprayPaintItem).GetField("sprayHit", BindingFlags.Instance | BindingFlags.NonPublic);

			[HarmonyPatch("SprayPaintClientRpc")]
			[HarmonyPostfix]
			private static void SprayPaintClientRpcPatch(SprayPaintItem __instance, Vector3 sprayPos, Vector3 sprayRot)
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)MimicNetworker.Instance == (Object)null)
				{
					return;
				}
				RaycastHit val = (RaycastHit)SprayHit.GetValue(__instance);
				if ((Object)(object)((RaycastHit)(ref val)).collider != (Object)null && ((Object)((RaycastHit)(ref val)).collider).name == "MimicSprayCollider")
				{
					MimicDoor component = ((Component)((Component)((RaycastHit)(ref val)).collider).transform.parent.parent).GetComponent<MimicDoor>();
					component.sprayCount++;
					if (component.sprayCount > 8)
					{
						MimicNetworker.Instance.MimicAddAnger(1, component.mimicIndex);
					}
				}
			}
		}

		[HarmonyPatch(typeof(LockPicker))]
		internal class LockPickerPatch
		{
			private static FieldInfo RayHit = typeof(LockPicker).GetField("hit", BindingFlags.Instance | BindingFlags.NonPublic);

			[HarmonyPatch("ItemActivate")]
			[HarmonyPostfix]
			private static void ItemActivatePatch(LockPicker __instance, bool used, bool buttonDown = true)
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: 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)
				if ((Object)(object)MimicNetworker.Instance == (Object)null)
				{
					return;
				}
				RaycastHit val = (RaycastHit)RayHit.GetValue(__instance);
				if (!((Object)(object)((GrabbableObject)__instance).playerHeldBy == (Object)null) && !((object)(RaycastHit)(ref val)).Equals((object)default(RaycastHit)) && !((Object)(object)((RaycastHit)(ref val)).transform.parent == (Object)null))
				{
					Transform parent = ((RaycastHit)(ref val)).transform.parent;
					if (((Object)parent).name.StartsWith("MimicDoor"))
					{
						MimicNetworker.Instance.MimicLockPick(__instance, ((Component)parent).GetComponent<MimicDoor>().mimicIndex);
					}
				}
			}
		}

		private const string modGUID = "x753.Mimics";

		private const string modName = "Mimics";

		private const string modVersion = "2.6.4";

		private readonly Harmony harmony = new Harmony("x753.Mimics");

		internal static ManualLogSource MimicsLogger;

		private static Mimics Instance;

		public static GameObject MimicPrefab;

		public static GameObject MimicNetworkerPrefab;

		public static TerminalNode MimicFile;

		public static int MimicCreatureID;

		public static int[] SpawnRates;

		public static bool MimicPerfection;

		public static bool UpgradeCompatibility;

		public static bool EasyMode;

		public static bool ColorBlindMode;

		public static float MimicVolume;

		public static bool DynamicSpawnRate;

		public static List<string> InteriorWhitelist;

		private void Awake()
		{
			AssetBundle val = AssetBundle.LoadFromMemory(Resources.mimicdoor);
			MimicPrefab = val.LoadAsset<GameObject>("Assets/MimicDoor.prefab");
			MimicNetworkerPrefab = val.LoadAsset<GameObject>("Assets/MimicNetworker.prefab");
			MimicFile = val.LoadAsset<TerminalNode>("Assets/MimicFile.asset");
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			harmony.PatchAll();
			MimicsLogger = Logger.CreateLogSource("x753.Mimics");
			MimicsLogger.LogInfo((object)"Plugin Mimics is loaded!!");
			string value = ((BaseUnityPlugin)this).Config.Bind<string>("Compatibility", "Interiors Whitelist", "Level1Flow, Level1Flow3Exits, Level1FlowExtraLarge, Level2Flow, SDMLevel, OfficeDungeonFlow, TranquillityManorFlow", "Comma separated list of interiors that mimics can spawn in. Not all interiors will work.").Value;
			InteriorWhitelist = (from s in value.ToLower().Split(',')
				select s.Trim()).ToList();
			SpawnRates = new int[6]
			{
				((BaseUnityPlugin)this).Config.Bind<int>("Spawn Rate", "Zero Mimics", 23, "Weight of zero mimics spawning").Value,
				((BaseUnityPlugin)this).Config.Bind<int>("Spawn Rate", "One Mimic", 69, "Weight of one mimic spawning").Value,
				((BaseUnityPlugin)this).Config.Bind<int>("Spawn Rate", "Two Mimics", 7, "Weight of two mimics spawning").Value,
				((BaseUnityPlugin)this).Config.Bind<int>("Spawn Rate", "Three Mimics", 1, "Weight of three mimics spawning").Value,
				((BaseUnityPlugin)this).Config.Bind<int>("Spawn Rate", "Four Mimics", 0, "Weight of four mimics spawning").Value,
				((BaseUnityPlugin)this).Config.Bind<int>("Spawn Rate", "Maximum Mimics", 0, "Weight of maximum mimics spawning").Value
			};
			DynamicSpawnRate = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawn Rate", "Dynamic Spawn Rate", true, "Increases mimic spawn rate based on dungeon size and the number of instances of the real thing.").Value;
			MimicPerfection = ((BaseUnityPlugin)this).Config.Bind<bool>("Difficulty", "Perfect Mimics", false, "Select this if you want mimics to be the exact same color as the real thing. Overrides all difficulty settings.").Value;
			UpgradeCompatibility = ((BaseUnityPlugin)this).Config.Bind<bool>("Difficulty", "Upgrade Compatibility", false, "Mimics won't instantly attack when struck with a powerful blow, such as an upgraded shovel.").Value;
			EasyMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Difficulty", "Easy Mode", false, "Each mimic will have one of several possible imperfections to help you tell if it's a mimic.").Value;
			ColorBlindMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Difficulty", "Color Blind Mode", false, "Replaces all color differences with another way to differentiate mimics.").Value;
			MimicVolume = ((BaseUnityPlugin)this).Config.Bind<int>("General", "SFX Volume", 100, "Volume of the mimic's SFX (0-100)").Value;
			if (MimicVolume < 0f)
			{
				MimicVolume = 0f;
			}
			if (MimicVolume > 100f)
			{
				MimicVolume = 100f;
			}
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
		}

		public static void Shuffle<T>(IList<T> list, int seed)
		{
			Random random = new Random(seed);
			int num = list.Count;
			while (num > 1)
			{
				num--;
				int index = random.Next(num + 1);
				T value = list[index];
				list[index] = list[num];
				list[num] = value;
			}
		}
	}
	public class MimicNetworker : NetworkBehaviour
	{
		public static MimicNetworker Instance;

		public static NetworkVariable<int> SpawnWeight0 = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public static NetworkVariable<int> SpawnWeight1 = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public static NetworkVariable<int> SpawnWeight2 = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public static NetworkVariable<int> SpawnWeight3 = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public static NetworkVariable<int> SpawnWeight4 = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public static NetworkVariable<int> SpawnWeightMax = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public static NetworkVariable<bool> SpawnRateDynamic = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		private void Awake()
		{
			Instance = this;
		}

		public void MimicAttack(int playerId, int mimicIndex, bool ownerOnly = false)
		{
			if (((NetworkBehaviour)this).IsOwner)
			{
				Instance.MimicAttackClientRpc(playerId, mimicIndex);
			}
			else if (!ownerOnly)
			{
				Instance.MimicAttackServerRpc(playerId, mimicIndex);
			}
		}

		[ClientRpc]
		public void MimicAttackClientRpc(int playerId, int mimicIndex)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2885019175u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, playerId);
					BytePacker.WriteValueBitPacked(val2, mimicIndex);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2885019175u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
				{
					((MonoBehaviour)this).StartCoroutine(MimicDoor.allMimics[mimicIndex].Attack(playerId));
				}
			}
		}

		[ServerRpc(RequireOwnership = false)]
		public void MimicAttackServerRpc(int playerId, int mimicIndex)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val = default(ServerRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(1024971481u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, playerId);
					BytePacker.WriteValueBitPacked(val2, mimicIndex);
					((NetworkBehaviour)this).__endSendServerRpc(ref val2, 1024971481u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
				{
					Instance.MimicAttackClientRpc(playerId, mimicIndex);
				}
			}
		}

		public void MimicAddAnger(int amount, int mimicIndex)
		{
			if (((NetworkBehaviour)this).IsOwner)
			{
				Instance.MimicAddAngerClientRpc(amount, mimicIndex);
			}
			else
			{
				Instance.MimicAddAngerServerRpc(amount, mimicIndex);
			}
		}

		[ClientRpc]
		public void MimicAddAngerClientRpc(int amount, int mimicIndex)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1137632670u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, amount);
					BytePacker.WriteValueBitPacked(val2, mimicIndex);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1137632670u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
				{
					((MonoBehaviour)this).StartCoroutine(MimicDoor.allMimics[mimicIndex].AddAnger(amount));
				}
			}
		}

		[ServerRpc(RequireOwnership = false)]
		public void MimicAddAngerServerRpc(int amount, int mimicIndex)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val = default(ServerRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(669208889u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, amount);
					BytePacker.WriteValueBitPacked(val2, mimicIndex);
					((NetworkBehaviour)this).__endSendServerRpc(ref val2, 669208889u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
				{
					Instance.MimicAddAngerClientRpc(amount, mimicIndex);
				}
			}
		}

		public void MimicLockPick(LockPicker lockPicker, int mimicIndex, bool ownerOnly = false)
		{
			int playerId = (int)((GrabbableObject)lockPicker).playerHeldBy.playerClientId;
			if (((NetworkBehaviour)this).IsOwner)
			{
				Instance.MimicLockPickClientRpc(playerId, mimicIndex);
			}
			else if (!ownerOnly)
			{
				Instance.MimicLockPickServerRpc(playerId, mimicIndex);
			}
		}

		[ClientRpc]
		public void MimicLockPickClientRpc(int playerId, int mimicIndex)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3716888238u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, playerId);
					BytePacker.WriteValueBitPacked(val2, mimicIndex);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3716888238u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
				{
					((MonoBehaviour)this).StartCoroutine(MimicDoor.allMimics[mimicIndex].MimicLockPick(playerId));
				}
			}
		}

		[ServerRpc(RequireOwnership = false)]
		public void MimicLockPickServerRpc(int playerId, int mimicIndex)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val = default(ServerRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(1897916243u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, playerId);
					BytePacker.WriteValueBitPacked(val2, mimicIndex);
					((NetworkBehaviour)this).__endSendServerRpc(ref val2, 1897916243u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
				{
					Instance.MimicLockPickClientRpc(playerId, mimicIndex);
				}
			}
		}

		protected override void __initializeVariables()
		{
			if (SpawnWeight0 == null)
			{
				throw new Exception("MimicNetworker.SpawnWeight0 cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)SpawnWeight0).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)SpawnWeight0, "SpawnWeight0");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)SpawnWeight0);
			if (SpawnWeight1 == null)
			{
				throw new Exception("MimicNetworker.SpawnWeight1 cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)SpawnWeight1).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)SpawnWeight1, "SpawnWeight1");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)SpawnWeight1);
			if (SpawnWeight2 == null)
			{
				throw new Exception("MimicNetworker.SpawnWeight2 cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)SpawnWeight2).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)SpawnWeight2, "SpawnWeight2");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)SpawnWeight2);
			if (SpawnWeight3 == null)
			{
				throw new Exception("MimicNetworker.SpawnWeight3 cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)SpawnWeight3).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)SpawnWeight3, "SpawnWeight3");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)SpawnWeight3);
			if (SpawnWeight4 == null)
			{
				throw new Exception("MimicNetworker.SpawnWeight4 cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)SpawnWeight4).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)SpawnWeight4, "SpawnWeight4");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)SpawnWeight4);
			if (SpawnWeightMax == null)
			{
				throw new Exception("MimicNetworker.SpawnWeightMax cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)SpawnWeightMax).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)SpawnWeightMax, "SpawnWeightMax");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)SpawnWeightMax);
			if (SpawnRateDynamic == null)
			{
				throw new Exception("MimicNetworker.SpawnRateDynamic cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)SpawnRateDynamic).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)SpawnRateDynamic, "SpawnRateDynamic");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)SpawnRateDynamic);
			((NetworkBehaviour)this).__initializeVariables();
		}

		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeRPCS_MimicNetworker()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			NetworkManager.__rpc_func_table.Add(2885019175u, new RpcReceiveHandler(__rpc_handler_2885019175));
			NetworkManager.__rpc_func_table.Add(1024971481u, new RpcReceiveHandler(__rpc_handler_1024971481));
			NetworkManager.__rpc_func_table.Add(1137632670u, new RpcReceiveHandler(__rpc_handler_1137632670));
			NetworkManager.__rpc_func_table.Add(669208889u, new RpcReceiveHandler(__rpc_handler_669208889));
			NetworkManager.__rpc_func_table.Add(3716888238u, new RpcReceiveHandler(__rpc_handler_3716888238));
			NetworkManager.__rpc_func_table.Add(1897916243u, new RpcReceiveHandler(__rpc_handler_1897916243));
		}

		private static void __rpc_handler_2885019175(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				int playerId = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref playerId);
				int mimicIndex = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref mimicIndex);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((MimicNetworker)(object)target).MimicAttackClientRpc(playerId, mimicIndex);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_1024971481(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				int playerId = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref playerId);
				int mimicIndex = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref mimicIndex);
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((MimicNetworker)(object)target).MimicAttackServerRpc(playerId, mimicIndex);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_1137632670(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				int amount = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref amount);
				int mimicIndex = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref mimicIndex);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((MimicNetworker)(object)target).MimicAddAngerClientRpc(amount, mimicIndex);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_669208889(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				int amount = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref amount);
				int mimicIndex = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref mimicIndex);
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((MimicNetworker)(object)target).MimicAddAngerServerRpc(amount, mimicIndex);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_3716888238(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				int playerId = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref playerId);
				int mimicIndex = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref mimicIndex);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((MimicNetworker)(object)target).MimicLockPickClientRpc(playerId, mimicIndex);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_1897916243(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				int playerId = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref playerId);
				int mimicIndex = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref mimicIndex);
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((MimicNetworker)(object)target).MimicLockPickServerRpc(playerId, mimicIndex);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		protected internal override string __getTypeName()
		{
			return "MimicNetworker";
		}
	}
	public class MimicDoor : MonoBehaviour
	{
		public GameObject playerTarget;

		public BoxCollider frameBox;

		public Sprite LostFingersIcon;

		public Animator mimicAnimator;

		public GameObject grabPoint;

		public InteractTrigger interactTrigger;

		public ScanNodeProperties scanNode;

		public int anger;

		public bool angering;

		public int sprayCount;

		private bool attacking;

		public static List<MimicDoor> allMimics;

		public int mimicIndex;

		private static MethodInfo RetractClaws = typeof(LockPicker).GetMethod("RetractClaws", BindingFlags.Instance | BindingFlags.NonPublic);

		public void TouchMimic(PlayerControllerB player)
		{
			if (!attacking)
			{
				MimicNetworker.Instance.MimicAttack((int)player.playerClientId, mimicIndex);
			}
		}

		public IEnumerator Attack(int playerId)
		{
			PlayerControllerB player = StartOfRound.Instance.allPlayerScripts[playerId];
			MimicsAPI.MainAPI.OnMimicAttackStart(this, player);
			attacking = true;
			interactTrigger.interactable = false;
			mimicAnimator.SetTrigger("Attack");
			playerTarget.transform.position = ((Component)player).transform.position;
			yield return (object)new WaitForSeconds(0.1f);
			playerTarget.transform.position = ((Component)player).transform.position;
			yield return (object)new WaitForSeconds(0.1f);
			playerTarget.transform.position = ((Component)player).transform.position;
			yield return (object)new WaitForSeconds(0.1f);
			playerTarget.transform.position = ((Component)player).transform.position;
			yield return (object)new WaitForSeconds(0.1f);
			float num = Vector3.Distance(((Component)GameNetworkManager.Instance.localPlayerController).transform.position, ((Component)frameBox).transform.position);
			if (num < 8f)
			{
				HUDManager.Instance.ShakeCamera((ScreenShakeType)1);
			}
			else if (num < 14f)
			{
				HUDManager.Instance.ShakeCamera((ScreenShakeType)0);
			}
			yield return (object)new WaitForSeconds(0.2f);
			if (((NetworkBehaviour)player).IsOwner && Vector3.Distance(((Component)player).transform.position, ((Component)this).transform.position) < 8.45f)
			{
				player.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 0, default(Vector3));
			}
			float startTime = Time.timeSinceLevelLoad;
			yield return (object)new WaitUntil((Func<bool>)(() => (Object)(object)player.deadBody != (Object)null || Time.timeSinceLevelLoad - startTime > 4f));
			if ((Object)(object)player.deadBody != (Object)null)
			{
				player.deadBody.attachedTo = grabPoint.transform;
				player.deadBody.attachedLimb = player.deadBody.bodyParts[5];
				player.deadBody.matchPositionExactly = true;
				for (int i = 0; i < player.deadBody.bodyParts.Length; i++)
				{
					((Component)player.deadBody.bodyParts[i]).GetComponent<Collider>().excludeLayers = LayerMask.op_Implicit(-1);
				}
			}
			yield return (object)new WaitForSeconds(2f);
			if ((Object)(object)player.deadBody != (Object)null)
			{
				player.deadBody.attachedTo = null;
				player.deadBody.attachedLimb = null;
				player.deadBody.matchPositionExactly = false;
				((Component)((Component)player.deadBody).transform.GetChild(0)).gameObject.SetActive(false);
				player.deadBody = null;
			}
			yield return (object)new WaitForSeconds(4.5f);
			attacking = false;
			interactTrigger.interactable = true;
			MimicsAPI.MainAPI.OnMimicAttackEnd(this);
		}

		public IEnumerator MimicLockPick(int playerId)
		{
			if (angering || attacking)
			{
				yield break;
			}
			LockPicker lockPicker = default(LockPicker);
			ref LockPicker reference = ref lockPicker;
			GrabbableObject currentlyHeldObjectServer = StartOfRound.Instance.allPlayerScripts[playerId].currentlyHeldObjectServer;
			reference = (LockPicker)(object)((currentlyHeldObjectServer is LockPicker) ? currentlyHeldObjectServer : null);
			if ((Object)(object)lockPicker == (Object)null)
			{
				yield break;
			}
			attacking = true;
			interactTrigger.interactable = false;
			AudioSource component = ((Component)lockPicker).GetComponent<AudioSource>();
			component.PlayOneShot(lockPicker.placeLockPickerClips[Random.Range(0, lockPicker.placeLockPickerClips.Length)]);
			lockPicker.armsAnimator.SetBool("mounted", true);
			lockPicker.armsAnimator.SetBool("picking", true);
			component.Play();
			component.pitch = Random.Range(0.94f, 1.06f);
			lockPicker.isOnDoor = true;
			lockPicker.isPickingLock = true;
			((GrabbableObject)lockPicker).grabbable = false;
			if (((NetworkBehaviour)lockPicker).IsOwner)
			{
				((GrabbableObject)lockPicker).playerHeldBy.DiscardHeldObject(true, ((NetworkBehaviour)MimicNetworker.Instance).NetworkObject, ((Component)this).transform.position + ((Component)this).transform.up * 1.5f - ((Component)this).transform.forward * 1.15f, true);
			}
			float startTime = Time.timeSinceLevelLoad;
			yield return (object)new WaitUntil((Func<bool>)(() => !((GrabbableObject)lockPicker).isHeld || Time.timeSinceLevelLoad - startTime > 10f));
			((Component)lockPicker).transform.localEulerAngles = new Vector3(((Component)this).transform.eulerAngles.x, ((Component)this).transform.eulerAngles.y + 90f, ((Component)this).transform.eulerAngles.z);
			yield return (object)new WaitForSeconds(5f);
			RetractClaws.Invoke(lockPicker, null);
			((Component)lockPicker).transform.SetParent((Transform)null);
			((GrabbableObject)lockPicker).startFallingPosition = ((Component)lockPicker).transform.position;
			((GrabbableObject)lockPicker).FallToGround(false);
			((GrabbableObject)lockPicker).grabbable = true;
			yield return (object)new WaitForSeconds(1f);
			anger = 3;
			attacking = false;
			interactTrigger.interactable = false;
			PlayerControllerB val = null;
			float num = 9999f;
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val2 in allPlayerScripts)
			{
				float num2 = Vector3.Distance(((Component)this).transform.position, ((Component)val2).transform.position);
				if (num2 < num)
				{
					num = num2;
					val = val2;
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				MimicNetworker.Instance.MimicAttackClientRpc((int)val.playerClientId, mimicIndex);
			}
			else
			{
				interactTrigger.interactable = true;
			}
		}

		public IEnumerator AddAnger(int amount)
		{
			if (angering || attacking)
			{
				yield break;
			}
			angering = true;
			anger += amount;
			if (anger == 1)
			{
				Sprite oldIcon2 = interactTrigger.hoverIcon;
				interactTrigger.hoverIcon = LostFingersIcon;
				mimicAnimator.SetTrigger("Growl");
				yield return (object)new WaitForSeconds(2.75f);
				interactTrigger.hoverIcon = oldIcon2;
				sprayCount = 0;
				angering = false;
				yield break;
			}
			if (anger == 2)
			{
				interactTrigger.holdTip = "DIE : [LMB]";
				interactTrigger.timeToHold = 0.25f;
				Sprite oldIcon2 = interactTrigger.hoverIcon;
				interactTrigger.hoverIcon = LostFingersIcon;
				mimicAnimator.SetTrigger("Growl");
				yield return (object)new WaitForSeconds(2.75f);
				interactTrigger.hoverIcon = oldIcon2;
				sprayCount = 0;
				angering = false;
				yield break;
			}
			if (anger > 2)
			{
				PlayerControllerB val = null;
				float num = 9999f;
				PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
				foreach (PlayerControllerB val2 in allPlayerScripts)
				{
					float num2 = Vector3.Distance(((Component)this).transform.position, ((Component)val2).transform.position);
					if (num2 < num)
					{
						num = num2;
						val = val2;
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					MimicNetworker.Instance.MimicAttackClientRpc((int)val.playerClientId, mimicIndex);
				}
			}
			sprayCount = 0;
			angering = false;
		}
	}
	public class MimicCollider : MonoBehaviour, IHittable
	{
		public MimicDoor mimic;

		bool IHittable.Hit(int force, Vector3 hitDirection, PlayerControllerB playerWhoHit = null, bool playHitSFX = false, int hitID = -1)
		{
			if (Mimics.UpgradeCompatibility)
			{
				force = 1;
			}
			MimicNetworker.Instance.MimicAddAnger(force, mimic.mimicIndex);
			return true;
		}
	}
	public class MimicListener : MonoBehaviour, INoiseListener
	{
		public MimicDoor mimic;

		private int tolerance = 100;

		void INoiseListener.DetectNoise(Vector3 noisePosition, float noiseLoudness, int timesPlayedInOneSpot, int noiseID)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if ((noiseLoudness >= 0.9f || noiseID == 101158) && Vector3.Distance(noisePosition, ((Component)mimic).transform.position) < 5f)
			{
				switch (noiseID)
				{
				case 75:
					tolerance--;
					break;
				case 5:
					tolerance -= 15;
					break;
				case 101158:
					tolerance -= 35;
					break;
				default:
					tolerance -= 30;
					break;
				}
				if (tolerance <= 0)
				{
					tolerance = 100;
					MimicNetworker.Instance.MimicAddAnger(1, mimic.mimicIndex);
				}
			}
		}
	}
}
namespace Mimics.API
{
	public static class MimicsAPI
	{
		private static MainMimicsAPI _API;

		internal static MainMimicsAPI MainAPI
		{
			get
			{
				if (_API == null)
				{
					_API = new MainMimicsAPI();
				}
				return _API;
			}
		}

		public static IMimicsAPI GetAPI()
		{
			return MainAPI;
		}
	}
	public interface IMimicsAPI
	{
		void RegisterMimicEventHandler(MimicEventHandler handler);

		MimicEventHandler GetCurrentMimicEventHandler();
	}
	internal class MainMimicsAPI : IMimicsAPI
	{
		internal List<MimicEventHandler> mimicEventHandlers = new List<MimicEventHandler>();

		internal MimicEventHandler _currentMimicEventHandler;

		public void RegisterMimicEventHandler(MimicEventHandler handler)
		{
			Mimics.MimicsLogger.LogInfo((object)("Registered handler for " + handler.ModGUID));
			mimicEventHandlers.Add(handler);
		}

		public MimicEventHandler GetCurrentMimicEventHandler()
		{
			return _currentMimicEventHandler;
		}

		internal void RefreshMimicEventHandler()
		{
			_currentMimicEventHandler = null;
			foreach (MimicEventHandler mimicEventHandler in mimicEventHandlers)
			{
				try
				{
					if (mimicEventHandler.IsMyInteriorLoaded && (_currentMimicEventHandler == null || mimicEventHandler.Priority > _currentMimicEventHandler.Priority))
					{
						_currentMimicEventHandler = mimicEventHandler;
					}
				}
				catch (Exception ex)
				{
					string text = ((_currentMimicEventHandler != null) ? _currentMimicEventHandler.ModGUID : "NULL");
					Mimics.MimicsLogger.LogError((object)("Error with IsMyInteriorLoaded/Priority function for handler " + mimicEventHandler.ModGUID + " or " + text));
					Mimics.MimicsLogger.LogError((object)ex.ToString());
				}
			}
		}

		internal bool IgnoreDefaultPlacementValidation(Doorway doorway)
		{
			try
			{
				if (_currentMimicEventHandler == null)
				{
					return false;
				}
				return _currentMimicEventHandler.IgnoreDefaultPlacementValidation(doorway);
			}
			catch (Exception ex)
			{
				Mimics.MimicsLogger.LogError((object)("Error with IgnoreDefaultPlacementValidation function for handler " + _currentMimicEventHandler.ModGUID));
				Mimics.MimicsLogger.LogError((object)ex.ToString());
			}
			return false;
		}

		internal bool IsPlacementValid(Doorway doorway)
		{
			try
			{
				if (_currentMimicEventHandler == null)
				{
					return true;
				}
				return _currentMimicEventHandler.IsPlacementValid(doorway);
			}
			catch (Exception ex)
			{
				Mimics.MimicsLogger.LogError((object)("Error with IsPlacementValid function for handler " + _currentMimicEventHandler.ModGUID));
				Mimics.MimicsLogger.LogError((object)ex.ToString());
			}
			return true;
		}

		internal bool OverrideDefaultImperfectionCreation(MimicDoor mimicDoor, Doorway doorway)
		{
			try
			{
				if (_currentMimicEventHandler == null)
				{
					return false;
				}
				return _currentMimicEventHandler.OverrideDefaultImperfectionCreation(mimicDoor, doorway);
			}
			catch (Exception ex)
			{
				Mimics.MimicsLogger.LogError((object)("Error with OverrideDefaultImperfectionCreation function for handler " + _currentMimicEventHandler.ModGUID));
				Mimics.MimicsLogger.LogError((object)ex.ToString());
			}
			return false;
		}

		internal void OnMimicCreated(MimicDoor mimicDoor, Doorway doorway)
		{
			try
			{
				_currentMimicEventHandler?.OnMimicCreated(mimicDoor, doorway);
			}
			catch (Exception ex)
			{
				Mimics.MimicsLogger.LogError((object)("Error with OnMimicCreated function for handler " + _currentMimicEventHandler.ModGUID));
				Mimics.MimicsLogger.LogError((object)ex.ToString());
			}
		}

		internal void OnMimicCreateImperfections(MimicDoor mimicDoor)
		{
			try
			{
				_currentMimicEventHandler?.OnMimicCreateImperfections(mimicDoor);
			}
			catch (Exception ex)
			{
				Mimics.MimicsLogger.LogError((object)("Error with OnMimicCreateImperfections function for handler " + _currentMimicEventHandler.ModGUID));
				Mimics.MimicsLogger.LogError((object)ex.ToString());
			}
		}

		internal void OnMimicAttackStart(MimicDoor mimicDoor, PlayerControllerB playerToAttack)
		{
			try
			{
				_currentMimicEventHandler?.OnMimicAttackStart(mimicDoor, playerToAttack);
			}
			catch (Exception ex)
			{
				Mimics.MimicsLogger.LogError((object)("Error with OnMimicAttackStart function for handler " + _currentMimicEventHandler.ModGUID));
				Mimics.MimicsLogger.LogError((object)ex.ToString());
			}
		}

		internal void OnMimicAttackEnd(MimicDoor mimicDoor)
		{
			try
			{
				_currentMimicEventHandler?.OnMimicAttackEnd(mimicDoor);
			}
			catch (Exception ex)
			{
				Mimics.MimicsLogger.LogError((object)("Error with OnMimicAttackEnd function for handler " + _currentMimicEventHandler.ModGUID));
				Mimics.MimicsLogger.LogError((object)ex.ToString());
			}
		}
	}
	public abstract class MimicEventHandler
	{
		public abstract string ModGUID { get; }

		public virtual bool IsMyInteriorLoaded => false;

		public virtual int Priority => 0;

		public virtual bool IsPlacementValid(Doorway doorway)
		{
			return true;
		}

		public virtual bool IgnoreDefaultPlacementValidation(Doorway doorway)
		{
			return false;
		}

		public virtual bool OverrideDefaultImperfectionCreation(MimicDoor mimicDoor, Doorway doorway)
		{
			return false;
		}

		public virtual void OnMimicCreated(MimicDoor mimicDoor, Doorway doorway)
		{
		}

		public virtual void OnMimicCreateImperfections(MimicDoor mimicDoor)
		{
		}

		public virtual void OnMimicAttackStart(MimicDoor mimicDoor, PlayerControllerB playerToAttack)
		{
		}

		public virtual void OnMimicAttackEnd(MimicDoor mimicDoor)
		{
		}
	}
}
namespace Mimics.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}

plugins/MoreBlood.dll

Decompiled 2 months ago
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using GameNetcodeStuff;
using HarmonyLib;
using MoreBlood.Config;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("MoreBlood")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MoreBlood")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("d1f1321d-30a3-4600-9bf8-1e69fe1abf8c")]
[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 MoreBlood
{
	[BepInPlugin("FlipMods.MoreBlood", "MoreBlood", "1.0.2")]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin instance;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			instance = this;
			_harmony = new Harmony("MoreBlood");
			ConfigSettings.BindConfigSettings();
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"MoreBlood loaded");
		}

		public static void Log(string message)
		{
			((BaseUnityPlugin)instance).Logger.LogInfo((object)message);
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "FlipMods.MoreBlood";

		public const string PLUGIN_NAME = "MoreBlood";

		public const string PLUGIN_VERSION = "1.0.2";
	}
}
namespace MoreBlood.Patches
{
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class MoreBloodPatcher
	{
		private static int bloodCount;

		[HarmonyPatch("DropBlood")]
		[HarmonyPostfix]
		public static void MoreBlood(PlayerControllerB __instance, Vector3 direction = default(Vector3), bool leaveBlood = true, bool leaveFootprint = false)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			bloodCount++;
			if (bloodCount < ConfigSettings.numBloodPools.Value)
			{
				__instance.DropBlood(direction, leaveBlood, leaveFootprint);
			}
			else
			{
				bloodCount = 0;
			}
		}

		[HarmonyPatch("RandomizeBloodRotationAndScale")]
		[HarmonyPostfix]
		public static void RandomizeBloodScale(ref Transform blood, PlayerControllerB __instance)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			Transform obj = blood;
			obj.localScale *= ConfigSettings.bloodScale.Value;
			blood.position += new Vector3((float)Random.Range(-1, 1) * ConfigSettings.bloodScale.Value, 0.55f, (float)Random.Range(-1, 1) * ConfigSettings.bloodScale.Value);
		}
	}
}
namespace MoreBlood.Config
{
	public static class ConfigSettings
	{
		public static ConfigEntry<float> bloodScale;

		public static ConfigEntry<int> numBloodPools;

		public static void BindConfigSettings()
		{
			Plugin.Log("BindingConfigs");
			bloodScale = ((BaseUnityPlugin)Plugin.instance).Config.Bind<float>("MoreBlood", "BloodScale", 4f, "The size of the blood pools");
			numBloodPools = ((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("MoreBlood", "NumberOfBloodPools", 4, "Max number of blood pools spread around the blood source.");
		}
	}
}

plugins/MoreCompany.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MoreCompany.Cosmetics;
using MoreCompany.Utils;
using Steamworks;
using Steamworks.Data;
using TMPro;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MoreCompany")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyCopyright("Copyright © NotNotSwipez 2023")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MoreCompany")]
[assembly: AssemblyTitle("MoreCompany")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 MoreCompany
{
	[HarmonyPatch(typeof(AudioMixer), "SetFloat")]
	public static class AudioMixerSetFloatPatch
	{
		public static bool Prefix(string name, ref float value)
		{
			if (name.StartsWith("PlayerVolume"))
			{
				string s = name.Replace("PlayerVolume", "");
				int num = int.Parse(s);
				if (!SoundManagerPatch.initialVolumeSet)
				{
					MainClass.StaticLogger.LogInfo((object)$"Setting initial volume for {num} to {value}");
					return true;
				}
				PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[num];
				if ((Object)(object)val != (Object)null)
				{
					AudioSource currentVoiceChatAudioSource = val.currentVoiceChatAudioSource;
					if (Object.op_Implicit((Object)(object)currentVoiceChatAudioSource))
					{
						currentVoiceChatAudioSource.volume = value / 16f;
					}
				}
				return false;
			}
			if (name.StartsWith("PlayerPitch"))
			{
				return MainClass.newPlayerCount <= 4;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(HUDManager), "AddTextToChatOnServer")]
	public static class SendChatToServerPatch
	{
		public static bool Prefix(string chatMessage, int playerId = -1)
		{
			if (((NetworkBehaviour)StartOfRound.Instance).IsHost && chatMessage.StartsWith("/mc") && DebugCommandRegistry.commandEnabled)
			{
				string text = chatMessage.Replace("/mc ", "");
				DebugCommandRegistry.HandleCommand(text.Split(' '));
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	public static class ClientReceiveMessagePatch
	{
		internal enum __RpcExecStage
		{
			None,
			Server,
			Client
		}

		internal static MethodInfo AddTextMessageServerRpc = AccessTools.Method(typeof(HUDManager), "AddTextMessageServerRpc", (Type[])null, (Type[])null);

		internal static FieldInfo __rpc_exec_stage = AccessTools.Field(typeof(NetworkBehaviour), "__rpc_exec_stage");

		[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
		[HarmonyPostfix]
		public static void ConnectClientToPlayerObject_Postfix(PlayerControllerB __instance)
		{
			MainClass.playerIdsAndCosmetics.Clear();
			string text = $"[morecompanycosmetics];{__instance.playerClientId};-1";
			foreach (string locallySelectedCosmetic in CosmeticRegistry.locallySelectedCosmetics)
			{
				if (CosmeticRegistry.cosmeticInstances.ContainsKey(locallySelectedCosmetic))
				{
					text = text + ";" + locallySelectedCosmetic;
				}
			}
			AddTextMessageServerRpc?.Invoke(HUDManager.Instance, new object[1] { text });
		}

		[HarmonyPatch(typeof(HUDManager), "AddTextMessageServerRpc")]
		[HarmonyPostfix]
		public static void AddTextMessageServerRpc_Postfix(HUDManager __instance, string chatMessage)
		{
			if (!chatMessage.StartsWith("[morecompanycosmetics]"))
			{
				return;
			}
			NetworkManager networkManager = ((NetworkBehaviour)__instance).NetworkManager;
			if ((Object)(object)networkManager == (Object)null || !networkManager.IsListening || (__RpcExecStage)__rpc_exec_stage.GetValue(__instance) == __RpcExecStage.Server || !networkManager.IsHost)
			{
				return;
			}
			string[] array = chatMessage.Split(';');
			int num = int.Parse(array[1]);
			int num2 = int.Parse(array[2]);
			if (num2 != -1)
			{
				return;
			}
			foreach (KeyValuePair<int, List<string>> item in MainClass.playerIdsAndCosmetics.ToList())
			{
				if (item.Key == num)
				{
					continue;
				}
				string text = $"[morecompanycosmetics];{item.Key};{num}";
				foreach (string item2 in item.Value)
				{
					text = text + ";" + item2;
				}
				AddTextMessageServerRpc?.Invoke(__instance, new object[1] { text });
			}
		}

		[HarmonyPatch(typeof(HUDManager), "AddTextMessageClientRpc")]
		[HarmonyPrefix]
		public static void AddTextMessageClientRpc_Prefix(HUDManager __instance, string chatMessage)
		{
			if (chatMessage.StartsWith("[morecompanycosmetics]"))
			{
				NetworkManager networkManager = ((NetworkBehaviour)__instance).NetworkManager;
				if (!((Object)(object)networkManager == (Object)null) && networkManager.IsListening && (__RpcExecStage)__rpc_exec_stage.GetValue(__instance) == __RpcExecStage.Client && (networkManager.IsClient || networkManager.IsHost))
				{
					HandleDataMessage(chatMessage);
				}
			}
		}

		internal static void HandleDataMessage(string chatMessage)
		{
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			string[] array = chatMessage.Split(';');
			int num = int.Parse(array[1]);
			int num2 = int.Parse(array[2]);
			array = array.Skip(3).ToArray();
			if (num2 != -1 && num2 != StartOfRound.Instance.thisClientPlayerId)
			{
				return;
			}
			CosmeticApplication cosmeticApplication = ((Component)((Component)StartOfRound.Instance.allPlayerScripts[num]).transform.Find("ScavengerModel").Find("metarig")).gameObject.GetComponent<CosmeticApplication>();
			if (!Object.op_Implicit((Object)(object)cosmeticApplication))
			{
				cosmeticApplication = ((Component)((Component)StartOfRound.Instance.allPlayerScripts[num]).transform.Find("ScavengerModel").Find("metarig")).gameObject.AddComponent<CosmeticApplication>();
			}
			cosmeticApplication.ClearCosmetics();
			List<string> list = new List<string>();
			string[] array2 = array;
			foreach (string text in array2)
			{
				list.Add(text);
				if (MainClass.cosmeticsSyncOther.Value)
				{
					cosmeticApplication.ApplyCosmetic(text, startEnabled: true);
				}
			}
			if (num == StartOfRound.Instance.thisClientPlayerId)
			{
				cosmeticApplication.ClearCosmetics();
			}
			foreach (CosmeticInstance spawnedCosmetic in cosmeticApplication.spawnedCosmetics)
			{
				Transform transform = ((Component)spawnedCosmetic).transform;
				transform.localScale *= 0.38f;
			}
			if (MainClass.playerIdsAndCosmetics.ContainsKey(num))
			{
				MainClass.playerIdsAndCosmetics[num] = list;
			}
			else
			{
				MainClass.playerIdsAndCosmetics.Add(num, list);
			}
		}
	}
	[HarmonyPatch]
	public static class PreventOldVersionChatSpamPatch
	{
		[HarmonyPatch(typeof(HUDManager), "AddChatMessage")]
		[HarmonyPrefix]
		public static bool AddChatMessage_Prefix(string chatMessage, string nameOfUserWhoTyped = "")
		{
			if (chatMessage.StartsWith("[replacewithdata]") || chatMessage.StartsWith("[morecompanycosmetics]"))
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(HUDManager), "AddPlayerChatMessageClientRpc")]
		[HarmonyPrefix]
		public static bool AddPlayerChatMessageClientRpc_Prefix(string chatMessage, int playerId)
		{
			if (chatMessage.StartsWith("[replacewithdata]") || chatMessage.StartsWith("[morecompanycosmetics]"))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	public class CosmeticPatches
	{
		public static bool CloneCosmeticsToNonPlayer(Transform cosmeticRoot, int playerClientId, bool detachedHead = false)
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			if (MainClass.cosmeticsSyncOther.Value && MainClass.playerIdsAndCosmetics.ContainsKey(playerClientId))
			{
				List<string> list = MainClass.playerIdsAndCosmetics[playerClientId];
				CosmeticApplication component = ((Component)cosmeticRoot).GetComponent<CosmeticApplication>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.ClearCosmetics();
					Object.Destroy((Object)(object)component);
				}
				component = ((Component)cosmeticRoot).gameObject.AddComponent<CosmeticApplication>();
				component.detachedHead = detachedHead;
				foreach (string item in list)
				{
					component.ApplyCosmetic(item, startEnabled: true);
				}
				foreach (CosmeticInstance spawnedCosmetic in component.spawnedCosmetics)
				{
					Transform transform = ((Component)spawnedCosmetic).transform;
					transform.localScale *= 0.38f;
				}
				return true;
			}
			return false;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "SpawnDeadBody")]
		[HarmonyPostfix]
		public static void SpawnDeadBody(ref PlayerControllerB __instance, int deathAnimation = 0)
		{
			if (!MainClass.cosmeticsDeadBodies.Value)
			{
				return;
			}
			Transform transform = ((Component)__instance.deadBody).transform;
			if (!((Object)(object)transform == (Object)null))
			{
				bool detachedHead = __instance.deadBody.detachedHead;
				if (deathAnimation == 4 || deathAnimation == 5)
				{
					detachedHead = true;
				}
				CloneCosmeticsToNonPlayer(transform, (int)__instance.playerClientId, detachedHead);
			}
		}

		[HarmonyPatch(typeof(MaskedPlayerEnemy), "SetEnemyOutside")]
		[HarmonyPostfix]
		public static void SetEnemyOutside(MaskedPlayerEnemy __instance)
		{
			if (MainClass.cosmeticsMaskedEnemy.Value && (Object)(object)__instance.mimickingPlayer != (Object)null)
			{
				Transform cosmeticRoot = ((Component)__instance).transform.Find("ScavengerModel").Find("metarig");
				CloneCosmeticsToNonPlayer(cosmeticRoot, (int)__instance.mimickingPlayer.playerClientId);
				((EnemyAI)__instance).skinnedMeshRenderers = ((Component)__instance).gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();
				((EnemyAI)__instance).meshRenderers = ((Component)__instance).gameObject.GetComponentsInChildren<MeshRenderer>();
			}
		}
	}
	public class DebugCommandRegistry
	{
		public static bool commandEnabled;

		public static void HandleCommand(string[] args)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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_0164: 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_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			if (!commandEnabled)
			{
				return;
			}
			PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController;
			switch (args[0])
			{
			case "money":
			{
				int groupCredits = int.Parse(args[1]);
				Terminal val5 = Resources.FindObjectsOfTypeAll<Terminal>().First();
				val5.groupCredits = groupCredits;
				break;
			}
			case "spawnscrap":
			{
				string text = "";
				for (int i = 1; i < args.Length; i++)
				{
					text = text + args[i] + " ";
				}
				text = text.Trim();
				Vector3 val = ((Component)localPlayerController).transform.position + ((Component)localPlayerController).transform.forward * 2f;
				SpawnableItemWithRarity val2 = null;
				foreach (SpawnableItemWithRarity item in StartOfRound.Instance.currentLevel.spawnableScrap)
				{
					if (item.spawnableItem.itemName.ToLower() == text.ToLower())
					{
						val2 = item;
						break;
					}
				}
				GameObject val3 = Object.Instantiate<GameObject>(val2.spawnableItem.spawnPrefab, val, Quaternion.identity, (Transform)null);
				GrabbableObject component = val3.GetComponent<GrabbableObject>();
				((Component)component).transform.rotation = Quaternion.Euler(component.itemProperties.restingRotation);
				component.fallTime = 0f;
				NetworkObject component2 = val3.GetComponent<NetworkObject>();
				component2.Spawn(false);
				break;
			}
			case "spawnenemy":
			{
				string text2 = "";
				for (int j = 1; j < args.Length; j++)
				{
					text2 = text2 + args[j] + " ";
				}
				text2 = text2.Trim();
				SpawnableEnemyWithRarity val4 = null;
				foreach (SpawnableEnemyWithRarity enemy in StartOfRound.Instance.currentLevel.Enemies)
				{
					if (enemy.enemyType.enemyName.ToLower() == text2.ToLower())
					{
						val4 = enemy;
						break;
					}
				}
				RoundManager.Instance.SpawnEnemyGameObject(((Component)localPlayerController).transform.position + ((Component)localPlayerController).transform.forward * 2f, 0f, -1, val4.enemyType);
				break;
			}
			case "listall":
				MainClass.StaticLogger.LogInfo((object)"Spawnable scrap:");
				foreach (SpawnableItemWithRarity item2 in StartOfRound.Instance.currentLevel.spawnableScrap)
				{
					MainClass.StaticLogger.LogInfo((object)item2.spawnableItem.itemName);
				}
				MainClass.StaticLogger.LogInfo((object)"Spawnable enemies:");
				{
					foreach (SpawnableEnemyWithRarity enemy2 in StartOfRound.Instance.currentLevel.Enemies)
					{
						MainClass.StaticLogger.LogInfo((object)enemy2.enemyType.enemyName);
					}
					break;
				}
			}
		}
	}
	[HarmonyPatch(typeof(ForestGiantAI), "LookForPlayers")]
	public static class LookForPlayersForestGiantPatch
	{
		public static void Prefix(ref ForestGiantAI __instance)
		{
			if (__instance.playerStealthMeters.Length != MainClass.newPlayerCount)
			{
				Array.Resize(ref __instance.playerStealthMeters, MainClass.newPlayerCount);
				for (int i = 0; i < MainClass.newPlayerCount; i++)
				{
					__instance.playerStealthMeters[i] = 0f;
				}
			}
		}
	}
	[HarmonyPatch(typeof(BlobAI), "Start")]
	public static class BlobAIStartPatch
	{
		public static void Postfix(ref BlobAI __instance)
		{
			Collider[] value = (Collider[])(object)new Collider[MainClass.newPlayerCount];
			ReflectionUtils.SetFieldValue(__instance, "ragdollColliders", value);
		}
	}
	[HarmonyPatch(typeof(CrawlerAI), "Start")]
	public static class CrawlerAIStartPatch
	{
		public static void Postfix(ref CrawlerAI __instance)
		{
			Collider[] value = (Collider[])(object)new Collider[MainClass.newPlayerCount];
			ReflectionUtils.SetFieldValue(__instance, "nearPlayerColliders", value);
		}
	}
	[HarmonyPatch(typeof(SpringManAI), "Update")]
	public static class SpringManAIUpdatePatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			bool flag = false;
			bool flag2 = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (!flag2)
				{
					if (!flag && ((object)instruction).ToString() == "call static float UnityEngine.Vector3::Distance(UnityEngine.Vector3 a, UnityEngine.Vector3 b)")
					{
						flag = true;
					}
					else if (flag && ((object)instruction).ToString() == "ldc.i4.4 NULL")
					{
						flag2 = true;
						CodeInstruction item = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(MainClass), "newPlayerCount"));
						list.Add(item);
						continue;
					}
				}
				list.Add(instruction);
			}
			if (!flag2)
			{
				MainClass.StaticLogger.LogWarning((object)"SpringManAIUpdatePatch failed to replace newPlayerCount");
			}
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(EnemyAI), "GetClosestPlayer")]
	public static class GetClosestPlayerPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			bool flag = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (!flag && ((object)instruction).ToString() == "ldc.i4.4 NULL")
				{
					flag = true;
					CodeInstruction item = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(MainClass), "newPlayerCount"));
					list.Add(item);
				}
				else
				{
					list.Add(instruction);
				}
			}
			if (!flag)
			{
				MainClass.StaticLogger.LogWarning((object)"GetClosestPlayerPatch failed to replace newPlayerCount");
			}
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(EnemyAI), "GetAllPlayersInLineOfSight")]
	public static class GetAllPlayersInLineOfSightPatch
	{
		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>();
			int num = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Ldc_I4_4)
				{
					num++;
					instruction.opcode = OpCodes.Ldsfld;
					instruction.operand = AccessTools.Field(typeof(MainClass), "newPlayerCount");
				}
				list.Add(instruction);
			}
			if (num != 2)
			{
				MainClass.StaticLogger.LogWarning((object)$"GetAllPlayersInLineOfSightPatch failed to replace newPlayerCount: {num}/2");
			}
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(DressGirlAI), "ChoosePlayerToHaunt")]
	public static class DressGirlHauntPatch
	{
		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			int num = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (((object)instruction).ToString() == "ldc.i4.4 NULL")
				{
					num++;
					CodeInstruction item = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(MainClass), "newPlayerCount"));
					list.Add(item);
				}
				else
				{
					list.Add(instruction);
				}
			}
			if (num != 3)
			{
				MainClass.StaticLogger.LogWarning((object)$"DressGirlHauntPatch failed to replace newPlayerCount: {num}/3");
			}
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(ButlerEnemyAI), "Start")]
	public static class ButlerEnemyAIPatch
	{
		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			int num = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (((object)instruction).ToString() == "ldc.i4.4 NULL")
				{
					num++;
					CodeInstruction item = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(MainClass), "newPlayerCount"));
					list.Add(item);
				}
				else
				{
					list.Add(instruction);
				}
			}
			if (num != 3)
			{
				MainClass.StaticLogger.LogWarning((object)$"ButlerEnemyAIPatch failed to replace newPlayerCount: {num}/3");
			}
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(CaveDwellerAI), "GetAllPlayerBodiesInLineOfSight")]
	public static class GetAllPlayerBodiesInLineOfSightPatch
	{
		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>();
			int num = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Ldc_I4_4)
				{
					num++;
					instruction.opcode = OpCodes.Ldsfld;
					instruction.operand = AccessTools.Field(typeof(MainClass), "newPlayerCount");
				}
				list.Add(instruction);
			}
			if (num != 2)
			{
				MainClass.StaticLogger.LogWarning((object)$"GetAllPlayerBodiesInLineOfSightPatch failed to replace newPlayerCount: {num}/2");
			}
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(HUDManager), "AddChatMessage")]
	public static class HudChatPatch
	{
		public static void Prefix(HUDManager __instance, ref string chatMessage, string nameOfUserWhoTyped = "")
		{
			if (!(__instance.lastChatMessage == chatMessage))
			{
				StringBuilder stringBuilder = new StringBuilder(chatMessage);
				for (int i = 0; i < MainClass.newPlayerCount; i++)
				{
					string oldValue = $"[playerNum{i}]";
					string playerUsername = StartOfRound.Instance.allPlayerScripts[i].playerUsername;
					stringBuilder.Replace(oldValue, playerUsername);
				}
				chatMessage = stringBuilder.ToString();
			}
		}
	}
	[HarmonyPatch(typeof(MenuManager), "Awake")]
	public static class MenuManagerLogoOverridePatch
	{
		public static List<TMP_InputField> inputFields = new List<TMP_InputField>();

		public static void Postfix(MenuManager __instance)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				MainClass.ReadSettingsFromFile();
				GameObject gameObject = ((Component)((Component)__instance).transform.parent).gameObject;
				Sprite sprite = Sprite.Create(MainClass.mainLogo, new Rect(0f, 0f, (float)((Texture)MainClass.mainLogo).width, (float)((Texture)MainClass.mainLogo).height), new Vector2(0.5f, 0.5f));
				Transform val = gameObject.transform.Find("MenuContainer/MainButtons/HeaderImage");
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).gameObject.GetComponent<Image>().sprite = sprite;
				}
				Transform val2 = gameObject.transform.Find("MenuContainer/LoadingScreen");
				if ((Object)(object)val2 != (Object)null)
				{
					val2.localScale = new Vector3(1.02f, 1.06f, 1.02f);
					Transform val3 = val2.Find("Image");
					if ((Object)(object)val3 != (Object)null)
					{
						((Component)val3).GetComponent<Image>().sprite = sprite;
					}
				}
				CosmeticRegistry.SpawnCosmeticGUI();
				LANMenu.InitializeMenu();
				inputFields.Clear();
				Transform val4 = gameObject.transform.Find("MenuContainer/LobbyHostSettings/HostSettingsContainer/LobbyHostOptions");
				if ((Object)(object)val4 != (Object)null)
				{
					CreateCrewCountInput(val4.Find(GameNetworkManager.Instance.disableSteam ? "LANOptions" : "OptionsNormal"));
				}
				Transform val5 = gameObject.transform.Find("MenuContainer/LobbyJoinSettings/JoinSettingsContainer/LobbyJoinOptions");
				if ((Object)(object)val5 != (Object)null)
				{
					CreateCrewCountInput(val5.Find("LANOptions"));
				}
			}
			catch (Exception ex)
			{
				MainClass.StaticLogger.LogError((object)ex);
			}
		}

		private static void CreateCrewCountInput(Transform parent)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(MainClass.crewCountUI, parent);
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).localPosition = new Vector3(96.9f, -70f, -6.7f);
			TMP_InputField inputField = ((Component)val.transform.Find("InputField (TMP)")).GetComponent<TMP_InputField>();
			inputField.characterLimit = 3;
			inputField.text = MainClass.newPlayerCount.ToString();
			inputFields.Add(inputField);
			((UnityEvent<string>)(object)inputField.onSubmit).AddListener((UnityAction<string>)delegate(string s)
			{
				UpdateTextBox(inputField, s);
			});
			((UnityEvent<string>)(object)inputField.onDeselect).AddListener((UnityAction<string>)delegate(string s)
			{
				UpdateTextBox(inputField, s);
			});
		}

		public static void UpdateTextBox(TMP_InputField inputField, string s)
		{
			if (inputField.text == MainClass.newPlayerCount.ToString())
			{
				return;
			}
			if (int.TryParse(s, out var result))
			{
				int newPlayerCount = MainClass.newPlayerCount;
				MainClass.newPlayerCount = Mathf.Clamp(result, MainClass.minPlayerCount, MainClass.maxPlayerCount);
				foreach (TMP_InputField inputField2 in inputFields)
				{
					inputField2.text = MainClass.newPlayerCount.ToString();
				}
				MainClass.SaveSettingsToFile();
				if (MainClass.newPlayerCount != newPlayerCount)
				{
					MainClass.StaticLogger.LogInfo((object)$"Changed Crew Count: {MainClass.newPlayerCount}");
				}
			}
			else
			{
				if (s.Length == 0)
				{
					return;
				}
				foreach (TMP_InputField inputField3 in inputFields)
				{
					inputField3.text = MainClass.newPlayerCount.ToString();
					inputField3.caretPosition = 1;
				}
			}
		}
	}
	[HarmonyPatch(typeof(QuickMenuManager), "AddUserToPlayerList")]
	public static class AddUserPlayerListPatch
	{
		private static bool Prefix(QuickMenuManager __instance, ulong steamId, string playerName, int playerObjectId)
		{
			QuickmenuVisualInjectPatch.PopulateQuickMenu(__instance);
			return false;
		}
	}
	[HarmonyPatch(typeof(QuickMenuManager), "RemoveUserFromPlayerList")]
	public static class RemoveUserPlayerListPatch
	{
		public static bool Prefix(QuickMenuManager __instance)
		{
			QuickmenuVisualInjectPatch.PopulateQuickMenu(__instance);
			return false;
		}
	}
	[HarmonyPatch(typeof(QuickMenuManager), "Update")]
	public static class QuickMenuUpdatePatch
	{
		public static bool Prefix()
		{
			return false;
		}
	}
	[HarmonyPatch(typeof(QuickMenuManager), "NonHostPlayerSlotsEnabled")]
	public static class QuickMenuDisplayPatch
	{
		public static bool Prefix(ref bool __result)
		{
			__result = false;
			for (int i = 1; i < StartOfRound.Instance.allPlayerScripts.Length; i++)
			{
				PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[i];
				if (val.isPlayerControlled || val.isPlayerDead)
				{
					__result = true;
					break;
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(QuickMenuManager), "Start")]
	public static class QuickmenuVisualInjectPatch
	{
		public static GameObject quickMenuScrollInstance;

		public static void Postfix(QuickMenuManager __instance)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			GameObject gameObject = ((Component)__instance.playerListPanel.transform.Find("Image")).gameObject;
			GameObject val = Object.Instantiate<GameObject>(MainClass.quickMenuScrollParent);
			val.transform.SetParent(gameObject.transform);
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).localPosition = new Vector3(0f, -31.2f, 0f);
			((Transform)component).localScale = Vector3.one;
			quickMenuScrollInstance = val;
		}

		public static void PopulateQuickMenu(QuickMenuManager __instance)
		{
			//IL_0152: 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_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Expected O, but got Unknown
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Expected O, but got Unknown
			if ((Object)(object)quickMenuScrollInstance == (Object)null)
			{
				return;
			}
			Transform val = quickMenuScrollInstance.transform.Find("Holder");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			List<GameObject> list = new List<GameObject>();
			int childCount = val.childCount;
			for (int i = 0; i < childCount; i++)
			{
				list.Add(((Component)val.GetChild(i)).gameObject);
			}
			foreach (GameObject item in list)
			{
				Object.Destroy((Object)(object)item);
			}
			if (!Object.op_Implicit((Object)(object)StartOfRound.Instance))
			{
				return;
			}
			for (int j = 0; j < StartOfRound.Instance.allPlayerScripts.Length; j++)
			{
				PlayerControllerB playerScript = StartOfRound.Instance.allPlayerScripts[j];
				if (!playerScript.isPlayerControlled && !playerScript.isPlayerDead)
				{
					continue;
				}
				GameObject val2 = Object.Instantiate<GameObject>(MainClass.playerEntry, val);
				RectTransform component = val2.GetComponent<RectTransform>();
				((Transform)component).localScale = Vector3.one;
				((Transform)component).localPosition = new Vector3(0f, 0f - ((Transform)component).localPosition.y, 0f);
				TextMeshProUGUI component2 = ((Component)val2.transform.Find("PlayerNameButton").Find("PName")).GetComponent<TextMeshProUGUI>();
				((TMP_Text)component2).text = playerScript.playerUsername;
				Slider playerVolume = ((Component)val2.transform.Find("PlayerVolumeSlider")).GetComponent<Slider>();
				int finalIndex = j;
				((UnityEvent<float>)(object)playerVolume.onValueChanged).AddListener((UnityAction<float>)delegate(float f)
				{
					if (playerScript.isPlayerControlled || playerScript.isPlayerDead)
					{
						float num = (f - playerVolume.minValue) / (playerVolume.maxValue - playerVolume.minValue);
						if (num <= 0f)
						{
							num = -70f;
						}
						SoundManager.Instance.playerVoiceVolumes[finalIndex] = num;
					}
				});
				playerVolume.value = Math.Clamp(SoundManager.Instance.playerVoiceVolumes[j] * (playerVolume.maxValue - playerVolume.minValue) + playerVolume.minValue, playerVolume.minValue, playerVolume.maxValue);
				Button component3 = ((Component)val2.transform.Find("KickButton")).GetComponent<Button>();
				((UnityEvent)component3.onClick).AddListener((UnityAction)delegate
				{
					__instance.KickUserFromServer(finalIndex);
				});
				if ((Object)(object)StartOfRound.Instance.localPlayerController != (Object)null && StartOfRound.Instance.localPlayerController.playerClientId == playerScript.playerClientId)
				{
					((Component)playerVolume).gameObject.SetActive(false);
					((Component)val2.transform.Find("Text (1)")).gameObject.SetActive(false);
					((Component)component3).gameObject.SetActive(false);
				}
				else if (!GameNetworkManager.Instance.isHostingGame)
				{
					((Component)component3).gameObject.SetActive(false);
				}
				Button component4 = ((Component)val2.transform.Find("ProfileIcon")).GetComponent<Button>();
				((UnityEvent)component4.onClick).AddListener((UnityAction)delegate
				{
					//IL_001d: Unknown result type (might be due to invalid IL or missing references)
					if (!GameNetworkManager.Instance.disableSteam)
					{
						SteamFriends.OpenUserOverlay(SteamId.op_Implicit(playerScript.playerSteamId), "steamid");
					}
				});
			}
		}
	}
	[HarmonyPatch(typeof(QuickMenuManager), "ConfirmKickUserFromServer")]
	public static class KickPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			bool flag = false;
			bool flag2 = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (!flag2)
				{
					if (!flag && ((object)instruction).ToString() == "ldfld int QuickMenuManager::playerObjToKick")
					{
						flag = true;
					}
					else if (flag && ((object)instruction).ToString() == "ldc.i4.3 NULL")
					{
						flag2 = true;
						CodeInstruction item = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(MainClass), "newPlayerCount"));
						list.Add(item);
						continue;
					}
				}
				list.Add(instruction);
			}
			if (!flag2)
			{
				MainClass.StaticLogger.LogWarning((object)"KickPatch failed to replace newPlayerCount");
			}
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(HUDManager), "UpdateBoxesSpectateUI")]
	public static class SpectatorBoxUpdatePatch
	{
		public static void Postfix(HUDManager __instance)
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<Animator, PlayerControllerB> fieldValue = ReflectionUtils.GetFieldValue<Dictionary<Animator, PlayerControllerB>>(__instance, "spectatingPlayerBoxes");
			int num = -64;
			int num2 = 0;
			int num3 = 0;
			int num4 = -70;
			int num5 = 230;
			int num6 = 4;
			foreach (KeyValuePair<Animator, PlayerControllerB> item in fieldValue)
			{
				if (((Component)item.Key).gameObject.activeInHierarchy)
				{
					GameObject gameObject = ((Component)item.Key).gameObject;
					RectTransform component = gameObject.GetComponent<RectTransform>();
					int num7 = (int)Math.Floor((double)num3 / (double)num6);
					int num8 = num3 % num6;
					int num9 = num8 * num4;
					int num10 = num7 * num5;
					component.anchoredPosition = Vector2.op_Implicit(new Vector3((float)(num + num10), (float)(num2 + num9), 0f));
					num3++;
				}
			}
		}
	}
	[HarmonyPatch(typeof(HUDManager), "Start")]
	public static class HudStartPatch
	{
		public static void Postfix(HUDManager __instance)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			EndOfGameStatUIElements statsUIElements = __instance.statsUIElements;
			GameObject gameObject = ((Component)((Component)statsUIElements.playerNamesText[0]).gameObject.transform.parent).gameObject;
			GameObject gameObject2 = ((Component)gameObject.transform.parent.parent).gameObject;
			GameObject gameObject3 = ((Component)gameObject2.transform.Find("BGBoxes")).gameObject;
			gameObject2.transform.parent.Find("DeathScreen").SetSiblingIndex(3);
			gameObject3.transform.localScale = new Vector3(2.5f, 1f, 1f);
			MakePlayerHolder(4, gameObject, statsUIElements, new Vector3(426.9556f, -0.7932f, 0f));
			MakePlayerHolder(5, gameObject, statsUIElements, new Vector3(426.9556f, -115.4483f, 0f));
			MakePlayerHolder(6, gameObject, statsUIElements, new Vector3(-253.6783f, -115.4483f, 0f));
			MakePlayerHolder(7, gameObject, statsUIElements, new Vector3(-253.6783f, -0.7932f, 0f));
			for (int i = 8; i < MainClass.newPlayerCount; i++)
			{
				MakePlayerHolder(i, gameObject, statsUIElements, new Vector3(10000f, 10000f, 0f));
			}
		}

		public static void MakePlayerHolder(int index, GameObject original, EndOfGameStatUIElements uiElements, Vector3 localPosition)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			if (index + 1 <= MainClass.newPlayerCount)
			{
				GameObject val = Object.Instantiate<GameObject>(original);
				RectTransform component = val.GetComponent<RectTransform>();
				RectTransform component2 = original.GetComponent<RectTransform>();
				((Transform)component).SetParent(((Transform)component2).parent);
				((Transform)component).localScale = new Vector3(1f, 1f, 1f);
				((Transform)component).localPosition = localPosition;
				GameObject gameObject = ((Component)val.transform.Find("PlayerName1")).gameObject;
				GameObject gameObject2 = ((Component)val.transform.Find("Notes")).gameObject;
				((Transform)gameObject2.GetComponent<RectTransform>()).localPosition = new Vector3(-95.7222f, 43.3303f, 0f);
				GameObject gameObject3 = ((Component)val.transform.Find("Symbol")).gameObject;
				if (index >= uiElements.playerNamesText.Length)
				{
					Array.Resize(ref uiElements.playerNamesText, index + 1);
					Array.Resize(ref uiElements.playerStates, index + 1);
					Array.Resize(ref uiElements.playerNotesText, index + 1);
				}
				uiElements.playerNamesText[index] = gameObject.GetComponent<TextMeshProUGUI>();
				uiElements.playerNotesText[index] = gameObject2.GetComponent<TextMeshProUGUI>();
				uiElements.playerStates[index] = gameObject3.GetComponent<Image>();
			}
		}
	}
	public class LANMenu : MonoBehaviour
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__0_0;

			internal void <InitializeMenu>b__0_0()
			{
				TextMeshProUGUI component = GameObject.Find("Canvas/MenuContainer/LobbyJoinSettings/JoinSettingsContainer/PrivatePublicDescription").GetComponent<TextMeshProUGUI>();
				if ((Object)(object)component != (Object)null)
				{
					((TMP_Text)component).text = "The mod will attempt to auto-detect the crew size however you can manually specify it to reduce chance of failure.";
				}
				GameObject.Find("Canvas/MenuContainer/LobbyJoinSettings").gameObject.SetActive(true);
			}
		}

		public static void InitializeMenu()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			CreateUI();
			GameObject val = GameObject.Find("Canvas/MenuContainer/MainButtons/StartLAN");
			if (!((Object)(object)val != (Object)null))
			{
				return;
			}
			MainClass.StaticLogger.LogInfo((object)"LANMenu startLAN Patched");
			val.GetComponent<Button>().onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick = val.GetComponent<Button>().onClick;
			object obj = <>c.<>9__0_0;
			if (obj == null)
			{
				UnityAction val2 = delegate
				{
					TextMeshProUGUI component = GameObject.Find("Canvas/MenuContainer/LobbyJoinSettings/JoinSettingsContainer/PrivatePublicDescription").GetComponent<TextMeshProUGUI>();
					if ((Object)(object)component != (Object)null)
					{
						((TMP_Text)component).text = "The mod will attempt to auto-detect the crew size however you can manually specify it to reduce chance of failure.";
					}
					GameObject.Find("Canvas/MenuContainer/LobbyJoinSettings").gameObject.SetActive(true);
				};
				<>c.<>9__0_0 = val2;
				obj = (object)val2;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
		}

		private static GameObject CreateUI()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Expected O, but got Unknown
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Expected O, but got Unknown
			if ((Object)(object)GameObject.Find("Canvas/MenuContainer/LobbyJoinSettings") != (Object)null)
			{
				return null;
			}
			GameObject val = GameObject.Find("Canvas/MenuContainer");
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GameObject val2 = GameObject.Find("Canvas/MenuContainer/LobbyHostSettings");
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
			GameObject val3 = Object.Instantiate<GameObject>(val2, val2.transform.position, val2.transform.rotation, val.transform);
			((Object)val3).name = "LobbyJoinSettings";
			Transform val4 = val3.transform.Find("HostSettingsContainer");
			if ((Object)(object)val4 != (Object)null)
			{
				((Object)val4).name = "JoinSettingsContainer";
				((Object)((Component)val4).transform.Find("LobbyHostOptions")).name = "LobbyJoinOptions";
				Object.Destroy((Object)(object)((Component)val3.transform.Find("ChallengeLeaderboard")).gameObject);
				Object.Destroy((Object)(object)((Component)val3.transform.Find("FilesPanel")).gameObject);
				Object.Destroy((Object)(object)((Component)((Component)val4).transform.Find("LobbyJoinOptions/OptionsNormal")).gameObject);
				Object.Destroy((Object)(object)((Component)((Component)val4).transform.Find("LobbyJoinOptions/LANOptions/AllowRemote")).gameObject);
				Object.Destroy((Object)(object)((Component)((Component)val4).transform.Find("LobbyJoinOptions/LANOptions/Local")).gameObject);
				Transform val5 = ((Component)val4).transform.Find("LobbyJoinOptions/LANOptions/Header");
				if ((Object)(object)val5 != (Object)null)
				{
					((TMP_Text)((Component)val5).GetComponent<TextMeshProUGUI>()).text = "Join LAN Server:";
				}
				Transform val6 = ((Component)val4).transform.Find("LobbyJoinOptions/LANOptions/ServerNameField");
				if ((Object)(object)val6 != (Object)null)
				{
					((Component)val6).transform.localPosition = new Vector3(0f, 15f, -6.5f);
					((Component)val6).gameObject.SetActive(true);
				}
				TMP_InputField ip_field = ((Component)val6).GetComponent<TMP_InputField>();
				if ((Object)(object)ip_field != (Object)null)
				{
					TextMeshProUGUI ip_placeholder = ((Component)ip_field.placeholder).GetComponent<TextMeshProUGUI>();
					((TMP_Text)ip_placeholder).text = ES3.Load<string>("LANIPAddress", "LCGeneralSaveData", "127.0.0.1");
					Transform obj = ((Component)val4).transform.Find("Confirm");
					Button val7 = ((obj != null) ? ((Component)obj).GetComponent<Button>() : null);
					if ((Object)(object)val7 != (Object)null)
					{
						val7.onClick = new ButtonClickedEvent();
						((UnityEvent)val7.onClick).AddListener((UnityAction)delegate
						{
							string text = "127.0.0.1";
							text = ((!(ip_field.text != "")) ? ((TMP_Text)ip_placeholder).text : ip_field.text);
							ES3.Save<string>("LANIPAddress", text, "LCGeneralSaveData");
							GameObject.Find("Canvas/MenuContainer/LobbyJoinSettings").gameObject.SetActive(false);
							((Component)NetworkManager.Singleton).GetComponent<UnityTransport>().ConnectionData.Address = text;
							MainClass.StaticLogger.LogInfo((object)("Listening to LAN server: " + text));
							GameObject.Find("MenuManager").GetComponent<MenuManager>().StartAClient();
						});
					}
				}
				TextMeshProUGUI component = ((Component)((Component)val4).transform.Find("PrivatePublicDescription")).GetComponent<TextMeshProUGUI>();
				if ((Object)(object)component != (Object)null)
				{
					((TMP_Text)component).text = "The mod will attempt to auto-detect the crew size however you can manually specify it to reduce chance of failure.";
				}
				((Component)((Component)val4).transform.Find("LobbyJoinOptions/LANOptions")).gameObject.SetActive(true);
			}
			return val3;
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager), "SetConnectionDataBeforeConnecting")]
	public static class ConnectionDataPatch
	{
		public static void Postfix(ref GameNetworkManager __instance)
		{
			if (__instance.disableSteam)
			{
				NetworkManager.Singleton.NetworkConfig.ConnectionData = Encoding.ASCII.GetBytes(__instance.gameVersionNum + "," + MainClass.newPlayerCount);
			}
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager), "OnLocalClientConnectionDisapproved")]
	public static class ConnectionDisapprovedPatch
	{
		private static int crewSizeMismatch;

		private static IEnumerator delayedReconnect()
		{
			yield return (object)new WaitForSeconds(0.5f);
			GameObject.Find("MenuManager").GetComponent<MenuManager>().StartAClient();
		}

		private static void Prefix(ref GameNetworkManager __instance, ulong clientId)
		{
			crewSizeMismatch = 0;
			if (!__instance.disableSteam)
			{
				return;
			}
			try
			{
				if (!string.IsNullOrEmpty(NetworkManager.Singleton.DisconnectReason) && NetworkManager.Singleton.DisconnectReason.StartsWith("Crew size mismatch!"))
				{
					crewSizeMismatch = int.Parse(NetworkManager.Singleton.DisconnectReason.Split("Their size: ")[1].Split(". ")[0]);
				}
			}
			catch
			{
			}
		}

		private static void Postfix(ref GameNetworkManager __instance, ulong clientId)
		{
			if (__instance.disableSteam && crewSizeMismatch != 0)
			{
				MainClass.newPlayerCount = Mathf.Clamp(crewSizeMismatch, MainClass.minPlayerCount, MainClass.maxPlayerCount);
				if (MainClass.newPlayerCount == crewSizeMismatch)
				{
					GameObject.Find("MenuManager").GetComponent<MenuManager>().menuNotification.SetActive(false);
					Object.FindObjectOfType<MenuManager>().SetLoadingScreen(true, (RoomEnter)5, "");
					((MonoBehaviour)__instance).StartCoroutine(delayedReconnect());
				}
				crewSizeMismatch = 0;
			}
		}
	}
	public static class PluginInformation
	{
		public const string PLUGIN_NAME = "MoreCompany";

		public const string PLUGIN_VERSION = "1.10.1";

		public const string PLUGIN_GUID = "me.swipez.melonloader.morecompany";
	}
	[BepInPlugin("me.swipez.melonloader.morecompany", "MoreCompany", "1.10.1")]
	public class MainClass : BaseUnityPlugin
	{
		public static int defaultPlayerCount = 32;

		public static int minPlayerCount = 4;

		public static int maxPlayerCount = 50;

		public static int newPlayerCount = 32;

		public static ConfigFile StaticConfig;

		public static ConfigEntry<int> playerCount;

		public static ConfigEntry<bool> cosmeticsDeadBodies;

		public static ConfigEntry<bool> cosmeticsMaskedEnemy;

		public static ConfigEntry<bool> cosmeticsSyncOther;

		public static ConfigEntry<bool> defaultCosmetics;

		public static ConfigEntry<bool> cosmeticsPerProfile;

		public static Texture2D mainLogo;

		public static GameObject quickMenuScrollParent;

		public static GameObject playerEntry;

		public static GameObject crewCountUI;

		public static GameObject cosmeticGUIInstance;

		public static GameObject cosmeticButton;

		public static ManualLogSource StaticLogger;

		public static Dictionary<int, List<string>> playerIdsAndCosmetics = new Dictionary<int, List<string>>();

		public static string dynamicCosmeticsPath;

		public static string cosmeticSavePath;

		private void Awake()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			StaticLogger = ((BaseUnityPlugin)this).Logger;
			StaticConfig = ((BaseUnityPlugin)this).Config;
			playerCount = StaticConfig.Bind<int>("General", "Player Count", defaultPlayerCount, new ConfigDescription("How many players can be in your lobby?", (AcceptableValueBase)(object)new AcceptableValueRange<int>(minPlayerCount, maxPlayerCount), Array.Empty<object>()));
			cosmeticsSyncOther = StaticConfig.Bind<bool>("Cosmetics", "Show Cosmetics", true, "Should you be able to see cosmetics of other players?");
			cosmeticsDeadBodies = StaticConfig.Bind<bool>("Cosmetics", "Show On Dead Bodies", true, "Should you be able to see cosmetics on dead bodies?");
			cosmeticsMaskedEnemy = StaticConfig.Bind<bool>("Cosmetics", "Show On Masked Enemy", true, "Should you be able to see cosmetics on the masked enemy?");
			defaultCosmetics = StaticConfig.Bind<bool>("Cosmetics", "Default Cosmetics", true, "Should the default cosmetics be enabled?");
			cosmeticsPerProfile = StaticConfig.Bind<bool>("Cosmetics", "Per Profile Cosmetics", false, "Should the cosmetics be saved per-profile?");
			Harmony val = new Harmony("me.swipez.melonloader.morecompany");
			try
			{
				val.PatchAll();
			}
			catch (Exception ex)
			{
				StaticLogger.LogError((object)("Failed to patch: " + ex));
			}
			StaticLogger.LogInfo((object)"Loading MoreCompany...");
			SteamFriends.OnGameLobbyJoinRequested += delegate(Lobby lobby, SteamId steamId)
			{
				newPlayerCount = ((Lobby)(ref lobby)).MaxMembers;
			};
			SteamMatchmaking.OnLobbyEntered += delegate(Lobby lobby)
			{
				newPlayerCount = ((Lobby)(ref lobby)).MaxMembers;
			};
			StaticLogger.LogInfo((object)"Loading SETTINGS...");
			ReadSettingsFromFile();
			dynamicCosmeticsPath = Paths.PluginPath + "/MoreCompanyCosmetics";
			if (cosmeticsPerProfile.Value)
			{
				cosmeticSavePath = Application.persistentDataPath + "/morecompanycosmetics-" + Directory.GetParent(Paths.BepInExRootPath).Name + ".txt";
			}
			else
			{
				cosmeticSavePath = Application.persistentDataPath + "/morecompanycosmetics.txt";
			}
			cosmeticsPerProfile.SettingChanged += delegate
			{
				if (cosmeticsPerProfile.Value)
				{
					cosmeticSavePath = Application.persistentDataPath + "/MCCosmeticsSave-" + Directory.GetParent(Paths.BepInExRootPath).Name + ".mcs";
				}
				else
				{
					cosmeticSavePath = Application.persistentDataPath + "/MCCosmeticsSave.mcs";
				}
			};
			StaticLogger.LogInfo((object)("Checking: " + dynamicCosmeticsPath));
			if (!Directory.Exists(dynamicCosmeticsPath))
			{
				StaticLogger.LogInfo((object)"Creating cosmetics directory");
				Directory.CreateDirectory(dynamicCosmeticsPath);
			}
			StaticLogger.LogInfo((object)"Loading COSMETICS...");
			ReadCosmeticsFromFile();
			if (defaultCosmetics.Value)
			{
				StaticLogger.LogInfo((object)"Loading DEFAULT COSMETICS...");
				AssetBundle val2 = BundleUtilities.LoadBundleFromInternalAssembly("morecompany.cosmetics", Assembly.GetExecutingAssembly());
				CosmeticRegistry.LoadCosmeticsFromBundle(val2);
				val2.Unload(false);
			}
			StaticLogger.LogInfo((object)"Loading USER COSMETICS...");
			RecursiveCosmeticLoad(Paths.PluginPath);
			AssetBundle bundle = BundleUtilities.LoadBundleFromInternalAssembly("morecompany.assets", Assembly.GetExecutingAssembly());
			LoadAssets(bundle);
			StaticLogger.LogInfo((object)"Loaded MoreCompany FULLY");
		}

		private void RecursiveCosmeticLoad(string directory)
		{
			string[] directories = Directory.GetDirectories(directory);
			foreach (string directory2 in directories)
			{
				RecursiveCosmeticLoad(directory2);
			}
			string[] files = Directory.GetFiles(directory);
			foreach (string text in files)
			{
				if (text.EndsWith(".cosmetics"))
				{
					AssetBundle val = AssetBundle.LoadFromFile(text);
					CosmeticRegistry.LoadCosmeticsFromBundle(val);
					val.Unload(false);
				}
			}
		}

		private void ReadCosmeticsFromFile()
		{
			if (File.Exists(cosmeticSavePath))
			{
				string[] array = File.ReadAllLines(cosmeticSavePath);
				string[] array2 = array;
				foreach (string item in array2)
				{
					CosmeticRegistry.locallySelectedCosmetics.Add(item);
				}
			}
		}

		public static void WriteCosmeticsToFile()
		{
			string text = "";
			foreach (string locallySelectedCosmetic in CosmeticRegistry.locallySelectedCosmetics)
			{
				text = text + locallySelectedCosmetic + "\n";
			}
			File.WriteAllText(cosmeticSavePath, text);
		}

		public static void SaveSettingsToFile()
		{
			playerCount.Value = newPlayerCount;
			StaticConfig.Save();
		}

		public static void ReadSettingsFromFile()
		{
			try
			{
				newPlayerCount = Mathf.Clamp(playerCount.Value, minPlayerCount, maxPlayerCount);
			}
			catch
			{
				newPlayerCount = defaultPlayerCount;
				playerCount.Value = newPlayerCount;
				StaticConfig.Save();
			}
		}

		private static void LoadAssets(AssetBundle bundle)
		{
			if (Object.op_Implicit((Object)(object)bundle))
			{
				mainLogo = bundle.LoadPersistentAsset<Texture2D>("assets/morecompanyassets/morecompanytransparentred.png");
				quickMenuScrollParent = bundle.LoadPersistentAsset<GameObject>("assets/morecompanyassets/quickmenuoverride.prefab");
				playerEntry = bundle.LoadPersistentAsset<GameObject>("assets/morecompanyassets/playerlistslot.prefab");
				cosmeticGUIInstance = bundle.LoadPersistentAsset<GameObject>("assets/morecompanyassets/testoverlay.prefab");
				cosmeticButton = bundle.LoadPersistentAsset<GameObject>("assets/morecompanyassets/cosmeticinstance.prefab");
				crewCountUI = bundle.LoadPersistentAsset<GameObject>("assets/morecompanyassets/crewcountfield.prefab");
				bundle.Unload(false);
			}
		}

		public static void ResizePlayerCache(Dictionary<uint, Dictionary<int, NetworkObject>> ScenePlacedObjects)
		{
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Expected O, but got Unknown
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Expected O, but got Unknown
			StartOfRound instance = StartOfRound.Instance;
			if (instance.allPlayerObjects.Length != newPlayerCount)
			{
				StaticLogger.LogInfo((object)$"ResizePlayerCache: {newPlayerCount}");
				uint num = 10000u;
				int num2 = instance.allPlayerObjects.Length;
				int num3 = newPlayerCount - num2;
				Array.Resize(ref instance.allPlayerObjects, newPlayerCount);
				Array.Resize(ref instance.allPlayerScripts, newPlayerCount);
				Array.Resize(ref instance.gameStats.allPlayerStats, newPlayerCount);
				Array.Resize(ref instance.playerSpawnPositions, newPlayerCount);
				StaticLogger.LogInfo((object)$"Resizing player cache from {num2} to {newPlayerCount} with difference of {num3}");
				if (num3 > 0)
				{
					GameObject val = instance.allPlayerObjects[3];
					for (int i = 0; i < num3; i++)
					{
						uint num4 = num + (uint)i;
						GameObject val2 = Object.Instantiate<GameObject>(val, val.transform.parent);
						NetworkObject component = val2.GetComponent<NetworkObject>();
						ReflectionUtils.SetFieldValue(component, "GlobalObjectIdHash", num4);
						Scene scene = ((Component)component).gameObject.scene;
						int handle = ((Scene)(ref scene)).handle;
						uint num5 = num4;
						if (!ScenePlacedObjects.ContainsKey(num5))
						{
							ScenePlacedObjects.Add(num5, new Dictionary<int, NetworkObject>());
						}
						if (ScenePlacedObjects[num5].ContainsKey(handle))
						{
							string arg = (((Object)(object)ScenePlacedObjects[num5][handle] != (Object)null) ? ((Object)ScenePlacedObjects[num5][handle]).name : "Null Entry");
							throw new Exception(((Object)component).name + " tried to registered with ScenePlacedObjects which already contains " + string.Format("the same {0} value {1} for {2}!", "GlobalObjectIdHash", num5, arg));
						}
						ScenePlacedObjects[num5].Add(handle, component);
						((Object)val2).name = $"Player ({4 + i})";
						PlayerControllerB componentInChildren = val2.GetComponentInChildren<PlayerControllerB>();
						componentInChildren.playerClientId = (ulong)(4 + i);
						componentInChildren.playerUsername = $"Player #{componentInChildren.playerClientId}";
						componentInChildren.isPlayerControlled = false;
						componentInChildren.isPlayerDead = false;
						componentInChildren.DropAllHeldItems(false, false);
						componentInChildren.TeleportPlayer(instance.notSpawnedPosition.position, false, 0f, false, true);
						UnlockableSuit.SwitchSuitForPlayer(componentInChildren, 0, false);
						instance.allPlayerObjects[num2 + i] = val2;
						instance.gameStats.allPlayerStats[num2 + i] = new PlayerStats();
						instance.allPlayerScripts[num2 + i] = componentInChildren;
						instance.playerSpawnPositions[num2 + i] = instance.playerSpawnPositions[3];
						StartOfRound.Instance.mapScreen.radarTargets.Add(new TransformAndName(((Component)componentInChildren).transform, componentInChildren.playerUsername, false));
					}
				}
			}
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val3 in allPlayerScripts)
			{
				((TMP_Text)val3.usernameBillboardText).text = val3.playerUsername;
			}
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "Start")]
	public static class PlayerControllerBStartPatch
	{
		public static void Postfix(ref PlayerControllerB __instance)
		{
			Collider[] value = (Collider[])(object)new Collider[MainClass.newPlayerCount];
			ReflectionUtils.SetFieldValue(__instance, "nearByPlayers", value);
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "SendNewPlayerValuesServerRpc")]
	public static class SendNewPlayerValuesServerRpcPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			bool flag = false;
			bool flag2 = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (!flag2)
				{
					if (!flag && ((object)instruction).ToString() == "callvirt virtual void System.Collections.Generic.List<ulong>::Add(ulong item)")
					{
						flag = true;
					}
					else if (flag && ((object)instruction).ToString() == "ldc.i4.4 NULL")
					{
						flag2 = true;
						CodeInstruction item = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(MainClass), "newPlayerCount"));
						list.Add(item);
						continue;
					}
				}
				list.Add(instruction);
			}
			if (!flag2)
			{
				MainClass.StaticLogger.LogWarning((object)"SendNewPlayerValuesServerRpcPatch failed to replace newPlayerCount");
			}
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(HUDManager), "SyncAllPlayerLevelsServerRpc", new Type[] { })]
	public static class SyncAllPlayerLevelsPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			int num = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (((object)instruction).ToString() == "ldc.i4.4 NULL")
				{
					num++;
					CodeInstruction item = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(MainClass), "newPlayerCount"));
					list.Add(item);
				}
				else
				{
					list.Add(instruction);
				}
			}
			if (num != 2)
			{
				MainClass.StaticLogger.LogWarning((object)$"SyncAllPlayerLevelsPatch failed to replace newPlayerCount: {num}/2");
			}
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	public static class SyncShipUnlockablesPatch
	{
		[HarmonyPatch(typeof(StartOfRound), "SyncShipUnlockablesServerRpc")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ServerTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			bool flag = false;
			int num = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (num != 2)
				{
					if (!flag && ((object)instruction).ToString() == "callvirt bool Unity.Netcode.NetworkManager::get_IsHost()")
					{
						flag = true;
					}
					else if (((object)instruction).ToString().StartsWith("ldc.i4.4 NULL"))
					{
						num++;
						CodeInstruction val = new CodeInstruction(instruction);
						val.opcode = OpCodes.Ldsfld;
						val.operand = AccessTools.Field(typeof(MainClass), "newPlayerCount");
						list.Add(val);
						continue;
					}
				}
				list.Add(instruction);
			}
			if (num != 2)
			{
				MainClass.StaticLogger.LogWarning((object)$"SyncShipUnlockablesServerRpc failed to replace newPlayerCount: {num}/2");
			}
			return list.AsEnumerable();
		}

		[HarmonyPatch(typeof(StartOfRound), "SyncShipUnlockablesClientRpc")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ClientTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			bool flag = false;
			bool flag2 = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (!flag2)
				{
					if (!flag && ((object)instruction).ToString() == "callvirt void UnityEngine.Renderer::set_sharedMaterial(UnityEngine.Material value)")
					{
						flag = true;
					}
					else if (flag && ((object)instruction).ToString() == "ldc.i4.4 NULL")
					{
						flag2 = true;
						CodeInstruction item = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(MainClass), "newPlayerCount"));
						list.Add(item);
						continue;
					}
				}
				list.Add(instruction);
			}
			if (!flag2)
			{
				MainClass.StaticLogger.LogWarning((object)"SyncShipUnlockablesClientRpc failed to replace newPlayerCount");
			}
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(NetworkSceneManager), "PopulateScenePlacedObjects")]
	public static class ScenePlacedObjectsInitPatch
	{
		public static void Postfix(ref Dictionary<uint, Dictionary<int, NetworkObject>> ___ScenePlacedObjects)
		{
			MainClass.ResizePlayerCache(___ScenePlacedObjects);
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager), "LobbyDataIsJoinable")]
	public static class LobbyDataJoinablePatch
	{
		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			bool flag = false;
			bool flag2 = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (!flag2)
				{
					if (!flag && ((object)instruction).ToString() == "call int Steamworks.Data.Lobby::get_MemberCount()")
					{
						flag = true;
					}
					else if (flag && ((object)instruction).ToString() == "ldc.i4.4 NULL")
					{
						flag2 = true;
						CodeInstruction item = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(MainClass), "maxPlayerCount"));
						list.Add(item);
						continue;
					}
				}
				list.Add(instruction);
			}
			if (!flag2)
			{
				MainClass.StaticLogger.LogWarning((object)"LobbyDataIsJoinable failed to replace maxPlayerCount");
			}
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(SteamMatchmaking), "CreateLobbyAsync")]
	public static class LobbyThingPatch
	{
		public static void Prefix(ref int maxMembers)
		{
			MainClass.ReadSettingsFromFile();
			maxMembers = MainClass.newPlayerCount;
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager), "ConnectionApproval")]
	public static class ConnectionApproval
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			bool flag = false;
			bool flag2 = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (!flag2)
				{
					if (!flag && ((object)instruction).ToString() == "ldfld int GameNetworkManager::connectedPlayers")
					{
						flag = true;
					}
					else if (flag && ((object)instruction).ToString() == "ldc.i4.4 NULL")
					{
						flag2 = true;
						CodeInstruction item = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(MainClass), "newPlayerCount"));
						list.Add(item);
						continue;
					}
				}
				list.Add(instruction);
			}
			if (!flag2)
			{
				MainClass.StaticLogger.LogWarning((object)"ConnectionApproval failed to replace newPlayerCount");
			}
			return list.AsEnumerable();
		}

		private static void Postfix(ref GameNetworkManager __instance, ref ConnectionApprovalRequest request, ref ConnectionApprovalResponse response)
		{
			if (response.Approved && __instance.disableSteam)
			{
				string @string = Encoding.ASCII.GetString(request.Payload);
				string[] array = @string.Split(",");
				if (!string.IsNullOrEmpty(@string) && (array.Length < 2 || array[1] != MainClass.newPlayerCount.ToString()))
				{
					response.Reason = $"Crew size mismatch! Their size: {MainClass.newPlayerCount}. Your size: {array[1]}";
					response.Approved = false;
				}
			}
		}
	}
	[HarmonyPatch]
	public static class TogglePlayerObjectsPatch
	{
		[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
		[HarmonyPrefix]
		private static void ConnectClientToPlayerObject()
		{
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (val.isPlayerControlled || val.isPlayerDead)
				{
					((Component)val).gameObject.SetActive(true);
				}
				else
				{
					((Component)val).gameObject.SetActive(false);
				}
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "OnPlayerConnectedClientRpc")]
		[HarmonyPrefix]
		private static void OnPlayerConnectedClientRpc(StartOfRound __instance, ulong clientId, int connectedPlayers, ulong[] connectedPlayerIdsOrdered, int assignedPlayerObjectId, int serverMoneyAmount, int levelID, int profitQuota, int timeUntilDeadline, int quotaFulfilled, int randomSeed, bool isChallenge)
		{
			((Component)__instance.allPlayerScripts[assignedPlayerObjectId]).gameObject.SetActive(true);
			SoundManager.Instance.playerVoiceVolumes[assignedPlayerObjectId] = 0.5f;
		}

		[HarmonyPatch(typeof(StartOfRound), "OnPlayerDC")]
		[HarmonyPostfix]
		private static void OnPlayerDC(StartOfRound __instance, int playerObjectNumber, ulong clientId)
		{
			((Component)__instance.allPlayerScripts[playerObjectNumber]).gameObject.SetActive(false);
		}
	}
	public class ReflectionUtils
	{
		public static void InvokeMethod(object obj, string methodName, object[] parameters)
		{
			Type type = obj.GetType();
			MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			method.Invoke(obj, parameters);
		}

		public static void InvokeMethod(object obj, Type forceType, string methodName, object[] parameters)
		{
			MethodInfo method = forceType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			method.Invoke(obj, parameters);
		}

		public static void SetPropertyValue(object obj, string propertyName, object value)
		{
			Type type = obj.GetType();
			PropertyInfo property = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			property.SetValue(obj, value);
		}

		public static T InvokeMethod<T>(object obj, string methodName, object[] parameters)
		{
			Type type = obj.GetType();
			MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			return (T)method.Invoke(obj, parameters);
		}

		public static T GetFieldValue<T>(object obj, string fieldName)
		{
			Type type = obj.GetType();
			FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			return (T)field.GetValue(obj);
		}

		public static void SetFieldValue(object obj, string fieldName, object value)
		{
			Type type = obj.GetType();
			FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			field.SetValue(obj, value);
		}
	}
	[HarmonyPatch(typeof(ShipTeleporter), "Awake")]
	public static class ShipTeleporterAwakePatch
	{
		public static void Postfix(ref ShipTeleporter __instance)
		{
			int[] array = new int[MainClass.newPlayerCount];
			for (int i = 0; i < MainClass.newPlayerCount; i++)
			{
				array[i] = -1;
			}
			ReflectionUtils.SetFieldValue(__instance, "playersBeingTeleported", array);
		}
	}
	[HarmonyPatch]
	public static class SoundManagerPatch
	{
		internal const float defaultPlayerVolume = 0.5f;

		internal static bool initialVolumeSet;

		[HarmonyPatch(typeof(SoundManager), "Start")]
		[HarmonyPostfix]
		public static void SM_Start(ref SoundManager __instance)
		{
			initialVolumeSet = false;
			float num = 16f;
			__instance.diageticMixer.SetFloat("PlayerVolume0", num);
			__instance.diageticMixer.SetFloat("PlayerVolume1", num);
			__instance.diageticMixer.SetFloat("PlayerVolume2", num);
			__instance.diageticMixer.SetFloat("PlayerVolume3", num);
			initialVolumeSet = true;
			Array.Resize(ref __instance.playerVoicePitchLerpSpeed, MainClass.newPlayerCount);
			Array.Resize(ref __instance.playerVoicePitchTargets, MainClass.newPlayerCount);
			Array.Resize(ref __instance.playerVoicePitches, MainClass.newPlayerCount);
			Array.Resize(ref __instance.playerVoiceVolumes, MainClass.newPlayerCount);
			Array.Resize(ref __instance.playerVoiceMixers, MainClass.newPlayerCount);
			AudioMixerGroup val = ((IEnumerable<AudioMixerGroup>)Resources.FindObjectsOfTypeAll<AudioMixerGroup>()).FirstOrDefault((Func<AudioMixerGroup, bool>)((AudioMixerGroup x) => ((Object)x).name.StartsWith("VoicePlayer")));
			for (int i = 0; i < MainClass.newPlayerCount; i++)
			{
				__instance.playerVoicePitchLerpSpeed[i] = 3f;
				__instance.playerVoicePitchTargets[i] = 1f;
				__instance.playerVoicePitches[i] = 1f;
				__instance.playerVoiceVolumes[i] = 0.5f;
				if (!Object.op_Implicit((Object)(object)__instance.playerVoiceMixers[i]))
				{
					__instance.playerVoiceMixers[i] = val;
				}
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "GetPlayerSpawnPosition")]
	public static class SpawnPositionClampPatch
	{
		public static void Prefix(ref StartOfRound __instance, ref int playerNum, bool simpleTeleport = false)
		{
			if (!Object.op_Implicit((Object)(object)__instance.playerSpawnPositions[playerNum]))
			{
				playerNum = __instance.playerSpawnPositions.Length - 1;
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "OnClientConnect")]
	public static class OnClientConnectedPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			bool flag = false;
			bool flag2 = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (!flag2)
				{
					if (!flag && ((object)instruction).ToString() == "callvirt virtual bool System.Collections.Generic.List<int>::Contains(int item)")
					{
						flag = true;
					}
					else if (flag && ((object)instruction).ToString() == "ldc.i4.4 NULL")
					{
						flag2 = true;
						CodeInstruction item = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(MainClass), "newPlayerCount"));
						list.Add(item);
						continue;
					}
				}
				list.Add(instruction);
			}
			if (!flag2)
			{
				MainClass.StaticLogger.LogWarning((object)"OnClientConnect failed to replace newPlayerCount");
			}
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "OnPlayerDC")]
	public static class OnPlayerDCPatch
	{
		public static void Postfix(int playerObjectNumber, ulong clientId)
		{
			if (MainClass.playerIdsAndCosmetics.ContainsKey(playerObjectNumber))
			{
				MainClass.playerIdsAndCosmetics.Remove(playerObjectNumber);
			}
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	public static class LoadLobbyListAndFilterPatch
	{
		private static void Postfix()
		{
			LobbySlot[] array = Object.FindObjectsOfType<LobbySlot>();
			LobbySlot[] array2 = array;
			foreach (LobbySlot val in array2)
			{
				((TMP_Text)val.playerCount).text = $"{((Lobby)(ref val.thisLobby)).MemberCount} / {((Lobby)(ref val.thisLobby)).MaxMembers}";
			}
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager), "Awake")]
	public static class GameNetworkAwakePatch
	{
		public static int originalVersion;

		public static void Postfix(GameNetworkManager __instance)
		{
			originalVersion = __instance.gameVersionNum;
			if (!Chainloader.PluginInfos.ContainsKey("LC_API"))
			{
				__instance.gameVersionNum = 9950 + originalVersion;
			}
		}
	}
	[HarmonyPatch(typeof(MenuManager), "Awake")]
	public static class MenuManagerVersionDisplayPatch
	{
		public static void Postfix(MenuManager __instance)
		{
			if ((Object)(object)GameNetworkManager.Instance != (Object)null && (Object)(object)__instance.versionNumberText != (Object)null)
			{
				((TMP_Text)__instance.versionNumberText).text = $"v{GameNetworkAwakePatch.originalVersion} (MC)";
			}
		}
	}
}
namespace MoreCompany.Utils
{
	public class BundleUtilities
	{
		public static byte[] GetResourceBytes(string filename, Assembly assembly)
		{
			string[] manifestResourceNames = assembly.GetManifestResourceNames();
			foreach (string text in manifestResourceNames)
			{
				if (!text.Contains(filename))
				{
					continue;
				}
				using Stream stream = assembly.GetManifestResourceStream(text);
				if (stream == null)
				{
					return null;
				}
				byte[] array = new byte[stream.Length];
				stream.Read(array, 0, array.Length);
				return array;
			}
			return null;
		}

		public static AssetBundle LoadBundleFromInternalAssembly(string filename, Assembly assembly)
		{
			return AssetBundle.LoadFromMemory(GetResourceBytes(filename, assembly));
		}
	}
	public static class AssetBundleExtension
	{
		public static T LoadPersistentAsset<T>(this AssetBundle bundle, string name) where T : Object
		{
			Object val = bundle.LoadAsset(name);
			if (val != (Object)null)
			{
				val.hideFlags = (HideFlags)32;
				return (T)(object)val;
			}
			return default(T);
		}
	}
}
namespace MoreCompany.Cosmetics
{
	public class CosmeticApplication : MonoBehaviour
	{
		public bool detachedHead = false;

		public Transform head;

		public Transform hip;

		public Transform lowerArmRight;

		public Transform shinLeft;

		public Transform shinRight;

		public Transform chest;

		public List<CosmeticInstance> spawnedCosmetics = new List<CosmeticInstance>();

		public void Awake()
		{
			Transform val = ((Component)this).transform.Find("spine") ?? ((Component)this).transform;
			head = val.Find("spine.001").Find("spine.002").Find("spine.003")
				.Find("spine.004");
			chest = val.Find("spine.001").Find("spine.002").Find("spine.003");
			lowerArmRight = val.Find("spine.001").Find("spine.002").Find("spine.003")
				.Find("shoulder.R")
				.Find("arm.R_upper")
				.Find("arm.R_lower");
			hip = val;
			shinLeft = val.Find("thigh.L").Find("shin.L");
			shinRight = val.Find("thigh.R").Find("shin.R");
			RefreshAllCosmeticPositions();
		}

		private void OnDisable()
		{
			foreach (CosmeticInstance spawnedCosmetic in spawnedCosmetics)
			{
				((Component)spawnedCosmetic).gameObject.SetActive(false);
			}
		}

		private void OnEnable()
		{
			foreach (CosmeticInstance spawnedCosmetic in spawnedCosmetics)
			{
				((Component)spawnedCosmetic).gameObject.SetActive(true);
			}
		}

		public void ClearCosmetics()
		{
			foreach (CosmeticInstance spawnedCosmetic in spawnedCosmetics)
			{
				Object.Destroy((Object)(object)((Component)spawnedCosmetic).gameObject);
			}
			spawnedCosmetics.Clear();
		}

		public void ApplyCosmetic(string cosmeticId, bool startEnabled)
		{
			if (!CosmeticRegistry.cosmeticInstances.ContainsKey(cosmeticId))
			{
				return;
			}
			CosmeticInstance cosmeticInstance = CosmeticRegistry.cosmeticInstances[cosmeticId];
			if (!startEnabled || cosmeticInstance.cosmeticType != 0 || !detachedHead)
			{
				GameObject val = Object.Instantiate<GameObject>(((Component)cosmeticInstance).gameObject);
				val.SetActive(startEnabled);
				CosmeticInstance component = val.GetComponent<CosmeticInstance>();
				spawnedCosmetics.Add(component);
				if (startEnabled)
				{
					ParentCosmetic(component);
				}
			}
		}

		public void RefreshAllCosmeticPositions()
		{
			foreach (CosmeticInstance spawnedCosmetic in spawnedCosmetics)
			{
				ParentCosmetic(spawnedCosmetic);
			}
		}

		private void ParentCosmetic(CosmeticInstance cosmeticInstance)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			Transform val = null;
			switch (cosmeticInstance.cosmeticType)
			{
			case CosmeticType.HAT:
				val = head;
				break;
			case CosmeticType.R_LOWER_ARM:
				val = lowerArmRight;
				break;
			case CosmeticType.HIP:
				val = hip;
				break;
			case CosmeticType.L_SHIN:
				val = shinLeft;
				break;
			case CosmeticType.R_SHIN:
				val = shinRight;
				break;
			case CosmeticType.CHEST:
				val = chest;
				break;
			}
			if ((Object)(object)val == (Object)null)
			{
				MainClass.StaticLogger.LogError((object)("Failed to find transform of type: " + cosmeticInstance.cosmeticType));
				return;
			}
			((Component)cosmeticInstance).transform.position = val.position;
			((Component)cosmeticInstance).transform.rotation = val.rotation;
			((Component)cosmeticInstance).transform.parent = val;
		}
	}
	public class CosmeticInstance : MonoBehaviour
	{
		public CosmeticType cosmeticType;

		public string cosmeticId;

		public Texture2D icon;
	}
	public class CosmeticGeneric
	{
		public virtual string gameObjectPath { get; }

		public virtual string cosmeticId { get; }

		public virtual string textureIconPath { get; }

		public CosmeticType cosmeticType { get; }

		public void LoadFromBundle(AssetBundle bundle)
		{
			GameObject val = bundle.LoadPersistentAsset<GameObject>(gameObjectPath);
			Texture2D icon = bundle.LoadPersistentAsset<Texture2D>(textureIconPath);
			CosmeticInstance cosmeticInstance = val.AddComponent<CosmeticInstance>();
			cosmeticInstance.cosmeticId = cosmeticId;
			cosmeticInstance.icon = icon;
			cosmeticInstance.cosmeticType = cosmeticType;
			MainClass.StaticLogger.LogInfo((object)("Loaded cosmetic: " + cosmeticId + " from bundle: " + ((Object)bundle).name));
			CosmeticRegistry.cosmeticInstances.Add(cosmeticId, cosmeticInstance);
		}
	}
	public enum CosmeticType
	{
		HAT,
		WRIST,
		CHEST,
		R_LOWER_ARM,
		HIP,
		L_SHIN,
		R_SHIN
	}
	public class CosmeticRegistry
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__9_0;

			public static UnityAction <>9__9_1;

			internal void <SpawnCosmeticGUI>b__9_0()
			{
				MainClass.cosmeticsSyncOther.Value = true;
				MainClass.StaticConfig.Save();
			}

			internal void <SpawnCosmeticGUI>b__9_1()
			{
				MainClass.cosmeticsSyncOther.Value = false;
				MainClass.StaticConfig.Save();
			}
		}

		public static Dictionary<string, CosmeticInstance> cosmeticInstances = new Dictionary<string, CosmeticInstance>();

		public static GameObject cosmeticGUI;

		private static GameObject displayGuy;

		private static CosmeticApplication cosmeticApplication;

		public static List<string> locallySelectedCosmetics = new List<string>();

		public const float COSMETIC_PLAYER_SCALE_MULT = 0.38f;

		public static void LoadCosmeticsFromBundle(AssetBundle bundle)
		{
			string[] allAssetNames = bundle.GetAllAssetNames();
			foreach (string text in allAssetNames)
			{
				if (!text.EndsWith(".prefab"))
				{
					continue;
				}
				GameObject val = bundle.LoadPersistentAsset<GameObject>(text);
				CosmeticInstance component = val.GetComponent<CosmeticInstance>();
				if (!((Object)(object)component == (Object)null))
				{
					MainClass.StaticLogger.LogInfo((object)("Loaded cosmetic: " + component.cosmeticId + " from bundle"));
					if (cosmeticInstances.ContainsKey(component.cosmeticId))
					{
						MainClass.StaticLogger.LogError((object)("Duplicate cosmetic id: " + component.cosmeticId));
					}
					else
					{
						cosmeticInstances.Add(component.cosmeticId, component);
					}
				}
			}
		}

		public static void LoadCosmeticsFromAssembly(Assembly assembly, AssetBundle bundle)
		{
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				if (type.IsSubclassOf(typeof(CosmeticGeneric)))
				{
					CosmeticGeneric cosmeticGeneric = (CosmeticGeneric)type.GetConstructor(new Type[0]).Invoke(new object[0]);
					cosmeticGeneric.LoadFromBundle(bundle);
				}
			}
		}

		public static void UpdateVisibilityCheckbox(GameObject enableCosmeticsButton, GameObject disableCosmeticsButton)
		{
			if (MainClass.cosmeticsSyncOther.Value)
			{
				enableCosmeticsButton.SetActive(false);
				disableCosmeticsButton.SetActive(true);
			}
			else
			{
				enableCosmeticsButton.SetActive(true);
				disableCosmeticsButton.SetActive(false);
			}
		}

		public static void SpawnCosmeticGUI()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Expected O, but got Unknown
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Expected O, but got Unknown
			cosmeticGUI = Object.Instantiate<GameObject>(MainClass.cosmeticGUIInstance);
			((Component)cosmeticGUI.transform.Find("Canvas").Find("GlobalScale")).transform.localScale = new Vector3(2f, 2f, 2f);
			displayGuy = ((Component)cosmeticGUI.transform.Find("Canvas").Find("GlobalScale").Find("CosmeticsScreen")
				.Find("ObjectHolder")
				.Find("ScavengerModel")
				.Find("metarig")).gameObject;
			cosmeticApplication = displayGuy.AddComponent<CosmeticApplication>();
			GameObject gameObject = ((Component)cosmeticGUI.transform.Find("Canvas").Find("GlobalScale").Find("CosmeticsScreen")
				.Find("EnableButton")).gameObject;
			GameObject gameObject2 = ((Component)cosmeticGUI.transform.Find("Canvas").Find("GlobalScale").Find("CosmeticsScreen")
				.Find("DisableButton")).gameObject;
			ButtonClickedEvent onClick = gameObject.GetComponent<Button>().onClick;
			object obj = <>c.<>9__9_0;
			if (obj == null)
			{
				UnityAction val = delegate
				{
					MainClass.cosmeticsSyncOther.Value = true;
					MainClass.StaticConfig.Save();
				};
				<>c.<>9__9_0 = val;
				obj = (object)val;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			ButtonClickedEvent onClick2 = gameObject2.GetComponent<Button>().onClick;
			object obj2 = <>c.<>9__9_1;
			if (obj2 == null)
			{
				UnityAction val2 = delegate
				{
					MainClass.cosmeticsSyncOther.Value = false;
					MainClass.StaticConfig.Save();
				};
				<>c.<>9__9_1 = val2;
				obj2 = (object)val2;
			}
			((UnityEvent)onClick2).AddListener((UnityAction)obj2);
			UpdateVisibilityCheckbox(gameObject, gameObject2);
			PopulateCosmetics();
			UpdateCosmeticsOnDisplayGuy(startEnabled: false);
		}

		public static void PopulateCosmetics()
		{
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Expected O, but got Unknown
			GameObject gameObject = ((Component)cosmeticGUI.transform.Find("Canvas").Find("GlobalScale").Find("CosmeticsScreen")
				.Find("CosmeticsHolder")
				.Find("Content")).gameObject;
			List<Transform> list = new List<Transform>();
			for (int i = 0; i < gameObject.transform.childCount; i++)
			{
				list.Add(gameObject.transform.GetChild(i));
			}
			foreach (Transform item in list)
			{
				Object.Destroy((Object)(object)((Component)item).gameObject);
			}
			foreach (KeyValuePair<string, CosmeticInstance> cosmeticInstance in cosmeticInstances)
			{
				GameObject val = Object.Instantiate<GameObject>(MainClass.cosmeticButton, gameObject.transform);
				val.transform.localScale = Vector3.one;
				GameObject disabledOverlay = ((Component)val.transform.Find("Deselected")).gameObject;
				disabledOverlay.SetActive(true);
				GameObject enabledOverlay = ((Component)val.transform.Find("Selected")).gameObject;
				enabledOverlay.SetActive(true);
				if (IsEquipped(cosmeticInstance.Value.cosmeticId))
				{
					enabledOverlay.SetActive(true);
					disabledOverlay.SetActive(false);
				}
				else
				{
					enabledOverlay.SetActive(false);
					disabledOverlay.SetActive(true);
				}
				RawImage component = ((Component)val.transform.Find("Icon")).GetComponent<RawImage>();
				component.texture = (Texture)(object)cosmeticInstance.Value.icon;
				Button component2 = val.GetComponent<Button>();
				((UnityEvent)component2.onClick).AddListener((UnityAction)delegate
				{
					ToggleCosmetic(cosmeticInstance.Value.cosmeticId);
					if (IsEquipped(cosmeticInstance.Value.cosmeticId))
					{
						enabledOverlay.SetActive(true);
						disabledOverlay.SetActive(false);
					}
					else
					{
						enabledOverlay.SetActive(false);
						disabledOverlay.SetActive(true);
					}
					MainClass.WriteCosmeticsToFile();
					UpdateCosmeticsOnDisplayGuy(startEnabled: true);
				});
			}
		}

		private static Color HexToColor(string hex)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			Color result = default(Color);
			ColorUtility.TryParseHtmlString(hex, ref result);
			return result;
		}

		public static void UpdateCosmeticsOnDisplayGuy(bool startEnabled)
		{
			cosmeticApplication.ClearCosmetics();
			foreach (string locallySelectedCosmetic in locallySelectedCosmetics)
			{
				cosmeticApplication.ApplyCosmetic(locallySelectedCosmetic, startEnabled);
			}
			foreach (CosmeticInstance spawnedCosmetic in cosmeticApplication.spawnedCosmetics)
			{
				RecursiveLayerChange(((Component)spawnedCosmetic).transform, 5);
			}
		}

		private static void RecursiveLayerChange(Transform transform, int layer)
		{
			((Component)transform).gameObject.layer = layer;
			for (int i = 0; i < transform.childCount; i++)
			{
				RecursiveLayerChange(transform.GetChild(i), layer);
			}
		}

		public static bool IsEquipped(string cosmeticId)
		{
			return locallySelectedCosmetics.Contains(cosmeticId);
		}

		public static void ToggleCosmetic(string cosmeticId)
		{
			if (locallySelectedCosmetics.Contains(cosmeticId))
			{
				locallySelectedCosmetics.Remove(cosmeticId);
			}
			else
			{
				locallySelectedCosmetics.Add(cosmeticId);
			}
		}
	}
}
namespace MoreCompany.Behaviors
{
	public class SpinDragger : MonoBehaviour, IPointerDownHandler, IEventSystemHandler, IPointerUpHandler
	{
		public float speed = 1f;

		private Vector2 lastMousePosition;

		private bool dragging = false;

		private Vector3 rotationalVelocity = Vector3.zero;

		public float dragSpeed = 1f;

		public float airDrag = 0.99f;

		public GameObject target;

		private void Update()
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if (dragging)
			{
				Vector3 val = Vector2.op_Implicit(((InputControl<Vector2>)(object)((Pointer)Mouse.current).position).ReadValue() - lastMousePosition);
				rotationalVelocity += new Vector3(0f, 0f - val.x, 0f) * dragSpeed;
				lastMousePosition = ((InputControl<Vector2>)(object)((Pointer)Mouse.current).position).ReadValue();
			}
			rotationalVelocity *= airDrag;
			target.transform.Rotate(rotationalVelocity * Time.deltaTime * speed, (Space)0);
		}

		public void OnPointerDown(PointerEventData eventData)
		{
			//IL_000c: 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)
			lastMousePosition = ((InputControl<Vector2>)(object)((Pointer)Mouse.current).position).ReadValue();
			dragging = true;
		}

		public void OnPointerUp(PointerEventData eventData)
		{
			dragging = false;
		}
	}
}

plugins/MoreItems.dll

Decompiled 2 months ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MoreItems.Patches;

[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("MoreItems")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("My first plugin")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2")]
[assembly: AssemblyProduct("MoreItems")]
[assembly: AssemblyTitle("MoreItems")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.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 MoreItems
{
	[BepInPlugin("MoreItems", "MoreItems", "1.0.2")]
	public class Plugin : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("MoreItems");

		private void Awake()
		{
			try
			{
				harmony.PatchAll(typeof(GameNetworkManagerPatch));
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin MoreItems is loaded!");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Plugin MoreItems failed to load and threw an exception:\n" + ex.Message));
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "MoreItems";

		public const string PLUGIN_NAME = "MoreItems";

		public const string PLUGIN_VERSION = "1.0.2";
	}
}
namespace MoreItems.Patches
{
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal class GameNetworkManagerPatch
	{
		private const int newMaxItemCapacity = 999;

		[HarmonyPatch("SaveItemsInShip")]
		[HarmonyPrefix]
		private static void IncreaseShipItemCapacity()
		{
			StartOfRound.Instance.maxShipItemCapacity = 999;
			Logger.CreateLogSource("MoreItems").LogInfo((object)$"Maximum amount of items that can be saved set to {999} just before saving.");
		}
	}
}

plugins/MoreScreams.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dissonance.Audio.Playback;
using GameNetcodeStuff;
using HarmonyLib;
using MoreScreams.Configuration;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("MoreScreams")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MoreScreams")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("ba7e5619-9c03-4b8d-9888-381fda81ea0f")]
[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 MoreScreams
{
	[BepInPlugin("egeadam.MoreScreams", "MoreScreams", "1.0.3")]
	public class MoreScreams : BaseUnityPlugin
	{
		private const string modGUID = "egeadam.MoreScreams";

		private const string modName = "MoreScreams";

		private const string modVersion = "1.0.3";

		private readonly Harmony harmony = new Harmony("egeadam.MoreScreams");

		private static MoreScreams Instance;

		internal static ManualLogSource mls;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			mls = Logger.CreateLogSource("egeadam.MoreScreams");
			Config.Init();
			harmony.PatchAll();
		}
	}
}
namespace MoreScreams.Patches
{
	public class AudioConfig
	{
		private PlayerControllerB playerControllerB;

		private float shutUpAt;

		private bool lowPassFilter;

		private bool highPassFilter;

		private float panStereo;

		private float playerVoicePitchTargets;

		private float playerPitch;

		private float spatialBlend;

		private bool set2D;

		private float volume;

		public bool IsAliveOrShuttedUp
		{
			get
			{
				if (!(shutUpAt < Time.time))
				{
					return !playerControllerB.isPlayerDead;
				}
				return true;
			}
		}

		public float ShutUpAt => shutUpAt;

		public bool LowPassFilter => lowPassFilter;

		public bool HighPassFilter => highPassFilter;

		public float PanStereo => panStereo;

		public float PlayerVoicePitchTargets => playerVoicePitchTargets;

		public float PlayerPitch => playerPitch;

		public float SpatialBlend => spatialBlend;

		public bool Set2D => set2D;

		public float Volume => volume;

		public Transform DeadBodyT => ((Component)playerControllerB.deadBody).transform;

		public Transform AudioSourceT => ((Component)playerControllerB.currentVoiceChatAudioSource).transform;

		public AudioConfig(PlayerControllerB playerControllerB, float shutUpAt, bool lowPassFilter, bool highPassFilter, float panStereo, float playerVoicePitchTargets, float playerPitch, float spatialBlend, bool set2D, float volume)
		{
			this.playerControllerB = playerControllerB;
			this.shutUpAt = shutUpAt;
			this.lowPassFilter = lowPassFilter;
			this.highPassFilter = highPassFilter;
			this.panStereo = panStereo;
			this.playerVoicePitchTargets = playerVoicePitchTargets;
			this.playerPitch = playerPitch;
			this.spatialBlend = spatialBlend;
			this.set2D = set2D;
			this.volume = volume;
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "UpdatePlayerVoiceEffects")]
	internal class UpdatePlayerVoiceEffectsPatch
	{
		private static bool updateStarted = false;

		private static Dictionary<PlayerControllerB, AudioConfig> configs = new Dictionary<PlayerControllerB, AudioConfig>();

		public static Dictionary<PlayerControllerB, AudioConfig> Configs => configs;

		[HarmonyBefore(new string[] { "BiggerLobby" })]
		private static void Prefix()
		{
			if (configs == null)
			{
				configs = new Dictionary<PlayerControllerB, AudioConfig>();
			}
			if (!updateStarted)
			{
				((MonoBehaviour)HUDManager.Instance).StartCoroutine(UpdateNumerator());
				updateStarted = true;
			}
			if ((Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.allPlayerScripts == null)
			{
				return;
			}
			for (int i = 0; i < StartOfRound.Instance.allPlayerScripts.Length; i++)
			{
				PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[i];
				if (!((Object)(object)val == (Object)null) && (val.isPlayerControlled || val.isPlayerDead) && (Object)(object)val != (Object)(object)GameNetworkManager.Instance.localPlayerController)
				{
					AudioSource currentVoiceChatAudioSource = val.currentVoiceChatAudioSource;
					if (!((Object)(object)currentVoiceChatAudioSource == (Object)null) && val.isPlayerDead && !configs.ContainsKey(val))
					{
						Dictionary<PlayerControllerB, AudioConfig> dictionary = configs;
						float shutUpAt = Time.time + Config.ShutUpAfter;
						bool enabled = ((Behaviour)((Component)currentVoiceChatAudioSource).GetComponent<AudioLowPassFilter>()).enabled;
						bool enabled2 = ((Behaviour)((Component)currentVoiceChatAudioSource).GetComponent<AudioHighPassFilter>()).enabled;
						float panStereo = (currentVoiceChatAudioSource.panStereo = 0f);
						dictionary.Add(val, new AudioConfig(val, shutUpAt, enabled, enabled2, panStereo, SoundManager.Instance.playerVoicePitchTargets[(int)(IntPtr)(long)val.playerClientId], GetPitch(val), currentVoiceChatAudioSource.spatialBlend, val.currentVoiceChatIngameSettings.set2D, val.voicePlayerState.Volume));
					}
				}
			}
		}

		private static void Postfix()
		{
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			if (configs == null)
			{
				configs = new Dictionary<PlayerControllerB, AudioConfig>();
			}
			if ((Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null)
			{
				return;
			}
			PlayerControllerB[] array = configs.Keys.ToArray();
			foreach (PlayerControllerB val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				AudioConfig audioConfig = configs[val];
				if (audioConfig == null)
				{
					continue;
				}
				if ((val.isPlayerControlled || val.isPlayerDead) && !((Object)(object)val == (Object)(object)GameNetworkManager.Instance.localPlayerController))
				{
					if ((Object)(object)val.currentVoiceChatAudioSource == (Object)null)
					{
						continue;
					}
					AudioSource currentVoiceChatAudioSource = val.currentVoiceChatAudioSource;
					if (!audioConfig.IsAliveOrShuttedUp)
					{
						if ((Object)(object)val.deadBody != (Object)null)
						{
							((Component)currentVoiceChatAudioSource).transform.position = ((Component)val.deadBody).transform.position;
						}
						currentVoiceChatAudioSource.panStereo = audioConfig.PanStereo;
						currentVoiceChatAudioSource.spatialBlend = audioConfig.SpatialBlend;
						AudioLowPassFilter component = ((Component)currentVoiceChatAudioSource).GetComponent<AudioLowPassFilter>();
						AudioHighPassFilter component2 = ((Component)currentVoiceChatAudioSource).GetComponent<AudioHighPassFilter>();
						if ((Object)(object)component != (Object)null)
						{
							((Behaviour)component).enabled = audioConfig.LowPassFilter;
						}
						if ((Object)(object)component2 != (Object)null)
						{
							((Behaviour)component2).enabled = audioConfig.HighPassFilter;
						}
						if ((Object)(object)SoundManager.Instance != (Object)null)
						{
							SoundManager.Instance.playerVoicePitchTargets[(int)(IntPtr)(long)val.playerClientId] = audioConfig.PlayerVoicePitchTargets;
							SoundManager.Instance.SetPlayerPitch(audioConfig.PlayerPitch, (int)val.playerClientId);
						}
						val.currentVoiceChatIngameSettings.set2D = audioConfig.Set2D;
						val.voicePlayerState.Volume = audioConfig.Volume;
						val.currentVoiceChatAudioSource.volume = audioConfig.Volume;
					}
				}
				else if (!val.isPlayerDead)
				{
					configs.Remove(val);
				}
			}
		}

		private static IEnumerator UpdateNumerator()
		{
			yield return 0;
			while (true)
			{
				UpdatePlayersStatus();
				yield return (object)new WaitForFixedUpdate();
			}
		}

		private static void UpdatePlayersStatus()
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			if (configs == null)
			{
				return;
			}
			bool flag = false;
			KeyValuePair<PlayerControllerB, AudioConfig>[] array = configs.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<PlayerControllerB, AudioConfig> keyValuePair = array[i];
				if (!((Object)(object)keyValuePair.Key == (Object)null))
				{
					if (!keyValuePair.Key.isPlayerDead)
					{
						configs.Remove(keyValuePair.Key);
						flag = true;
					}
					else if ((Object)(object)keyValuePair.Value.DeadBodyT != (Object)null && (Object)(object)keyValuePair.Value.AudioSourceT != (Object)null)
					{
						keyValuePair.Value.AudioSourceT.position = keyValuePair.Value.DeadBodyT.position;
					}
				}
			}
			if (flag)
			{
				StartOfRound.Instance.UpdatePlayerVoiceEffects();
			}
		}

		private static float GetPitch(PlayerControllerB playerControllerB)
		{
			int num = (int)playerControllerB.playerClientId;
			float result = default(float);
			SoundManager.Instance.diageticMixer.GetFloat($"PlayerPitch{num}", ref result);
			return result;
		}
	}
	[HarmonyPatch]
	internal class DissonancePatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.FirstMethod(typeof(VoicePlayback), (Func<MethodInfo, bool>)((MethodInfo method) => method.Name.Contains("SetTransform")));
		}

		private static bool Prefix(object __instance)
		{
			foreach (AudioConfig value in UpdatePlayerVoiceEffectsPatch.Configs.Values)
			{
				if (!value.IsAliveOrShuttedUp && ((object)((Component)((__instance is VoicePlayback) ? __instance : null)).transform).Equals((object?)value.AudioSourceT))
				{
					return false;
				}
			}
			return true;
		}
	}
}
namespace MoreScreams.Configuration
{
	internal static class Config
	{
		private const string CONFIG_FILE_NAME = "MoreScreams.cfg";

		private static ConfigFile config;

		private static ConfigEntry<float> shutUpAfter;

		public static float ShutUpAfter => shutUpAfter.Value;

		public static void Init()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			config = new ConfigFile(Path.Combine(Paths.ConfigPath, "MoreScreams.cfg"), true);
			shutUpAfter = config.Bind<float>("Config", "Shut up after", 2f, "Mutes death player after given seconds.");
		}
	}
}

plugins/MoreSuits.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("MoreSuits")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A mod that adds more suit options to Lethal Company")]
[assembly: AssemblyFileVersion("1.4.3.0")]
[assembly: AssemblyInformationalVersion("1.4.3")]
[assembly: AssemblyProduct("MoreSuits")]
[assembly: AssemblyTitle("MoreSuits")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.3.0")]
[module: UnverifiableCode]
namespace MoreSuits;

[BepInPlugin("x753.More_Suits", "More Suits", "1.4.3")]
public class MoreSuitsMod : BaseUnityPlugin
{
	[HarmonyPatch(typeof(StartOfRound))]
	internal class StartOfRoundPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPrefix]
		private static void StartPatch(ref StartOfRound __instance)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0695: Unknown result type (might be due to invalid IL or missing references)
			//IL_069a: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_0409: Expected O, but got Unknown
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Expected O, but got Unknown
			//IL_05b1: 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_020b: Expected O, but got Unknown
			try
			{
				if (SuitsAdded)
				{
					return;
				}
				int count = __instance.unlockablesList.unlockables.Count;
				UnlockableItem val = new UnlockableItem();
				int num = 0;
				for (int i = 0; i < __instance.unlockablesList.unlockables.Count; i++)
				{
					UnlockableItem val2 = __instance.unlockablesList.unlockables[i];
					if (!((Object)(object)val2.suitMaterial != (Object)null) || !val2.alreadyUnlocked)
					{
						continue;
					}
					val = val2;
					List<string> list = Directory.GetDirectories(Paths.PluginPath, "moresuits", SearchOption.AllDirectories).ToList();
					List<string> list2 = new List<string>();
					List<string> list3 = new List<string>();
					List<string> list4 = DisabledSuits.ToLower().Replace(".png", "").Split(',')
						.ToList();
					List<string> list5 = new List<string>();
					if (!LoadAllSuits)
					{
						foreach (string item2 in list)
						{
							if (File.Exists(Path.Combine(item2, "!less-suits.txt")))
							{
								string[] collection = new string[9] { "glow", "kirby", "knuckles", "luigi", "mario", "minion", "skeleton", "slayer", "smile" };
								list5.AddRange(collection);
								break;
							}
						}
					}
					foreach (string item3 in list)
					{
						if (item3 != "")
						{
							string[] files = Directory.GetFiles(item3, "*.png");
							string[] files2 = Directory.GetFiles(item3, "*.matbundle");
							list2.AddRange(files);
							list3.AddRange(files2);
						}
					}
					list3.Sort();
					list2.Sort();
					try
					{
						foreach (string item4 in list3)
						{
							Object[] array = AssetBundle.LoadFromFile(item4).LoadAllAssets();
							foreach (Object val3 in array)
							{
								if (val3 is Material)
								{
									Material item = (Material)val3;
									customMaterials.Add(item);
								}
							}
						}
					}
					catch (Exception ex)
					{
						Debug.Log((object)("Something went wrong with More Suits! Could not load materials from asset bundle(s). Error: " + ex));
					}
					foreach (string item5 in list2)
					{
						if (list4.Contains(Path.GetFileNameWithoutExtension(item5).ToLower()))
						{
							continue;
						}
						string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
						if (list5.Contains(Path.GetFileNameWithoutExtension(item5).ToLower()) && item5.Contains(directoryName))
						{
							continue;
						}
						UnlockableItem val4;
						Material val5;
						if (Path.GetFileNameWithoutExtension(item5).ToLower() == "default")
						{
							val4 = val;
							val5 = val4.suitMaterial;
						}
						else
						{
							val4 = JsonUtility.FromJson<UnlockableItem>(JsonUtility.ToJson((object)val));
							val5 = Object.Instantiate<Material>(val4.suitMaterial);
						}
						byte[] array2 = File.ReadAllBytes(item5);
						Texture2D val6 = new Texture2D(2, 2);
						ImageConversion.LoadImage(val6, array2);
						val6.Apply(true, true);
						val5.mainTexture = (Texture)(object)val6;
						val4.unlockableName = Path.GetFileNameWithoutExtension(item5);
						try
						{
							string path = Path.Combine(Path.GetDirectoryName(item5), "advanced", val4.unlockableName + ".json");
							if (File.Exists(path))
							{
								string[] array3 = File.ReadAllLines(path);
								for (int j = 0; j < array3.Length; j++)
								{
									string[] array4 = array3[j].Trim().Split(':');
									if (array4.Length != 2)
									{
										continue;
									}
									string text = array4[0].Trim('"', ' ', ',');
									string text2 = array4[1].Trim('"', ' ', ',');
									if (text2.Contains(".png"))
									{
										byte[] array5 = File.ReadAllBytes(Path.Combine(Path.GetDirectoryName(item5), "advanced", text2));
										Texture2D val7 = new Texture2D(2, 2);
										ImageConversion.LoadImage(val7, array5);
										val7.Apply(true, true);
										val5.SetTexture(text, (Texture)(object)val7);
										continue;
									}
									if (text == "PRICE" && int.TryParse(text2, out var result))
									{
										try
										{
											if (!UnlockAll)
											{
												val4 = AddToRotatingShop(val4, result, __instance.unlockablesList.unlockables.Count);
											}
										}
										catch (Exception ex2)
										{
											Debug.Log((object)("Something went wrong with More Suits! Could not add a suit to the rotating shop. Error: " + ex2));
										}
										continue;
									}
									switch (text2)
									{
									case "KEYWORD":
										val5.EnableKeyword(text);
										continue;
									case "DISABLEKEYWORD":
										val5.DisableKeyword(text);
										continue;
									case "SHADERPASS":
										val5.SetShaderPassEnabled(text, true);
										continue;
									case "DISABLESHADERPASS":
										val5.SetShaderPassEnabled(text, false);
										continue;
									}
									float result2;
									Vector4 vector;
									if (text == "SHADER")
									{
										Shader shader = Shader.Find(text2);
										val5.shader = shader;
									}
									else if (text == "MATERIAL")
									{
										foreach (Material customMaterial in customMaterials)
										{
											if (((Object)customMaterial).name == text2)
											{
												val5 = Object.Instantiate<Material>(customMaterial);
												val5.mainTexture = (Texture)(object)val6;
												break;
											}
										}
									}
									else if (float.TryParse(text2, out result2))
									{
										val5.SetFloat(text, result2);
									}
									else if (TryParseVector4(text2, out vector))
									{
										val5.SetVector(text, vector);
									}
								}
							}
						}
						catch (Exception ex3)
						{
							Debug.Log((object)("Something went wrong with More Suits! Error: " + ex3));
						}
						val4.suitMaterial = val5;
						if (val4.unlockableName.ToLower() != "default")
						{
							if (num == MaxSuits)
							{
								Debug.Log((object)"Attempted to add a suit, but you've already reached the max number of suits! Modify the config if you want more.");
								continue;
							}
							__instance.unlockablesList.unlockables.Add(val4);
							num++;
						}
					}
					SuitsAdded = true;
					break;
				}
				UnlockableItem val8 = JsonUtility.FromJson<UnlockableItem>(JsonUtility.ToJson((object)val));
				val8.alreadyUnlocked = false;
				val8.hasBeenMoved = false;
				val8.placedPosition = Vector3.zero;
				val8.placedRotation = Vector3.zero;
				val8.unlockableType = 753;
				while (__instance.unlockablesList.unlockables.Count < count + MaxSuits)
				{
					__instance.unlockablesList.unlockables.Add(val8);
				}
			}
			catch (Exception ex4)
			{
				Debug.Log((object)("Something went wrong with More Suits! Error: " + ex4));
			}
		}

		[HarmonyPatch("PositionSuitsOnRack")]
		[HarmonyPrefix]
		private static bool PositionSuitsOnRackPatch(ref StartOfRound __instance)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			List<UnlockableSuit> source = Object.FindObjectsOfType<UnlockableSuit>().ToList();
			source = source.OrderBy((UnlockableSuit suit) => suit.syncedSuitID.Value).ToList();
			int num = 0;
			foreach (UnlockableSuit item in source)
			{
				AutoParentToShip component = ((Component)item).gameObject.GetComponent<AutoParentToShip>();
				component.overrideOffset = true;
				float num2 = 0.18f;
				if (MakeSuitsFitOnRack && source.Count > 13)
				{
					num2 /= (float)Math.Min(source.Count, 20) / 12f;
				}
				component.positionOffset = new Vector3(-2.45f, 2.75f, -8.41f) + __instance.rightmostSuitPosition.forward * num2 * (float)num;
				component.rotationOffset = new Vector3(0f, 90f, 0f);
				num++;
			}
			return false;
		}
	}

	private const string modGUID = "x753.More_Suits";

	private const string modName = "More Suits";

	private const string modVersion = "1.4.3";

	private readonly Harmony harmony = new Harmony("x753.More_Suits");

	private static MoreSuitsMod Instance;

	public static bool SuitsAdded = false;

	public static string DisabledSuits;

	public static bool LoadAllSuits;

	public static bool MakeSuitsFitOnRack;

	public static bool UnlockAll;

	public static int MaxSuits;

	public static List<Material> customMaterials = new List<Material>();

	private static TerminalNode cancelPurchase;

	private static TerminalKeyword buyKeyword;

	private void Awake()
	{
		if ((Object)(object)Instance == (Object)null)
		{
			Instance = this;
		}
		DisabledSuits = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Disabled Suit List", "UglySuit751.png,UglySuit752.png,UglySuit753.png", "Comma-separated list of suits that shouldn't be loaded").Value;
		LoadAllSuits = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Ignore !less-suits.txt", false, "If true, ignores the !less-suits.txt file and will attempt to load every suit, except those in the disabled list. This should be true if you're not worried about having too many suits.").Value;
		MakeSuitsFitOnRack = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Make Suits Fit on Rack", true, "If true, squishes the suits together so more can fit on the rack.").Value;
		UnlockAll = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Unlock All Suits", false, "If true, unlocks all custom suits that would normally be sold in the shop.").Value;
		MaxSuits = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Max Suits", 100, "The maximum number of suits to load. If you have more, some will be ignored.").Value;
		harmony.PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin More Suits is loaded!");
	}

	private static UnlockableItem AddToRotatingShop(UnlockableItem newSuit, int price, int unlockableID)
	{
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Expected O, but got Unknown
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Expected O, but got Unknown
		//IL_0298: Unknown result type (might be due to invalid IL or missing references)
		//IL_029f: Expected O, but got Unknown
		Terminal val = Object.FindObjectOfType<Terminal>();
		for (int i = 0; i < val.terminalNodes.allKeywords.Length; i++)
		{
			if (((Object)val.terminalNodes.allKeywords[i]).name == "Buy")
			{
				buyKeyword = val.terminalNodes.allKeywords[i];
				break;
			}
		}
		newSuit.alreadyUnlocked = false;
		newSuit.hasBeenMoved = false;
		newSuit.placedPosition = Vector3.zero;
		newSuit.placedRotation = Vector3.zero;
		newSuit.shopSelectionNode = ScriptableObject.CreateInstance<TerminalNode>();
		((Object)newSuit.shopSelectionNode).name = newSuit.unlockableName + "SuitBuy1";
		newSuit.shopSelectionNode.creatureName = newSuit.unlockableName + " suit";
		newSuit.shopSelectionNode.displayText = "You have requested to order " + newSuit.unlockableName + " suits.\nTotal cost of item: [totalCost].\n\nPlease CONFIRM or DENY.\n\n";
		newSuit.shopSelectionNode.clearPreviousText = true;
		newSuit.shopSelectionNode.shipUnlockableID = unlockableID;
		newSuit.shopSelectionNode.itemCost = price;
		newSuit.shopSelectionNode.overrideOptions = true;
		CompatibleNoun val2 = new CompatibleNoun();
		val2.noun = ScriptableObject.CreateInstance<TerminalKeyword>();
		val2.noun.word = "confirm";
		val2.noun.isVerb = true;
		val2.result = ScriptableObject.CreateInstance<TerminalNode>();
		((Object)val2.result).name = newSuit.unlockableName + "SuitBuyConfirm";
		val2.result.creatureName = "";
		val2.result.displayText = "Ordered " + newSuit.unlockableName + " suits! Your new balance is [playerCredits].\n\n";
		val2.result.clearPreviousText = true;
		val2.result.shipUnlockableID = unlockableID;
		val2.result.buyUnlockable = true;
		val2.result.itemCost = price;
		val2.result.terminalEvent = "";
		CompatibleNoun val3 = new CompatibleNoun();
		val3.noun = ScriptableObject.CreateInstance<TerminalKeyword>();
		val3.noun.word = "deny";
		val3.noun.isVerb = true;
		if ((Object)(object)cancelPurchase == (Object)null)
		{
			cancelPurchase = ScriptableObject.CreateInstance<TerminalNode>();
		}
		val3.result = cancelPurchase;
		((Object)val3.result).name = "MoreSuitsCancelPurchase";
		val3.result.displayText = "Cancelled order.\n";
		newSuit.shopSelectionNode.terminalOptions = (CompatibleNoun[])(object)new CompatibleNoun[2] { val2, val3 };
		TerminalKeyword val4 = ScriptableObject.CreateInstance<TerminalKeyword>();
		((Object)val4).name = newSuit.unlockableName + "Suit";
		val4.word = newSuit.unlockableName.ToLower() + " suit";
		val4.defaultVerb = buyKeyword;
		CompatibleNoun val5 = new CompatibleNoun();
		val5.noun = val4;
		val5.result = newSuit.shopSelectionNode;
		List<CompatibleNoun> list = buyKeyword.compatibleNouns.ToList();
		list.Add(val5);
		buyKeyword.compatibleNouns = list.ToArray();
		List<TerminalKeyword> list2 = val.terminalNodes.allKeywords.ToList();
		list2.Add(val4);
		list2.Add(val2.noun);
		list2.Add(val3.noun);
		val.terminalNodes.allKeywords = list2.ToArray();
		return newSuit;
	}

	public static bool TryParseVector4(string input, out Vector4 vector)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		vector = Vector4.zero;
		string[] array = input.Split(',');
		if (array.Length == 4 && float.TryParse(array[0], out var result) && float.TryParse(array[1], out var result2) && float.TryParse(array[2], out var result3) && float.TryParse(array[3], out var result4))
		{
			vector = new Vector4(result, result2, result3, result4);
			return true;
		}
		return false;
	}
}

plugins/ReservedFlashlightSlot.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalCompanyInputUtils.Api;
using ReservedFlashlightSlot.Config;
using ReservedFlashlightSlot.Patches;
using ReservedItemSlotCore;
using ReservedItemSlotCore.Config;
using ReservedItemSlotCore.Data;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ReservedFlashlightSlot")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ReservedFlashlightSlot")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("5b7d6563-4e51-4a69-bcf9-fa1dea6eff75")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ReservedFlashlightSlot
{
	[BepInPlugin("FlipMods.ReservedFlashlightSlot", "ReservedFlashlightSlot", "2.0.8")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin instance;

		private static ManualLogSource logger;

		private Harmony _harmony;

		public static ReservedItemSlotData flashlightSlotData;

		public static ReservedItemData flashlightData;

		public static ReservedItemData proFlashlightData;

		public static ReservedItemData laserPointerData;

		public static List<ReservedItemData> additionalItemData = new List<ReservedItemData>();

		private void Awake()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			instance = this;
			CreateCustomLogger();
			ConfigSettings.BindConfigSettings();
			CreateReservedItemSlots();
			CreateAdditionalReservedItemSlots();
			_harmony = new Harmony("ReservedFlashlightSlot");
			PatchAll();
			Log("ReservedFlashlightSlot loaded");
		}

		private void CreateReservedItemSlots()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			flashlightSlotData = ReservedItemSlotData.CreateReservedItemSlotData("flashlight", ConfigSettings.overrideItemSlotPriority.Value, ConfigSettings.overridePurchasePrice.Value);
			flashlightData = flashlightSlotData.AddItemToReservedItemSlot(new ReservedItemData("Flashlight", (PlayerBone)4, new Vector3(0.2f, 0.25f, 0f), new Vector3(90f, 0f, 0f)));
			proFlashlightData = flashlightSlotData.AddItemToReservedItemSlot(new ReservedItemData("Pro-flashlight", (PlayerBone)4, new Vector3(0.2f, 0.25f, 0f), new Vector3(90f, 0f, 0f)));
			if (ConfigSettings.includeLaserPointer.Value)
			{
				laserPointerData = flashlightSlotData.AddItemToReservedItemSlot(new ReservedItemData("Laser pointer", (PlayerBone)4, new Vector3(0.2f, 0.25f, 0f), new Vector3(90f, 0f, 0f)));
			}
		}

		private void CreateAdditionalReservedItemSlots()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			string[] array = ConfigSettings.ParseAdditionalItems();
			string[] array2 = array;
			foreach (string text in array2)
			{
				if (!flashlightSlotData.ContainsItem(text))
				{
					LogWarning("Adding additional item to reserved item slot. Item: " + text);
					ReservedItemData val = new ReservedItemData(text, (PlayerBone)0, default(Vector3), default(Vector3));
					additionalItemData.Add(val);
					flashlightSlotData.AddItemToReservedItemSlot(val);
				}
			}
		}

		private void PatchAll()
		{
			IEnumerable<Type> enumerable;
			try
			{
				enumerable = Assembly.GetExecutingAssembly().GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				enumerable = ex.Types.Where((Type t) => t != null);
			}
			foreach (Type item in enumerable)
			{
				_harmony.PatchAll(item);
			}
		}

		private void CreateCustomLogger()
		{
			try
			{
				logger = Logger.CreateLogSource(string.Format("{0}-{1}", "ReservedFlashlightSlot", "2.0.8"));
			}
			catch
			{
				logger = ((BaseUnityPlugin)this).Logger;
			}
		}

		public static void Log(string message)
		{
			logger.LogInfo((object)message);
		}

		public static void LogError(string message)
		{
			logger.LogError((object)message);
		}

		public static void LogWarning(string message)
		{
			logger.LogWarning((object)message);
		}

		public static bool IsModLoaded(string guid)
		{
			return Chainloader.PluginInfos.ContainsKey(guid);
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "FlipMods.ReservedFlashlightSlot";

		public const string PLUGIN_NAME = "ReservedFlashlightSlot";

		public const string PLUGIN_VERSION = "2.0.8";
	}
}
namespace ReservedFlashlightSlot.Patches
{
	[HarmonyPatch]
	public static class FlashlightPatcher
	{
		public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;

		public static PlayerControllerB GetPreviousPlayerHeldBy(FlashlightItem flashlightItem)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			return (PlayerControllerB)Traverse.Create((object)flashlightItem).Field("previousPlayerHeldBy").GetValue();
		}

		public static FlashlightItem GetMainFlashlight(PlayerControllerB playerController)
		{
			FlashlightItem currentlySelectedFlashlight = GetCurrentlySelectedFlashlight(playerController);
			if (Object.op_Implicit((Object)(object)currentlySelectedFlashlight))
			{
				return currentlySelectedFlashlight;
			}
			GrabbableObject obj = playerController?.pocketedFlashlight;
			FlashlightItem val = (FlashlightItem)(object)((obj is FlashlightItem) ? obj : null);
			FlashlightItem reservedFlashlight = GetReservedFlashlight(playerController);
			return (Object.op_Implicit((Object)(object)val) && (!Object.op_Implicit((Object)(object)reservedFlashlight) || (((GrabbableObject)val).isBeingUsed && !((GrabbableObject)reservedFlashlight).isBeingUsed))) ? val : reservedFlashlight;
		}

		public static FlashlightItem GetReservedFlashlight(PlayerControllerB playerController)
		{
			ReservedItemSlotData val = default(ReservedItemSlotData);
			ReservedPlayerData value;
			return (FlashlightItem)((SessionManager.TryGetUnlockedItemSlotData(Plugin.flashlightSlotData.slotName, ref val) && ReservedPlayerData.allPlayerData.TryGetValue(playerController, out value)) ? /*isinst with value type is only supported in some contexts*/: null);
		}

		public static FlashlightItem GetCurrentlySelectedFlashlight(PlayerControllerB playerController)
		{
			return (FlashlightItem)((playerController.currentItemSlot >= 0 && playerController.currentItemSlot < playerController.ItemSlots.Length) ? /*isinst with value type is only supported in some contexts*/: null);
		}

		public static FlashlightItem GetFirstFlashlightItem(PlayerControllerB playerController)
		{
			GrabbableObject[] itemSlots = playerController.ItemSlots;
			foreach (GrabbableObject val in itemSlots)
			{
				if ((Object)(object)val != (Object)null)
				{
					FlashlightItem val2 = (FlashlightItem)(object)((val is FlashlightItem) ? val : null);
					if (val2 != null)
					{
						return val2;
					}
				}
			}
			return null;
		}

		[HarmonyPatch(typeof(FlashlightItem), "PocketItem")]
		[HarmonyPostfix]
		private static void OnPocketFlashlight(FlashlightItem __instance)
		{
			OnPocketFlashlightLocal(__instance);
		}

		[HarmonyPatch(typeof(FlashlightItem), "PocketFlashlightClientRpc")]
		[HarmonyPostfix]
		private static void OnPocketFlashlightClientRpc(bool stillUsingFlashlight, FlashlightItem __instance)
		{
			PlayerControllerB val = ((GrabbableObject)(__instance?)).playerHeldBy;
			if (Object.op_Implicit((Object)(object)val) && !((Object)(object)val == (Object)(object)localPlayerController) && NetworkManager.Singleton.IsClient && (int)Traverse.Create((object)__instance).Field("__rpc_exec_stage").GetValue() == 2)
			{
				OnPocketFlashlightLocal(__instance);
			}
		}

		private static void OnPocketFlashlightLocal(FlashlightItem flashlightItem)
		{
			PlayerControllerB val = ((GrabbableObject)(flashlightItem?)).playerHeldBy;
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			GrabbableObject pocketedFlashlight = val.pocketedFlashlight;
			FlashlightItem val2 = (FlashlightItem)(object)((pocketedFlashlight is FlashlightItem) ? pocketedFlashlight : null);
			if (((GrabbableObject)flashlightItem).isBeingUsed)
			{
				if (Object.op_Implicit((Object)(object)val2) && (Object)(object)val2 != (Object)(object)flashlightItem)
				{
					UpdateFlashlightState(val2, active: false);
				}
				UpdateFlashlightState(flashlightItem, active: true);
				val.pocketedFlashlight = (GrabbableObject)(object)flashlightItem;
			}
		}

		[HarmonyPatch(typeof(FlashlightItem), "EquipItem")]
		[HarmonyPostfix]
		private static void OnEquipFlashlight(FlashlightItem __instance)
		{
			PlayerControllerB val = ((GrabbableObject)(__instance?)).playerHeldBy;
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			GrabbableObject pocketedFlashlight = val.pocketedFlashlight;
			FlashlightItem val2 = (FlashlightItem)(object)((pocketedFlashlight is FlashlightItem) ? pocketedFlashlight : null);
			if (!((Object)(object)__instance != (Object)(object)val2))
			{
				return;
			}
			if (((GrabbableObject)__instance).isBeingUsed)
			{
				UpdateFlashlightState(__instance, active: true);
				if (Object.op_Implicit((Object)(object)val2))
				{
					UpdateFlashlightState(val2, active: false);
				}
			}
			else if (Object.op_Implicit((Object)(object)val2) && ((GrabbableObject)val2).isBeingUsed)
			{
				UpdateFlashlightState(__instance, active: false);
				UpdateFlashlightState(val2, active: true);
			}
		}

		[HarmonyPatch(typeof(FlashlightItem), "DiscardItem")]
		[HarmonyPostfix]
		private static void ResetPocketedFlashlightPost(FlashlightItem __instance)
		{
			if (!Object.op_Implicit((Object)(object)__instance))
			{
				return;
			}
			PlayerControllerB val = GetPreviousPlayerHeldBy(__instance);
			if (!Object.op_Implicit((Object)(object)val))
			{
				PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
				foreach (PlayerControllerB val2 in allPlayerScripts)
				{
					if ((Object)(object)__instance == (Object)(object)val2.pocketedFlashlight)
					{
						val = val2;
						break;
					}
				}
				if (!Object.op_Implicit((Object)(object)val))
				{
					return;
				}
			}
			FlashlightItem currentlySelectedFlashlight = GetCurrentlySelectedFlashlight(val);
			FlashlightItem reservedFlashlight = GetReservedFlashlight(val);
			GrabbableObject pocketedFlashlight = val.pocketedFlashlight;
			FlashlightItem val3 = (FlashlightItem)(object)((pocketedFlashlight is FlashlightItem) ? pocketedFlashlight : null);
			if ((Object)(object)__instance == (Object)(object)val3)
			{
				FlashlightItem val4 = ((Object.op_Implicit((Object)(object)reservedFlashlight) && (!Object.op_Implicit((Object)(object)currentlySelectedFlashlight) || (((GrabbableObject)reservedFlashlight).isBeingUsed && !((GrabbableObject)currentlySelectedFlashlight).isBeingUsed))) ? reservedFlashlight : currentlySelectedFlashlight);
				val.pocketedFlashlight = null;
				if (Object.op_Implicit((Object)(object)val4))
				{
					if ((Object)(object)val4 != (Object)(object)currentlySelectedFlashlight)
					{
						val.pocketedFlashlight = (GrabbableObject)(object)val4;
					}
					UpdateFlashlightState(val4, ((GrabbableObject)val4).isBeingUsed);
				}
			}
			else if ((Object)(object)val3 != (Object)null && ((GrabbableObject)val3).isBeingUsed)
			{
				UpdateFlashlightState(val3, active: true);
			}
		}

		[HarmonyPatch(typeof(FlashlightItem), "SwitchFlashlight")]
		[HarmonyPostfix]
		private static void OnToggleFlashlight(bool on, FlashlightItem __instance)
		{
			PlayerControllerB val = ((GrabbableObject)(__instance?)).playerHeldBy;
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			GrabbableObject pocketedFlashlight = val.pocketedFlashlight;
			FlashlightItem val2 = (FlashlightItem)(object)((pocketedFlashlight is FlashlightItem) ? pocketedFlashlight : null);
			if (!((GrabbableObject)__instance).isBeingUsed)
			{
				if ((Object)(object)__instance == (Object)(object)val2)
				{
					val.pocketedFlashlight = null;
				}
				return;
			}
			Traverse.Create((object)__instance).Field("previousPlayerHeldBy").SetValue((object)val);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)__instance)
			{
				if (((GrabbableObject)val2).isBeingUsed)
				{
					val2.SwitchFlashlight(false);
					UpdateFlashlightState(val2, active: false);
				}
				val.pocketedFlashlight = null;
			}
			if ((Object)(object)__instance != (Object)(object)GetCurrentlySelectedFlashlight(val))
			{
				val.pocketedFlashlight = (GrabbableObject)(object)__instance;
			}
			UpdateFlashlightState(__instance, active: true);
		}

		internal static void UpdateFlashlightState(FlashlightItem flashlightItem, bool active)
		{
			PlayerControllerB val = ((GrabbableObject)(flashlightItem?)).playerHeldBy;
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			((GrabbableObject)flashlightItem).isBeingUsed = active;
			bool flag = active && ((Object)(object)flashlightItem == (Object)(object)GetCurrentlySelectedFlashlight(val) || ((Object)(object)val != (Object)(object)localPlayerController && (Object)(object)flashlightItem == (Object)(object)GetReservedFlashlight(val)));
			bool flag2 = active && !flag;
			((Behaviour)flashlightItem.flashlightBulb).enabled = flag;
			((Behaviour)flashlightItem.flashlightBulbGlow).enabled = flag;
			flashlightItem.usingPlayerHelmetLight = flag2;
			((Behaviour)val.helmetLight).enabled = flag2;
			if (flag2)
			{
				val.ChangeHelmetLight(flashlightItem.flashlightTypeID, true);
			}
			if (!flashlightItem.changeMaterial)
			{
				return;
			}
			try
			{
				((Renderer)flashlightItem.flashlightMesh).sharedMaterials[1] = (flag ? flashlightItem.bulbLight : flashlightItem.bulbDark);
			}
			catch
			{
			}
		}
	}
}
namespace ReservedFlashlightSlot.Input
{
	internal class IngameKeybinds : LcInputActions
	{
		internal static IngameKeybinds Instance = new IngameKeybinds();

		[InputAction("<Keyboard>/f", Name = "[ReservedItemSlots]\nToggle flashlight")]
		public InputAction ToggleFlashlightHotkey { get; set; }

		internal static InputActionAsset GetAsset()
		{
			return ((LcInputActions)Instance).Asset;
		}
	}
	internal class InputUtilsCompat
	{
		internal static InputActionAsset Asset => IngameKeybinds.GetAsset();

		internal static bool Enabled => Plugin.IsModLoaded("com.rune580.LethalCompanyInputUtils");

		public static InputAction ToggleFlashlightHotkey => IngameKeybinds.Instance.ToggleFlashlightHotkey;
	}
	[HarmonyPatch]
	public static class KeybindDisplayNames
	{
		public static bool usingControllerPrevious = false;

		public static string[] keyboardKeywords = new string[2] { "keyboard", "mouse" };

		public static string[] controllerKeywords = new string[2] { "gamepad", "controller" };

		public static bool usingController => StartOfRound.Instance.localPlayerUsingController;

		public static string GetKeybindDisplayName(InputAction inputAction)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//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)
			if (inputAction == null || !inputAction.enabled)
			{
				return "";
			}
			int num = (usingController ? 1 : 0);
			InputBinding val = inputAction.bindings[num];
			string effectivePath = ((InputBinding)(ref val)).effectivePath;
			return GetKeybindDisplayName(effectivePath);
		}

		public static string GetKeybindDisplayName(string controlPath)
		{
			if (controlPath.Length <= 1)
			{
				return "";
			}
			string text = controlPath.ToLower();
			int num = text.IndexOf(">/");
			text = ((num >= 0) ? text.Substring(num + 2) : text);
			if (text.Contains("not-bound"))
			{
				return "";
			}
			text = text.Replace("leftalt", "Alt");
			text = text.Replace("rightalt", "Alt");
			text = text.Replace("leftctrl", "Ctrl");
			text = text.Replace("rightctrl", "Ctrl");
			text = text.Replace("leftshift", "Shift");
			text = text.Replace("rightshift", "Shift");
			text = text.Replace("leftbutton", "LMB");
			text = text.Replace("rightbutton", "RMB");
			text = text.Replace("middlebutton", "MMB");
			text = text.Replace("lefttrigger", "LT");
			text = text.Replace("righttrigger", "RT");
			text = text.Replace("leftshoulder", "LB");
			text = text.Replace("rightshoulder", "RB");
			text = text.Replace("leftstickpress", "LS");
			text = text.Replace("rightstickpress", "RS");
			text = text.Replace("dpad/", "DPad-");
			text = text.Replace("backquote", "`");
			try
			{
				text = char.ToUpper(text[0]) + text.Substring(1);
			}
			catch
			{
			}
			return text;
		}
	}
	[HarmonyPatch]
	internal static class Keybinds
	{
		public static InputActionAsset Asset;

		public static InputActionMap ActionMap;

		private static InputAction ActivateFlashlightAction;

		public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;

		[HarmonyPatch(typeof(PreInitSceneScript), "Awake")]
		[HarmonyPrefix]
		public static void AddToKeybindMenu()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Log("Initializing hotkeys.");
			if (InputUtilsCompat.Enabled)
			{
				Asset = InputUtilsCompat.Asset;
				ActionMap = Asset.actionMaps[0];
				ActivateFlashlightAction = InputUtilsCompat.ToggleFlashlightHotkey;
			}
			else
			{
				Asset = ScriptableObject.CreateInstance<InputActionAsset>();
				ActionMap = new InputActionMap("ReservedItemSlots");
				InputActionSetupExtensions.AddActionMap(Asset, ActionMap);
				ActivateFlashlightAction = InputActionSetupExtensions.AddAction(ActionMap, "ReservedItemSlots.ToggleFlashlight", (InputActionType)0, "<keyboard>/f", (string)null, (string)null, (string)null, (string)null);
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "OnEnable")]
		[HarmonyPostfix]
		public static void OnEnable()
		{
			Asset.Enable();
			ActivateFlashlightAction.performed += OnActivateFlashlightPerformed;
		}

		[HarmonyPatch(typeof(StartOfRound), "OnDisable")]
		[HarmonyPostfix]
		public static void OnDisable()
		{
			Asset.Disable();
			ActivateFlashlightAction.performed -= OnActivateFlashlightPerformed;
		}

		private static void OnActivateFlashlightPerformed(CallbackContext context)
		{
			if ((Object)(object)localPlayerController == (Object)null || !localPlayerController.isPlayerControlled || (((NetworkBehaviour)localPlayerController).IsServer && !localPlayerController.isHostPlayerObject) || !((CallbackContext)(ref context)).performed || ShipBuildModeManager.Instance.InBuildMode || localPlayerController.inTerminalMenu || ReservedPlayerData.localPlayerData.timeSinceSwitchingSlots < 0.075f || localPlayerController.isTypingChat || localPlayerController.inTerminalMenu || localPlayerController.quickMenuManager.isMenuOpen || localPlayerController.isPlayerDead || localPlayerController.isGrabbingObjectAnimation || ReservedPlayerData.localPlayerData.isGrabbingReservedItem)
			{
				return;
			}
			FlashlightItem val = FlashlightPatcher.GetMainFlashlight(localPlayerController);
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = FlashlightPatcher.GetFirstFlashlightItem(localPlayerController);
				if (!Object.op_Implicit((Object)(object)val))
				{
					return;
				}
			}
			bool flag = !((GrabbableObject)val).isBeingUsed;
			if (flag && (Object)(object)val != (Object)(object)FlashlightPatcher.GetCurrentlySelectedFlashlight(localPlayerController))
			{
				localPlayerController.pocketedFlashlight = (GrabbableObject)(object)val;
			}
			((GrabbableObject)val).UseItemOnClient(flag);
			Traverse.Create((object)localPlayerController).Field("timeSinceSwitchingSlots").SetValue((object)0);
		}
	}
}
namespace ReservedFlashlightSlot.Config
{
	public static class ConfigSettings
	{
		public static ConfigEntry<int> overrideItemSlotPriority;

		public static ConfigEntry<int> overridePurchasePrice;

		public static ConfigEntry<bool> includeLaserPointer;

		public static ConfigEntry<string> additionalItemsInSlot;

		public static Dictionary<string, ConfigEntryBase> currentConfigEntries = new Dictionary<string, ConfigEntryBase>();

		public static void BindConfigSettings()
		{
			Plugin.Log("BindingConfigs");
			overrideItemSlotPriority = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "FlashlightSlotPriorityOverride", 200, "[Host only] Manually set the priority for this item slot. Higher priority slots will come first in the reserved item slots, which will appear below the other slots. Negative priority items will appear on the left side of the screen, this is disabled in the core mod's config."));
			includeLaserPointer = AddConfigEntry<bool>(((BaseUnityPlugin)Plugin.instance).Config.Bind<bool>("Server-side", "IncludeLaserPointer", false, "[Host only] If enabled, the laser pointer will be added to the reserved flashlight slot."));
			overridePurchasePrice = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "FlashlightSlotPriceOverride", 200, "[Host only] Manually set the price for this item in the store. Setting 0 will force this item to be unlocked immediately after the game starts."));
			additionalItemsInSlot = AddConfigEntry<string>(((BaseUnityPlugin)Plugin.instance).Config.Bind<string>("Server-side", "AdditionalItemsInSlot", "", "[Host only] Syntax: \"Item1,Item name2\" (without quotes). When adding items, use the item's name as it appears in game. Include spaces if there are spaces in the item name. Adding items that do not exist, or that are from a mod which is not enabled will not cause any problems.\nNOTE: IF YOU ARE USING A TRANSLATION MOD, YOU MAY NEED TO ADD THE TRANSLATED NAME OF ANY ITEM YOU WANT IN THIS SLOT."));
			additionalItemsInSlot.Value = additionalItemsInSlot.Value.Replace(", ", ",");
			TryRemoveOldConfigSettings();
		}

		public static ConfigEntry<T> AddConfigEntry<T>(ConfigEntry<T> configEntry)
		{
			currentConfigEntries.Add(((ConfigEntryBase)configEntry).Definition.Key, (ConfigEntryBase)(object)configEntry);
			return configEntry;
		}

		public static string[] ParseAdditionalItems()
		{
			return ConfigSettings.ParseItemNames(additionalItemsInSlot.Value);
		}

		public static void TryRemoveOldConfigSettings()
		{
			HashSet<string> hashSet = new HashSet<string>();
			HashSet<string> hashSet2 = new HashSet<string>();
			foreach (ConfigEntryBase value in currentConfigEntries.Values)
			{
				hashSet.Add(value.Definition.Section);
				hashSet2.Add(value.Definition.Key);
			}
			try
			{
				ConfigFile config = ((BaseUnityPlugin)Plugin.instance).Config;
				string configFilePath = config.ConfigFilePath;
				if (!File.Exists(configFilePath))
				{
					return;
				}
				string text = File.ReadAllText(configFilePath);
				string[] array = File.ReadAllLines(configFilePath);
				string text2 = "";
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = array[i].Replace("\n", "");
					if (array[i].Length <= 0)
					{
						continue;
					}
					if (array[i].StartsWith("["))
					{
						if (text2 != "" && !hashSet.Contains(text2))
						{
							text2 = "[" + text2 + "]";
							int num = text.IndexOf(text2);
							int num2 = text.IndexOf(array[i]);
							text = text.Remove(num, num2 - num);
						}
						text2 = array[i].Replace("[", "").Replace("]", "").Trim();
					}
					else
					{
						if (!(text2 != ""))
						{
							continue;
						}
						if (i <= array.Length - 4 && array[i].StartsWith("##"))
						{
							int j;
							for (j = 1; i + j < array.Length && array[i + j].Length > 3; j++)
							{
							}
							if (hashSet.Contains(text2))
							{
								int num3 = array[i + j - 1].IndexOf("=");
								string item = array[i + j - 1].Substring(0, num3 - 1);
								if (!hashSet2.Contains(item))
								{
									int num4 = text.IndexOf(array[i]);
									int num5 = text.IndexOf(array[i + j - 1]) + array[i + j - 1].Length;
									text = text.Remove(num4, num5 - num4);
								}
							}
							i += j - 1;
						}
						else if (array[i].Length > 3)
						{
							text = text.Replace(array[i], "");
						}
					}
				}
				if (!hashSet.Contains(text2))
				{
					text2 = "[" + text2 + "]";
					int num6 = text.IndexOf(text2);
					text = text.Remove(num6, text.Length - num6);
				}
				while (text.Contains("\n\n\n"))
				{
					text = text.Replace("\n\n\n", "\n\n");
				}
				File.WriteAllText(configFilePath, text);
				config.Reload();
			}
			catch
			{
			}
		}
	}
}

plugins/ReservedItemSlotCore.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalCompanyInputUtils.Api;
using ReservedItemSlotCore.Compatibility;
using ReservedItemSlotCore.Config;
using ReservedItemSlotCore.Data;
using ReservedItemSlotCore.Input;
using ReservedItemSlotCore.Networking;
using ReservedItemSlotCore.Patches;
using TMPro;
using TooManyEmotes;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
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("ReservedItemSlotCore")]
[assembly: AssemblyDescription("Mod made by flipf17")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ReservedItemSlotCore")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("238ce080-e339-46b6-9b08-992a950453a1")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: InternalsVisibleTo("ReservedFlashlightSlot")]
[assembly: InternalsVisibleTo("ReservedWalkieSlot")]
[assembly: InternalsVisibleTo("ReservedWeaponSlot")]
[assembly: InternalsVisibleTo("ReservedSprayPaintSlot")]
[assembly: InternalsVisibleTo("ReservedUtilitySlot")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ReservedItemSlotCore
{
	[HarmonyPatch]
	internal static class ItemNameMap
	{
		private static Dictionary<string, Item> originalNameToItemMap = new Dictionary<string, Item>();

		private static Dictionary<Item, string> itemToNameMap = new Dictionary<Item, string>();

		[HarmonyPatch(typeof(StartOfRound), "Start")]
		[HarmonyPrefix]
		private static void RecordOriginalItemNames(StartOfRound __instance)
		{
			List<Item> list = __instance?.allItemsList?.itemsList;
			if (list == null)
			{
				Plugin.LogError("Failed to record original item names. This might be fine if you're not using translation/localization mods. (no guarantees)");
				return;
			}
			foreach (Item item in list)
			{
				string text = item?.itemName;
				if (!string.IsNullOrEmpty(text))
				{
					if (!itemToNameMap.ContainsKey(item))
					{
						itemToNameMap.Add(item, text);
					}
					if (!originalNameToItemMap.ContainsKey(text))
					{
						originalNameToItemMap.Add(text, item);
					}
				}
			}
		}

		internal static string GetItemName(GrabbableObject grabbableObject)
		{
			if ((Object)(object)grabbableObject?.itemProperties == (Object)null)
			{
				return "";
			}
			string itemName = GetItemName(grabbableObject.itemProperties);
			return (itemName != null) ? itemName : "";
		}

		internal static string GetItemName(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return "";
			}
			if (itemToNameMap.TryGetValue(item, out var value) && value != null)
			{
				return value;
			}
			return "";
		}
	}
	[BepInPlugin("FlipMods.ReservedItemSlotCore", "ReservedItemSlotCore", "2.0.38")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal class Plugin : BaseUnityPlugin
	{
		private Harmony _harmony;

		public static Plugin instance;

		private static ManualLogSource logger;

		public static List<ReservedItemSlotData> customItemSlots = new List<ReservedItemSlotData>();

		private void Awake()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			instance = this;
			CreateCustomLogger();
			ConfigSettings.BindConfigSettings();
			AddCustomItemSlots();
			if (InputUtilsCompat.Enabled)
			{
				InputUtilsCompat.Init();
			}
			_harmony = new Harmony("ReservedItemSlotCore");
			PatchAll();
			Log("ReservedItemSlotCore loaded");
		}

		private void AddCustomItemSlots()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			foreach (CustomItemSlotConfigEntry customItemSlotConfig in ConfigSettings.customItemSlotConfigs)
			{
				if (!(customItemSlotConfig.customItemSlotName == "") && customItemSlotConfig.customItemSlotItems.Length != 0)
				{
					ReservedItemSlotData reservedItemSlotData = ReservedItemSlotData.CreateReservedItemSlotData(customItemSlotConfig.customItemSlotName, customItemSlotConfig.customItemSlotPriority, customItemSlotConfig.customItemSlotPrice);
					string[] customItemSlotItems = customItemSlotConfig.customItemSlotItems;
					foreach (string itemName in customItemSlotItems)
					{
						ReservedItemData itemData = new ReservedItemData(itemName);
						reservedItemSlotData.AddItemToReservedItemSlot(itemData);
					}
					customItemSlots.Add(reservedItemSlotData);
				}
			}
		}

		private void PatchAll()
		{
			IEnumerable<Type> enumerable;
			try
			{
				enumerable = Assembly.GetExecutingAssembly().GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				enumerable = ex.Types.Where((Type t) => t != null);
			}
			foreach (Type item in enumerable)
			{
				_harmony.PatchAll(item);
			}
		}

		private void CreateCustomLogger()
		{
			try
			{
				logger = Logger.CreateLogSource(string.Format("{0}-{1}", "ReservedItemSlotCore", "2.0.38"));
			}
			catch
			{
				logger = ((BaseUnityPlugin)this).Logger;
			}
		}

		public static void Log(string message)
		{
			logger.LogInfo((object)message);
		}

		public static void LogError(string message)
		{
			logger.LogError((object)message);
		}

		public static void LogWarning(string message)
		{
			logger.LogWarning((object)message);
		}

		public static bool IsModLoaded(string guid)
		{
			return Chainloader.PluginInfos.ContainsKey(guid);
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "FlipMods.ReservedItemSlotCore";

		public const string PLUGIN_NAME = "ReservedItemSlotCore";

		public const string PLUGIN_VERSION = "2.0.38";
	}
	[HarmonyPatch]
	public static class ReservedHotbarManager
	{
		public static int indexInHotbar = 0;

		public static int indexInReservedHotbar = 0;

		internal static List<ReservedItemSlotData> currentlyToggledItemSlots = new List<ReservedItemSlotData>();

		public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;

		public static ReservedPlayerData localPlayerData => ReservedPlayerData.localPlayerData;

		public static int reservedHotbarSize => SessionManager.numReservedItemSlotsUnlocked;

		public static bool isToggledInReservedSlots
		{
			get
			{
				ReservedItemSlotData currentlySelectedReservedItemSlot = localPlayerData.GetCurrentlySelectedReservedItemSlot();
				return (ReservedPlayerData.localPlayerData.inReservedHotbarSlots && Keybinds.pressedToggleKey) || (currentlyToggledItemSlots != null && currentlySelectedReservedItemSlot != null && currentlyToggledItemSlots.Contains(currentlySelectedReservedItemSlot));
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPrefix]
		public static void InitSession(StartOfRound __instance)
		{
			currentlyToggledItemSlots = new List<ReservedItemSlotData>();
			ReservedPlayerData.allPlayerData.Clear();
			indexInHotbar = 0;
			indexInReservedHotbar = -1;
		}

		public static void ForceToggleReservedHotbar(params ReservedItemSlotData[] reservedItemSlots)
		{
			if (((NetworkBehaviour)localPlayerController).IsOwner && localPlayerController.isPlayerControlled && (!((NetworkBehaviour)localPlayerController).IsServer || localPlayerController.isHostPlayerObject) && HUDPatcher.hasReservedItemSlotsAndEnabled && reservedHotbarSize > 0 && CanSwapHotbars() && reservedItemSlots != null && reservedItemSlots.Length != 0 && !((Object)(object)localPlayerController == (Object)null))
			{
				currentlyToggledItemSlots = new List<ReservedItemSlotData>(reservedItemSlots);
				int num = currentlyToggledItemSlots.First().GetReservedItemSlotIndex() + localPlayerData.reservedHotbarStartIndex;
				bool active = ReservedPlayerData.localPlayerData.IsReservedItemSlot(num);
				if (currentlyToggledItemSlots.Contains(localPlayerData.GetCurrentlySelectedReservedItemSlot()))
				{
					FocusReservedHotbarSlots(active: false);
					return;
				}
				HUDPatcher.UpdateToggledReservedItemSlotsUI();
				FocusReservedHotbarSlots(active, num);
			}
		}

		public static void FocusReservedHotbarSlots(bool active, int forceSlot = -1)
		{
			if (!HUDPatcher.hasReservedItemSlotsAndEnabled || (reservedHotbarSize <= 0 && active) || (ReservedPlayerData.localPlayerData.currentItemSlotIsReserved == active && (forceSlot == -1 || localPlayerData.currentItemSlot == forceSlot)))
			{
				return;
			}
			if (forceSlot != -1)
			{
				active = localPlayerData.IsReservedItemSlot(forceSlot);
			}
			ReservedPlayerData reservedPlayerData = ReservedPlayerData.localPlayerData;
			indexInHotbar = Mathf.Clamp(indexInHotbar, 0, localPlayerController.ItemSlots.Length - 1);
			indexInHotbar = ((!reservedPlayerData.IsReservedItemSlot(indexInHotbar)) ? indexInHotbar : 0);
			indexInReservedHotbar = Mathf.Clamp(indexInReservedHotbar, reservedPlayerData.reservedHotbarStartIndex, reservedPlayerData.reservedHotbarEndIndexExcluded - 1);
			int num = Mathf.Clamp(localPlayerController.currentItemSlot, 0, localPlayerController.ItemSlots.Length);
			int i = num;
			bool flag = active;
			if (flag && (!reservedPlayerData.IsReservedItemSlot(num) || forceSlot != -1))
			{
				indexInHotbar = num;
				indexInHotbar = ((!reservedPlayerData.IsReservedItemSlot(indexInHotbar)) ? indexInHotbar : 0);
				if (forceSlot != -1 && reservedPlayerData.IsReservedItemSlot(forceSlot))
				{
					indexInReservedHotbar = forceSlot;
				}
				i = indexInReservedHotbar;
				if ((Object)(object)localPlayerController.ItemSlots[i] == (Object)null && reservedPlayerData.GetNumHeldReservedItems() > 0)
				{
					for (i = reservedPlayerData.reservedHotbarStartIndex; i < reservedPlayerData.reservedHotbarEndIndexExcluded && !((Object)(object)localPlayerController.ItemSlots[i] != (Object)null); i++)
					{
					}
				}
				Plugin.Log("Focusing reserved hotbar slots. NewIndex: " + i + " OldIndex: " + num + " ReservedStartIndex: " + ReservedPlayerData.localPlayerData.reservedHotbarStartIndex);
			}
			else if (!flag && (ReservedPlayerData.localPlayerData.IsReservedItemSlot(num) || forceSlot != -1))
			{
				indexInReservedHotbar = Mathf.Clamp(num, reservedPlayerData.reservedHotbarStartIndex, reservedPlayerData.reservedHotbarEndIndexExcluded - 1);
				if (forceSlot != -1 && !reservedPlayerData.IsReservedItemSlot(forceSlot))
				{
					indexInHotbar = forceSlot;
				}
				i = indexInHotbar;
				Plugin.Log("Unfocusing reserved hotbar slots. NewIndex: " + i + " OldIndex: " + num + " ReservedStartIndex: " + ReservedPlayerData.localPlayerData.reservedHotbarStartIndex);
			}
			if (i < 0)
			{
				Plugin.LogError("Swapping to hotbar slot: " + i + ". Maybe send these logs to Flip? :)");
			}
			else if (i >= localPlayerController.ItemSlots.Length)
			{
				Plugin.LogError("Swapping to hotbar slot: " + i + " InventorySize: " + localPlayerController.ItemSlots.Length + ". Maybe send these logs to Flip? :)");
			}
			SyncManager.SwapHotbarSlot(i);
			if (localPlayerController.currentItemSlot != i)
			{
				Plugin.LogWarning("OnFocusReservedHotbarSlots - New hotbar index does not match target hotbar index. Tried to swap to index: " + i + " Current index: " + localPlayerController.currentItemSlot + " Tried swapping to reserved hotbar: " + active);
			}
		}

		public static bool CanSwapHotbars()
		{
			if (!HUDPatcher.hasReservedItemSlotsAndEnabled)
			{
				return false;
			}
			if (TooManyEmotes_Compat.Enabled && TooManyEmotes_Compat.IsLocalPlayerPerformingCustomEmote() && !TooManyEmotes_Compat.CanMoveWhileEmoting())
			{
				return false;
			}
			return ReservedPlayerData.localPlayerData.grabbingReservedItemData == null && !localPlayerController.isGrabbingObjectAnimation && !localPlayerController.quickMenuManager.isMenuOpen && !localPlayerController.inSpecialInteractAnimation && !localPlayerData.throwingObject && !localPlayerController.isTypingChat && !localPlayerController.twoHanded && !localPlayerController.activatingItem && !localPlayerController.jetpackControls && !localPlayerController.disablingJetpackControls && !localPlayerController.inTerminalMenu && !localPlayerController.isPlayerDead && !(localPlayerData.timeSinceSwitchingSlots < 0.3f);
		}

		internal static void OnSwapToReservedHotbar()
		{
			if (!localPlayerData.currentItemSlotIsReserved)
			{
				return;
			}
			if (localPlayerData.currentItemSlotIsReserved)
			{
				indexInReservedHotbar = localPlayerController.currentItemSlot;
			}
			ReservedItemSlotData currentlySelectedReservedItemSlot = localPlayerData.GetCurrentlySelectedReservedItemSlot();
			if (isToggledInReservedSlots && currentlyToggledItemSlots != null && !currentlyToggledItemSlots.Contains(currentlySelectedReservedItemSlot))
			{
				currentlyToggledItemSlots = null;
			}
			if (HUDPatcher.reservedItemSlots == null)
			{
				return;
			}
			foreach (Image reservedItemSlot in HUDPatcher.reservedItemSlots)
			{
				CanvasGroup component = ((Component)reservedItemSlot).GetComponent<CanvasGroup>();
				if ((Object)(object)component != (Object)null)
				{
					component.ignoreParentGroups = true;
				}
			}
		}

		internal static void OnSwapToVanillaHotbar()
		{
			if (localPlayerData.currentItemSlotIsReserved)
			{
				return;
			}
			if (!localPlayerData.currentItemSlotIsReserved)
			{
				indexInHotbar = localPlayerController.currentItemSlot;
			}
			currentlyToggledItemSlots = null;
			if (HUDPatcher.reservedItemSlots == null)
			{
				return;
			}
			foreach (Image reservedItemSlot in HUDPatcher.reservedItemSlots)
			{
				CanvasGroup component = ((Component)reservedItemSlot).GetComponent<CanvasGroup>();
				if ((Object)(object)component != (Object)null)
				{
					component.ignoreParentGroups = ConfigSettings.preventReservedItemSlotFade.Value;
				}
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")]
		[HarmonyPrefix]
		private static void RefocusReservedHotbarAfterAnimation(PlayerControllerB __instance)
		{
			if (HUDPatcher.hasReservedItemSlotsAndEnabled && !((Object)(object)__instance != (Object)(object)localPlayerController) && !Keybinds.pressedToggleKey && Keybinds.holdingModifierKey != ReservedPlayerData.localPlayerData.currentItemSlotIsReserved && !isToggledInReservedSlots && CanSwapHotbars())
			{
				FocusReservedHotbarSlots(Keybinds.holdingModifierKey);
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "UpdateSpecialAnimationValue")]
		[HarmonyPostfix]
		private static void UpdateReservedHotbarAfterAnimation(bool specialAnimation, PlayerControllerB __instance)
		{
			if (HUDPatcher.hasReservedItemSlotsAndEnabled && !((Object)(object)__instance != (Object)(object)localPlayerController) && !specialAnimation && !Keybinds.pressedToggleKey && ReservedPlayerData.localPlayerData.currentItemSlotIsReserved != Keybinds.holdingModifierKey)
			{
				FocusReservedHotbarSlots(Keybinds.holdingModifierKey);
			}
		}
	}
	[HarmonyPatch]
	public static class SessionManager
	{
		internal static List<ReservedItemSlotData> unlockedReservedItemSlots = new List<ReservedItemSlotData>();

		internal static Dictionary<string, ReservedItemSlotData> unlockedReservedItemSlotsDict = new Dictionary<string, ReservedItemSlotData>();

		internal static List<ReservedItemSlotData> pendingUnlockedReservedItemSlots = new List<ReservedItemSlotData>();

		internal static Dictionary<string, ReservedItemSlotData> pendingUnlockedReservedItemSlotsDict = new Dictionary<string, ReservedItemSlotData>();

		private static Dictionary<string, ReservedItemData> allReservedItemData = new Dictionary<string, ReservedItemData>();

		internal static bool gameStarted = false;

		internal static List<ReservedItemSlotData> allUnlockableReservedItemSlots => SyncManager.unlockableReservedItemSlots;

		internal static Dictionary<string, ReservedItemSlotData> allUnlockableReservedItemSlotsDict => SyncManager.unlockableReservedItemSlotsDict;

		public static int numReservedItemSlotsUnlocked => (unlockedReservedItemSlots != null) ? unlockedReservedItemSlots.Count : 0;

		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPrefix]
		private static void InitSession()
		{
			unlockedReservedItemSlots.Clear();
			unlockedReservedItemSlotsDict.Clear();
			pendingUnlockedReservedItemSlots.Clear();
			pendingUnlockedReservedItemSlotsDict.Clear();
			allReservedItemData.Clear();
			gameStarted = false;
		}

		[HarmonyPatch(typeof(StartOfRound), "ResetPlayersLoadedValueClientRpc")]
		[HarmonyPostfix]
		private static void OnStartGame(StartOfRound __instance, bool landingShip = false)
		{
			if (gameStarted || !NetworkManager.Singleton.IsClient)
			{
				return;
			}
			if (!SyncManager.hostHasMod && SyncManager.canUseModDisabledOnHost)
			{
				Plugin.LogWarning("Starting game while host does not have this mod, and ForceEnableReservedItemSlots is enabled in the config. Unlocking: " + ReservedItemSlotData.allReservedItemSlotData.Count + " slots. THIS MAY NOT BE STABLE");
				SyncManager.isSynced = true;
				SyncManager.enablePurchasingItemSlots = false;
				ReservedPlayerData.localPlayerData.reservedHotbarStartIndex = ReservedPlayerData.localPlayerData.itemSlots.Length;
				foreach (ReservedItemSlotData value in ReservedItemSlotData.allReservedItemSlotData.Values)
				{
					SyncManager.AddReservedItemSlotData(value);
					UnlockReservedItemSlot(value);
				}
				pendingUnlockedReservedItemSlots?.Clear();
				pendingUnlockedReservedItemSlotsDict?.Clear();
				SyncManager.UpdateReservedItemsList();
			}
			gameStarted = true;
		}

		public static void UnlockReservedItemSlot(ReservedItemSlotData itemSlotData)
		{
			if (itemSlotData == null)
			{
				return;
			}
			Plugin.Log("Unlocking reserved item slot: " + itemSlotData.slotName);
			if (!SyncManager.isSynced)
			{
				if (!pendingUnlockedReservedItemSlotsDict.ContainsKey(itemSlotData.slotName))
				{
					pendingUnlockedReservedItemSlotsDict.Add(itemSlotData.slotName, itemSlotData);
					pendingUnlockedReservedItemSlots.Add(itemSlotData);
				}
				return;
			}
			if (!unlockedReservedItemSlotsDict.ContainsKey(itemSlotData.slotName))
			{
				unlockedReservedItemSlotsDict.Add(itemSlotData.slotName, itemSlotData);
				if (!unlockedReservedItemSlots.Contains(itemSlotData))
				{
					int num = -1;
					for (int i = 0; i < unlockedReservedItemSlots.Count; i++)
					{
						if (itemSlotData.slotPriority > unlockedReservedItemSlots[i].slotPriority)
						{
							num = i;
							break;
						}
					}
					if (num == -1)
					{
						num = unlockedReservedItemSlots.Count;
					}
					unlockedReservedItemSlots.Insert(num, itemSlotData);
					foreach (ReservedPlayerData value in ReservedPlayerData.allPlayerData.Values)
					{
						if (unlockedReservedItemSlots.Count == 1)
						{
							value.reservedHotbarStartIndex = value.itemSlots.Length;
						}
						int index = value.reservedHotbarStartIndex + num;
						List<GrabbableObject> list = new List<GrabbableObject>(value.itemSlots);
						list.Insert(index, null);
						value.playerController.ItemSlots = list.ToArray();
						value.hotbarSize = list.Count;
					}
				}
			}
			if (ReservedHotbarManager.indexInReservedHotbar < ReservedPlayerData.localPlayerData.reservedHotbarStartIndex || ReservedHotbarManager.indexInReservedHotbar >= ReservedPlayerData.localPlayerData.reservedHotbarEndIndexExcluded)
			{
				ReservedHotbarManager.indexInReservedHotbar = ReservedPlayerData.localPlayerData.reservedHotbarStartIndex;
			}
			UpdateReservedItemsList();
			HUDPatcher.OnUpdateReservedItemSlots();
		}

		internal static void UnlockAllPendingItemSlots()
		{
			foreach (ReservedItemSlotData pendingUnlockedReservedItemSlot in pendingUnlockedReservedItemSlots)
			{
				UnlockReservedItemSlot(pendingUnlockedReservedItemSlot);
			}
			pendingUnlockedReservedItemSlots.Clear();
			pendingUnlockedReservedItemSlotsDict.Clear();
		}

		public static ReservedItemSlotData GetUnlockedReservedItemSlot(int indexInUnlockedItemSlots)
		{
			return (unlockedReservedItemSlots != null && indexInUnlockedItemSlots >= 0 && indexInUnlockedItemSlots < unlockedReservedItemSlots.Count) ? unlockedReservedItemSlots[indexInUnlockedItemSlots] : null;
		}

		public static ReservedItemSlotData GetUnlockedReservedItemSlot(string itemSlotName)
		{
			if (TryGetUnlockedItemSlotData(itemSlotName, out var itemSlotData))
			{
				return itemSlotData;
			}
			return null;
		}

		public static bool IsItemSlotUnlocked(ReservedItemSlotData itemSlotData)
		{
			return itemSlotData != null && IsItemSlotUnlocked(itemSlotData.slotName);
		}

		public static bool IsItemSlotUnlocked(string itemSlotName)
		{
			return unlockedReservedItemSlotsDict.ContainsKey(itemSlotName);
		}

		internal static void UpdateReservedItemsList()
		{
			if (unlockedReservedItemSlots == null)
			{
				return;
			}
			allReservedItemData.Clear();
			foreach (ReservedItemSlotData unlockedReservedItemSlot in unlockedReservedItemSlots)
			{
				if (unlockedReservedItemSlot.reservedItemData == null)
				{
					continue;
				}
				foreach (ReservedItemData value in unlockedReservedItemSlot.reservedItemData.Values)
				{
					if (!allReservedItemData.ContainsKey(value.itemName))
					{
						allReservedItemData.Add(value.itemName, value);
					}
				}
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "ResetShip")]
		[HarmonyPostfix]
		private static void OnResetShip()
		{
			if (SyncManager.enablePurchasingItemSlots)
			{
				ResetProgress();
			}
			else if (!SyncManager.hostHasMod && SyncManager.canUseModDisabledOnHost)
			{
				SyncManager.isSynced = false;
				ResetProgress(force: true);
			}
			gameStarted = false;
		}

		[HarmonyPatch(typeof(GameNetworkManager), "SaveGameValues")]
		[HarmonyPostfix]
		private static void OnSaveGameValues()
		{
			if (NetworkManager.Singleton.IsHost && StartOfRound.Instance.inShipPhase && SyncManager.enablePurchasingItemSlots)
			{
				SaveGameValues();
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "LoadUnlockables")]
		[HarmonyPostfix]
		private static void OnLoadGameValues()
		{
			if (NetworkManager.Singleton.IsServer && SyncManager.isSynced && SyncManager.enablePurchasingItemSlots)
			{
				LoadGameValues();
			}
		}

		internal static void ResetProgress(bool force = false)
		{
			if (!SyncManager.enablePurchasingItemSlots && !force)
			{
				return;
			}
			Plugin.Log("Resetting progress.");
			foreach (ReservedPlayerData value in ReservedPlayerData.allPlayerData.Values)
			{
				GrabbableObject[] itemSlots = value.playerController.ItemSlots;
				List<GrabbableObject> list = new List<GrabbableObject>();
				for (int i = 0; i < itemSlots.Length; i++)
				{
					if (i < value.reservedHotbarStartIndex || i >= value.reservedHotbarEndIndexExcluded)
					{
						list.Add(itemSlots[i]);
					}
				}
				value.playerController.ItemSlots = list.ToArray();
			}
			unlockedReservedItemSlots?.Clear();
			unlockedReservedItemSlotsDict?.Clear();
			pendingUnlockedReservedItemSlots?.Clear();
			pendingUnlockedReservedItemSlotsDict?.Clear();
			List<Image> list2 = new List<Image>();
			List<Image> list3 = new List<Image>();
			for (int j = 0; j < HUDManager.Instance.itemSlotIconFrames.Length; j++)
			{
				Image val = HUDManager.Instance.itemSlotIconFrames[j];
				Image item = HUDManager.Instance.itemSlotIcons[j];
				if (!HUDPatcher.reservedItemSlots.Contains(val))
				{
					list2.Add(val);
					list3.Add(item);
				}
				else
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
			HUDPatcher.reservedItemSlots.Clear();
			HUDManager.Instance.itemSlotIconFrames = list2.ToArray();
			HUDManager.Instance.itemSlotIcons = list3.ToArray();
			foreach (ReservedPlayerData value2 in ReservedPlayerData.allPlayerData.Values)
			{
				if (value2.playerController.currentItemSlot < 0 || value2.playerController.currentItemSlot >= value2.playerController.ItemSlots.Length)
				{
					PlayerPatcher.SwitchToItemSlot(value2.playerController, 0);
				}
				value2.reservedHotbarStartIndex = value2.itemSlots.Length;
			}
			foreach (ReservedItemSlotData allUnlockableReservedItemSlot in allUnlockableReservedItemSlots)
			{
				if (allUnlockableReservedItemSlot.purchasePrice <= 0)
				{
					UnlockReservedItemSlot(allUnlockableReservedItemSlot);
				}
			}
			if (SyncManager.hostHasMod)
			{
			}
			HUDPatcher.OnUpdateReservedItemSlots();
			if (NetworkManager.Singleton.IsServer)
			{
				ES3.DeleteKey("ReservedItemSlots.UnlockedItemSlots", GameNetworkManager.Instance.currentSaveFileName);
			}
		}

		internal static void SaveGameValues()
		{
			if (!NetworkManager.Singleton.IsServer || unlockedReservedItemSlots == null)
			{
				return;
			}
			List<string> list = new List<string>();
			foreach (ReservedItemSlotData unlockedReservedItemSlot in unlockedReservedItemSlots)
			{
				if (!list.Contains(unlockedReservedItemSlot.slotName))
				{
					list.Add(unlockedReservedItemSlot.slotName);
				}
			}
			Plugin.LogWarning("Saving " + list.Count + " unlocked reserved item slots.");
			string[] array = list.ToArray();
			ES3.Save<string[]>("ReservedItemSlots.UnlockedItemSlots", array, GameNetworkManager.Instance.currentSaveFileName);
		}

		internal static void LoadGameValues()
		{
			if (!NetworkManager.Singleton.IsServer || SyncManager.unlockableReservedItemSlotsDict == null)
			{
				return;
			}
			string[] array = ES3.Load<string[]>("ReservedItemSlots.UnlockedItemSlots", GameNetworkManager.Instance.currentSaveFileName, new string[0]);
			Plugin.LogWarning("Loading " + array.Length + " unlocked reserved item slots.");
			int num = 0;
			string[] array2 = array;
			foreach (string key in array2)
			{
				if (SyncManager.unlockableReservedItemSlotsDict.TryGetValue(key, out var value))
				{
					num++;
					UnlockReservedItemSlot(value);
					SyncManager.SendUnlockItemSlotToClients(value.slotId);
				}
			}
			Plugin.Log("Loaded " + num + " unlocked reserved items.");
		}

		public static bool IsReservedItem(GrabbableObject grabbableObject)
		{
			string itemName = ItemNameMap.GetItemName(grabbableObject);
			return IsReservedItem(itemName) || ((Object)(object)grabbableObject?.itemProperties != (Object)null && IsReservedItem(grabbableObject.itemProperties.itemName));
		}

		public static bool IsReservedItem(string itemName)
		{
			return allReservedItemData.ContainsKey(itemName);
		}

		public static bool TryGetUnlockedItemSlotData(string itemSlotName, out ReservedItemSlotData itemSlotData)
		{
			itemSlotData = null;
			unlockedReservedItemSlotsDict.TryGetValue(itemSlotName, out itemSlotData);
			return itemSlotData != null;
		}

		public static bool TryGetUnlockedItemData(GrabbableObject item, out ReservedItemData itemData)
		{
			itemData = null;
			string itemName = ItemNameMap.GetItemName(item);
			return TryGetUnlockedItemData(itemName, out itemData) || ((Object)(object)item?.itemProperties != (Object)null && TryGetUnlockedItemData(item.itemProperties.itemName, out itemData));
		}

		public static bool TryGetUnlockedItemData(string itemName, out ReservedItemData itemData)
		{
			itemData = null;
			return allReservedItemData.TryGetValue(itemName, out itemData);
		}
	}
}
namespace ReservedItemSlotCore.Patches
{
	[HarmonyPatch]
	internal static class DropReservedItemPatcher
	{
		private static HashSet<PlayerControllerB> playersDiscardingItems = new HashSet<PlayerControllerB>();

		private static float timeLoggedPreventedScroll = 0f;

		private static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;

		[HarmonyPatch(typeof(PlayerControllerB), "SetObjectAsNoLongerHeld")]
		[HarmonyPostfix]
		private static void OnSetObjectNoLongerHeld(bool droppedInElevator, bool droppedInShipRoom, Vector3 targetFloorPosition, GrabbableObject dropObject, PlayerControllerB __instance)
		{
			OnDiscardItem(__instance);
		}

		[HarmonyPatch(typeof(PlayerControllerB), "PlaceGrabbableObject")]
		[HarmonyPostfix]
		private static void OnPlaceGrabbableObject(Transform parentObject, Vector3 positionOffset, bool matchRotationOfParent, GrabbableObject placeObject, PlayerControllerB __instance)
		{
			OnDiscardItem(__instance);
		}

		[HarmonyPatch(typeof(PlayerControllerB), "DestroyItemInSlot")]
		[HarmonyPostfix]
		private static void OnDestroyItem(int itemSlot, PlayerControllerB __instance)
		{
			if ((Object)(object)__instance == (Object)(object)localPlayerController && itemSlot >= ReservedPlayerData.localPlayerData.reservedHotbarStartIndex && itemSlot < ReservedPlayerData.localPlayerData.reservedHotbarEndIndexExcluded)
			{
				HUDPatcher.UpdateUI();
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "DespawnHeldObjectOnClient")]
		[HarmonyPostfix]
		private static void OnDespawnItem(PlayerControllerB __instance)
		{
			if ((Object)(object)__instance == (Object)(object)localPlayerController)
			{
				HUDPatcher.UpdateUI();
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "DropAllHeldItems")]
		[HarmonyPostfix]
		private static void OnDropAllHeldItems(PlayerControllerB __instance)
		{
			if ((Object)(object)__instance == (Object)(object)localPlayerController)
			{
				HUDPatcher.UpdateUI();
			}
		}

		private static void OnDiscardItem(PlayerControllerB playerController)
		{
			if (!((Object)(object)playerController != (Object)null) || playersDiscardingItems.Contains(playerController) || !ReservedPlayerData.allPlayerData.TryGetValue(playerController, out var value) || !value.currentItemSlotIsReserved || !((Object)(object)value.currentlySelectedItem == (Object)null))
			{
				return;
			}
			if (value.GetNumHeldReservedItems() > 0)
			{
				int num = value.CallGetNextItemSlot(forward: true);
				if (!value.IsReservedItemSlot(num) && !value.IsReservedItemSlot(ReservedHotbarManager.indexInHotbar))
				{
					num = ReservedHotbarManager.indexInHotbar;
				}
				playersDiscardingItems.Add(playerController);
				((MonoBehaviour)playerController).StartCoroutine(SwitchToItemSlotAfterDelay(playerController, num));
			}
			if ((Object)(object)playerController == (Object)(object)localPlayerController)
			{
				HUDPatcher.UpdateUI();
			}
		}

		private static IEnumerator SwitchToItemSlotAfterDelay(PlayerControllerB playerController, int slot)
		{
			float time = Time.time;
			if ((Object)(object)playerController == (Object)(object)localPlayerController)
			{
				yield return (object)new WaitUntil((Func<bool>)(() => (Object)(object)playerController.currentlyHeldObjectServer == (Object)null || Time.time - time >= 5f));
			}
			yield return (object)new WaitForEndOfFrame();
			playersDiscardingItems.Remove(playerController);
			if (playerController.currentItemSlot != slot && Time.time - time < 3f && ReservedPlayerData.allPlayerData.TryGetValue(playerController, out var playerData))
			{
				playerData.CallSwitchToItemSlot(slot);
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "ScrollMouse_performed")]
		[HarmonyPrefix]
		private static bool PreventItemSwappingDroppingItem(CallbackContext context, PlayerControllerB __instance)
		{
			if ((Object)(object)__instance == (Object)(object)localPlayerController && playersDiscardingItems.Contains(__instance))
			{
				float time = Time.time;
				if (ConfigSettings.verboseLogs.Value && time - timeLoggedPreventedScroll > 1f)
				{
					timeLoggedPreventedScroll = time;
					Plugin.LogWarning("[VERBOSE] Prevented item swap. Player is currently discarding an item? This should be fine, unless these logs are spamming.");
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	public static class HUDPatcher
	{
		private static bool usingController = false;

		private static float itemSlotWidth;

		internal static float itemSlotSpacing;

		private static float defaultItemSlotPosX;

		private static float defaultItemSlotPosY;

		private static float defaultItemSlotSpacing;

		private static Vector2 defaultItemSlotSize;

		private static Vector2 defaultItemIconSize;

		private static TextMeshProUGUI hotkeyTooltip;

		public static List<Image> reservedItemSlots = new List<Image>();

		public static HashSet<ReservedItemSlotData> toggledReservedItemSlots = new HashSet<ReservedItemSlotData>();

		private static bool lerpToggledItemSlotFrames = false;

		private static float largestPositionDifference = 0f;

		private static bool currentApplyHotbarPlusSize;

		private static bool currentHideEmptySlots;

		public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;

		public static ReservedPlayerData localPlayerData => ReservedPlayerData.localPlayerData;

		public static bool localPlayerUsingController => (Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.localPlayerUsingController;

		private static float currentItemSlotScale => itemSlotWidth / defaultItemSlotSize.x;

		public static bool hasReservedItemSlotsAndEnabled => reservedItemSlots != null && reservedItemSlots.Count > 0 && ((Component)reservedItemSlots[0]).gameObject.activeSelf && ((Behaviour)reservedItemSlots[0]).enabled;

		[HarmonyPatch(typeof(HUDManager), "Awake")]
		[HarmonyPostfix]
		public static void Initialize(HUDManager __instance)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			CanvasScaler componentInParent = ((Component)__instance.itemSlotIconFrames[0]).GetComponentInParent<CanvasScaler>();
			AspectRatioFitter componentInParent2 = ((Component)__instance.itemSlotIconFrames[0]).GetComponentInParent<AspectRatioFitter>();
			itemSlotWidth = ((Graphic)__instance.itemSlotIconFrames[0]).rectTransform.sizeDelta.x;
			itemSlotSpacing = 1.125f * itemSlotWidth;
			defaultItemSlotPosX = componentInParent.referenceResolution.x / 2f / componentInParent2.aspectRatio - itemSlotWidth / 4f;
			defaultItemSlotSpacing = itemSlotSpacing;
			defaultItemSlotSize = ((Graphic)__instance.itemSlotIconFrames[0]).rectTransform.sizeDelta;
			defaultItemIconSize = ((Graphic)__instance.itemSlotIcons[0]).rectTransform.sizeDelta;
			defaultItemSlotPosY = ((Graphic)__instance.itemSlotIconFrames[0]).rectTransform.anchoredPosition.y;
			reservedItemSlots.Clear();
		}

		[HarmonyPatch(typeof(StartOfRound), "Update")]
		[HarmonyPrefix]
		public static void UpdateUsingController(StartOfRound __instance)
		{
			if (!((Object)(object)__instance.localPlayerController == (Object)null) && !((Object)(object)hotkeyTooltip == (Object)null) && ((Component)hotkeyTooltip).gameObject.activeSelf && ((Behaviour)hotkeyTooltip).enabled)
			{
				if (__instance.localPlayerUsingController != usingController)
				{
					usingController = __instance.localPlayerUsingController;
					UpdateHotkeyTooltipText();
				}
				LerpItemSlotFrames();
			}
		}

		private static void LerpItemSlotFrames()
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: 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_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: 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)
			if (!lerpToggledItemSlotFrames)
			{
				return;
			}
			if (largestPositionDifference < 2f && largestPositionDifference != -1f)
			{
				lerpToggledItemSlotFrames = false;
			}
			for (int i = 0; i < SessionManager.numReservedItemSlotsUnlocked; i++)
			{
				ReservedItemSlotData unlockedReservedItemSlot = SessionManager.GetUnlockedReservedItemSlot(i);
				Image val = HUDManager.Instance.itemSlotIconFrames[ReservedPlayerData.localPlayerData.reservedHotbarStartIndex + i];
				bool flag = unlockedReservedItemSlot.slotPriority >= 0 || !ConfigSettings.displayNegativePrioritySlotsLeftSideOfScreen.Value;
				Vector2 anchoredPosition = ((Graphic)val).rectTransform.anchoredPosition;
				anchoredPosition.x = (defaultItemSlotPosX + (defaultItemSlotSize.x - itemSlotWidth) / 2f) * (float)(flag ? 1 : (-1));
				if (ReservedHotbarManager.isToggledInReservedSlots && ReservedHotbarManager.currentlyToggledItemSlots != null && ReservedHotbarManager.currentlyToggledItemSlots.Contains(unlockedReservedItemSlot))
				{
					anchoredPosition.x += itemSlotWidth / 2f * (float)((!flag) ? 1 : (-1));
				}
				float num = Mathf.Abs(anchoredPosition.x - ((Graphic)val).rectTransform.anchoredPosition.x);
				largestPositionDifference = Mathf.Max(largestPositionDifference, num);
				if (lerpToggledItemSlotFrames)
				{
					((Graphic)val).rectTransform.anchoredPosition = Vector2.Lerp(((Graphic)val).rectTransform.anchoredPosition, anchoredPosition, Time.deltaTime * 10f);
				}
				else
				{
					((Graphic)val).rectTransform.anchoredPosition = anchoredPosition;
				}
			}
		}

		public static void OnUpdateReservedItemSlots()
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			if (reservedItemSlots == null || SessionManager.numReservedItemSlotsUnlocked <= 0 || reservedItemSlots.Count == SessionManager.numReservedItemSlotsUnlocked)
			{
				return;
			}
			List<Image> list = new List<Image>(HUDManager.Instance.itemSlotIconFrames);
			List<Image> list2 = new List<Image>(HUDManager.Instance.itemSlotIcons);
			for (int i = reservedItemSlots.Count; i < SessionManager.numReservedItemSlotsUnlocked; i++)
			{
				GameObject val = Object.Instantiate<GameObject>(((Component)list[0]).gameObject, ((Component)list[0]).transform.parent);
				Image component = val.GetComponent<Image>();
				Image component2 = ((Component)((Component)component).transform.GetChild(0)).GetComponent<Image>();
				((Component)component).transform.localScale = ((Component)list[0]).transform.localScale;
				((Transform)((Graphic)component).rectTransform).eulerAngles = ((Transform)((Graphic)list[0]).rectTransform).eulerAngles;
				((Transform)((Graphic)component2).rectTransform).eulerAngles = ((Transform)((Graphic)list2[0]).rectTransform).eulerAngles;
				CanvasGroup val2 = ((Component)component).gameObject.AddComponent<CanvasGroup>();
				val2.ignoreParentGroups = ConfigSettings.preventReservedItemSlotFade.Value;
				val2.alpha = 1f;
				component.fillMethod = list[0].fillMethod;
				component.sprite = list[0].sprite;
				((Graphic)component).material = ((Graphic)list[0]).material;
				if (Plugin.IsModLoaded("xuxiaolan.hotbarrd"))
				{
					component.overrideSprite = list[0].overrideSprite;
				}
				int index = ReservedPlayerData.localPlayerData.reservedHotbarStartIndex + reservedItemSlots.Count;
				list.Insert(index, component);
				list2.Insert(index, component2);
				reservedItemSlots.Add(component);
			}
			HUDManager.Instance.itemSlotIconFrames = list.ToArray();
			HUDManager.Instance.itemSlotIcons = list2.ToArray();
			UpdateUI();
		}

		public static void UpdateUI()
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0401: Unknown result type (might be due to invalid IL or missing references)
			//IL_0416: Unknown result type (might be due to invalid IL or missing references)
			//IL_0423: Unknown result type (might be due to invalid IL or missing references)
			//IL_042d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_0469: Unknown result type (might be due to invalid IL or missing references)
			//IL_049b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			if (reservedItemSlots.Count != SessionManager.numReservedItemSlotsUnlocked)
			{
				Plugin.LogError("Called UpdateUI with mismatched unlocked reserved item slots and reserved item slot hud elements.");
				return;
			}
			int num = 0;
			int num2 = 0;
			RectTransform val = null;
			Vector2 anchoredPosition = default(Vector2);
			for (int i = 0; i < SessionManager.numReservedItemSlotsUnlocked; i++)
			{
				ReservedItemSlotData unlockedReservedItemSlot = SessionManager.GetUnlockedReservedItemSlot(i);
				int num3 = Array.IndexOf(HUDManager.Instance.itemSlotIconFrames, reservedItemSlots[i]);
				Image val2 = HUDManager.Instance.itemSlotIconFrames[ReservedPlayerData.localPlayerData.reservedHotbarStartIndex + i];
				Image val3 = HUDManager.Instance.itemSlotIcons[ReservedPlayerData.localPlayerData.reservedHotbarStartIndex + i];
				((Graphic)val2).rectTransform.sizeDelta = ((Graphic)HUDManager.Instance.itemSlotIconFrames[0]).rectTransform.sizeDelta;
				((Graphic)val3).rectTransform.sizeDelta = ((Graphic)HUDManager.Instance.itemSlotIcons[0]).rectTransform.sizeDelta;
				if (HotbarPlus_Compat.Enabled && !ConfigSettings.applyHotbarPlusItemSlotSize.Value)
				{
					((Graphic)val2).rectTransform.sizeDelta = defaultItemSlotSize;
					((Graphic)val3).rectTransform.sizeDelta = defaultItemIconSize;
				}
				itemSlotWidth = ((Graphic)val2).rectTransform.sizeDelta.x;
				itemSlotSpacing = defaultItemSlotSpacing * currentItemSlotScale;
				GrabbableObject reservedItem = ReservedPlayerData.localPlayerData.GetReservedItem(unlockedReservedItemSlot);
				((Object)val2).name = "Slot" + i + " [ReservedItemSlot] (" + unlockedReservedItemSlot.slotName + ")";
				((Vector2)(ref anchoredPosition))..ctor(defaultItemSlotPosX, defaultItemSlotPosY);
				if (unlockedReservedItemSlot.slotPriority >= 0 || !ConfigSettings.displayNegativePrioritySlotsLeftSideOfScreen.Value)
				{
					anchoredPosition.x = defaultItemSlotPosX + (defaultItemSlotSize.x - itemSlotWidth) / 2f;
					anchoredPosition.y = defaultItemSlotPosY + 36f * ((itemSlotWidth / defaultItemSlotSize.x - 1f) / 2f) + itemSlotSpacing * (float)num;
					if (!ConfigSettings.hideEmptyReservedItemSlots.Value || (Object)(object)reservedItem != (Object)null)
					{
						if (!Object.op_Implicit((Object)(object)val))
						{
							val = ((Graphic)val2).rectTransform;
						}
						num++;
					}
					else
					{
						anchoredPosition.y = -1000f;
					}
				}
				else
				{
					anchoredPosition.x = 0f - defaultItemSlotPosX - (defaultItemSlotSize.x - itemSlotWidth) / 2f;
					anchoredPosition.y = defaultItemSlotPosY + 36f * ((itemSlotWidth / defaultItemSlotSize.x - 1f) / 2f) + itemSlotSpacing * (float)num2;
					if (!ConfigSettings.hideEmptyReservedItemSlots.Value || (Object)(object)reservedItem != (Object)null)
					{
						num2++;
					}
					else
					{
						anchoredPosition.y = -1000f;
					}
				}
				((Graphic)val2).rectTransform.anchoredPosition = anchoredPosition;
				if ((Object)(object)reservedItem != (Object)null)
				{
					((Behaviour)val3).enabled = true;
					val3.sprite = reservedItem.itemProperties.itemIcon;
				}
				else
				{
					((Behaviour)val3).enabled = false;
					val3.sprite = null;
				}
			}
			if (SessionManager.numReservedItemSlotsUnlocked > 0 && !ConfigSettings.hideFocusHotbarTooltip.Value)
			{
				if ((Object)(object)hotkeyTooltip == (Object)null)
				{
					hotkeyTooltip = new GameObject("ReservedItemSlotTooltip", new Type[2]
					{
						typeof(RectTransform),
						typeof(TextMeshProUGUI)
					}).GetComponent<TextMeshProUGUI>();
				}
				RectTransform rectTransform = ((TMP_Text)hotkeyTooltip).rectTransform;
				((Transform)rectTransform).parent = (Transform)(object)val;
				if (Object.op_Implicit((Object)(object)val))
				{
					((Transform)rectTransform).localScale = Vector3.one;
					rectTransform.sizeDelta = new Vector2(val.sizeDelta.x * 2f, 10f);
					rectTransform.pivot = Vector2.one / 2f;
					rectTransform.anchoredPosition3D = new Vector3(0f, 0f - rectTransform.sizeDelta.x / 2f - itemSlotWidth / 2f - 5f, 0f);
					((TMP_Text)hotkeyTooltip).font = ((TMP_Text)HUDManager.Instance.controlTipLines[0]).font;
					((TMP_Text)hotkeyTooltip).fontSize = 7f * (val.sizeDelta.x / defaultItemSlotSize.x);
					((TMP_Text)hotkeyTooltip).alignment = (TextAlignmentOptions)4100;
					UpdateHotkeyTooltipText();
				}
				else
				{
					((Transform)rectTransform).localScale = Vector3.zero;
				}
			}
			currentApplyHotbarPlusSize = ConfigSettings.applyHotbarPlusItemSlotSize.Value;
			currentHideEmptySlots = ConfigSettings.hideEmptyReservedItemSlots.Value;
		}

		public static void UpdateHotkeyTooltipText()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)localPlayerController == (Object)null || (Object)(object)hotkeyTooltip == (Object)null || Keybinds.FocusReservedHotbarAction == null)
			{
				return;
			}
			int num = (localPlayerUsingController ? 1 : 0);
			string text = "";
			string text2 = "";
			InputBinding val;
			if (num >= 0 && num < Keybinds.FocusReservedHotbarAction.bindings.Count)
			{
				val = Keybinds.FocusReservedHotbarAction.bindings[num];
				text = KeybindDisplayNames.GetKeybindDisplayName(((InputBinding)(ref val)).effectivePath);
			}
			else
			{
				Plugin.LogError("Failed to update FocusReservedHotbar keybind tooltip. Using controller: " + localPlayerUsingController + " NumFocusReservedHotbarActionBindings: " + Keybinds.FocusReservedHotbarAction.bindings.Count);
			}
			if (num >= 0 && num < Keybinds.ToggleFocusReservedHotbarAction.bindings.Count)
			{
				val = Keybinds.ToggleFocusReservedHotbarAction.bindings[num];
				text2 = KeybindDisplayNames.GetKeybindDisplayName(((InputBinding)(ref val)).effectivePath);
			}
			else
			{
				Plugin.LogError("Failed to update ToggleFocusReservedHotbar keybind tooltip. Using controller: " + localPlayerUsingController + " NumToggleFocusReservedHotbarActionBindings: " + Keybinds.ToggleFocusReservedHotbarAction.bindings.Count);
			}
			((TMP_Text)hotkeyTooltip).text = "";
			if (text != "")
			{
				((TMP_Text)hotkeyTooltip).text = $"Hold: [{text}]";
			}
			if (text2 != "" && text2 != text)
			{
				if (((TMP_Text)hotkeyTooltip).text != "")
				{
					TextMeshProUGUI obj = hotkeyTooltip;
					((TMP_Text)obj).text = ((TMP_Text)obj).text + "\n";
				}
				TextMeshProUGUI obj2 = hotkeyTooltip;
				((TMP_Text)obj2).text = ((TMP_Text)obj2).text + $"Toggle: [{text2}]";
			}
		}

		public static void UpdateToggledReservedItemSlotsUI()
		{
			if (ReservedHotbarManager.currentlyToggledItemSlots != null)
			{
				toggledReservedItemSlots = new HashSet<ReservedItemSlotData>(ReservedHotbarManager.currentlyToggledItemSlots);
			}
			else
			{
				toggledReservedItemSlots.Clear();
			}
			lerpToggledItemSlotFrames = true;
			largestPositionDifference = -1f;
		}

		private static float GetCurrentItemSlotSpacing()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Image val = HUDManager.Instance.itemSlotIconFrames[0];
				Image val2 = HUDManager.Instance.itemSlotIconFrames[1];
				if (((Object)val).name.ToLower().Contains("reserved") || ((Object)val2).name.ToLower().Contains("reserved"))
				{
					return defaultItemSlotSpacing;
				}
				return Mathf.Abs(((Graphic)val2).rectTransform.anchoredPosition.x - ((Graphic)val).rectTransform.anchoredPosition.x);
			}
			catch
			{
			}
			return defaultItemSlotSpacing;
		}

		[HarmonyPatch(typeof(QuickMenuManager), "CloseQuickMenu")]
		[HarmonyPostfix]
		public static void OnCloseQuickMenu()
		{
			if (HotbarPlus_Compat.Enabled || currentHideEmptySlots != ConfigSettings.hideEmptyReservedItemSlots.Value)
			{
				UpdateUI();
			}
		}
	}
	[HarmonyPatch]
	internal class MaskedEnemyPatcher
	{
		[HarmonyPatch(typeof(MaskedPlayerEnemy), "Awake")]
		[HarmonyPrefix]
		public static void InitMaskedEnemy(MaskedPlayerEnemy __instance)
		{
			if (ConfigSettings.showReservedItemsHolsteredMaskedEnemy.Value && !MaskedEnemyData.allMaskedEnemyData.ContainsKey(__instance))
			{
				MaskedEnemyData.allMaskedEnemyData.Add(__instance, new MaskedEnemyData(__instance));
			}
		}

		[HarmonyPatch(typeof(MaskedPlayerEnemy), "OnDestroy")]
		[HarmonyPrefix]
		public static void OnDestroy(MaskedPlayerEnemy __instance)
		{
			if (MaskedEnemyData.allMaskedEnemyData.TryGetValue(__instance, out var value))
			{
				value.DestroyEquippedItems();
				MaskedEnemyData.allMaskedEnemyData.Remove(__instance);
			}
		}

		[HarmonyPatch(typeof(MaskedPlayerEnemy), "Update")]
		[HarmonyPostfix]
		public static void Update(MaskedPlayerEnemy __instance)
		{
			if (ConfigSettings.showReservedItemsHolsteredMaskedEnemy.Value && MaskedEnemyData.allMaskedEnemyData.TryGetValue(__instance, out var value) && (Object)(object)value.originallyMimickingPlayer == (Object)null && (Object)(object)value.maskedEnemy.mimickingPlayer != (Object)null)
			{
				AddReservedItemsToMaskedEnemy(__instance);
			}
		}

		public static void AddReservedItemsToMaskedEnemy(MaskedPlayerEnemy maskedEnemy)
		{
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			if (!ConfigSettings.showReservedItemsHolsteredMaskedEnemy.Value || !MaskedEnemyData.allMaskedEnemyData.TryGetValue(maskedEnemy, out var value))
			{
				return;
			}
			value.originallyMimickingPlayer = value.maskedEnemy.mimickingPlayer;
			if (!ReservedPlayerData.allPlayerData.TryGetValue(value.originallyMimickingPlayer, out var value2))
			{
				Plugin.LogWarning("Failed to mimic player's equipped reserved items. Could not retrieve player data from: " + value.originallyMimickingPlayer.playerUsername);
				return;
			}
			for (int i = value2.reservedHotbarStartIndex; i < Mathf.Min(value2.reservedHotbarEndIndexExcluded, value2.playerController.ItemSlots.Length); i++)
			{
				GrabbableObject val = value2.playerController.ItemSlots[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				int num = i - value2.reservedHotbarStartIndex;
				if (num < 0 || num >= SessionManager.unlockedReservedItemSlots.Count)
				{
					Plugin.LogWarning("Failed to add reserved item to MaskedEnemy. Could not get ReservedItemSlot at index: " + num + " Item: " + val.itemProperties.itemName + " SlotIndexInInventory: " + i + " ReservedHotbarStartIndex: " + value2.reservedHotbarStartIndex);
					continue;
				}
				ReservedItemSlotData reservedItemSlotData = SessionManager.unlockedReservedItemSlots[num];
				ReservedItemData reservedItemData = reservedItemSlotData.GetReservedItemData(val);
				if (reservedItemData.holsteredParentBone == PlayerBone.None)
				{
					continue;
				}
				Transform bone = value.boneMap.GetBone(reservedItemData.holsteredParentBone);
				if ((Object)(object)bone == (Object)null)
				{
					Plugin.LogWarning("Failed to get bone from masked enemy: " + reservedItemData.holsteredParentBone);
					continue;
				}
				GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, bone);
				val2.transform.localEulerAngles = reservedItemData.holsteredRotationOffset;
				val2.transform.localPosition = reservedItemData.holsteredPositionOffset;
				val2.transform.localScale = ((Component)val).transform.localScale;
				val2.layer = 6;
				MeshRenderer[] componentsInChildren = val2.GetComponentsInChildren<MeshRenderer>();
				foreach (MeshRenderer val3 in componentsInChildren)
				{
					if (!((Object)val3).name.Contains("ScanNode") && !((Component)val3).gameObject.CompareTag("DoNotSet") && !((Component)val3).gameObject.CompareTag("InteractTrigger"))
					{
						((Component)val3).gameObject.layer = 6;
					}
				}
				if (val is FlashlightItem)
				{
					Light[] componentsInChildren2 = val2.GetComponentsInChildren<Light>();
					foreach (Light val4 in componentsInChildren2)
					{
						((Behaviour)val4).enabled = false;
					}
				}
				else
				{
					Light[] componentsInChildren3 = val2.GetComponentsInChildren<Light>();
					foreach (Light val5 in componentsInChildren3)
					{
						((Behaviour)val5).enabled = true;
					}
				}
				GrabbableObject componentInChildren = val2.GetComponentInChildren<GrabbableObject>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.playerHeldBy = null;
					FlashlightItem val6 = (FlashlightItem)(object)((componentInChildren is FlashlightItem) ? componentInChildren : null);
					if ((Object)(object)val6 != (Object)null)
					{
						((Behaviour)val6.flashlightBulb).enabled = true;
						((Behaviour)val6.flashlightBulbGlow).enabled = true;
						((Renderer)val6.flashlightMesh).sharedMaterials[1] = val6.bulbLight;
					}
					ReservedItemsPatcher.ForceEnableItemMesh(componentInChildren, enabled: true);
					componentInChildren.EnablePhysics(false);
				}
				Object.DestroyImmediate((Object)(object)val2.GetComponentInChildren<NetworkObject>());
				Collider[] componentsInChildren4 = val2.GetComponentsInChildren<Collider>();
				foreach (Collider val7 in componentsInChildren4)
				{
					Object.DestroyImmediate((Object)(object)val7);
				}
				MonoBehaviour[] componentsInChildren5 = val2.GetComponentsInChildren<MonoBehaviour>();
				foreach (MonoBehaviour val8 in componentsInChildren5)
				{
					Object.DestroyImmediate((Object)(object)val8);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class MouseScrollPatcher
	{
		private static bool scrollingItemSlots;

		private static float timeLoggedPreventedScroll;

		public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;

		[HarmonyPatch(typeof(PlayerControllerB), "NextItemSlot")]
		[HarmonyPrefix]
		public static void CorrectReservedScrollDirectionNextItemSlot(ref bool forward)
		{
			if (Keybinds.scrollingReservedHotbar)
			{
				forward = Keybinds.RawScrollAction.ReadValue<float>() > 0f;
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "SwitchItemSlotsServerRpc")]
		[HarmonyPrefix]
		public static void CorrectReservedScrollDirectionServerRpc(ref bool forward)
		{
			if (Keybinds.scrollingReservedHotbar)
			{
				forward = Keybinds.RawScrollAction.ReadValue<float>() > 0f;
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "ScrollMouse_performed")]
		[HarmonyPrefix]
		public static bool PreventInvertedScrollingReservedHotbar(CallbackContext context)
		{
			if (StartOfRound.Instance.localPlayerUsingController || SessionManager.numReservedItemSlotsUnlocked <= 0 || HUDPatcher.reservedItemSlots == null || localPlayerController.inTerminalMenu)
			{
				return true;
			}
			if (ReservedPlayerData.localPlayerData.currentItemSlotIsReserved)
			{
				if (!HUDPatcher.hasReservedItemSlotsAndEnabled)
				{
					return true;
				}
				float time = Time.time;
				if (!Keybinds.scrollingReservedHotbar)
				{
					return false;
				}
				if (ReservedPlayerData.localPlayerData.GetNumHeldReservedItems() == 1 && (Object)(object)ReservedPlayerData.localPlayerData.currentlySelectedItem != (Object)null && !ReservedHotbarManager.isToggledInReservedSlots)
				{
					if (ConfigSettings.verboseLogs.Value && time - timeLoggedPreventedScroll > 1f)
					{
						timeLoggedPreventedScroll = time;
					}
					return false;
				}
			}
			return true;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "ScrollMouse_performed")]
		[HarmonyPostfix]
		public static void ScrollReservedItemSlots(CallbackContext context)
		{
			scrollingItemSlots = false;
		}
	}
	[HarmonyPatch]
	internal static class PlayerPatcher
	{
		private static int INTERACTABLE_OBJECT_MASK = 0;

		public static int vanillaHotbarSize = 4;

		private static bool initialized = false;

		public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;

		public static Dictionary<PlayerControllerB, ReservedPlayerData> allPlayerData => ReservedPlayerData.allPlayerData;

		public static ReservedPlayerData localPlayerData => ReservedPlayerData.localPlayerData;

		public static int reservedHotbarSize => SessionManager.numReservedItemSlotsUnlocked;

		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPrefix]
		private static void InitSession(StartOfRound __instance)
		{
			initialized = false;
			vanillaHotbarSize = 4;
			ReservedPlayerData.allPlayerData?.Clear();
		}

		[HarmonyPatch(typeof(PlayerControllerB), "Awake")]
		[HarmonyPostfix]
		private static void InitializePlayerController(PlayerControllerB __instance)
		{
			if (!initialized)
			{
				vanillaHotbarSize = __instance.ItemSlots.Length;
				INTERACTABLE_OBJECT_MASK = (int)Traverse.Create((object)__instance).Field("interactableObjectsMask").GetValue();
				initialized = true;
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "Start")]
		[HarmonyPrefix]
		private static void InitializePlayerControllerLate(PlayerControllerB __instance)
		{
			ReservedPlayerData value = new ReservedPlayerData(__instance);
			if (!allPlayerData.ContainsKey(__instance))
			{
				Plugin.Log("Initializing ReservedPlayerData for player: " + ((Object)__instance).name);
				allPlayerData.Add(__instance, value);
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")]
		[HarmonyPostfix]
		private static void CheckForChangedInventorySize(PlayerControllerB __instance)
		{
			if ((!SyncManager.isSynced && !SyncManager.canUseModDisabledOnHost) || !ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value) || reservedHotbarSize <= 0 || value.hotbarSize == __instance.ItemSlots.Length)
			{
				return;
			}
			value.hotbarSize = __instance.ItemSlots.Length;
			int num = -1;
			if ((Object)(object)__instance == (Object)(object)localPlayerController)
			{
				if (HUDPatcher.reservedItemSlots != null && HUDPatcher.reservedItemSlots.Count > 0)
				{
					num = Array.IndexOf(HUDManager.Instance.itemSlotIconFrames, HUDPatcher.reservedItemSlots[0]);
					Plugin.Log("OnUpdateInventorySize A for local player: " + ((Object)__instance).name + " NewReservedItemsStartIndex: " + num);
				}
				if (num == -1)
				{
					for (int i = 0; i < HUDManager.Instance.itemSlotIconFrames.Length; i++)
					{
						if (((Object)HUDManager.Instance.itemSlotIconFrames[i]).name.ToLower().Contains("reserved"))
						{
							num = i;
							Plugin.Log("OnUpdateInventorySize B for local player: " + ((Object)__instance).name + " NewReservedItemsStartIndex: " + num);
							break;
						}
					}
				}
				PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
				foreach (PlayerControllerB val in allPlayerScripts)
				{
					if (ReservedPlayerData.allPlayerData.TryGetValue(val, out var value2) && value2 != value && reservedHotbarSize > 0 && value2.hotbarSize != val.ItemSlots.Length)
					{
						value2.reservedHotbarStartIndex = num;
					}
				}
			}
			if (num == -1)
			{
				num = value.reservedHotbarStartIndex;
				Plugin.Log("OnUpdateInventorySize C for player: " + ((Object)__instance).name + " NewReservedItemsStartIndex: " + num);
			}
			if (num == -1)
			{
				num = vanillaHotbarSize;
				Plugin.Log("OnUpdateInventorySize D for player: " + ((Object)__instance).name + " NewReservedItemsStartIndex: " + num);
			}
			value.reservedHotbarStartIndex = num;
			if (value.reservedHotbarStartIndex < 0)
			{
				Plugin.LogError("Set new reserved start index to slot: " + value.reservedHotbarStartIndex + ". Maybe share these logs with Flip? :)");
			}
			if (value.reservedHotbarEndIndexExcluded - 1 >= value.playerController.ItemSlots.Length)
			{
				Plugin.LogError("Set new reserved start index to slot: " + value.reservedHotbarStartIndex + " Last reserved slot index: " + (value.reservedHotbarEndIndexExcluded - 1) + " Inventory size: " + value.playerController.ItemSlots.Length + ". Maybe share these logs with Flip? :)");
			}
			if (value.isLocalPlayer)
			{
				HUDPatcher.UpdateUI();
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")]
		[HarmonyPrefix]
		private static bool BeginGrabReservedItemPrefix(PlayerControllerB __instance)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			if ((!SyncManager.isSynced && !SyncManager.canUseModDisabledOnHost) || !HUDPatcher.hasReservedItemSlotsAndEnabled)
			{
				return true;
			}
			localPlayerData.grabbingReservedItemSlotData = null;
			localPlayerData.grabbingReservedItemData = null;
			localPlayerData.grabbingReservedItem = null;
			localPlayerData.previousHotbarIndex = -1;
			if (__instance.twoHanded || __instance.sinkingValue > 0.73f)
			{
				return true;
			}
			Ray val = default(Ray);
			((Ray)(ref val))..ctor(((Component)__instance.gameplayCamera).transform.position, ((Component)__instance.gameplayCamera).transform.forward);
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(val, ref val2, __instance.grabDistance, INTERACTABLE_OBJECT_MASK) && ((Component)((RaycastHit)(ref val2)).collider).gameObject.layer != 8 && ((Component)((RaycastHit)(ref val2)).collider).tag == "PhysicsProp")
			{
				GrabbableObject component = ((Component)((Component)((RaycastHit)(ref val2)).collider).transform).gameObject.GetComponent<GrabbableObject>();
				if ((Object)(object)component != (Object)null && !__instance.inSpecialInteractAnimation && !component.isHeld && !component.isPocketed)
				{
					NetworkObject networkObject = ((NetworkBehaviour)component).NetworkObject;
					if ((Object)(object)networkObject != (Object)null && networkObject.IsSpawned && SessionManager.TryGetUnlockedItemData(component, out var itemData))
					{
						localPlayerData.grabbingReservedItemData = itemData;
						localPlayerData.grabbingReservedItem = component;
						localPlayerData.previousHotbarIndex = Mathf.Clamp(__instance.currentItemSlot, 0, __instance.ItemSlots.Length - 1);
						Plugin.Log("Beginning grab on reserved item: " + itemData.itemName + " Previous item slot: " + localPlayerData.previousHotbarIndex);
					}
				}
			}
			return true;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")]
		[HarmonyPostfix]
		private static void BeginGrabReservedItemPostfix(PlayerControllerB __instance)
		{
			if (localPlayerData != null && localPlayerData.isGrabbingReservedItem && !localPlayerData.IsReservedItemSlot(localPlayerData.previousHotbarIndex))
			{
				SetSpecialGrabAnimationBool(__instance, setTrue: false);
				SetSpecialGrabAnimationBool(__instance, (Object)(object)localPlayerData.previouslyHeldItem != (Object)null, localPlayerData.previouslyHeldItem);
				__instance.playerBodyAnimator.SetBool("GrabValidated", true);
				__instance.playerBodyAnimator.SetBool("GrabInvalidated", false);
				__instance.playerBodyAnimator.ResetTrigger("SwitchHoldAnimation");
				__instance.playerBodyAnimator.ResetTrigger("SwitchHoldAnimationTwoHanded");
				if ((Object)(object)localPlayerData.previouslyHeldItem != (Object)null)
				{
					__instance.playerBodyAnimator.ResetTrigger(localPlayerData.previouslyHeldItem.itemProperties.pocketAnim);
				}
				__instance.twoHanded = (Object)(object)localPlayerData.previouslyHeldItem != (Object)null && localPlayerData.previouslyHeldItem.itemProperties.twoHanded;
				__instance.twoHandedAnimation = (Object)(object)localPlayerData.previouslyHeldItem != (Object)null && localPlayerData.previouslyHeldItem.itemProperties.twoHandedAnimation;
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "GrabObjectClientRpc")]
		[HarmonyPrefix]
		private static void GrabReservedItemClientRpcPrefix(bool grabValidated, NetworkObjectReference grabbedObject, PlayerControllerB __instance)
		{
			if ((!SyncManager.isSynced && !SyncManager.canUseModDisabledOnHost) || !NetworkHelper.IsClientExecStage((NetworkBehaviour)(object)__instance) || !ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value))
			{
				return;
			}
			NetworkObject val = default(NetworkObject);
			GrabbableObject val2 = default(GrabbableObject);
			if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsListening && grabValidated && ((NetworkObjectReference)(ref grabbedObject)).TryGet(ref val, (NetworkManager)null) && ((Component)val).TryGetComponent<GrabbableObject>(ref val2) && SessionManager.TryGetUnlockedItemData(val2, out var itemData))
			{
				ReservedItemSlotData firstEmptySlotForReservedItem = value.GetFirstEmptySlotForReservedItem(itemData.itemName);
				if (firstEmptySlotForReservedItem != null)
				{
					value.grabbingReservedItemSlotData = firstEmptySlotForReservedItem;
					value.grabbingReservedItemData = itemData;
					value.grabbingReservedItem = val2;
					value.previousHotbarIndex = Mathf.Clamp(__instance.currentItemSlot, 0, __instance.ItemSlots.Length - 1);
					return;
				}
			}
			value.grabbingReservedItemSlotData = null;
			value.grabbingReservedItemData = null;
			value.grabbingReservedItem = null;
			value.previousHotbarIndex = -1;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "GrabObjectClientRpc")]
		[HarmonyPostfix]
		private static void GrabReservedItemClientRpcPostfix(bool grabValidated, NetworkObjectReference grabbedObject, PlayerControllerB __instance)
		{
			if ((!SyncManager.isSynced && !SyncManager.canUseModDisabledOnHost) || !NetworkHelper.IsClientExecStage((NetworkBehaviour)(object)__instance) || !ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value) || !value.isGrabbingReservedItem)
			{
				return;
			}
			if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsListening)
			{
				NetworkObject val = default(NetworkObject);
				GrabbableObject val2 = default(GrabbableObject);
				if (grabValidated && ((NetworkObjectReference)(ref grabbedObject)).TryGet(ref val, (NetworkManager)null) && ((Component)val).TryGetComponent<GrabbableObject>(ref val2))
				{
					if (SessionManager.TryGetUnlockedItemData(val2, out var itemData))
					{
						if (!value.IsReservedItemSlot(value.previousHotbarIndex))
						{
							if ((Object)(object)value.previouslyHeldItem != (Object)null)
							{
								value.previouslyHeldItem.EnableItemMeshes(true);
							}
							ReservedItemsPatcher.ForceEnableItemMesh(value.grabbingReservedItem, enabled: false);
							Traverse.Create((object)val2).Field("previousPlayerHeldBy").SetValue((object)__instance);
							if (value.isLocalPlayer)
							{
								int num = value.reservedHotbarStartIndex + value.grabbingReservedItemSlotData.GetReservedItemSlotIndex();
								((Component)HUDManager.Instance.itemSlotIconFrames[num]).GetComponent<Animator>().SetBool("selectedSlot", false);
								((Component)HUDManager.Instance.itemSlotIconFrames[value.previousHotbarIndex]).GetComponent<Animator>().SetBool("selectedSlot", true);
								((Component)HUDManager.Instance.itemSlotIconFrames[num]).GetComponent<Animator>().Play("PanelLines", 0, 1f);
								((Component)HUDManager.Instance.itemSlotIconFrames[value.previousHotbarIndex]).GetComponent<Animator>().Play("PanelEnlarge", 0, 1f);
							}
							else
							{
								SwitchToItemSlot(__instance, value.previousHotbarIndex);
								if (itemData.showOnPlayerWhileHolstered)
								{
									val2.EnableItemMeshes(true);
								}
							}
							SetSpecialGrabAnimationBool(__instance, setTrue: false);
							SetSpecialGrabAnimationBool(__instance, (Object)(object)value.previouslyHeldItem != (Object)null, value.previouslyHeldItem);
							__instance.playerBodyAnimator.SetBool("GrabValidated", true);
							__instance.playerBodyAnimator.SetBool("GrabInvalidated", false);
							__instance.playerBodyAnimator.ResetTrigger("SwitchHoldAnimation");
							__instance.playerBodyAnimator.ResetTrigger("SwitchHoldAnimationTwoHanded");
							if ((Object)(object)value.previouslyHeldItem != (Object)null)
							{
								__instance.playerBodyAnimator.ResetTrigger(value.previouslyHeldItem.itemProperties.pocketAnim);
							}
							__instance.twoHanded = (Object)(object)value.previouslyHeldItem != (Object)null && value.previouslyHeldItem.itemProperties.twoHanded;
							__instance.twoHandedAnimation = (Object)(object)value.previouslyHeldItem != (Object)null && value.previouslyHeldItem.itemProperties.twoHandedAnimation;
						}
						if (value.isLocalPlayer)
						{
							HUDPatcher.UpdateUI();
							return;
						}
						value.grabbingReservedItemSlotData = null;
						value.grabbingReservedItemData = null;
						value.grabbingReservedItem = null;
						value.previousHotbarIndex = -1;
						return;
					}
				}
				else if (value.isLocalPlayer)
				{
					Plugin.LogWarning("Failed to validate ReservedItemGrab by the local player. Object id: " + ((NetworkObjectReference)(ref grabbedObject)).NetworkObjectId + ". Internal error?");
					Traverse.Create((object)localPlayerController).Field("grabInvalidated").SetValue((object)true);
				}
				else
				{
					Plugin.LogWarning("Failed to validate ReservedItemGrab by player with id: " + ((Object)__instance).name + ". Object id: " + ((NetworkObjectReference)(ref grabbedObject)).NetworkObjectId + ". Internal error?");
				}
			}
			value.grabbingReservedItemSlotData = null;
			value.grabbingReservedItemData = null;
			value.grabbingReservedItem = null;
			value.previousHotbarIndex = -1;
		}

		[HarmonyPatch(typeof(GrabbableObject), "GrabItemOnClient")]
		[HarmonyPrefix]
		private static void OnReservedItemGrabbed(GrabbableObject __instance)
		{
			if (localPlayerData.grabbingReservedItemData != null && (Object)(object)__instance == (Object)(object)GetCurrentlyGrabbingObject(localPlayerController))
			{
				((MonoBehaviour)localPlayerController).StartCoroutine(OnReservedItemGrabbedEndOfFrame());
			}
			IEnumerator OnReservedItemGrabbedEndOfFrame()
			{
				yield return (object)new WaitForEndOfFrame();
				if (localPlayerData.isGrabbingReservedItem)
				{
					if (localPlayerData.previousHotbarIndex < 0 || localPlayerData.previousHotbarIndex >= localPlayerController.ItemSlots.Length || localPlayerData.IsReservedItemSlot(localPlayerData.previousHotbarIndex))
					{
						localPlayerData.previousHotbarIndex = 0;
					}
					SwitchToItemSlot(localPlayerController, localPlayerData.previousHotbarIndex);
					GrabbableObject obj = __instance;
					if (obj != null)
					{
						obj.PocketItem();
					}
					SetSpecialGrabAnimationBool(localPlayerController, setTrue: false);
					SetSpecialGrabAnimationBool(localPlayerController, (Object)(object)localPlayerData.previouslyHeldItem != (Object)null, localPlayerData.previouslyHeldItem);
					localPlayerController.playerBodyAnimator.SetBool("GrabValidated", true);
					localPlayerController.playerBodyAnimator.SetBool("GrabInvalidated", false);
					localPlayerController.playerBodyAnimator.ResetTrigger("SwitchHoldAnimation");
					localPlayerController.isGrabbingObjectAnimation = false;
					localPlayerController.playerBodyAnimator.ResetTrigger("SwitchHoldAnimationTwoHanded");
					if ((Object)(object)localPlayerData.previouslyHeldItem != (Object)null)
					{
						localPlayerController.playerBodyAnimator.ResetTrigger(localPlayerData.previouslyHeldItem.itemProperties.pocketAnim);
					}
					localPlayerController.twoHanded = (Object)(object)localPlayerData.previouslyHeldItem != (Object)null && localPlayerData.previouslyHeldItem.itemProperties.twoHanded;
					localPlayerController.twoHandedAnimation = (Object)(object)localPlayerData.previouslyHeldItem != (Object)null && localPlayerData.previouslyHeldItem.itemProperties.twoHandedAnimation;
				}
				localPlayerData.grabbingReservedItemSlotData = null;
				localPlayerData.grabbingReservedItemData = null;
				localPlayerData.grabbingReservedItem = null;
				localPlayerData.previousHotbarIndex = -1;
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "SwitchToItemSlot")]
		[HarmonyPrefix]
		private static void UpdateLastSelectedHotbarIndex(int slot, PlayerControllerB __instance)
		{
			int currentItemSlot = __instance.currentItemSlot;
			if (ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value))
			{
				if (value.IsReservedItemSlot(currentItemSlot))
				{
					ReservedHotbarManager.indexInReservedHotbar = currentItemSlot;
				}
				else
				{
					ReservedHotbarManager.indexInHotbar = currentItemSlot;
				}
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "SwitchToItemSlot")]
		[HarmonyPostfix]
		private static void UpdateFocusReservedHotbar(int slot, PlayerControllerB __instance)
		{
			if (HUDPatcher.hasReservedItemSlotsAndEnabled && ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value))
			{
				bool inReservedHotbarSlots = value.inReservedHotbarSlots;
				value.inReservedHotbarSlots = value.IsReservedItemSlot(__instance.currentItemSlot);
				bool flag = false;
				if (inReservedHotbarSlots != value.inReservedHotbarSlots || (value.inReservedHotbarSlots && ReservedHotbarManager.isToggledInReservedSlots && ReservedHotbarManager.currentlyToggledItemSlots != null && !ReservedHotbarManager.currentlyToggledItemSlots.Contains(value.GetCurrentlySelectedReservedItemSlot())))
				{
					flag = true;
				}
				if (value.inReservedHotbarSlots)
				{
					ReservedHotbarManager.OnSwapToReservedHotbar();
				}
				else
				{
					ReservedHotbarManager.OnSwapToVanillaHotbar();
				}
				if (flag)
				{
					HUDPatcher.UpdateToggledReservedItemSlotsUI();
				}
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "FirstEmptyItemSlot")]
		[HarmonyPostfix]
		private static void GetReservedItemSlotPlacementIndex(ref int __result, PlayerControllerB __instance)
		{
			if (reservedHotbarSize <= 0 || !HUDPatcher.hasReservedItemSlotsAndEnabled || !ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value))
			{
				return;
			}
			ReservedItemData grabbingReservedItemData = value.grabbingReservedItemData;
			if (grabbingReservedItemData != null)
			{
				ReservedItemSlotData firstEmptySlotForReservedItem = value.GetFirstEmptySlotForReservedItem(grabbingReservedItemData.itemName);
				if (firstEmptySlotForReservedItem != null)
				{
					__result = firstEmptySlotForReservedItem.GetIndexInInventory(__instance);
					return;
				}
				value.grabbingReservedItemSlotData = null;
				value.grabbingReservedItemData = null;
				value.grabbingReservedItem = null;
				value.previousHotbarIndex = -1;
			}
			if (!value.IsReservedItemSlot(__result))
			{
				return;
			}
			__result = -1;
			for (int i = 0; i < __instance.ItemSlots.Length; i++)
			{
				if (!value.IsReservedItemSlot(i) && (Object)(object)__instance.ItemSlots[i] == (Object)null)
				{
					__result = i;
					break;
				}
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "NextItemSlot")]
		[HarmonyPostfix]
		private static void OnNextItemSlot(ref int __result, bool forward, PlayerControllerB __instance)
		{
			if (reservedHotbarSize <= 0 || !HUDPatcher.hasReservedItemSlotsAndEnabled || !ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value))
			{
				return;
			}
			bool inReservedHotbarSlots = value.inReservedHotbarSlots;
			bool flag = value.IsReservedItemSlot(__result);
			bool flag2 = inReservedHotbarSlots;
			if (inReservedHotbarSlots)
			{
				ReservedItemSlotData unlockedReservedItemSlot = SessionManager.GetUnlockedReservedItemSlot(__result - value.reservedHotbarStartIndex);
				if (ReservedHotbarManager.isToggledInReservedSlots && !Keybinds.pressedToggleKey && !Keybinds.holdingModifierKey && ReservedHotbarManager.currentlyToggledItemSlots != null && (!flag || (Object)(object)value.itemSlots[__result] == (Object)null || !ReservedHotbarManager.currentlyToggledItemSlots.Contains(unlockedReservedItemSlot)))
				{
					__result = ReservedHotbarManager.indexInHotbar;
					return;
				}
			}
			if (flag == flag2 && (!flag || (Object)(object)__instance.ItemSlots[__result] != (Object)null))
			{
				return;
			}
			int num = (forward ? 1 : (-1));
			__result = __instance.currentItemSlot + num;
			__result = ((__result < 0) ? (__instance.ItemSlots.Length - 1) : ((__result < __instance.ItemSlots.Length) ? __result : 0));
			flag = value.IsReservedItemSlot(__result);
			if (!flag2)
			{
				if (flag)
				{
					__result = (forward ? ((value.reservedHotbarStartIndex + reservedHotbarSize) % __instance.ItemSlots.Length) : (value.reservedHotbarStartIndex - 1));
				}
				return;
			}
			__result = (flag ? __result : (forward ? value.reservedHotbarStartIndex : (value.reservedHotbarStartIndex + reservedHotbarSize - 1)));
			int numHeldReservedItems = value.GetNumHeldReservedItems();
			while (numHeldReservedItems > 0 && __result != value.currentItemSlot && (Object)(object)__instance.ItemSlots[__result] == (Object)null)
			{
				__result += num;
				__result = ((!value.IsReservedItemSlot(__result)) ? (forward ? value.reservedHotbarStartIndex : (value.reservedHotbarStartIndex + reservedHotbarSize - 1)) : __result);
			}
		}

		[HarmonyPatch(typeof(HUDManager), "ClearControlTips")]
		[HarmonyPrefix]
		private static bool PreventClearControlTipsGrabbingReservedItem(HUDManager __instance)
		{
			return ReservedPlayerData.localPlayerData == null || (Object)(object)ReservedPlayerData.localPlayerData.grabbingReservedItem == (Object)null;
		}

		[HarmonyPatch(typeof(GrabbableObject), "SetControlTipsForItem")]
		[HarmonyPrefix]
		private static bool PreventUpdateControlTipsGrabbingReservedItem(GrabbableObject __instance)
		{
			return ReservedPlayerData.localPlayerData == null || (Object)(object)ReservedPlayerData.localPlayerData.grabbingReservedItem != (Object)(object)__instance;
		}

		private static GrabbableObject GetCurrentlyGrabbingObject(PlayerControllerB playerController)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			return (GrabbableObject)Traverse.Create((object)playerController).Field("currentlyGrabbingObject").GetValue();
		}

		private static void SetCurrentlyGrabbingObject(PlayerControllerB playerController, GrabbableObject grabbable)
		{
			Traverse.Create((object)playerController).Field("currentlyGrabbingObject").SetValue((object)grabbable);
		}

		public static bool ReservedItemIsBeingGrabbed(GrabbableObject grabbableObject)
		{
			if ((Object)(object)grabbableObject == (Object)null)
			{
				return false;
			}
			foreach (ReservedPlayerData value in ReservedPlayerData.allPlayerData.Values)
			{
				if ((Object)(object)grabbableObject == (Object)(object)value.grabbingReservedItem)
				{
					return true;
				}
			}
			return false;
		}

		public static void SetSpecialGrabAnimationBool(PlayerControllerB playerController, bool setTrue, GrabbableObject currentItem = null)
		{
			MethodInfo method = ((object)playerController).GetType().GetMethod("SetSpecialGrabAnimationBool", BindingFlags.Instance | BindingFlags.NonPublic);
			method.Invoke(playerController, new object[2] { setTrue, currentItem });
		}

		public static void SwitchToItemSlot(PlayerControllerB playerController, int slot, GrabbableObject fillSlotWithItem = null)
		{
			MethodInfo method = ((object)playerController).GetType().GetMethod("SwitchToItemSlot", BindingFlags.Instance | BindingFlags.NonPublic);
			method.Invoke(playerController, new object[2] { slot, fillSlotWithItem });
			if (ReservedPlayerData.allPlayerData.TryGetValue(playerController, out var value))
			{
				value.timeSinceSwitchingSlots = 0f;
			}
		}
	}
	[HarmonyPatch]
	internal static class ReservedItemsPatcher
	{
		public static bool ignoreMeshOverride;

		public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;

		[HarmonyPatch(typeof(GrabbableObject), "PocketItem")]
		[HarmonyPostfix]
		private static void OnPocketReservedItem(GrabbableObject __instance)
		{
			if (!ConfigSettings.showReservedItemsHolstered.Value || (Object)(object)__instance.playerHeldBy == (Object)null || !ReservedPlayerData.allPlayerData.TryGetValue(__instance.playerHeldBy, out var value) || !SessionManager.TryGetUnlockedItemData(__instance, out var itemData) || !value.IsItemInReservedItemSlot(__instance) || !itemData.showOnPlayerWhileHolstered)
			{
				return;
			}
			MeshRenderer[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<MeshRenderer>();
			foreach (MeshRenderer val in componentsInChildren)
			{
				if (!((Component)val).gameObject.CompareTag("DoNotSet") && !((Component)val).gameObject.CompareTag("InteractTrigger") && ((Component)val).gameObject.layer != 14 && ((Component)val).gameObject.layer != 22)
				{
					((Component)val).gameObject.layer = (value.isLocalPlayer ? 23 : 6);
				}
			}
			__instance.parentObject = value.boneMap.GetBone(itemData.holsteredParentBone);
			ForceEnableItemMesh(__instance, enabled: true);
		}

		[HarmonyPatch(typeof(GrabbableObject), "EquipItem")]
		[HarmonyPostfix]
		private static void OnEquipReservedItem(GrabbableObject __instance)
		{
			if (!ConfigSettings.showReservedItemsHolstered.Value || (Object)(object)__instance.playerHeldBy == (Object)null || !ReservedPlayerData.allPlayerData.TryGetValue(__instance.playerHeldBy, out var value) || !SessionManager.TryGetUnlockedItemData(__instance, out var itemData) || !value.IsItemInReservedItemSlot(__instance) || !itemData.showOnPlayerWhileHolstered)
			{
				return;
			}
			MeshRenderer[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<MeshRenderer>();
			foreach (MeshRenderer val in componentsInChildren)
			{
				if (!((Component)val).gameObject.CompareTag("DoNotSet") && !((Component)val).gameObject.CompareTag("InteractTrigger") && ((Component)val).gameObject.layer != 14 && ((Component)val).gameObject.layer != 22)
				{
					((Component)val).gameObject.layer = 6;
				}
			}
			__instance.parentObject = (value.isLocalPlayer ? __instance.playerHeldBy.localItemHolder : __instance.playerHeldBy.serverItemHolder);
		}

		[HarmonyPatch(typeof(GrabbableObject), "DiscardItem")]
		[HarmonyPostfix]
		private static void ResetReservedItemLayer(GrabbableObject __instance)
		{
			if (!SessionManager.TryGetUnlockedItemData(__instance, out var itemData) || !itemData.showOnPlayerWhileHolstered)
			{
				return;
			}
			MeshRenderer[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<MeshRenderer>();
			foreach (MeshRenderer val in componentsInChildren)
			{
				if (!((Component)val).gameObject.CompareTag("DoNotSet") && !((Component)val).gameObject.CompareTag("InteractTrigger") && ((Component)val).gameObject.layer != 14 && ((Component)val).gameObject.layer != 22)
				{
					((Component)val).gameObject.layer = 6;
				}
			}
		}

		[HarmonyPatch(typeof(GrabbableObject), "LateUpdate")]
		[HarmonyPostfix]
		private static void SetHolsteredPositionRotation(GrabbableObject __instance)
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			if (ConfigSettings.showReservedItemsHolstered.Value && !((Object)(object)__instance.playerHeldBy == (Object)null) && !((Object)(object)__instance.parentObject == (Object)null) && ReservedPlayerData.allPlayerData.TryGetValue(__instance.playerHeldBy, out var value) && SessionManager.TryGetUnlockedItemData(__instance, out var itemData) && value.IsItemInReservedItemSlot(__instance) && itemData.showOnPlayerWhileHolstered && (Object)(object)__instance != (Object)(object)value.currentlySelectedItem)
			{
				Transform transform = ((Component)__instance.parentObject).transform;
				((Component)__instance).transform.rotation = ((Component)__instance.parentObject).transform.rotation * Quaternion.Euler(itemData.holsteredRotationOffset);
				((Component)__instance).transform.position = transform.position + transform.rotation * itemData.holsteredPositionOffset;
			}
		}

		[HarmonyPatch(typeof(GrabbableObject), "EnableItemMeshes")]
		[HarmonyPrefix]
		private static void OnEnableItemMeshes(ref bool enable, GrabbableObject __instance)
		{
			if (ConfigSettings.showReservedItemsHolstered.Value)
			{
				if ((Object)(object)__instance.playerHeldBy != (Object)null && !ignoreMeshOverride && ReservedPlayerData.allPlayerData.TryGetValue(__instance.playerHeldBy, out var value) && SessionManager.TryGetUnlockedItemData(__instance, out var itemData) && value.IsItemInReservedItemSlot(__instance) && itemData.showOnPlayerWhileHolstered && (Object)(object)value.currentlySelectedItem != (Object)(object)__instance && !PlayerPatcher.ReservedItemIsBeingGrabbed(__instance))
				{
					enable = true;
				}
				ignoreMeshOverride = false;
			}
		}

		public static void ForceEnableItemMesh(GrabbableObject grabbableObject, bool enabled)
		{
			ignoreMeshOverride = true;
			grabbableObject.EnableItemMeshes(enabled);
		}
	}
	[HarmonyPatch]
	internal static class SyncAlreadyHeldObjectsPatcher
	{
		[HarmonyPatch(typeof(StartOfRound), "SyncAlreadyHeldObjectsClientRpc")]
		[HarmonyPrefix]
		private static bool SyncAlreadyHeldReservedObjectsClientRpc(ref NetworkObjectReference[] gObjects, ref int[] playersHeldBy, ref int[] itemSlotNumbers, ref int[] isObjectPocketed, int syncWithClient, StartOfRound __instance)
		{
			if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsListening)
			{
				return true;
			}
			if ((NetworkHelper.IsClientExecStage((NetworkBehaviour)(object)__instance) || (!NetworkManager.Singleton.IsServer && !NetworkManager.Singleton.IsHost)) && (!NetworkHelper.IsClientExecStage((NetworkBehaviour)(object)__instance) || (!NetworkManager.Singleton.IsClient && !NetworkManager.Singleton.IsHost) || syncWithClient != (int)NetworkManager.Singleton.LocalClientId))
			{
				return false;
			}
			bool flag = false;
			List<NetworkObjectReference> list = new List<NetworkObjectReference>(gObjects);
			List<int> list2 = new List<int>(playersHeldBy);
			List<int> list3 = new List<int>(itemSlotNumbers);
			List<int> list4 = new List<int>(isObjectPocketed);
			for (int num = itemSlotNumbers.Length - 1; num >= 0; num--)
			{
				if (itemSlotNumbers[num] >= __instance.localPlayerController.ItemSlots.Length)
				{
					list.RemoveAt(num);
					list2.RemoveAt(num);
					list3.RemoveAt(num);
					list4.Remove(num);
					flag = true;
				}
			}
			if (flag)
			{
				gObjects = list.ToArray();
				playersHeldBy = list2.ToArray();
				itemSlotNumbers = list3.ToArray();
				isObjectPocketed = list4.ToArray();
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class TerminalPatcher
	{
		public static Terminal terminalInstance;

		public static bool initializedTerminalNodes;

		public static ReservedItemSlotData purchasingItemSlot;

		[HarmonyPatch(typeof(Terminal), "Awake")]
		[HarmonyPrefix]
		public static void InitializeTerminal(Terminal __instance)
		{
			terminalInstance = __instance;
			initializedTerminalNodes = false;
			EditExistingTerminalNodes();
		}

		[HarmonyPatch(typeof(Terminal), "BeginUsingTerminal")]
		[HarmonyPrefix]
		public static void OnBeginUsingTerminal(Terminal __instance)
		{
			if (!initializedTerminalNodes && SyncManager.isSynced)
			{
				EditExistingTerminalNodes();
			}
		}

		public static void EditExistingTerminalNodes()
		{
			if (!SyncManager.isSynced)
			{
				return;
			}
			initializedTerminalNodes = true;
			if (!SyncManager.enablePurchasingItemSlots)
			{
				return;
			}
			foreach (TerminalNode specialNode in terminalInstance.terminalNodes.specialNodes)
			{
				if (((Object)specialNode).name == "Start" && !specialNode.displayText.Contains("[ReservedItemSlots]"))
				{
					string text = "Type \"Help\" for a list of commands.";
					int num = specialNode.displayText.IndexOf(text);
					if (num != -1)
					{
						num += text.Length;
						string value = "\n\n[ReservedItemSlots]\nType \"Reserved\" to purchase reserved item slots.";
						specialNode.displayText = specialNode.displayText.Insert(num, value);
					}
					else
					{
						Plugin.LogError("Failed to add reserved item slots tip to terminal. Maybe an update broke it?");
					}
				}
				else if (((Object)specialNode).name == "HelpCommands" && !specialNode.displayText.Contains(">RESERVED"))
				{
					string value2 = "[numberOfItemsOnRoute]";
					int num2 = specialNode.displayText.IndexOf(value2);
					if (num2 != -1)
					{
						string text2 = ">RESERVED\n";
						text2 += "Purchase reserved item slots.\n\n";
						specialNode.displayText = specialNode.displayText.Insert(num2, text2);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Terminal), "TextPostProcess")]
		[HarmonyPrefix]
		public static void TextPostProcess(ref string modifiedDisplayText, TerminalNode node)
		{
			if (modifiedDisplayText.Length <= 0)
			{
				return;
			}
			string text = "[[[reservedItemSlotsSelectionList]]]";
			if (!modifiedDisplayText.Contains(text))
			{
				return;
			}
			int num = modifiedDisplayText.IndexOf(text);
			int num2 = num + text.Length;
			string oldValue = modifiedDisplayText.Substring(num, num2 - num);
			string text2 = "";
			if (!SyncManager.enablePurchasingItemSlots)
			{
				text2 += "Every reserved item slot is unlocked!\n\n";
			}
			else
			{
				text2 += "Reserved Item Slots\n------------------------------\n\n";
				text2 += "To purchase a reserved item slot, type the following command.\n> RESERVED [item_slot]\n\n";
				int num3 = 0;
				foreach (ReservedItemSlotData value in SyncManager.unlockableReservedItemSlotsDict.Values)
				{
					num3 = Mathf.Max(num3, value.slotName.Length);
				}
				foreach (ReservedItemSlotData value2 in SyncManager.unlockableReservedItemSlotsDict.Values)
				{
					string arg = (SessionManager.IsItemSlotUnlocked(value2) ? "[Purchased]" : ("$" + value2.purchasePrice));
					text2 += $"* {value2.slotDisplayName}{new string(' ', num3 - value2.slotDisplayName.Length)}   //   {arg}\n";
				}
			}
			modifiedDisplayText = modifiedDisplayText.Replace(oldValue, text2);
		}

		[HarmonyPatch(typeof(Terminal), "ParsePlayerSentence")]
		[HarmonyPrefix]
		public static bool ParsePlayerSentence(ref TerminalNode __result, Terminal __instance)
		{
			if (__instance.screenText.text.Length <= 0)
			{
				return true;
			}
			string text = __instance.screenText.text.Substring(__instance.screenText.text.Length - __instance.textAdded).ToLower();
			string[] array = text.Split(new char[1] { ' ' });
			ReservedItemSlotData reservedItemSlotData = null;
			if (!SyncManager.isSynced)
			{
				if (text.StartsWith("reserved"))
				{
					__result = BuildTerminalNodeHostDoesNotHaveMod();
					return false;
				}
				return true;
			}
			if (purchasingItemSlot != null)
			{
				if ("confirm".StartsWith(text))
				{
					if (purchasingItemSlot.isUnlocked)
					{
						Plugin.LogWarning("Attempted to confirm purchase on reserved item slot that was already unlocked. Item slot: " + purchasingItemSlot.slotDisplayName);
						__result = BuildTerminalNodeAlreadyUnlocked(purchasingItemSlot);
					}
					else if (terminalInstance.groupCredits < purchasingItemSlot.purchasePrice)
					{
						Plugin.LogWarning("Attempted to confirm purchase with insufficient credits. Current credits: " + terminalInstance.groupCredits + " Required credits: " + purchasingItemSlot.purchasePrice);
						__result = BuildTerminalNodeInsufficientFunds(purchasingItemSlot);
					}
					else
					{
						Plugin.Log("Purchasing reserved item slot: " + purchasingItemSlot.slotDisplayName + ". Price: " + purchasingItemSlot.purchasePrice);
						Terminal obj = terminalInstance;
						obj.groupCredits -= purchasingItemSlot.purchasePrice;
						terminalInstance.BuyItemsServerRpc(new int[0], terminalInstance.groupCredits, terminalInstance.numberOfItemsInDropship);
						SyncManager.SendUnlockItemSlotUpdateToServer(purchasingItemSlot.slotId);
						__result = BuildTerminalNodeOnPurchased(purchasingItemSlot, terminalInstance.groupCredits);
					}
				}
				else
				{
					Plugin.Log("Canceling order.");
					__result = BuildCustomTerminalNode("Canceled order.\n\n");
				}
				purchasingItemSlot = null;
				return false;
			}
			purchasingItemSlot = null;
			if (array.Length == 0 || array[0] != "reserved")
			{
				return true;
			}
			if (array.Length == 1)
			{
				__result = BuildTerminalNodeHome();
				return false;
			}
			string text2 = text.Substring(9);
			reservedItemSlotData = TryGetReservedItemSlot(text2);
			if (reservedItemSlotData != null)
			{
				if (SessionManager.IsItemSlotUnlocked(reservedItemSlotData))
				{
					Plugin.LogWarning("Attempted to start purchase on reserved item slot that was already unlocked. Item slot: " + reservedItemSlotData.slotName);
					__result = BuildTerminalNodeAlreadyUnlocked(reservedItemSlotData);
				}
				else if (terminalInstance.groupCredits < reservedItemSlotData.purchasePrice)
				{
					Plugin.LogWarning("Attempted to start purchase with insufficient credits. Current credits: " + terminalInstance.groupCredits + ". Item slot price: " + reservedItemSlotData.purchasePrice);
					__result = BuildTerminalNodeInsufficientFunds(reservedItemSlotData);
				}
				else
				{
					Plugin.Log("Started purchasing reserved item slot: " + reservedItemSlotData.slotName);
					purchasingItemSlot = reservedItemSlotData;
					__result = BuildTerminalNodeConfirmDenyPurchase(reservedItemSlotData);
				}
				return false;
			}
			Plugin.LogWarning("Attempted to start purchase on invalid reserved item slot. Item slot: " + text2);
			__result = BuildTerminalNodeInvalidReservedItemSlot(text2);
			return false;
		}

		private static TerminalNode BuildTerminalNodeHome()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			return new TerminalNode
			{
				displayText = "[ReservedItemSlots]\n\nStore\n------------------------------\n[[[reservedItemSlotsSelectionList]]]\n\n",
				clearPreviousText = true,
				acceptAnything = false
			};
		}

		private static TerminalNode BuildTerminalNodeConfirmDenyPurchase(ReservedItemSlotData itemSlotData)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			TerminalNode val = new TerminalNode();
			val.displayText = "You have requested to purchase a reserved item slot for $" + itemSlotData.purchasePrice + " credits.\n> [" + itemSlotData.slotDisplayName + "]\n\n";
			val.isConfirmationNode = true;
			val.acceptAnything = false;
			val.clearPreviousText = true;
			TerminalNode val2 = val;
			val2.displayText = val2.displayText + "Credit balance: $" + terminalInstance.groupCredits + "\n";
			val2.displayText += "\n";
			val2.displayText += "Please CONFIRM or DENY.\n\n";
			return val2;
		}

		private static TerminalNode BuildTerminalNodeOnPurchased(ReservedItemSlotData itemSlotData, int newGroupCredits)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			TerminalNode val = new TerminalNode
			{
				displayText = "You have successfully purchased a new reserved item slot!\n> [" + itemSlotData.slotDisplayName + "]\n\n",
				buyUnlockable = true,
				clearPreviousText = true,
				acceptAnything = false,
				playSyncedClip = 0
			};
			val.displayText = val.displayText + "New credit balance: $" + newGroupCredits + "\n\n";
			return val;
		}

		private static TerminalNode BuildTerminalNodeAlreadyUnlocked(ReservedItemSlotData itemSlot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			return new TerminalNode
			{
				displayText = "You have already purchased this reserved item slot!\n> [" + itemSlot.slotDisplayName + "]\n\n",
				clearPreviousText = false,
				acceptAnything = false
			};
		}

		private static TerminalNode BuildTerminalNodeInsufficientFunds(ReservedItemSlotData itemSlot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			TerminalNode val = new TerminalNode();
			val.displayText = "You could not afford this reserved item slot!\n> [" + itemSlot.slotDisplayName + "]\n\nCredit balance is $" + terminalInstance.groupCredits + "\n";
			val.clearPreviousText = true;
			val.acceptAnything = false;
			TerminalNode val2 = val;
			val2.displayText = val2.displayText + "Price of reserved item slot is $" + itemSlot.purchasePrice + "\n\n";
			return val2;
		}

		private static TerminalNode BuildTerminalNodeInvalidReservedItemSlot(string reservedItemSlotName = "")
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			TerminalNode val = new TerminalNode
			{
				displayText = "Reserved item slot does not exist.",
				clearPreviousText = false,
				acceptAnything = false
			};
			if (reservedItemSlotName != "")
			{
				val.displayText = val.displayText + "\n\"" + reservedItemSlotName + "\"";
			}
			val.displayText += "\n";
			return val;
		}

		private static TerminalNode BuildTerminalNodeHostDoesNotHaveMod(string itemSlotName = "")
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result typ

plugins/ReservedSprayPaintSlot.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using ReservedItemSlotCore;
using ReservedItemSlotCore.Config;
using ReservedItemSlotCore.Data;
using ReservedSprayPaintSlot.Config;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ReservedSprayPaintSlot")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ReservedSprayPaintSlot")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("d5fcfd75-740b-418d-b185-a0bbdea6fa40")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ReservedSprayPaintSlot
{
	[BepInPlugin("FlipMods.ReservedSprayPaintSlot", "ReservedSprayPaintSlot", "1.1.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin instance;

		private static ManualLogSource logger;

		private Harmony _harmony;

		public static ReservedItemSlotData sprayPaintSlotData;

		public static ReservedItemData sprayPaintData;

		public static List<ReservedItemData> additionalItemData = new List<ReservedItemData>();

		private void Awake()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			instance = this;
			CreateCustomLogger();
			ConfigSettings.BindConfigSettings();
			CreateReservedItemSlots();
			CreateAdditionalReservedItemSlots();
			_harmony = new Harmony("ReservedSprayPaintSlot");
			PatchAll();
			Log("ReservedSprayPaintSlot loaded");
		}

		private void CreateReservedItemSlots()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			sprayPaintSlotData = ReservedItemSlotData.CreateReservedItemSlotData("spray_paint", ConfigSettings.overrideItemSlotPriority.Value, ConfigSettings.overridePurchasePrice.Value);
			sprayPaintData = sprayPaintSlotData.AddItemToReservedItemSlot(new ReservedItemData("Spray paint", (PlayerBone)1, new Vector3(0.26f, -0.05f, 0.2f), new Vector3(-105f, 0f, 0f)));
		}

		private void CreateAdditionalReservedItemSlots()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			string[] array = ConfigSettings.ParseAdditionalItems();
			string[] array2 = array;
			foreach (string text in array2)
			{
				if (!sprayPaintSlotData.ContainsItem(text))
				{
					LogWarning("Adding additional item to reserved item slot. Item: " + text);
					ReservedItemData val = new ReservedItemData(text, (PlayerBone)0, default(Vector3), default(Vector3));
					additionalItemData.Add(val);
					sprayPaintSlotData.AddItemToReservedItemSlot(val);
				}
			}
		}

		private void PatchAll()
		{
			IEnumerable<Type> enumerable;
			try
			{
				enumerable = Assembly.GetExecutingAssembly().GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				enumerable = ex.Types.Where((Type t) => t != null);
			}
			foreach (Type item in enumerable)
			{
				_harmony.PatchAll(item);
			}
		}

		private void CreateCustomLogger()
		{
			try
			{
				logger = Logger.CreateLogSource(string.Format("{0}-{1}", "ReservedSprayPaintSlot", "1.1.2"));
			}
			catch
			{
				logger = ((BaseUnityPlugin)this).Logger;
			}
		}

		public static void Log(string message)
		{
			logger.LogInfo((object)message);
		}

		public static void LogError(string message)
		{
			logger.LogError((object)message);
		}

		public static void LogWarning(string message)
		{
			logger.LogWarning((object)message);
		}

		public static bool IsModLoaded(string guid)
		{
			return Chainloader.PluginInfos.ContainsKey(guid);
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "FlipMods.ReservedSprayPaintSlot";

		public const string PLUGIN_NAME = "ReservedSprayPaintSlot";

		public const string PLUGIN_VERSION = "1.1.2";
	}
}
namespace ReservedSprayPaintSlot.Patches
{
	[HarmonyPatch]
	internal static class SprayPaintPatcher
	{
		public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;

		public static PlayerControllerB GetPreviousPlayerHeldBy(SprayPaintItem sprayPaintItem)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			return (PlayerControllerB)Traverse.Create((object)sprayPaintItem).Field("previousPlayerHeldBy").GetValue();
		}

		public static SprayPaintItem GetMainSprayPaint(PlayerControllerB playerController)
		{
			return GetCurrentlySelectedSprayPaint(playerController) ?? GetReservedSprayPaint(playerController);
		}

		public static SprayPaintItem GetReservedSprayPaint(PlayerControllerB playerController)
		{
			ReservedItemSlotData val = default(ReservedItemSlotData);
			ReservedPlayerData value;
			return (SprayPaintItem)((SessionManager.TryGetUnlockedItemSlotData(Plugin.sprayPaintSlotData.slotName, ref val) && ReservedPlayerData.allPlayerData.TryGetValue(playerController, out value)) ? /*isinst with value type is only supported in some contexts*/: null);
		}

		public static SprayPaintItem GetCurrentlySelectedSprayPaint(PlayerControllerB playerController)
		{
			return (SprayPaintItem)((playerController.currentItemSlot >= 0 && playerController.currentItemSlot < playerController.ItemSlots.Length) ? /*isinst with value type is only supported in some contexts*/: null);
		}
	}
	[HarmonyPatch]
	public class SprayPaintTweaks
	{
		public static float GetSprayCanTankValue(SprayPaintItem sprayPaintItem)
		{
			return (float)Traverse.Create((object)sprayPaintItem).Field("sprayCanTank").GetValue();
		}

		public static void SetSprayCanTankValue(SprayPaintItem sprayPaintItem, float value)
		{
			Traverse.Create((object)sprayPaintItem).Field("sprayCanTank").SetValue((object)value);
		}

		[HarmonyPatch(typeof(SprayPaintItem), "Start")]
		[HarmonyPrefix]
		public static void InitSprayPaint(SprayPaintItem __instance)
		{
			SetSprayCanTankValue(__instance, ConfigSettings.sprayPaintCapacityMultiplier.Value);
		}

		[HarmonyPatch(typeof(SprayPaintItem), "LoadItemSaveData")]
		[HarmonyPostfix]
		public static void OnLoadValues(int saveData, SprayPaintItem __instance)
		{
			float value = Mathf.Clamp(GetSprayCanTankValue(__instance) * ConfigSettings.sprayPaintCapacityMultiplier.Value, 0f, ConfigSettings.sprayPaintCapacityMultiplier.Value);
			SetSprayCanTankValue(__instance, value);
			Plugin.Log("Loading spraypaint save data. Remaining capacity: " + value);
		}

		[HarmonyPatch(typeof(SprayPaintItem), "GetItemDataToSave")]
		[HarmonyPostfix]
		public static void OnSaveValues(ref int __result, SprayPaintItem __instance)
		{
			__result = (int)Mathf.Clamp((float)__result / ConfigSettings.sprayPaintCapacityMultiplier.Value, 0f, 100f);
		}
	}
}
namespace ReservedSprayPaintSlot.Config
{
	public static class ConfigSettings
	{
		public static ConfigEntry<float> sprayPaintCapacityMultiplier;

		public static ConfigEntry<int> overrideItemSlotPriority;

		public static ConfigEntry<int> overridePurchasePrice;

		public static ConfigEntry<string> additionalItemsInSlot;

		public static Dictionary<string, ConfigEntryBase> currentConfigEntries = new Dictionary<string, ConfigEntryBase>();

		public static void BindConfigSettings()
		{
			Plugin.Log("BindingConfigs");
			sprayPaintCapacityMultiplier = AddConfigEntry<float>(((BaseUnityPlugin)Plugin.instance).Config.Bind<float>("Client-side", "SprayPaintCapacityMultiplier", 10f, "Extends the max capacity of spraypaint cans by this multiplier. This setting will soon be host only, and will sync with all non-host clients."));
			overrideItemSlotPriority = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "SprayPaintPriorityOverride", 25, "Manually set the priority for this item slot. Higher priority slots will come first in the reserved item slots, which will appear below the other slots. Negative priority items will appear on the left side of the screen, this is disabled in the core mod's config."));
			overridePurchasePrice = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "SprayPaintSlotPriceOverride", 50, "Manually set the price for this item in the store. Setting 0 will force this item to be unlocked immediately after the game starts."));
			additionalItemsInSlot = AddConfigEntry<string>(((BaseUnityPlugin)Plugin.instance).Config.Bind<string>("Server-side", "AdditionalItemsInSlot", "", "Syntax: \"Item1,Item name2\" (without quotes). When adding items, use the item's name as it appears in game. Include spaces if there are spaces in the item name. Adding items that do not exist, or that are from a mod which is not enabled will not cause any problems.\nNOTE: IF YOU ARE USING A TRANSLATION MOD, YOU MAY NEED TO ADD THE TRANSLATED NAME OF ANY ITEM YOU WANT IN THIS SLOT."));
			additionalItemsInSlot.Value = additionalItemsInSlot.Value.Replace(", ", ",");
			sprayPaintCapacityMultiplier.Value = Mathf.Max(sprayPaintCapacityMultiplier.Value, 0f);
			TryRemoveOldConfigSettings();
		}

		public static ConfigEntry<T> AddConfigEntry<T>(ConfigEntry<T> configEntry)
		{
			currentConfigEntries.Add(((ConfigEntryBase)configEntry).Definition.Key, (ConfigEntryBase)(object)configEntry);
			return configEntry;
		}

		public static string[] ParseAdditionalItems()
		{
			return ConfigSettings.ParseItemNames(additionalItemsInSlot.Value);
		}

		public static void TryRemoveOldConfigSettings()
		{
			HashSet<string> hashSet = new HashSet<string>();
			HashSet<string> hashSet2 = new HashSet<string>();
			foreach (ConfigEntryBase value in currentConfigEntries.Values)
			{
				hashSet.Add(value.Definition.Section);
				hashSet2.Add(value.Definition.Key);
			}
			try
			{
				ConfigFile config = ((BaseUnityPlugin)Plugin.instance).Config;
				string configFilePath = config.ConfigFilePath;
				if (!File.Exists(configFilePath))
				{
					return;
				}
				string text = File.ReadAllText(configFilePath);
				string[] array = File.ReadAllLines(configFilePath);
				string text2 = "";
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = array[i].Replace("\n", "");
					if (array[i].Length <= 0)
					{
						continue;
					}
					if (array[i].StartsWith("["))
					{
						if (text2 != "" && !hashSet.Contains(text2))
						{
							text2 = "[" + text2 + "]";
							int num = text.IndexOf(text2);
							int num2 = text.IndexOf(array[i]);
							text = text.Remove(num, num2 - num);
						}
						text2 = array[i].Replace("[", "").Replace("]", "").Trim();
					}
					else
					{
						if (!(text2 != ""))
						{
							continue;
						}
						if (i <= array.Length - 4 && array[i].StartsWith("##"))
						{
							int j;
							for (j = 1; i + j < array.Length && array[i + j].Length > 3; j++)
							{
							}
							if (hashSet.Contains(text2))
							{
								int num3 = array[i + j - 1].IndexOf("=");
								string item = array[i + j - 1].Substring(0, num3 - 1);
								if (!hashSet2.Contains(item))
								{
									int num4 = text.IndexOf(array[i]);
									int num5 = text.IndexOf(array[i + j - 1]) + array[i + j - 1].Length;
									text = text.Remove(num4, num5 - num4);
								}
							}
							i += j - 1;
						}
						else if (array[i].Length > 3)
						{
							text = text.Replace(array[i], "");
						}
					}
				}
				if (!hashSet.Contains(text2))
				{
					text2 = "[" + text2 + "]";
					int num6 = text.IndexOf(text2);
					text = text.Remove(num6, text.Length - num6);
				}
				while (text.Contains("\n\n\n"))
				{
					text = text.Replace("\n\n\n", "\n\n");
				}
				File.WriteAllText(configFilePath, text);
				config.Reload();
			}
			catch
			{
			}
		}
	}
}

plugins/ReservedWalkieSlot.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalCompanyInputUtils.Api;
using ReservedItemSlotCore;
using ReservedItemSlotCore.Config;
using ReservedItemSlotCore.Data;
using ReservedWalkieSlot.Config;
using ReservedWalkieSlot.Patches;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ReservedWalkieSlot")]
[assembly: AssemblyDescription("Mod made by flipf17")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ReservedWalkieSlot")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c15c320f-d8fc-4f1c-be3c-f2d2ffc41edd")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ReservedWalkieSlot
{
	[BepInPlugin("FlipMods.ReservedWalkieSlot", "ReservedWalkieSlot", "2.0.6")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin instance;

		private static ManualLogSource logger;

		private Harmony _harmony;

		public static ReservedItemSlotData walkieSlotData;

		public static ReservedItemData walkieData;

		public static List<ReservedItemData> additionalItemData = new List<ReservedItemData>();

		private void Awake()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			instance = this;
			CreateCustomLogger();
			ConfigSettings.BindConfigSettings();
			CreateReservedItemSlots();
			CreateAdditionalReservedItemSlots();
			_harmony = new Harmony("ReservedWalkieSlot");
			PatchAll();
			Log("ReservedWalkieSlot loaded");
		}

		private void CreateReservedItemSlots()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			walkieSlotData = ReservedItemSlotData.CreateReservedItemSlotData("walkie_talkie", ConfigSettings.overrideItemSlotPriority.Value, ConfigSettings.overridePurchasePrice.Value);
			walkieData = walkieSlotData.AddItemToReservedItemSlot(new ReservedItemData("Walkie-talkie", (PlayerBone)4, new Vector3(0.15f, -0.05f, 0.25f), new Vector3(0f, -90f, 100f)));
		}

		private void CreateAdditionalReservedItemSlots()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			string[] array = ConfigSettings.ParseAdditionalItems();
			string[] array2 = array;
			foreach (string text in array2)
			{
				if (!walkieSlotData.ContainsItem(text))
				{
					LogWarning("Adding additional item to reserved item slot. Item: " + text);
					ReservedItemData val = new ReservedItemData(text, (PlayerBone)0, default(Vector3), default(Vector3));
					additionalItemData.Add(val);
					walkieSlotData.AddItemToReservedItemSlot(val);
				}
			}
		}

		private void PatchAll()
		{
			IEnumerable<Type> enumerable;
			try
			{
				enumerable = Assembly.GetExecutingAssembly().GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				enumerable = ex.Types.Where((Type t) => t != null);
			}
			foreach (Type item in enumerable)
			{
				_harmony.PatchAll(item);
			}
		}

		private void CreateCustomLogger()
		{
			try
			{
				logger = Logger.CreateLogSource(string.Format("{0}-{1}", "ReservedWalkieSlot", "2.0.6"));
			}
			catch
			{
				logger = ((BaseUnityPlugin)this).Logger;
			}
		}

		public static void Log(string message)
		{
			logger.LogInfo((object)message);
		}

		public static void LogError(string message)
		{
			logger.LogError((object)message);
		}

		public static void LogWarning(string message)
		{
			logger.LogWarning((object)message);
		}

		public static bool IsModLoaded(string guid)
		{
			return Chainloader.PluginInfos.ContainsKey(guid);
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "FlipMods.ReservedWalkieSlot";

		public const string PLUGIN_NAME = "ReservedWalkieSlot";

		public const string PLUGIN_VERSION = "2.0.6";
	}
}
namespace ReservedWalkieSlot.Patches
{
	[HarmonyPatch(typeof(ShipBuildModeManager), "PlayerMeetsConditionsToBuild")]
	public class PlayerMeetsConditionsToBuildPatcher
	{
		private static bool activatingWalkie;

		private static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;

		public static void Prefix(ShipBuildModeManager __instance)
		{
			if (!((Object)(object)localPlayerController == (Object)null))
			{
				activatingWalkie = localPlayerController.activatingItem;
				WalkieTalkie mainWalkie = WalkiePatcher.GetMainWalkie(localPlayerController);
				if (!((Object)(object)mainWalkie == (Object)null) && !((Object)(object)((GrabbableObject)mainWalkie).playerHeldBy == (Object)null) && !((Object)(object)((GrabbableObject)mainWalkie).playerHeldBy != (Object)(object)localPlayerController) && localPlayerController.activatingItem && mainWalkie.speakingIntoWalkieTalkie)
				{
					localPlayerController.activatingItem = false;
				}
			}
		}

		public static void Postfix(ShipBuildModeManager __instance)
		{
			if (!((Object)(object)localPlayerController == (Object)null))
			{
				localPlayerController.activatingItem = activatingWalkie;
			}
		}
	}
	[HarmonyPatch]
	public static class WalkiePatcher
	{
		public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;

		public static WalkieTalkie GetMainWalkie(PlayerControllerB playerController)
		{
			return GetCurrentlySelectedWalkie(playerController) ?? GetReservedWalkie(playerController);
		}

		public static WalkieTalkie GetReservedWalkie(PlayerControllerB playerController)
		{
			ReservedItemSlotData val = default(ReservedItemSlotData);
			ReservedPlayerData value;
			return (WalkieTalkie)((SessionManager.TryGetUnlockedItemSlotData(Plugin.walkieSlotData.slotName, ref val) && ReservedPlayerData.allPlayerData.TryGetValue(playerController, out value)) ? /*isinst with value type is only supported in some contexts*/: null);
		}

		public static WalkieTalkie GetCurrentlySelectedWalkie(PlayerControllerB playerController)
		{
			return (WalkieTalkie)((playerController.currentItemSlot >= 0 && playerController.currentItemSlot < playerController.ItemSlots.Length) ? /*isinst with value type is only supported in some contexts*/: null);
		}
	}
}
namespace ReservedWalkieSlot.Input
{
	internal class IngameKeybinds : LcInputActions
	{
		internal static IngameKeybinds Instance = new IngameKeybinds();

		[InputAction("<Keyboard>/x", Name = "[ReservedItemSlots]\nActivate walkie")]
		public InputAction ActivateWalkieHotkey { get; set; }

		internal static InputActionAsset GetAsset()
		{
			return ((LcInputActions)Instance).Asset;
		}
	}
	internal class InputUtilsCompat
	{
		internal static InputActionAsset Asset => IngameKeybinds.GetAsset();

		internal static bool Enabled => Plugin.IsModLoaded("com.rune580.LethalCompanyInputUtils");

		public static InputAction ActivateWalkieHotkey => IngameKeybinds.Instance.ActivateWalkieHotkey;
	}
	[HarmonyPatch]
	internal static class Keybinds
	{
		public static InputActionAsset Asset;

		public static InputActionMap ActionMap;

		private static InputAction ActivateWalkieAction;

		public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;

		[HarmonyPatch(typeof(PreInitSceneScript), "Awake")]
		[HarmonyPrefix]
		public static void AddToKeybindMenu()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Log("Initializing hotkeys.");
			if (InputUtilsCompat.Enabled)
			{
				Asset = InputUtilsCompat.Asset;
				ActionMap = Asset.actionMaps[0];
				ActivateWalkieAction = InputUtilsCompat.ActivateWalkieHotkey;
			}
			else
			{
				Asset = ScriptableObject.CreateInstance<InputActionAsset>();
				ActionMap = new InputActionMap("ReservedItemSlots");
				InputActionSetupExtensions.AddActionMap(Asset, ActionMap);
				ActivateWalkieAction = InputActionSetupExtensions.AddAction(ActionMap, "ReservedItemSlots.ActivateWalkie", (InputActionType)0, "<keyboard>/x", (string)null, (string)null, (string)null, (string)null);
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "OnEnable")]
		[HarmonyPostfix]
		public static void OnEnable()
		{
			Asset.Enable();
			ActivateWalkieAction.performed += OnPressWalkieButtonPerformed;
			ActivateWalkieAction.canceled += OnReleaseWalkieButtonPerformed;
		}

		[HarmonyPatch(typeof(StartOfRound), "OnDisable")]
		[HarmonyPostfix]
		public static void OnDisable()
		{
			Asset.Disable();
			ActivateWalkieAction.performed -= OnPressWalkieButtonPerformed;
			ActivateWalkieAction.canceled -= OnReleaseWalkieButtonPerformed;
		}

		private static void OnPressWalkieButtonPerformed(CallbackContext context)
		{
			if ((Object)(object)localPlayerController == (Object)null || !localPlayerController.isPlayerControlled || (((NetworkBehaviour)localPlayerController).IsServer && !localPlayerController.isHostPlayerObject))
			{
				return;
			}
			WalkieTalkie mainWalkie = WalkiePatcher.GetMainWalkie(localPlayerController);
			if (((CallbackContext)(ref context)).performed && !((Object)(object)mainWalkie == (Object)null) && ((GrabbableObject)mainWalkie).isBeingUsed && !ShipBuildModeManager.Instance.InBuildMode && !localPlayerController.isTypingChat && !localPlayerController.quickMenuManager.isMenuOpen && !localPlayerController.isPlayerDead && !ReservedPlayerData.localPlayerData.isGrabbingReservedItem)
			{
				float num = (float)Traverse.Create((object)localPlayerController).Field("timeSinceSwitchingSlots").GetValue();
				if (!(num < 0.075f))
				{
					((GrabbableObject)mainWalkie).UseItemOnClient(true);
					Traverse.Create((object)localPlayerController).Field("timeSinceSwitchingSlots").SetValue((object)0);
				}
			}
		}

		private static void OnReleaseWalkieButtonPerformed(CallbackContext context)
		{
			if (!((Object)(object)localPlayerController == (Object)null) && localPlayerController.isPlayerControlled && (!((NetworkBehaviour)localPlayerController).IsServer || localPlayerController.isHostPlayerObject))
			{
				WalkieTalkie mainWalkie = WalkiePatcher.GetMainWalkie(localPlayerController);
				if (((CallbackContext)(ref context)).canceled && !((Object)(object)mainWalkie == (Object)null))
				{
					((GrabbableObject)mainWalkie).UseItemOnClient(false);
				}
			}
		}
	}
}
namespace ReservedWalkieSlot.Config
{
	public static class ConfigSettings
	{
		public static ConfigEntry<int> overrideItemSlotPriority;

		public static ConfigEntry<int> overridePurchasePrice;

		public static ConfigEntry<string> additionalItemsInSlot;

		public static Dictionary<string, ConfigEntryBase> currentConfigEntries = new Dictionary<string, ConfigEntryBase>();

		public static void BindConfigSettings()
		{
			Plugin.Log("BindingConfigs");
			overrideItemSlotPriority = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "WalkieSlotPriorityOverride", 150, "[Host only] Manually set the priority for this item slot. Higher priority slots will come first in the reserved item slots, which will appear below the other slots. Negative priority items will appear on the left side of the screen, this is disabled in the core mod's config."));
			overridePurchasePrice = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "WalkieSlotPriceOverride", 150, "[Host only] Manually set the price for this item in the store. Setting 0 will force this item to be unlocked immediately after the game starts."));
			additionalItemsInSlot = AddConfigEntry<string>(((BaseUnityPlugin)Plugin.instance).Config.Bind<string>("Server-side", "AdditionalItemsInSlot", "", "[Host only] Syntax: \"Item1,Item name2\" (without quotes). When adding items, use the item's name as it appears in game. Include spaces if there are spaces in the item name. Adding items that do not exist, or that are from a mod which is not enabled will not cause any problems.\nNOTE: IF YOU ARE USING A TRANSLATION MOD, YOU MAY NEED TO ADD THE TRANSLATED NAME OF ANY ITEM YOU WANT IN THIS SLOT."));
			additionalItemsInSlot.Value = additionalItemsInSlot.Value.Replace(", ", ",");
			TryRemoveOldConfigSettings();
		}

		public static ConfigEntry<T> AddConfigEntry<T>(ConfigEntry<T> configEntry)
		{
			currentConfigEntries.Add(((ConfigEntryBase)configEntry).Definition.Key, (ConfigEntryBase)(object)configEntry);
			return configEntry;
		}

		public static string[] ParseAdditionalItems()
		{
			return ConfigSettings.ParseItemNames(additionalItemsInSlot.Value);
		}

		public static void TryRemoveOldConfigSettings()
		{
			HashSet<string> hashSet = new HashSet<string>();
			HashSet<string> hashSet2 = new HashSet<string>();
			foreach (ConfigEntryBase value in currentConfigEntries.Values)
			{
				hashSet.Add(value.Definition.Section);
				hashSet2.Add(value.Definition.Key);
			}
			try
			{
				ConfigFile config = ((BaseUnityPlugin)Plugin.instance).Config;
				string configFilePath = config.ConfigFilePath;
				if (!File.Exists(configFilePath))
				{
					return;
				}
				string text = File.ReadAllText(configFilePath);
				string[] array = File.ReadAllLines(configFilePath);
				string text2 = "";
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = array[i].Replace("\n", "");
					if (array[i].Length <= 0)
					{
						continue;
					}
					if (array[i].StartsWith("["))
					{
						if (text2 != "" && !hashSet.Contains(text2))
						{
							text2 = "[" + text2 + "]";
							int num = text.IndexOf(text2);
							int num2 = text.IndexOf(array[i]);
							text = text.Remove(num, num2 - num);
						}
						text2 = array[i].Replace("[", "").Replace("]", "").Trim();
					}
					else
					{
						if (!(text2 != ""))
						{
							continue;
						}
						if (i <= array.Length - 4 && array[i].StartsWith("##"))
						{
							int j;
							for (j = 1; i + j < array.Length && array[i + j].Length > 3; j++)
							{
							}
							if (hashSet.Contains(text2))
							{
								int num3 = array[i + j - 1].IndexOf("=");
								string item = array[i + j - 1].Substring(0, num3 - 1);
								if (!hashSet2.Contains(item))
								{
									int num4 = text.IndexOf(array[i]);
									int num5 = text.IndexOf(array[i + j - 1]) + array[i + j - 1].Length;
									text = text.Remove(num4, num5 - num4);
								}
							}
							i += j - 1;
						}
						else if (array[i].Length > 3)
						{
							text = text.Replace(array[i], "");
						}
					}
				}
				if (!hashSet.Contains(text2))
				{
					text2 = "[" + text2 + "]";
					int num6 = text.IndexOf(text2);
					text = text.Remove(num6, text.Length - num6);
				}
				while (text.Contains("\n\n\n"))
				{
					text = text.Replace("\n\n\n", "\n\n");
				}
				File.WriteAllText(configFilePath, text);
				config.Reload();
			}
			catch
			{
			}
		}
	}
}

plugins/ReservedWeaponSlot.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalCompanyInputUtils.Api;
using ReservedItemSlotCore;
using ReservedItemSlotCore.Config;
using ReservedItemSlotCore.Data;
using ReservedWeaponSlot.Config;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ReservedWeaponSlot")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ReservedWeaponSlot")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("5b723481-f5bd-43e5-9f47-26325095eea7")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ReservedWeaponSlot
{
	[BepInPlugin("FlipMods.ReservedWeaponSlot", "ReservedWeaponSlot", "1.1.5")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin instance;

		private static ManualLogSource logger;

		private Harmony _harmony;

		public static ReservedItemSlotData weaponSlotData;

		public static ReservedItemSlotData rangedWeaponSlotData;

		public static ReservedItemSlotData mainAmmoSlotData;

		public static List<ReservedItemSlotData> allAmmoSlotData = new List<ReservedItemSlotData>();

		public static ReservedItemData shotgunData;

		public static ReservedItemData zapGunData;

		public static ReservedItemData shovelData;

		public static ReservedItemData stopSignData;

		public static ReservedItemData yieldSignData;

		public static ReservedItemData kitchenKnifeData;

		public static ReservedItemData rocketLauncherData;

		public static ReservedItemData flareGunData;

		public static ReservedItemData toyGunData;

		public static ReservedItemData toyHammerData;

		public static ReservedItemData goldenShovelData;

		public static ReservedItemData ammoData;

		public static ReservedItemData shotgunAmmoData;

		public static ReservedItemData flareGunAmmoData;

		public static List<ReservedItemData> additionalItemData = new List<ReservedItemData>();

		private void Awake()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			instance = this;
			CreateCustomLogger();
			ConfigSettings.BindConfigSettings();
			CreateReservedItemSlots();
			CreateAdditionalReservedItemSlots();
			_harmony = new Harmony("ReservedWeaponSlot");
			PatchAll();
			Log("ReservedWeaponSlot loaded");
		}

		private void CreateReservedItemSlots()
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Expected O, but got Unknown
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Expected O, but got Unknown
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Expected O, but got Unknown
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Expected O, but got Unknown
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: 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_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Expected O, but got Unknown
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Expected O, but got Unknown
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Expected O, but got Unknown
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Expected O, but got Unknown
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Expected O, but got Unknown
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Expected O, but got Unknown
			weaponSlotData = ReservedItemSlotData.CreateReservedItemSlotData("weapons", ConfigSettings.overrideMeleeSlotPriority.Value, ConfigSettings.overrideMeleeSlotPrice.Value);
			if (ConfigSettings.combineMeleeAndRangedWeaponSlots.Value)
			{
				rangedWeaponSlotData = weaponSlotData;
				weaponSlotData.purchasePrice = ConfigSettings.overrideCombinedWeaponSlotPrice.Value;
			}
			else
			{
				weaponSlotData.slotName = "melee_weapons";
				rangedWeaponSlotData = ReservedItemSlotData.CreateReservedItemSlotData("ranged_weapons", ConfigSettings.overrideRangedSlotPriority.Value, ConfigSettings.overrideRangedSlotPrice.Value);
			}
			shovelData = weaponSlotData.AddItemToReservedItemSlot(new ReservedItemData("Shovel", (PlayerBone)0, default(Vector3), default(Vector3)));
			stopSignData = weaponSlotData.AddItemToReservedItemSlot(new ReservedItemData("Stop sign", (PlayerBone)0, default(Vector3), default(Vector3)));
			yieldSignData = weaponSlotData.AddItemToReservedItemSlot(new ReservedItemData("Yield sign", (PlayerBone)0, default(Vector3), default(Vector3)));
			kitchenKnifeData = weaponSlotData.AddItemToReservedItemSlot(new ReservedItemData("Kitchen knife", (PlayerBone)0, default(Vector3), default(Vector3)));
			toyHammerData = weaponSlotData.AddItemToReservedItemSlot(new ReservedItemData("Toy Hammer", (PlayerBone)0, default(Vector3), default(Vector3)));
			goldenShovelData = weaponSlotData.AddItemToReservedItemSlot(new ReservedItemData("Australium Shovel", (PlayerBone)0, default(Vector3), default(Vector3)));
			shotgunData = rangedWeaponSlotData.AddItemToReservedItemSlot(new ReservedItemData("Shotgun", (PlayerBone)0, default(Vector3), default(Vector3)));
			zapGunData = rangedWeaponSlotData.AddItemToReservedItemSlot(new ReservedItemData("Zap gun", (PlayerBone)0, default(Vector3), default(Vector3)));
			rocketLauncherData = rangedWeaponSlotData.AddItemToReservedItemSlot(new ReservedItemData("Rocket Launcher", (PlayerBone)0, default(Vector3), default(Vector3)));
			flareGunData = rangedWeaponSlotData.AddItemToReservedItemSlot(new ReservedItemData("Flaregun", (PlayerBone)0, default(Vector3), default(Vector3)));
			toyGunData = rangedWeaponSlotData.AddItemToReservedItemSlot(new ReservedItemData("Revolver", (PlayerBone)0, default(Vector3), default(Vector3)));
			mainAmmoSlotData = null;
			if (ConfigSettings.disableReservedAmmoSlot.Value)
			{
				return;
			}
			for (int i = 0; i < ConfigSettings.numAmmoSlots.Value && ConfigSettings.overrideAmmoSlotPriority.Value - i < 0; i++)
			{
				string text = "ammo" + ((i > 0) ? (i + 1).ToString() : "");
				ReservedItemSlotData val = ReservedItemSlotData.CreateReservedItemSlotData(text, ConfigSettings.overrideAmmoSlotPriority.Value - i, Mathf.Max(ConfigSettings.overrideAmmoSlotPrice.Value + ConfigSettings.overrideExtraAmmoSlotPriceIncrease.Value * i, 0));
				if (mainAmmoSlotData == null)
				{
					mainAmmoSlotData = val;
				}
				if (ammoData == null)
				{
					ammoData = val.AddItemToReservedItemSlot(new ReservedItemData("Ammo", (PlayerBone)0, default(Vector3), default(Vector3)));
					shotgunAmmoData = val.AddItemToReservedItemSlot(new ReservedItemData("Shells", (PlayerBone)0, default(Vector3), default(Vector3)));
					flareGunAmmoData = val.AddItemToReservedItemSlot(new ReservedItemData("Emergency Flare (ammo)", (PlayerBone)0, default(Vector3), default(Vector3)));
				}
				else
				{
					val.AddItemToReservedItemSlot(ammoData);
					val.AddItemToReservedItemSlot(shotgunAmmoData);
					val.AddItemToReservedItemSlot(flareGunAmmoData);
				}
				allAmmoSlotData.Add(val);
			}
		}

		private void CreateAdditionalReservedItemSlots()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Expected O, but got Unknown
			string[] array = ConfigSettings.ParseAdditionalMeleeWeaponItems();
			string[] array2 = array;
			foreach (string text in array2)
			{
				if (!weaponSlotData.ContainsItem(text))
				{
					LogWarning("Adding additional item to reserved (melee weapons) item slot. Item: " + text);
					ReservedItemData val = new ReservedItemData(text, (PlayerBone)0, default(Vector3), default(Vector3));
					additionalItemData.Add(val);
					weaponSlotData.AddItemToReservedItemSlot(val);
				}
			}
			array = ConfigSettings.ParseAdditionalRangedWeaponItems();
			string[] array3 = array;
			foreach (string text2 in array3)
			{
				if (!rangedWeaponSlotData.ContainsItem(text2))
				{
					LogWarning("Adding additional item to reserved (ranged weapons) item slot. Item: " + text2);
					ReservedItemData val2 = new ReservedItemData(text2, (PlayerBone)0, default(Vector3), default(Vector3));
					additionalItemData.Add(val2);
					rangedWeaponSlotData.AddItemToReservedItemSlot(val2);
				}
			}
			if (!ConfigSettings.disableReservedAmmoSlot.Value)
			{
				array = ConfigSettings.ParseAdditionalAmmoItems();
				string[] array4 = array;
				foreach (string text3 in array4)
				{
					if (mainAmmoSlotData.ContainsItem(text3))
					{
						continue;
					}
					LogWarning("Adding additional item to reserved (ammo) item slot. Item: " + text3);
					ReservedItemData val3 = new ReservedItemData(text3, (PlayerBone)0, default(Vector3), default(Vector3));
					additionalItemData.Add(val3);
					foreach (ReservedItemSlotData allAmmoSlotDatum in allAmmoSlotData)
					{
						if (!allAmmoSlotDatum.ContainsItem(text3))
						{
							allAmmoSlotDatum.AddItemToReservedItemSlot(val3);
						}
					}
				}
			}
			string[] array5 = ConfigSettings.ParseRemoveMeleeWeaponItems();
			string[] array6 = array5;
			foreach (string text4 in array6)
			{
				if (weaponSlotData.ContainsItem(text4))
				{
					LogWarning("Removing item from reserved (melee weapons) item slot. Item: " + text4);
					weaponSlotData.RemoveItemFromReservedItemSlot(text4);
				}
			}
			array5 = ConfigSettings.ParseRemoveRangedWeaponItems();
			string[] array7 = array5;
			foreach (string text5 in array7)
			{
				if (rangedWeaponSlotData.ContainsItem(text5))
				{
					LogWarning("Removing item from reserved (ranged weapons) item slot. Item: " + text5);
					rangedWeaponSlotData.RemoveItemFromReservedItemSlot(text5);
				}
			}
			if (ammoData == null)
			{
				return;
			}
			array5 = ConfigSettings.ParseRemoveAmmoItems();
			string[] array8 = array5;
			foreach (string text6 in array8)
			{
				LogWarning("Removing item from reserved (ammo) item slot. Item: " + text6);
				foreach (ReservedItemSlotData allAmmoSlotDatum2 in allAmmoSlotData)
				{
					if (allAmmoSlotDatum2.ContainsItem(text6))
					{
						allAmmoSlotDatum2.RemoveItemFromReservedItemSlot(text6);
					}
				}
			}
		}

		private void PatchAll()
		{
			IEnumerable<Type> enumerable;
			try
			{
				enumerable = Assembly.GetExecutingAssembly().GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				enumerable = ex.Types.Where((Type t) => t != null);
			}
			foreach (Type item in enumerable)
			{
				_harmony.PatchAll(item);
			}
		}

		private void CreateCustomLogger()
		{
			try
			{
				logger = Logger.CreateLogSource($"{((BaseUnityPlugin)this).Info.Metadata.Name}-{((BaseUnityPlugin)this).Info.Metadata.Version}");
			}
			catch
			{
				logger = ((BaseUnityPlugin)this).Logger;
			}
		}

		public static void Log(string message)
		{
			logger.LogInfo((object)message);
		}

		public static void LogError(string message)
		{
			logger.LogError((object)message);
		}

		public static void LogWarning(string message)
		{
			logger.LogWarning((object)message);
		}

		public static bool IsModLoaded(string guid)
		{
			return Chainloader.PluginInfos.ContainsKey(guid);
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "FlipMods.ReservedWeaponSlot";

		public const string PLUGIN_NAME = "ReservedWeaponSlot";

		public const string PLUGIN_VERSION = "1.1.5";
	}
}
namespace ReservedWeaponSlot.Input
{
	internal class IngameKeybinds : LcInputActions
	{
		internal static IngameKeybinds Instance = new IngameKeybinds();

		[InputAction("<Keyboard>/t", Name = "[ReservedItemSlots]\nToggle Weapon Slot")]
		public InputAction ToggleWeaponSlotHotkey { get; set; }

		internal static InputActionAsset GetAsset()
		{
			return ((LcInputActions)Instance).Asset;
		}
	}
	internal class InputUtilsCompat
	{
		internal static InputActionAsset Asset => IngameKeybinds.GetAsset();

		internal static bool Enabled => Plugin.IsModLoaded("com.rune580.LethalCompanyInputUtils");

		public static InputAction ToggleWeaponHotkey => IngameKeybinds.Instance.ToggleWeaponSlotHotkey;
	}
	[HarmonyPatch]
	internal static class Keybinds
	{
		public static InputActionAsset Asset;

		public static InputActionMap ActionMap;

		private static InputAction ToggleWeaponSlotAction;

		public static bool holdingWeaponModifier;

		public static bool toggledWeaponSlot;

		public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;

		public static ReservedPlayerData localPlayerData => ReservedPlayerData.localPlayerData;

		[HarmonyPatch(typeof(PreInitSceneScript), "Awake")]
		[HarmonyPrefix]
		public static void AddToKeybindMenu()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Log("Initializing hotkeys.");
			if (InputUtilsCompat.Enabled)
			{
				Asset = InputUtilsCompat.Asset;
				ActionMap = Asset.actionMaps[0];
				ToggleWeaponSlotAction = InputUtilsCompat.ToggleWeaponHotkey;
			}
			else
			{
				Asset = ScriptableObject.CreateInstance<InputActionAsset>();
				ActionMap = new InputActionMap("ReservedItemSlots");
				InputActionSetupExtensions.AddActionMap(Asset, ActionMap);
				ToggleWeaponSlotAction = InputActionSetupExtensions.AddAction(ActionMap, "ReservedItemSlots.ToggleWeaponSlot", (InputActionType)0, "", (string)null, (string)null, (string)null, (string)null);
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "OnEnable")]
		[HarmonyPostfix]
		public static void OnEnable()
		{
			Asset.Enable();
			ToggleWeaponSlotAction.performed += OnSwapToWeaponSlot;
			ToggleWeaponSlotAction.canceled += OnSwapToWeaponSlot;
		}

		[HarmonyPatch(typeof(StartOfRound), "OnDisable")]
		[HarmonyPostfix]
		public static void OnDisable()
		{
			Asset.Disable();
			ToggleWeaponSlotAction.performed -= OnSwapToWeaponSlot;
			ToggleWeaponSlotAction.canceled -= OnSwapToWeaponSlot;
		}

		private static void OnSwapToWeaponSlot(CallbackContext context)
		{
			if (!((Object)(object)localPlayerController == (Object)null) && localPlayerData != null && localPlayerController.isPlayerControlled && (!((NetworkBehaviour)localPlayerController).IsServer || localPlayerController.isHostPlayerObject) && SessionManager.unlockedReservedItemSlotsDict.TryGetValue(Plugin.weaponSlotData.slotName, out var value))
			{
				List<ReservedItemSlotData> list = new List<ReservedItemSlotData> { value };
				if (SessionManager.unlockedReservedItemSlotsDict.TryGetValue(Plugin.rangedWeaponSlotData.slotName, out var value2) && !list.Contains(value2))
				{
					list.Add(value2);
				}
				ReservedHotbarManager.ForceToggleReservedHotbar(list.ToArray());
			}
		}
	}
}
namespace ReservedWeaponSlot.Config
{
	public static class ConfigSettings
	{
		public static ConfigEntry<int> overrideMeleeSlotPriority;

		public static ConfigEntry<int> overrideMeleeSlotPrice;

		public static ConfigEntry<int> overrideRangedSlotPriority;

		public static ConfigEntry<int> overrideRangedSlotPrice;

		public static ConfigEntry<bool> combineMeleeAndRangedWeaponSlots;

		public static ConfigEntry<int> overrideCombinedWeaponSlotPrice;

		public static ConfigEntry<bool> disableReservedAmmoSlot;

		public static ConfigEntry<int> overrideAmmoSlotPriority;

		public static ConfigEntry<int> overrideAmmoSlotPrice;

		public static ConfigEntry<int> numAmmoSlots;

		public static ConfigEntry<int> overrideExtraAmmoSlotPriceIncrease;

		public static ConfigEntry<string> additionalMeleeWeaponsInSlot;

		public static ConfigEntry<string> additionalRangedWeaponsInSlot;

		public static ConfigEntry<string> additionalAmmoInSlot;

		public static ConfigEntry<string> removeItemsFromMeleeWeaponsSlot;

		public static ConfigEntry<string> removeItemsFromRangedWeaponsSlot;

		public static ConfigEntry<string> removeItemsFromAmmoSlot;

		public static Dictionary<string, ConfigEntryBase> currentConfigEntries = new Dictionary<string, ConfigEntryBase>();

		public static void BindConfigSettings()
		{
			Plugin.Log("BindingConfigs");
			overrideMeleeSlotPriority = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "MeleeWeaponSlotPriorityOverride", 100, "[Host only] Manually set the priority for this item slot. Higher priority slots will come first in the reserved item slots, which will appear below the other slots. Negative priority items will appear on the left side of the screen, this is disabled in the core mod's config."));
			overrideMeleeSlotPrice = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "MeleeWeaponSlotPriceOverride", 150, "[Host only] Manually set the price for this item in the store. Setting 0 will force this item to be unlocked immediately after the game starts."));
			overrideRangedSlotPriority = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "RangedWeaponSlotPriorityOverride", 99, "[Host only] Manually set the priority for this item slot. Higher priority slots will come first in the reserved item slots, which will appear below the other slots. Negative priority items will appear on the left side of the screen, this is disabled in the core mod's config."));
			overrideRangedSlotPrice = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "RangedWeaponSlotPriceOverride", 250, "[Host only] Manually set the price for this item in the store. Setting 0 will force this item to be unlocked immediately after the game starts."));
			combineMeleeAndRangedWeaponSlots = AddConfigEntry<bool>(((BaseUnityPlugin)Plugin.instance).Config.Bind<bool>("Server-side", "CombineMeleeAndRangedWeaponSlots", true, "[Host only] If set to false, melee and ranged weapons will be added to two different reserved item slots. If purchasing item slots is enabled, each slots will need to be purchased separately. (prices for each will be reduced)"));
			overrideCombinedWeaponSlotPrice = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "CombinedWeaponSlotPriceOverride", 400, "[Host only] Only applies if CombineMeleeAndRangedWeaponSlots is true. Manually set the price for this item in the store. Setting 0 will force this item to be unlocked immediately after the game starts."));
			disableReservedAmmoSlot = AddConfigEntry<bool>(((BaseUnityPlugin)Plugin.instance).Config.Bind<bool>("Server-side", "DisableReservedAmmoSlot", false, "[Host only] Disables the reserved ammo slot. Will sync with clients."));
			overrideAmmoSlotPriority = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "AmmoSlotPriorityOverride", -100, "[Host only] Manually set the priority for this item slot. Higher priority slots will come first in the reserved item slots, which will appear below the other slots. Negative priority items will appear on the left side of the screen, this is disabled in the core mod's config."));
			overrideAmmoSlotPrice = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "AmmoSlotPriceOverride", 150, "[Host only] Manually set the price for this item in the store. Setting 0 will force this item to be unlocked immediately after the game starts."));
			numAmmoSlots = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "NumAmmoSlots", 1, "[Host only] Sets the number of reserved ammo slots. Only applies if this slot is enabled.\nNOTE: Ammo does NOT currently stack into one slot at this time. This is on my TODO list."));
			overrideExtraAmmoSlotPriceIncrease = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "ExtraAmmoSlotsPriceIncreaseOverride", 10, "[Host only] If multiple ammo slots are enabled, and purchasing slots is enabled, the price for each additional ammo slot will go up by this amount."));
			additionalMeleeWeaponsInSlot = AddConfigEntry<string>(((BaseUnityPlugin)Plugin.instance).Config.Bind<string>("Server-side", "AdditionalMeleeWeaponsInSlot", "", "[Host only] Syntax: \"Item1,Item name2\" (without quotes). When adding items, use the item's name as it appears in game. Include spaces if there are spaces in the item name. Adding items that do not exist, or that are from a mod which is not enabled will not cause any problems.\nNOTE: IF YOU ARE USING A TRANSLATION MOD, YOU MAY NEED TO ADD THE TRANSLATED NAME OF ANY ITEM YOU WANT IN THIS SLOT."));
			additionalRangedWeaponsInSlot = AddConfigEntry<string>(((BaseUnityPlugin)Plugin.instance).Config.Bind<string>("Server-side", "AdditionalRangedWeaponsInSlot", "", "[Host only] Syntax: \"Item1,Item name2\" (without quotes). When adding items, use the item's name as it appears in game. Include spaces if there are spaces in the item name. Adding items that do not exist, or that are from a mod which is not enabled will not cause any problems.\nNOTE: IF YOU ARE USING A TRANSLATION MOD, YOU MAY NEED TO ADD THE TRANSLATED NAME OF ANY ITEM YOU WANT IN THIS SLOT."));
			additionalAmmoInSlot = AddConfigEntry<string>(((BaseUnityPlugin)Plugin.instance).Config.Bind<string>("Server-side", "AdditionalAmmoInSlot", "", "[Host only] Syntax: \"Item1,Item name2\" (without quotes). When adding items, use the item's name as it appears in game. Include spaces if there are spaces in the item name. Adding items that do not exist, or that are from a mod which is not enabled will not cause any problems.\nNOTE: IF YOU ARE USING A TRANSLATION MOD, YOU MAY NEED TO ADD THE TRANSLATED NAME OF ANY ITEM YOU WANT IN THIS SLOT."));
			removeItemsFromMeleeWeaponsSlot = AddConfigEntry<string>(((BaseUnityPlugin)Plugin.instance).Config.Bind<string>("Server-side", "RemoveMeleeWeaponsFromSlot", "", "[Host only] Syntax: \"Item1,Item name2\" (without quotes). Removes the specified items from this reserved item slot. When removing items, use the item's name as it appears in game. Include spaces if there are spaces in the item name. Adding items that do not exist, or that are from a mod which is not enabled will not cause any problems.\nCURRENT MELEE WEAPONS IN SLOT: \"Shovel\", \"Stop sign\", \"Yield sign\", \"Kitchen knife\", \"Toy Hammer\", \"Australium Shovel\""));
			removeItemsFromRangedWeaponsSlot = AddConfigEntry<string>(((BaseUnityPlugin)Plugin.instance).Config.Bind<string>("Server-side", "RemoveRangedWeaponsFromSlot", "", "[Host only] Syntax: \"Item1,Item name2\" (without quotes). Removes the specified items from this reserved item slot. When removing items, use the item's name as it appears in game. Include spaces if there are spaces in the item name. Adding items that do not exist, or that are from a mod which is not enabled will not cause any problems.\nCURRENT RANGED WEAPONS IN SLOT: \"Shotgun\", \"Zap gun\", \"Rocket Launcher\", \"Flaregun\", \"Revolver\""));
			removeItemsFromAmmoSlot = AddConfigEntry<string>(((BaseUnityPlugin)Plugin.instance).Config.Bind<string>("Server-side", "RemoveAmmoItemsFromSlot", "", "[Host only] Syntax: \"Item1,Item name2\" (without quotes). Removes the specified items from this reserved item slot.When removing items, use the item's name as it appears in game. Include spaces if there are spaces in the item name. Adding items that do not exist, or that are from a mod which is not enabled will not cause any problems.\nCURRENT AMMO ITEMS IN SLOT: \"Ammo\", \"Shells\", \"Emergency Flare (ammo)\""));
			additionalMeleeWeaponsInSlot.Value = additionalMeleeWeaponsInSlot.Value.Replace(", ", ",");
			additionalRangedWeaponsInSlot.Value = additionalRangedWeaponsInSlot.Value.Replace(", ", ",");
			additionalAmmoInSlot.Value = additionalAmmoInSlot.Value.Replace(", ", ",");
			removeItemsFromMeleeWeaponsSlot.Value = removeItemsFromMeleeWeaponsSlot.Value.Replace(", ", ",");
			removeItemsFromRangedWeaponsSlot.Value = removeItemsFromRangedWeaponsSlot.Value.Replace(", ", ",");
			removeItemsFromAmmoSlot.Value = removeItemsFromAmmoSlot.Value.Replace(", ", ",");
			TryRemoveOldConfigSettings();
		}

		public static ConfigEntry<T> AddConfigEntry<T>(ConfigEntry<T> configEntry)
		{
			currentConfigEntries.Add(((ConfigEntryBase)configEntry).Definition.Key, (ConfigEntryBase)(object)configEntry);
			return configEntry;
		}

		public static string[] ParseAdditionalMeleeWeaponItems()
		{
			return ConfigSettings.ParseItemNames(additionalMeleeWeaponsInSlot.Value);
		}

		public static string[] ParseAdditionalRangedWeaponItems()
		{
			return ConfigSettings.ParseItemNames(additionalRangedWeaponsInSlot.Value);
		}

		public static string[] ParseAdditionalAmmoItems()
		{
			return ConfigSettings.ParseItemNames(additionalAmmoInSlot.Value);
		}

		public static string[] ParseRemoveMeleeWeaponItems()
		{
			return ConfigSettings.ParseItemNames(removeItemsFromMeleeWeaponsSlot.Value);
		}

		public static string[] ParseRemoveRangedWeaponItems()
		{
			return ConfigSettings.ParseItemNames(removeItemsFromRangedWeaponsSlot.Value);
		}

		public static string[] ParseRemoveAmmoItems()
		{
			return ConfigSettings.ParseItemNames(removeItemsFromAmmoSlot.Value);
		}

		public static void TryRemoveOldConfigSettings()
		{
			HashSet<string> hashSet = new HashSet<string>();
			HashSet<string> hashSet2 = new HashSet<string>();
			foreach (ConfigEntryBase value in currentConfigEntries.Values)
			{
				hashSet.Add(value.Definition.Section);
				hashSet2.Add(value.Definition.Key);
			}
			try
			{
				ConfigFile config = ((BaseUnityPlugin)Plugin.instance).Config;
				string configFilePath = config.ConfigFilePath;
				if (!File.Exists(configFilePath))
				{
					return;
				}
				string text = File.ReadAllText(configFilePath);
				string[] array = File.ReadAllLines(configFilePath);
				string text2 = "";
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = array[i].Replace("\n", "");
					if (array[i].Length <= 0)
					{
						continue;
					}
					if (array[i].StartsWith("["))
					{
						if (text2 != "" && !hashSet.Contains(text2))
						{
							text2 = "[" + text2 + "]";
							int num = text.IndexOf(text2);
							int num2 = text.IndexOf(array[i]);
							text = text.Remove(num, num2 - num);
						}
						text2 = array[i].Replace("[", "").Replace("]", "").Trim();
					}
					else
					{
						if (!(text2 != ""))
						{
							continue;
						}
						if (i <= array.Length - 4 && array[i].StartsWith("##"))
						{
							int j;
							for (j = 1; i + j < array.Length && array[i + j].Length > 3; j++)
							{
							}
							if (hashSet.Contains(text2))
							{
								int num3 = array[i + j - 1].IndexOf("=");
								string item = array[i + j - 1].Substring(0, num3 - 1);
								if (!hashSet2.Contains(item))
								{
									int num4 = text.IndexOf(array[i]);
									int num5 = text.IndexOf(array[i + j - 1]) + array[i + j - 1].Length;
									text = text.Remove(num4, num5 - num4);
								}
							}
							i += j - 1;
						}
						else if (array[i].Length > 3)
						{
							text = text.Replace(array[i], "");
						}
					}
				}
				if (!hashSet.Contains(text2))
				{
					text2 = "[" + text2 + "]";
					int num6 = text.IndexOf(text2);
					text = text.Remove(num6, text.Length - num6);
				}
				while (text.Contains("\n\n\n"))
				{
					text = text.Replace("\n\n\n", "\n\n");
				}
				File.WriteAllText(configFilePath, text);
				config.Reload();
			}
			catch
			{
			}
		}
	}
}

plugins/ShipLoot.dll

Decompiled 2 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.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ShipLoot")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("ShipLoot")]
[assembly: AssemblyCopyright("Copyright © tinyhoot 2023")]
[assembly: ComVisible(false)]
[assembly: AssemblyFileVersion("1.1")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
namespace ShipLoot
{
	[BepInPlugin("com.github.tinyhoot.ShipLoot", "ShipLoot", "1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal class ShipLoot : BaseUnityPlugin
	{
		public const string GUID = "com.github.tinyhoot.ShipLoot";

		public const string NAME = "ShipLoot";

		public const string VERSION = "1.1";

		internal static ShipLootConfig Config;

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Config = new ShipLootConfig(((BaseUnityPlugin)this).Config);
			Config.RegisterOptions();
			new Harmony("com.github.tinyhoot.ShipLoot").PatchAll(Assembly.GetExecutingAssembly());
		}

		private void Start()
		{
			SetLobbyCompatibility();
		}

		private void SetLobbyCompatibility()
		{
			if (!Chainloader.PluginInfos.ContainsKey("BMX.LobbyCompatibility"))
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method("LobbyCompatibility.Features.PluginHelper:RegisterPlugin", (Type[])null, (Type[])null);
			if ((object)methodInfo == null)
			{
				Log.LogWarning((object)"Found LobbyCompatibility mod but failed to find plugin register API method!");
				return;
			}
			Log.LogDebug((object)"Registering compatibility with LobbyCompatibility.");
			try
			{
				methodInfo.Invoke(null, new object[4]
				{
					"com.github.tinyhoot.ShipLoot",
					new Version("1.1"),
					0,
					0
				});
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to register plugin compatibility with LobbyCompatibility.\n{arg}");
				return;
			}
			Log.LogDebug((object)"Successfully registered with LobbyCompatibility.");
		}
	}
	internal class ShipLootConfig
	{
		private readonly ConfigFile _configFile;

		public ConfigEntry<float> DisplayTime;

		public ShipLootConfig(ConfigFile configFile)
		{
			_configFile = configFile;
		}

		public void RegisterOptions()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			DisplayTime = _configFile.Bind<float>("General", "DisplayTime", 5f, new ConfigDescription("How long to display the total scrap value for, counted in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
		}
	}
}
namespace ShipLoot.Patches
{
	[HarmonyPatch]
	internal class HudManagerPatcher
	{
		private static GameObject _ship;

		private static GameObject _totalCounter;

		private static TextMeshProUGUI _textMesh;

		private static float _displayTimeLeft;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(HUDManager), "PingScan_performed")]
		private static void OnScan(HUDManager __instance, CallbackContext context)
		{
			if (!((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null) && ((CallbackContext)(ref context)).performed && __instance.CanPlayerScan() && !(__instance.playerPingingScan > -0.5f) && (StartOfRound.Instance.inShipPhase || GameNetworkManager.Instance.localPlayerController.isInHangarShipRoom))
			{
				if (!Object.op_Implicit((Object)(object)_ship))
				{
					_ship = GameObject.Find("/Environment/HangarShip");
				}
				if (!Object.op_Implicit((Object)(object)_totalCounter))
				{
					CopyValueCounter();
				}
				float num = CalculateLootValue();
				((TMP_Text)_textMesh).text = $"SHIP: ${num:F0}";
				_displayTimeLeft = ShipLoot.Config.DisplayTime.Value;
				if (!_totalCounter.activeSelf)
				{
					((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(ShipLootCoroutine());
				}
			}
		}

		private static IEnumerator ShipLootCoroutine()
		{
			_totalCounter.SetActive(true);
			while (_displayTimeLeft > 0f)
			{
				float displayTimeLeft = _displayTimeLeft;
				_displayTimeLeft = 0f;
				yield return (object)new WaitForSeconds(displayTimeLeft);
			}
			_totalCounter.SetActive(false);
		}

		private static float CalculateLootValue()
		{
			List<GrabbableObject> list = (from obj in _ship.GetComponentsInChildren<GrabbableObject>()
				where obj.itemProperties.isScrap && !(obj is RagdollGrabbableObject)
				select obj).ToList();
			ShipLoot.Log.LogDebug((object)"Calculating total ship scrap value.");
			CollectionExtensions.Do<GrabbableObject>((IEnumerable<GrabbableObject>)list, (Action<GrabbableObject>)delegate(GrabbableObject scrap)
			{
				ShipLoot.Log.LogDebug((object)$"{((Object)scrap).name} - ${scrap.scrapValue}");
			});
			return list.Sum((GrabbableObject scrap) => scrap.scrapValue);
		}

		private static void CopyValueCounter()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.Find("/Systems/UI/Canvas/IngamePlayerHUD/BottomMiddle/ValueCounter");
			if (!Object.op_Implicit((Object)(object)val))
			{
				ShipLoot.Log.LogError((object)"Failed to find ValueCounter object to copy!");
			}
			_totalCounter = Object.Instantiate<GameObject>(val.gameObject, val.transform.parent, false);
			_totalCounter.transform.Translate(0f, 1f, 0f);
			Vector3 localPosition = _totalCounter.transform.localPosition;
			_totalCounter.transform.localPosition = new Vector3(localPosition.x + 50f, -50f, localPosition.z);
			_textMesh = _totalCounter.GetComponentInChildren<TextMeshProUGUI>();
		}
	}
}

plugins/SkinwalkerMod.dll

Decompiled 2 months ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dissonance;
using Dissonance.Config;
using HarmonyLib;
using SkinwalkerMod.Properties;
using Steamworks;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
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("SkinwalkerMod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SkinwalkerMod")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("fd4979a2-cef0-46af-8bf8-97e630b11475")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
internal class <Module>
{
	static <Module>()
	{
		NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<bool>();
		NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<bool>();
		NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<float>();
		NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<float>();
	}
}
namespace SkinwalkerMod
{
	internal class LogoManager : MonoBehaviour
	{
		private AssetBundle bundle;

		private readonly Logo[] logos = new Logo[5]
		{
			new Logo
			{
				fileName = "Teo",
				playerNames = new string[9] { "SAMMY", "paddy", "Ozias", "Teo", "Rugbug Redfern", "WuluKing", "Boolie", "TeaEditor", "FlashGamesNemesis" }
			},
			new Logo
			{
				fileName = "OfflineTV",
				playerNames = new string[3] { "Masayoshi", "QUARTERJADE", "DisguisedToast" }
			},
			new Logo
			{
				fileName = "Neuro",
				playerNames = new string[1] { "vedal" }
			},
			new Logo
			{
				fileName = "Mogul",
				playerNames = new string[2] { "ludwig", "AirCoots" }
			},
			new Logo
			{
				fileName = "Imp",
				playerNames = new string[1] { "camila" }
			}
		};

		private Image cachedHeader;

		private Image cachedLogoHeader;

		private void Awake()
		{
			try
			{
				bundle = AssetBundle.LoadFromMemory(Resources.logos);
				SceneManager.sceneLoaded += OnSceneLoaded;
			}
			catch (Exception ex)
			{
				SkinwalkerLogger.LogError("LogoManager Awake Error: " + ex.Message);
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			try
			{
				if (!(((Scene)(ref scene)).name == "MainMenu"))
				{
					return;
				}
				cachedHeader = GameObject.Find("HeaderImage").GetComponent<Image>();
				cachedLogoHeader = ((Component)GameObject.Find("Canvas/MenuContainer").transform.GetChild(0).GetChild(1)).GetComponent<Image>();
				string value = SteamClient.Name.ToString();
				Logo[] array = logos;
				foreach (Logo logo in array)
				{
					string[] playerNames = logo.playerNames;
					foreach (string text in playerNames)
					{
						if (text.Equals(value, StringComparison.OrdinalIgnoreCase))
						{
							((MonoBehaviour)this).StartCoroutine(I_ChangeLogo(bundle.LoadAsset<Sprite>("Assets/Logos/" + logo.fileName + ".png")));
							return;
						}
					}
				}
			}
			catch (Exception ex)
			{
				SkinwalkerLogger.LogError("LogoManager OnSceneLoaded Error: " + ex.Message + ". If you launched in LAN mode, then this is just gonna happen, it doesn't break anything so don't worry about it.");
			}
		}

		private IEnumerator I_ChangeLogo(Sprite sprite)
		{
			for (int i = 0; i < 20; i++)
			{
				if ((Object)(object)cachedHeader == (Object)null)
				{
					break;
				}
				if ((Object)(object)cachedLogoHeader == (Object)null)
				{
					break;
				}
				SetHeaderImage(sprite);
				yield return null;
			}
		}

		private void SetHeaderImage(Sprite sprite)
		{
			if (!((Object)(object)sprite == (Object)null))
			{
				cachedHeader.sprite = sprite;
				cachedLogoHeader.sprite = sprite;
			}
		}
	}
	internal class Logo
	{
		public string fileName;

		public string[] playerNames;
	}
	[BepInPlugin("RugbugRedfern.SkinwalkerMod", "Skinwalker Mod", "5.0.0")]
	internal class PluginLoader : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("RugbugRedfern.SkinwalkerMod");

		private const string modGUID = "RugbugRedfern.SkinwalkerMod";

		private const string modVersion = "5.0.0";

		private static bool initialized;

		public static PluginLoader Instance { get; private set; }

		private void Awake()
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Expected O, but got Unknown
			if (initialized)
			{
				return;
			}
			initialized = true;
			Instance = this;
			harmony.PatchAll(Assembly.GetExecutingAssembly());
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
			SkinwalkerLogger.Initialize("RugbugRedfern.SkinwalkerMod");
			SkinwalkerLogger.Log("SKINWALKER MOD STARTING UP 5.0.0");
			SkinwalkerConfig.InitConfig();
			SceneManager.sceneLoaded += SkinwalkerNetworkManagerHandler.ClientConnectInitializer;
			GameObject val = new GameObject("Skinwalker Mod");
			val.AddComponent<SkinwalkerModPersistent>();
			((Object)val).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)val);
			Logs.SetLogLevel((LogCategory)1, (LogLevel)4);
			Logs.SetLogLevel((LogCategory)3, (LogLevel)4);
			Logs.SetLogLevel((LogCategory)2, (LogLevel)4);
			GameObject val2 = new GameObject("Logo Manager");
			val2.AddComponent<LogoManager>();
			((Object)val2).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)val2);
		}

		public void BindConfig<T>(ref ConfigEntry<T> config, string section, string key, T defaultValue, string description = "")
		{
			config = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, description);
		}
	}
	internal class SkinwalkerBehaviour : MonoBehaviour
	{
		private AudioSource audioSource;

		public const float PLAY_INTERVAL_MIN = 15f;

		public const float PLAY_INTERVAL_MAX = 40f;

		private const float MAX_DIST = 100f;

		private float nextTimeToPlayAudio;

		private EnemyAI ai;

		public void Initialize(EnemyAI ai)
		{
			this.ai = ai;
			audioSource = ai.creatureVoice;
			SetNextTime();
		}

		private void Update()
		{
			if (Time.time > nextTimeToPlayAudio)
			{
				SetNextTime();
				AttemptPlaySound();
			}
		}

		private void AttemptPlaySound()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			float num = -1f;
			if (Object.op_Implicit((Object)(object)ai) && !ai.isEnemyDead)
			{
				if (((Object)((Component)ai).gameObject).name == "DressGirl(Clone)")
				{
					DressGirlAI val = (DressGirlAI)ai;
					if ((Object)(object)val.hauntingPlayer != (Object)(object)StartOfRound.Instance.localPlayerController)
					{
						SkinwalkerLogger.Log(((Object)this).name + " played voice line no (not haunted) EnemyAI: " + (object)ai);
						return;
					}
					if (!val.staringInHaunt && !((EnemyAI)val).moveTowardsDestination)
					{
						SkinwalkerLogger.Log(((Object)this).name + " played voice line no (not visible) EnemyAI: " + (object)ai);
						return;
					}
				}
				Vector3 val2 = (StartOfRound.Instance.localPlayerController.isPlayerDead ? ((Component)StartOfRound.Instance.spectateCamera).transform.position : ((Component)StartOfRound.Instance.localPlayerController).transform.position);
				if ((Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)StartOfRound.Instance.localPlayerController == (Object)null || (num = Vector3.Distance(val2, ((Component)this).transform.position)) < 100f)
				{
					AudioClip sample = SkinwalkerModPersistent.Instance.GetSample();
					if ((Object)(object)sample != (Object)null)
					{
						SkinwalkerLogger.Log(((Object)this).name + " played voice line 1");
						audioSource.PlayOneShot(sample);
					}
					else
					{
						SkinwalkerLogger.Log(((Object)this).name + " played voice line 0");
					}
				}
				else
				{
					SkinwalkerLogger.Log(((Object)this).name + " played voice line no (too far away) " + num);
				}
			}
			else
			{
				SkinwalkerLogger.Log(((Object)this).name + " played voice line no (dead) EnemyAI: " + (object)ai);
			}
		}

		private void SetNextTime()
		{
			if (SkinwalkerNetworkManager.Instance.VoiceLineFrequency.Value <= 0f)
			{
				nextTimeToPlayAudio = Time.time + 100000000f;
			}
			else
			{
				nextTimeToPlayAudio = Time.time + Random.Range(15f, 40f) / SkinwalkerNetworkManager.Instance.VoiceLineFrequency.Value;
			}
		}

		private T CopyComponent<T>(T original, GameObject destination) where T : Component
		{
			Type type = ((object)original).GetType();
			Component val = destination.AddComponent(type);
			FieldInfo[] fields = type.GetFields();
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				fieldInfo.SetValue(val, fieldInfo.GetValue(original));
			}
			return (T)(object)((val is T) ? val : null);
		}
	}
	internal class SkinwalkerConfig
	{
		public static ConfigEntry<bool> VoiceEnabled_BaboonHawk;

		public static ConfigEntry<bool> VoiceEnabled_Bracken;

		public static ConfigEntry<bool> VoiceEnabled_BunkerSpider;

		public static ConfigEntry<bool> VoiceEnabled_Centipede;

		public static ConfigEntry<bool> VoiceEnabled_CoilHead;

		public static ConfigEntry<bool> VoiceEnabled_EyelessDog;

		public static ConfigEntry<bool> VoiceEnabled_ForestGiant;

		public static ConfigEntry<bool> VoiceEnabled_GhostGirl;

		public static ConfigEntry<bool> VoiceEnabled_GiantWorm;

		public static ConfigEntry<bool> VoiceEnabled_HoardingBug;

		public static ConfigEntry<bool> VoiceEnabled_Hygrodere;

		public static ConfigEntry<bool> VoiceEnabled_Jester;

		public static ConfigEntry<bool> VoiceEnabled_Masked;

		public static ConfigEntry<bool> VoiceEnabled_Nutcracker;

		public static ConfigEntry<bool> VoiceEnabled_SporeLizard;

		public static ConfigEntry<bool> VoiceEnabled_Thumper;

		public static ConfigEntry<bool> VoiceEnabled_OtherEnemies;

		public static ConfigEntry<float> VoiceLineFrequency;

		public static void InitConfig()
		{
			PluginLoader.Instance.BindConfig(ref VoiceLineFrequency, "Voice Settings", "VoiceLineFrequency", 1f, "1 is the default, and voice lines will occur every " + 15f.ToString("0") + " to " + 40f.ToString("0") + " seconds per enemy. Setting this to 2 means they will occur twice as often, 0.5 means half as often, etc.");
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_BaboonHawk, "Monster Voices", "Baboon Hawk", defaultValue: true);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_Bracken, "Monster Voices", "Bracken", defaultValue: true);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_BunkerSpider, "Monster Voices", "Bunker Spider", defaultValue: true);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_Centipede, "Monster Voices", "Centipede", defaultValue: true);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_CoilHead, "Monster Voices", "Coil Head", defaultValue: true);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_EyelessDog, "Monster Voices", "Eyeless Dog", defaultValue: true);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_ForestGiant, "Monster Voices", "Forest Giant", defaultValue: false);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_GhostGirl, "Monster Voices", "Ghost Girl", defaultValue: true);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_GiantWorm, "Monster Voices", "Giant Worm", defaultValue: false);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_HoardingBug, "Monster Voices", "Hoarding Bug", defaultValue: true);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_Hygrodere, "Monster Voices", "Hygrodere", defaultValue: false);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_Jester, "Monster Voices", "Jester", defaultValue: true);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_Masked, "Monster Voices", "Masked", defaultValue: true);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_Nutcracker, "Monster Voices", "Nutcracker", defaultValue: true);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_SporeLizard, "Monster Voices", "Spore Lizard", defaultValue: true);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_Thumper, "Monster Voices", "Thumper", defaultValue: true);
			PluginLoader.Instance.BindConfig(ref VoiceEnabled_OtherEnemies, "Monster Voices", "Other Enemies (Including Modded)", defaultValue: true);
			SkinwalkerLogger.Log("VoiceEnabled_BaboonHawk" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_BaboonHawk.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_Bracken" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_Bracken.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_BunkerSpider" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_BunkerSpider.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_Centipede" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_Centipede.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_CoilHead" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_CoilHead.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_EyelessDog" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_EyelessDog.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_ForestGiant" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_ForestGiant.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_GhostGirl" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_GhostGirl.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_GiantWorm" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_GiantWorm.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_HoardingBug" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_HoardingBug.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_Hygrodere" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_Hygrodere.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_Jester" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_Jester.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_Masked" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_Masked.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_Nutcracker" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_Nutcracker.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_SporeLizard" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_SporeLizard.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_Thumper" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_Thumper.Value}]");
			SkinwalkerLogger.Log("VoiceEnabled_OtherEnemies" + $" VALUE LOADED FROM CONFIG: [{VoiceEnabled_OtherEnemies.Value}]");
			SkinwalkerLogger.Log("VoiceLineFrequency" + $" VALUE LOADED FROM CONFIG: [{VoiceLineFrequency.Value}]");
		}
	}
	internal static class SkinwalkerLogger
	{
		internal static ManualLogSource logSource;

		public static void Initialize(string modGUID)
		{
			logSource = Logger.CreateLogSource(modGUID);
		}

		public static void Log(object message)
		{
			logSource.LogInfo(message);
		}

		public static void LogError(object message)
		{
			logSource.LogError(message);
		}

		public static void LogWarning(object message)
		{
			logSource.LogWarning(message);
		}
	}
	public class SkinwalkerModPersistent : MonoBehaviour
	{
		private string audioFolder;

		private List<AudioClip> cachedAudio = new List<AudioClip>();

		private float nextTimeToCheckFolder = 30f;

		private float nextTimeToCheckEnemies = 30f;

		private const float folderScanInterval = 8f;

		private const float enemyScanInterval = 5f;

		public static SkinwalkerModPersistent Instance { get; private set; }

		private void Awake()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			((Component)this).transform.position = Vector3.zero;
			SkinwalkerLogger.Log("Skinwalker Mod Object Initialized");
			audioFolder = Path.Combine(Application.dataPath, "..", "Dissonance_Diagnostics");
			EnableRecording();
			if (!Directory.Exists(audioFolder))
			{
				Directory.CreateDirectory(audioFolder);
			}
		}

		private void Start()
		{
			try
			{
				if (Directory.Exists(audioFolder))
				{
					Directory.Delete(audioFolder, recursive: true);
				}
			}
			catch (Exception message)
			{
				SkinwalkerLogger.Log(message);
			}
		}

		private void OnApplicationQuit()
		{
			DisableRecording();
		}

		private void EnableRecording()
		{
			DebugSettings.Instance.EnablePlaybackDiagnostics = true;
			DebugSettings.Instance.RecordFinalAudio = true;
		}

		private void Update()
		{
			if (Time.realtimeSinceStartup > nextTimeToCheckFolder)
			{
				nextTimeToCheckFolder = Time.realtimeSinceStartup + 8f;
				if (!Directory.Exists(audioFolder))
				{
					SkinwalkerLogger.Log("Audio folder not present. Don't worry about it, it will be created automatically when you play with friends. (" + audioFolder + ")");
					return;
				}
				string[] files = Directory.GetFiles(audioFolder);
				SkinwalkerLogger.Log($"Got audio file paths ({files.Length})");
				string[] array = files;
				foreach (string path in array)
				{
					((MonoBehaviour)this).StartCoroutine(LoadWavFile(path, delegate(AudioClip audioClip)
					{
						cachedAudio.Add(audioClip);
					}));
				}
			}
			if (!(Time.realtimeSinceStartup > nextTimeToCheckEnemies))
			{
				return;
			}
			nextTimeToCheckEnemies = Time.realtimeSinceStartup + 5f;
			EnemyAI[] array2 = Object.FindObjectsOfType<EnemyAI>(true);
			EnemyAI[] array3 = array2;
			SkinwalkerBehaviour skinwalkerBehaviour = default(SkinwalkerBehaviour);
			foreach (EnemyAI val in array3)
			{
				SkinwalkerLogger.Log("IsEnemyEnabled " + ((Object)val).name + " " + IsEnemyEnabled(val));
				if (IsEnemyEnabled(val) && !((Component)val).TryGetComponent<SkinwalkerBehaviour>(ref skinwalkerBehaviour))
				{
					((Component)val).gameObject.AddComponent<SkinwalkerBehaviour>().Initialize(val);
				}
			}
		}

		private bool IsEnemyEnabled(EnemyAI enemy)
		{
			if ((Object)(object)enemy == (Object)null)
			{
				return false;
			}
			return ((Object)((Component)enemy).gameObject).name switch
			{
				"MaskedPlayerEnemy(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_Masked.Value, 
				"NutcrackerEnemy(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_Nutcracker.Value, 
				"BaboonHawkEnemy(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_BaboonHawk.Value, 
				"Flowerman(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_Bracken.Value, 
				"SandSpider(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_BunkerSpider.Value, 
				"RedLocustBees(Clone)" => false, 
				"Centipede(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_Centipede.Value, 
				"SpringMan(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_CoilHead.Value, 
				"MouthDog(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_EyelessDog.Value, 
				"ForestGiant(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_ForestGiant.Value, 
				"DressGirl(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_GhostGirl.Value, 
				"SandWorm(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_GiantWorm.Value, 
				"HoarderBug(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_HoardingBug.Value, 
				"Blob(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_Hygrodere.Value, 
				"JesterEnemy(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_Jester.Value, 
				"PufferEnemy(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_SporeLizard.Value, 
				"Crawler(Clone)" => SkinwalkerNetworkManager.Instance.VoiceEnabled_Thumper.Value, 
				"DocileLocustBees(Clone)" => false, 
				"DoublewingedBird(Clone)" => false, 
				_ => SkinwalkerNetworkManager.Instance.VoiceEnabled_OtherEnemies.Value, 
			};
		}

		internal IEnumerator LoadWavFile(string path, Action<AudioClip> callback)
		{
			UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(path, (AudioType)20);
			try
			{
				yield return www.SendWebRequest();
				if ((int)www.result == 1)
				{
					SkinwalkerLogger.Log("Loaded clip from path " + path);
					AudioClip audioClip = DownloadHandlerAudioClip.GetContent(www);
					if (audioClip.length > 0.9f)
					{
						callback(audioClip);
					}
					try
					{
						File.Delete(path);
					}
					catch (Exception e)
					{
						SkinwalkerLogger.LogWarning(e);
					}
				}
			}
			finally
			{
				((IDisposable)www)?.Dispose();
			}
		}

		private void DisableRecording()
		{
			DebugSettings.Instance.EnablePlaybackDiagnostics = false;
			DebugSettings.Instance.RecordFinalAudio = false;
			if (Directory.Exists(audioFolder))
			{
				Directory.Delete(audioFolder, recursive: true);
			}
		}

		public AudioClip GetSample()
		{
			while (cachedAudio.Count > 200)
			{
				cachedAudio.RemoveAt(Random.Range(0, cachedAudio.Count));
			}
			if (cachedAudio.Count > 0)
			{
				int index = Random.Range(0, cachedAudio.Count - 1);
				AudioClip result = cachedAudio[index];
				cachedAudio.RemoveAt(index);
				return result;
			}
			return null;
		}

		public void ClearCache()
		{
			cachedAudio.Clear();
		}
	}
	internal static class SkinwalkerNetworkManagerHandler
	{
		internal static void ClientConnectInitializer(Scene sceneName, LoadSceneMode sceneEnum)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			if (((Scene)(ref sceneName)).name == "SampleSceneRelay")
			{
				GameObject val = new GameObject("SkinwalkerNetworkManager");
				val.AddComponent<NetworkObject>();
				val.AddComponent<SkinwalkerNetworkManager>();
				Debug.Log((object)"Initialized SkinwalkerNetworkManager");
			}
		}
	}
	internal class SkinwalkerNetworkManager : NetworkBehaviour
	{
		public NetworkVariable<bool> VoiceEnabled_BaboonHawk = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_Bracken = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_BunkerSpider = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_Centipede = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_CoilHead = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_EyelessDog = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_ForestGiant = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_GhostGirl = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_GiantWorm = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_HoardingBug = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_Hygrodere = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_Jester = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_Masked = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_Nutcracker = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_SporeLizard = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_Thumper = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<bool> VoiceEnabled_OtherEnemies = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public NetworkVariable<float> VoiceLineFrequency = new NetworkVariable<float>(1f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public static SkinwalkerNetworkManager Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			if (GameNetworkManager.Instance.isHostingGame)
			{
				VoiceEnabled_BaboonHawk.Value = SkinwalkerConfig.VoiceEnabled_BaboonHawk.Value;
				VoiceEnabled_Bracken.Value = SkinwalkerConfig.VoiceEnabled_Bracken.Value;
				VoiceEnabled_BunkerSpider.Value = SkinwalkerConfig.VoiceEnabled_BunkerSpider.Value;
				VoiceEnabled_Centipede.Value = SkinwalkerConfig.VoiceEnabled_Centipede.Value;
				VoiceEnabled_CoilHead.Value = SkinwalkerConfig.VoiceEnabled_CoilHead.Value;
				VoiceEnabled_EyelessDog.Value = SkinwalkerConfig.VoiceEnabled_EyelessDog.Value;
				VoiceEnabled_ForestGiant.Value = SkinwalkerConfig.VoiceEnabled_ForestGiant.Value;
				VoiceEnabled_GhostGirl.Value = SkinwalkerConfig.VoiceEnabled_GhostGirl.Value;
				VoiceEnabled_GiantWorm.Value = SkinwalkerConfig.VoiceEnabled_GiantWorm.Value;
				VoiceEnabled_HoardingBug.Value = SkinwalkerConfig.VoiceEnabled_HoardingBug.Value;
				VoiceEnabled_Hygrodere.Value = SkinwalkerConfig.VoiceEnabled_Hygrodere.Value;
				VoiceEnabled_Jester.Value = SkinwalkerConfig.VoiceEnabled_Jester.Value;
				VoiceEnabled_Masked.Value = SkinwalkerConfig.VoiceEnabled_Masked.Value;
				VoiceEnabled_Nutcracker.Value = SkinwalkerConfig.VoiceEnabled_Nutcracker.Value;
				VoiceEnabled_SporeLizard.Value = SkinwalkerConfig.VoiceEnabled_SporeLizard.Value;
				VoiceEnabled_Thumper.Value = SkinwalkerConfig.VoiceEnabled_Thumper.Value;
				VoiceEnabled_OtherEnemies.Value = SkinwalkerConfig.VoiceEnabled_OtherEnemies.Value;
				VoiceLineFrequency.Value = SkinwalkerConfig.VoiceLineFrequency.Value;
				SkinwalkerLogger.Log("HOST SENDING CONFIG TO CLIENTS");
			}
			SkinwalkerLogger.Log("SkinwalkerNetworkManager Awake");
		}

		public override void OnDestroy()
		{
			((NetworkBehaviour)this).OnDestroy();
			SkinwalkerLogger.Log("SkinwalkerNetworkManager OnDestroy");
			SkinwalkerModPersistent.Instance?.ClearCache();
		}

		protected override void __initializeVariables()
		{
			if (VoiceEnabled_BaboonHawk == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_BaboonHawk cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_BaboonHawk).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_BaboonHawk, "VoiceEnabled_BaboonHawk");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_BaboonHawk);
			if (VoiceEnabled_Bracken == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_Bracken cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_Bracken).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_Bracken, "VoiceEnabled_Bracken");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_Bracken);
			if (VoiceEnabled_BunkerSpider == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_BunkerSpider cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_BunkerSpider).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_BunkerSpider, "VoiceEnabled_BunkerSpider");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_BunkerSpider);
			if (VoiceEnabled_Centipede == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_Centipede cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_Centipede).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_Centipede, "VoiceEnabled_Centipede");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_Centipede);
			if (VoiceEnabled_CoilHead == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_CoilHead cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_CoilHead).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_CoilHead, "VoiceEnabled_CoilHead");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_CoilHead);
			if (VoiceEnabled_EyelessDog == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_EyelessDog cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_EyelessDog).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_EyelessDog, "VoiceEnabled_EyelessDog");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_EyelessDog);
			if (VoiceEnabled_ForestGiant == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_ForestGiant cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_ForestGiant).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_ForestGiant, "VoiceEnabled_ForestGiant");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_ForestGiant);
			if (VoiceEnabled_GhostGirl == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_GhostGirl cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_GhostGirl).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_GhostGirl, "VoiceEnabled_GhostGirl");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_GhostGirl);
			if (VoiceEnabled_GiantWorm == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_GiantWorm cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_GiantWorm).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_GiantWorm, "VoiceEnabled_GiantWorm");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_GiantWorm);
			if (VoiceEnabled_HoardingBug == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_HoardingBug cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_HoardingBug).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_HoardingBug, "VoiceEnabled_HoardingBug");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_HoardingBug);
			if (VoiceEnabled_Hygrodere == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_Hygrodere cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_Hygrodere).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_Hygrodere, "VoiceEnabled_Hygrodere");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_Hygrodere);
			if (VoiceEnabled_Jester == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_Jester cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_Jester).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_Jester, "VoiceEnabled_Jester");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_Jester);
			if (VoiceEnabled_Masked == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_Masked cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_Masked).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_Masked, "VoiceEnabled_Masked");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_Masked);
			if (VoiceEnabled_Nutcracker == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_Nutcracker cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_Nutcracker).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_Nutcracker, "VoiceEnabled_Nutcracker");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_Nutcracker);
			if (VoiceEnabled_SporeLizard == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_SporeLizard cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_SporeLizard).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_SporeLizard, "VoiceEnabled_SporeLizard");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_SporeLizard);
			if (VoiceEnabled_Thumper == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_Thumper cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_Thumper).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_Thumper, "VoiceEnabled_Thumper");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_Thumper);
			if (VoiceEnabled_OtherEnemies == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceEnabled_OtherEnemies cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceEnabled_OtherEnemies).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceEnabled_OtherEnemies, "VoiceEnabled_OtherEnemies");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceEnabled_OtherEnemies);
			if (VoiceLineFrequency == null)
			{
				throw new Exception("SkinwalkerNetworkManager.VoiceLineFrequency cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)VoiceLineFrequency).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceLineFrequency, "VoiceLineFrequency");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceLineFrequency);
			((NetworkBehaviour)this).__initializeVariables();
		}

		protected internal override string __getTypeName()
		{
			return "SkinwalkerNetworkManager";
		}
	}
}
namespace SkinwalkerMod.Properties
{
	[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
	[DebuggerNonUserCode]
	[CompilerGenerated]
	internal class Resources
	{
		private static ResourceManager resourceMan;

		private static CultureInfo resourceCulture;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static ResourceManager ResourceManager
		{
			get
			{
				if (resourceMan == null)
				{
					ResourceManager resourceManager = new ResourceManager("SkinwalkerMod.Properties.Resources", typeof(Resources).Assembly);
					resourceMan = resourceManager;
				}
				return resourceMan;
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static CultureInfo Culture
		{
			get
			{
				return resourceCulture;
			}
			set
			{
				resourceCulture = value;
			}
		}

		internal static byte[] logos
		{
			get
			{
				object @object = ResourceManager.GetObject("logos", resourceCulture);
				return (byte[])@object;
			}
		}

		internal Resources()
		{
		}
	}
}

plugins/TooManyEmotes.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using AdvancedCompany.Cosmetics;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dissonance.Integrations.Unity_NFGO;
using GameNetcodeStuff;
using HarmonyLib;
using LCVR.Player;
using LethalCompanyInputUtils.Api;
using MoreCompany.Cosmetics;
using TMPro;
using TooManyEmotes.Audio;
using TooManyEmotes.Compatibility;
using TooManyEmotes.Config;
using TooManyEmotes.Input;
using TooManyEmotes.Networking;
using TooManyEmotes.Patches;
using TooManyEmotes.Props;
using TooManyEmotes.UI;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Animations.Rigging;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Experimental.Rendering;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
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("TooManyEmotes")]
[assembly: AssemblyDescription("Mod made by flipf17")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TooManyEmotes")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("d6950625-e3a1-4896-a183-87110491bf18")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: InternalsVisibleTo("TooManyEmotesScrap")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace TooManyEmotes
{
	[HarmonyPatch]
	public static class AdditionalEmoteData
	{
		public static void SetAdditionalEmoteData()
		{
		}

		public static void SetAdditionalPropData()
		{
			if (EmotesManager.allUnlockableEmotesDict != null)
			{
				AssignPropToEmote("jug_prop", "jug_band.jug");
				AssignPropToEmote("guitar_prop", "jug_band.guitar");
				AssignPropToEmote("banjo_prop", "jug_band.banjo");
				AssignPropToEmote("fiddle_prop", "jug_band.fiddle");
				AssignPropToEmote("sexy_saxophone.sexy_sax.prop", "sexy_saxophone.sexy_sax");
				AssignPropToEmote("sexy_saxophone.epic_sax.prop", "sexy_saxophone.epic_sax");
				AssignPropToEmote("trombone.prop", "sad_trombone");
				AssignPropToEmote("old_chair.prop", "ma-ya-hi");
				AssignPropToEmote("baseball_bat.prop", "miracle_trickshot");
				AssignPropToEmote("dumbbell.prop", "pumping_iron");
				AssignPropToEmote("paddle.prop", "paddle_royale");
				AssignPropToEmote("gamepad.prop", "controller_crew");
				AssignPropToEmote("jar_of_dirt.prop", "jar_of_dirt");
				AssignPropToEmote("travelers.banjo.prop", "travelers.banjo");
				AssignPropToEmote("travelers.harmonica.prop", "travelers.harmonica");
				AssignPropToEmote("travelers.drums.prop", "travelers.drums");
				AssignPropToEmote("travelers.flute.prop", "travelers.flute");
				AssignPropToEmote("travelers.whistle.prop", "travelers.whistle");
				AssignPropToEmote("travelers.piano.prop", "travelers.piano");
				AssignPropToEmote("travelers.bow.prop", "travelers.bow");
			}
		}

		public static void SetAdditionalMusicData()
		{
			if (EmotesManager.allUnlockableEmotesDict == null)
			{
				return;
			}
			SetEmoteDoesNotUseBoombox("jug_band.jug");
			SetEmoteDoesNotUseBoombox("jug_band.guitar");
			SetEmoteDoesNotUseBoombox("jug_band.banjo");
			SetEmoteDoesNotUseBoombox("jug_band.fiddle");
			SetEmoteDoesNotUseBoombox("hand_signals");
			SetEmoteDoesNotUseBoombox("red_card");
			SetEmoteDoesNotUseBoombox("sexy_saxophone.sexy_sax");
			SetEmoteDoesNotUseBoombox("sexy_saxophone.epic_sax");
			SetEmoteDoesNotUseBoombox("sad_trombone");
			SetEmoteDoesNotUseBoombox("snake_summoner");
			SetEmoteDoesNotUseBoombox("miracle_trickshot");
			SetEmoteDoesNotUseBoombox("junk_food");
			SetEmoteDoesNotUseBoombox("pumping_iron");
			SetEmoteDoesNotUseBoombox("paddle_royale");
			SetEmoteDoesNotUseBoombox("wolf_howl");
			SetEmoteDoesNotUseBoombox("jar_of_dirt");
			SetEmoteDoesNotUseBoombox("travelers.banjo");
			SetEmoteDoesNotUseBoombox("travelers.harmonica");
			SetEmoteDoesNotUseBoombox("travelers.drums");
			SetEmoteDoesNotUseBoombox("travelers.flute");
			SetEmoteDoesNotUseBoombox("travelers.whistle");
			SetEmoteDoesNotUseBoombox("travelers.piano");
			SetEmoteDoesNotUseBoombox("travelers.bow");
			AssignMusicToEmote("jug_band.jug", "jug_band.jug");
			AssignMusicToEmote("jug_band.guitar", "jug_band.guitar");
			AssignMusicToEmote("jug_band.banjo", "jug_band.banjo");
			AssignMusicToEmote("jug_band.fiddle", "jug_band.fiddle");
			AssignMusicToEmote("travelers.banjo", "travelers.banjo");
			AssignMusicToEmote("travelers.harmonica", "travelers.harmonica");
			AssignMusicToEmote("travelers.drums", "travelers.drums");
			AssignMusicToEmote("travelers.flute", "travelers.flute");
			AssignMusicToEmote("travelers.whistle", "travelers.whistle");
			AssignMusicToEmote("travelers.piano", "travelers.piano");
			AssignMusicToEmote("travelers.bow", "travelers.bow");
			if (EmotesManager.allUnlockableEmotesDict.TryGetValue("jug_band.banjo", out var value) && value.inEmoteSyncGroup)
			{
				foreach (UnlockableEmote item in value.emoteSyncGroup)
				{
					item.recordSongLoopValue = 1f;
				}
			}
			if (!EmotesManager.allUnlockableEmotesDict.TryGetValue("travelers.banjo", out value) || !value.inEmoteSyncGroup)
			{
				return;
			}
			foreach (UnlockableEmote item2 in value.emoteSyncGroup)
			{
				item2.recordSongLoopValue = 0.5f;
			}
		}

		public static void AssignPropToEmote(string propName, string emoteName)
		{
			if (!EmotePropManager.emotePropsDataDict.TryGetValue(propName, out var _))
			{
				CustomLogging.LogWarning("Failed to assign prop: " + propName + " to emote. Prop does not exist!");
				return;
			}
			if (!EmotesManager.allUnlockableEmotesDict.TryGetValue(emoteName, out var value2))
			{
				CustomLogging.LogWarning("Failed to assign prop: " + propName + " to emote: " + emoteName + ". Emote does not exist!");
				return;
			}
			if (!EmotePropManager.emotePropsDataDict.TryGetValue(propName, out var value3))
			{
				CustomLogging.LogWarning("Failed to assign prop: " + propName + " to emote: " + emoteName + ". Prop data does not exist for: " + propName);
				return;
			}
			if (value2.propNamesInEmote == null)
			{
				value2.propNamesInEmote = new List<string>();
			}
			value2.propNamesInEmote.Add(propName);
			if (value3.parentEmotes == null)
			{
				value3.parentEmotes = new List<UnlockableEmote>();
			}
			if (!value3.parentEmotes.Contains(value2))
			{
				value3.parentEmotes.Add(value2);
			}
		}

		public static void SetEmoteDoesNotUseBoombox(string emoteName)
		{
			if (EmotesManager.allUnlockableEmotesDict.TryGetValue(emoteName, out var value))
			{
				value.isBoomboxAudio = false;
			}
		}

		public static void SetCanMoveWhileEmoting(string emoteName)
		{
			if (EmotesManager.allUnlockableEmotesDict.TryGetValue(emoteName, out var value))
			{
				value.canMoveWhileEmoting = true;
			}
		}

		public static void AssignMusicToEmote(string emoteName, string audioName, string audioLoopName = "")
		{
			if (EmotesManager.allUnlockableEmotesDict.TryGetValue(emoteName, out var value) && AudioManager.AudioExists(audioName))
			{
				value.overrideAudioClipName = audioName;
				value.overrideAudioLoopClipName = audioLoopName;
			}
		}
	}
	public static class QuickEmotes
	{
		public static UnlockableEmote GetQuickEmote(int index)
		{
			if (index < 0 || index >= 8)
			{
				CustomLogging.LogError("Failed to get quick emote name at index: " + index + ". Index must be within range: 0 and 8");
				return null;
			}
			string key = ES3.Load<string>("QuickEmote" + index, SaveManager.TooManyEmotesSaveFileName, string.Empty);
			UnlockableEmote value = null;
			EmotesManager.allUnlockableEmotesDict.TryGetValue(key, out value);
			return value;
		}
	}
	public static class BoneMapper
	{
		public static Dictionary<Transform, Transform> CreateBoneMap(Transform sourceSkeleton, Transform targetSkeleton, List<string> sourceBoneNames, List<string> targetBoneNames = null)
		{
			if ((Object)(object)sourceSkeleton == (Object)null || (Object)(object)targetSkeleton == (Object)null || sourceBoneNames == null)
			{
				return null;
			}
			if (targetBoneNames == null)
			{
				targetBoneNames = sourceBoneNames;
			}
			if (sourceBoneNames.Count != targetBoneNames.Count)
			{
				CustomLogging.LogError("Attempted to map humanoid skeleton, but passed two sets of bone names with differing sizes.");
				return null;
			}
			int count = sourceBoneNames.Count;
			Transform[] array = (Transform[])(object)new Transform[count];
			Transform[] array2 = (Transform[])(object)new Transform[count];
			FindBones(sourceSkeleton, sourceBoneNames, array);
			FindBones(targetSkeleton, targetBoneNames, array2);
			Dictionary<Transform, Transform> dictionary = new Dictionary<Transform, Transform>();
			for (int i = 0; i < count; i++)
			{
				if ((Object)(object)array[i] != (Object)null && !dictionary.ContainsKey(array[i]))
				{
					dictionary.Add(array[i], array2[i]);
				}
			}
			return dictionary;
		}

		private static void FindBones(Transform bone, List<string> boneNames, Transform[] boneArray)
		{
			if ((Object)(object)((Component)bone).GetComponent<Rig>() != (Object)null || ((Object)bone).name == "ScavengerModelArmsOnly")
			{
				return;
			}
			if (boneNames.Contains(((Object)bone).name))
			{
				int num = boneNames.IndexOf(((Object)bone).name);
				if (!((Object)(object)boneArray[num] != (Object)null))
				{
					boneArray[num] = bone;
				}
			}
			for (int i = 0; i < bone.childCount; i++)
			{
				FindBones(bone.GetChild(i), boneNames, boneArray);
			}
		}
	}
	internal static class CustomLogging
	{
		private static ManualLogSource logger;

		public static void InitLogger()
		{
			try
			{
				logger = Logger.CreateLogSource($"{((BaseUnityPlugin)Plugin.instance).Info.Metadata.Name}-{((BaseUnityPlugin)Plugin.instance).Info.Metadata.Version}");
			}
			catch
			{
				logger = Plugin.defaultLogger;
			}
		}

		public static void Log(string message)
		{
			logger.LogInfo((object)message);
		}

		public static void LogError(string message)
		{
			logger.LogError((object)message);
		}

		public static void LogWarning(string message)
		{
			logger.LogWarning((object)message);
		}

		public static void LogVerbose(string message)
		{
			if (ConfigSettings.verboseLogs.Value)
			{
				logger.LogInfo((object)("[VERBOSE] " + message));
			}
		}

		public static void LogErrorVerbose(string message)
		{
			if (ConfigSettings.verboseLogs.Value)
			{
				logger.LogError((object)("[VERBOSE] " + message));
			}
		}

		public static void LogWarningVerbose(string message)
		{
			if (ConfigSettings.verboseLogs.Value)
			{
				logger.LogWarning((object)("[VERBOSE] " + message));
			}
		}

		public static bool Assert(bool condition, string failMessage)
		{
			if (!condition)
			{
				LogWarning(failMessage);
			}
			return condition;
		}
	}
	public class OnAnimatorIKHandler : MonoBehaviour
	{
		private EmoteController emoteController;

		private Animator animator;

		public float handIKWeight = 0.8f;

		private void Awake()
		{
			animator = ((Component)this).GetComponent<Animator>();
			if ((Object)(object)animator == (Object)null)
			{
				CustomLogging.LogWarning("OnIKHandler must be attached to a gameobject with an animator component.");
			}
		}

		public void SetParentEmoteController(EmoteController emoteController)
		{
			this.emoteController = emoteController;
		}

		protected void OnAnimatorIK(int layerIndex)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: 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_01bb: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)emoteController) && emoteController.initialized && emoteController.IsPerformingCustomEmote())
			{
				if (Object.op_Implicit((Object)(object)emoteController.ikLeftHand) && emoteController.ikLeftHand.localPosition != Vector3.zero)
				{
					animator.SetIKPositionWeight((AvatarIKGoal)2, handIKWeight);
					animator.SetIKRotationWeight((AvatarIKGoal)2, handIKWeight);
					animator.SetIKPosition((AvatarIKGoal)2, emoteController.ikLeftHand.position);
					animator.SetIKRotation((AvatarIKGoal)2, emoteController.ikLeftHand.rotation);
				}
				if (Object.op_Implicit((Object)(object)emoteController.ikRightHand) && emoteController.ikRightHand.localPosition != Vector3.zero)
				{
					animator.SetIKPositionWeight((AvatarIKGoal)3, handIKWeight);
					animator.SetIKRotationWeight((AvatarIKGoal)3, handIKWeight);
					animator.SetIKPosition((AvatarIKGoal)3, emoteController.ikRightHand.position);
					animator.SetIKRotation((AvatarIKGoal)3, emoteController.ikRightHand.rotation);
				}
				if (Object.op_Implicit((Object)(object)emoteController.ikHead) && emoteController.ikHead.localPosition != Vector3.zero)
				{
					animator.SetLookAtWeight(1f, 0.25f, 0.5f);
					animator.SetLookAtPosition(emoteController.ikHead.position);
				}
			}
		}
	}
	[HarmonyPatch]
	public class EmoteSyncGroup
	{
		public static int currentEmoteSyncId = 0;

		public static Dictionary<int, EmoteSyncGroup> allEmoteSyncGroups = new Dictionary<int, EmoteSyncGroup>();

		public int syncId = -1;

		public List<EmoteController> syncGroup;

		public Dictionary<UnlockableEmote, EmoteController> leadEmoteControllerByEmote = new Dictionary<UnlockableEmote, EmoteController>();

		public Dictionary<UnlockableEmote, EmoteAudioSource> currentEmoteAudioSources;

		public float timeStartedEmote;

		public UnlockableEmote performingEmote;

		public bool useAudio = true;

		public EmoteAudioPlayer currentAudioPlayer;

		public EmoteController leadEmoteController => (syncGroup != null && syncGroup.Count > 0) ? syncGroup[0] : null;

		public EmoteAudioSource leadEmoteAudioSource
		{
			get
			{
				if (currentEmoteAudioSources != null && currentEmoteAudioSources.Count > 0)
				{
					foreach (EmoteController item in syncGroup)
					{
						if ((Object)(object)item?.personalEmoteAudioSource != (Object)null && currentEmoteAudioSources.ContainsValue(item.personalEmoteAudioSource))
						{
							return item.personalEmoteAudioSource;
						}
					}
				}
				return null;
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPrefix]
		public static void Init()
		{
			currentEmoteSyncId = 0;
			allEmoteSyncGroups?.Clear();
		}

		public static EmoteSyncGroup CreateEmoteSyncGroup(EmoteController emoteController, bool useAudio = true)
		{
			return new EmoteSyncGroup(emoteController, useAudio);
		}

		public EmoteSyncGroup(EmoteController emoteController, bool useAudio = true)
		{
			syncGroup = new List<EmoteController> { emoteController };
			syncId = currentEmoteSyncId++;
			performingEmote = emoteController.performingEmote;
			leadEmoteControllerByEmote.Add(performingEmote, emoteController);
			this.useAudio = useAudio;
			if (useAudio && performingEmote.hasAudio)
			{
				if (!performingEmote.isBoomboxAudio)
				{
					currentEmoteAudioSources = new Dictionary<UnlockableEmote, EmoteAudioSource>();
					if ((Object)(object)emoteController.personalEmoteAudioSource == (Object)null)
					{
						CustomLogging.LogError("Attempted to perform emote with personal audio source, which is null.");
						this.useAudio = false;
					}
					else
					{
						currentEmoteAudioSources[performingEmote] = emoteController.personalEmoteAudioSource;
						emoteController.personalEmoteAudioSource.SyncWithEmoteControllerAudio(emoteController);
						emoteController.personalEmoteAudioSource.AddToEmoteSyncGroup(this);
					}
				}
				else
				{
					EmoteAudioPlayer nearestEmoteAudioPlayer = EmoteAudioPlayerManager.GetNearestEmoteAudioPlayer(((Component)emoteController).transform);
					if ((Object)(object)nearestEmoteAudioPlayer != (Object)null && nearestEmoteAudioPlayer.CanPlayMusic())
					{
						AssignExternalAudioPlayer(nearestEmoteAudioPlayer);
					}
					else
					{
						CustomLogging.LogWarning("Performing emote with no music. No available boomboxes found nearby. Don't worry. Everything will be okay.");
					}
				}
				UpdateAudioVolume();
			}
			allEmoteSyncGroups[syncId] = this;
			timeStartedEmote = Time.time;
		}

		public void AddToEmoteSyncGroup(EmoteController emoteController)
		{
			if (syncGroup == null || syncGroup.Contains(emoteController))
			{
				return;
			}
			syncGroup.Add(emoteController);
			if (!leadEmoteControllerByEmote.ContainsKey(emoteController.performingEmote) || (Object)(object)leadEmoteControllerByEmote[emoteController.performingEmote] == (Object)null)
			{
				leadEmoteControllerByEmote[emoteController.performingEmote] = emoteController;
			}
			if (!useAudio || !performingEmote.hasAudio)
			{
				return;
			}
			if (!performingEmote.isBoomboxAudio)
			{
				if (currentEmoteAudioSources != null && (!currentEmoteAudioSources.ContainsKey(emoteController.performingEmote) || (Object)(object)currentEmoteAudioSources[emoteController.performingEmote] == (Object)null))
				{
					currentEmoteAudioSources[emoteController.performingEmote] = emoteController.personalEmoteAudioSource;
					emoteController.personalEmoteAudioSource.SyncWithEmoteSyncGroup(this, emoteController);
					emoteController.personalEmoteAudioSource.AddToEmoteSyncGroup(this);
				}
			}
			else if ((Object)(object)currentAudioPlayer == (Object)null)
			{
				EmoteAudioPlayer nearestEmoteAudioPlayer = EmoteAudioPlayerManager.GetNearestEmoteAudioPlayer(((Component)emoteController).transform);
				if ((Object)(object)nearestEmoteAudioPlayer != (Object)null && nearestEmoteAudioPlayer.CanPlayMusic())
				{
					AssignExternalAudioPlayer(nearestEmoteAudioPlayer);
				}
			}
			UpdateAudioVolume();
		}

		public void RemoveFromEmoteSyncGroup(EmoteController emoteController)
		{
			if (syncGroup == null)
			{
				return;
			}
			syncGroup.Remove(emoteController);
			if (syncGroup.Count <= 0)
			{
				DestroyEmoteSyncGroup();
				return;
			}
			if (leadEmoteControllerByEmote.ContainsValue(emoteController))
			{
				UnlockableEmote key = leadEmoteControllerByEmote.FirstOrDefault((KeyValuePair<UnlockableEmote, EmoteController> x) => (Object)(object)x.Value == (Object)(object)emoteController).Key;
				leadEmoteControllerByEmote.Remove(key);
				foreach (EmoteController item in syncGroup)
				{
					if ((Object)(object)item == (Object)null || item.performingEmote == null || item.performingEmote != key)
					{
						continue;
					}
					leadEmoteControllerByEmote[key] = item;
					break;
				}
			}
			if (currentEmoteAudioSources == null)
			{
				return;
			}
			if (currentEmoteAudioSources.ContainsValue(emoteController.personalEmoteAudioSource))
			{
				emoteController.personalEmoteAudioSource.StopAudio();
				emoteController.personalEmoteAudioSource.RemoveFromEmoteSyncGroup();
				UnlockableEmote key2 = currentEmoteAudioSources.FirstOrDefault((KeyValuePair<UnlockableEmote, EmoteAudioSource> x) => (Object)(object)x.Value == (Object)(object)emoteController.personalEmoteAudioSource).Key;
				currentEmoteAudioSources.Remove(key2);
				if (useAudio && key2.hasAudio && !key2.isBoomboxAudio)
				{
					foreach (EmoteController item2 in syncGroup)
					{
						if (!((Object)(object)item2 == (Object)null) && item2.performingEmote != null && !((Object)(object)item2 == (Object)(object)emoteController))
						{
							EmoteAudioSource personalEmoteAudioSource = item2.personalEmoteAudioSource;
							if (item2.performingEmote == key2 && (Object)(object)personalEmoteAudioSource != (Object)null && personalEmoteAudioSource.CanPlayMusic())
							{
								currentEmoteAudioSources[key2] = personalEmoteAudioSource;
								personalEmoteAudioSource.SyncWithEmoteControllerAudio(item2);
								break;
							}
						}
					}
				}
			}
			UpdateAudioVolume();
		}

		public void DestroyEmoteSyncGroup()
		{
			CustomLogging.LogVerbose("Cleaning up emote sync group with id: " + syncId);
			if (currentEmoteAudioSources != null)
			{
				foreach (EmoteAudioSource value in currentEmoteAudioSources.Values)
				{
					if ((Object)(object)value != (Object)null)
					{
						value.StopAudio();
						value.RemoveFromEmoteSyncGroup();
					}
				}
				currentEmoteAudioSources = null;
			}
			if ((Object)(object)currentAudioPlayer != (Object)null)
			{
				currentAudioPlayer.StopAudio();
				currentAudioPlayer.RemoveFromEmoteSyncGroup();
			}
			allEmoteSyncGroups.Remove(syncId);
			syncGroup = null;
			syncId = -1;
		}

		public void UpdateAudioVolume()
		{
			if (currentEmoteAudioSources != null)
			{
				foreach (EmoteAudioSource value in currentEmoteAudioSources.Values)
				{
					if ((Object)(object)value != (Object)null)
					{
						value.UpdateVolume();
					}
				}
			}
			if ((Object)(object)currentAudioPlayer != (Object)null)
			{
				currentAudioPlayer.UpdateVolume();
			}
		}

		public void AssignExternalAudioPlayer(EmoteAudioPlayer audioPlayer)
		{
			if ((Object)(object)currentAudioPlayer != (Object)null)
			{
				currentAudioPlayer.StopAudio();
				currentAudioPlayer.RemoveFromEmoteSyncGroup();
				currentAudioPlayer = null;
			}
			if (useAudio && performingEmote.hasAudio && performingEmote.isBoomboxAudio)
			{
				currentAudioPlayer = audioPlayer;
				if ((Object)(object)currentAudioPlayer != (Object)null)
				{
					currentAudioPlayer.SyncWithEmoteControllerAudio(leadEmoteController);
					currentAudioPlayer.AddToEmoteSyncGroup(this);
					currentAudioPlayer.UpdateVolume();
				}
			}
		}
	}
	internal static class HelperTools
	{
		public static NetworkManager networkManager => NetworkManager.Singleton;

		public static bool isClient => networkManager.IsClient;

		public static bool isServer => networkManager.IsServer;

		public static bool isHost => networkManager.IsHost;

		public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;

		public static QuickMenuManager quickMenuManager => localPlayerController?.quickMenuManager;

		public static TextMeshProUGUI[] controlTipLines => HUDManager.Instance?.controlTipLines;

		public static List<Item> allItems => StartOfRound.Instance?.allItemsList?.itemsList;

		public static SelectableLevel[] selectableLevels => StartOfRound.Instance?.levels;

		public static string currentSaveFileName => GameNetworkManager.Instance?.currentSaveFileName;

		public static int groupCredits => ((Object)(object)TerminalPatcher.terminalInstance != (Object)null) ? groupCredits : (-1);

		public static int currentEmoteCredits => TerminalPatcher.currentEmoteCredits;

		public static EmoteControllerPlayer emoteControllerLocal => EmoteControllerPlayer.emoteControllerLocal;

		public static bool TryGetPlayerByClientId(ulong clientId, out PlayerControllerB playerController)
		{
			playerController = null;
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (val.actualClientId == clientId)
				{
					playerController = val;
					break;
				}
			}
			return (Object)(object)playerController != (Object)null;
		}

		public static bool TryGetPlayerByUsername(string username, out PlayerControllerB playerController)
		{
			playerController = null;
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (val.playerUsername == username)
				{
					playerController = val;
					break;
				}
			}
			return (Object)(object)playerController != (Object)null;
		}

		public static EmoteController GetEmoteControllerById(ulong id)
		{
			foreach (EmoteController value in EmoteController.allEmoteControllers.Values)
			{
				if (value.emoteControllerId == id)
				{
					return value;
				}
			}
			return null;
		}
	}
	[HarmonyPatch]
	public class EmoteControllerMaskedEnemy : EmoteController
	{
		public static Dictionary<MaskedPlayerEnemy, EmoteControllerMaskedEnemy> allMaskedEnemyEmoteControllers = new Dictionary<MaskedPlayerEnemy, EmoteControllerMaskedEnemy>();

		public MaskedPlayerEnemy maskedEnemy;

		public int emoteCount = 0;

		public bool stoppedAndStaring = false;

		public bool behaviour1 = false;

		public Vector3 emotedAtPosition;

		public int id => (int)((NetworkBehaviour)maskedEnemy).NetworkObjectId;

		public float stopAndStareTimer
		{
			get
			{
				return (float)Traverse.Create((object)maskedEnemy).Field("stopAndStareTimer").GetValue();
			}
			set
			{
				Traverse.Create((object)maskedEnemy).Field("stopAndStareTimer").SetValue((object)value);
			}
		}

		public NavMeshAgent agent => ((EnemyAI)maskedEnemy).agent;

		public PlayerControllerB lookingAtPlayer
		{
			get
			{
				Transform stareAtTransform = maskedEnemy.stareAtTransform;
				return (stareAtTransform != null) ? ((Component)stareAtTransform).GetComponentInParent<PlayerControllerB>() : null;
			}
		}

		public bool inKillAnimation => (bool)Traverse.Create((object)maskedEnemy).Field("inKillAnimation").GetValue();

		public bool handsOut => (bool)Traverse.Create((object)maskedEnemy).Field("handsOut").GetValue();

		public float localSpeed
		{
			get
			{
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = (Vector3)Traverse.Create((object)maskedEnemy).Field("agentLocalVelocity").GetValue();
				return ((Vector3)(ref val)).magnitude;
			}
		}

		public bool isMoving => animator.GetBool("IsMoving");

		public override void Initialize(string sourceRootBoneName = "metarig")
		{
			base.Initialize();
			if (initialized)
			{
				maskedEnemy = ((Component)this).GetComponentInParent<MaskedPlayerEnemy>();
				if ((Object)(object)maskedEnemy == (Object)null)
				{
					CustomLogging.LogError("Failed to find MaskedPlayerEnemy component in parent of EmoteControllerMaskedEnemy.");
				}
				else
				{
					allMaskedEnemyEmoteControllers.Add(maskedEnemy, this);
				}
			}
		}

		protected override void OnDestroy()
		{
			base.OnDestroy();
			allMaskedEnemyEmoteControllers?.Remove(maskedEnemy);
		}

		protected override bool CheckIfShouldStopEmoting()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (!isPerformingEmote)
			{
				return false;
			}
			if (base.CheckIfShouldStopEmoting())
			{
				return true;
			}
			return ((EnemyAI)maskedEnemy).isEnemyDead || (NetworkManager.Singleton.IsServer && (agent.speed > 0f || stopAndStareTimer <= 0f)) || (!NetworkManager.Singleton.IsServer && Vector3.Distance(emotedAtPosition, ((Component)maskedEnemy).transform.position) > 0.01f) || inKillAnimation;
		}

		public override bool IsPerformingCustomEmote()
		{
			return base.IsPerformingCustomEmote();
		}

		public override bool CanPerformEmote()
		{
			return base.CanPerformEmote() && (Object)(object)lookingAtPlayer != (Object)null && (!NetworkManager.Singleton.IsServer || stopAndStareTimer >= 2f) && !inKillAnimation && ((NetworkManager.Singleton.IsServer && agent.speed == 0f) || (!NetworkManager.Singleton.IsServer && !isMoving)) && !((EnemyAI)maskedEnemy).isEnemyDead;
		}

		public override bool PerformEmote(UnlockableEmote emote, int overrideEmoteId = -1, bool doNotTriggerAudio = false)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			bool result = base.PerformEmote(emote, overrideEmoteId, doNotTriggerAudio);
			if (isPerformingEmote)
			{
				emoteCount++;
				emotedAtPosition = ((Component)maskedEnemy).transform.position;
			}
			return result;
		}

		public override void StopPerformingEmote()
		{
			base.StopPerformingEmote();
			stoppedAndStaring = false;
		}

		protected override void CreateBoneMap()
		{
			boneMap = BoneMapper.CreateBoneMap(humanoidSkeleton, metarig, EmoteControllerPlayer.sourceBoneNames);
		}

		protected override ulong GetEmoteControllerId()
		{
			return ((Object)(object)maskedEnemy != (Object)null) ? ((NetworkBehaviour)maskedEnemy).NetworkObjectId : 0;
		}

		protected override string GetEmoteControllerName()
		{
			return ((Object)(object)maskedEnemy != (Object)null) ? ((Object)maskedEnemy).name : base.GetEmoteControllerName();
		}
	}
	[DefaultExecutionOrder(-2)]
	public class EmoteControllerPlayer : EmoteController
	{
		public static Dictionary<PlayerControllerB, EmoteControllerPlayer> allPlayerEmoteControllers = new Dictionary<PlayerControllerB, EmoteControllerPlayer>();

		public PlayerControllerB playerController;

		public Animator originalAnimator;

		private Dictionary<Transform, Transform> boneMapLocalPlayerArms;

		internal Transform humanoidHead;

		private Transform cameraContainerTarget;

		private Transform cameraContainerLerp;

		public static List<string> sourceBoneNames = new List<string>
		{
			"spine", "spine.001", "spine.002", "spine.003", "spine.004", "shoulder.L", "arm.L_upper", "arm.L_lower", "hand.L", "finger1.L",
			"finger1.L.001", "finger2.L", "finger2.L.001", "finger3.L", "finger3.L.001", "finger4.L", "finger4.L.001", "finger5.L", "finger5.L.001", "shoulder.R",
			"arm.R_upper", "arm.R_lower", "hand.R", "finger1.R", "finger1.R.001", "finger2.R", "finger2.R.001", "finger3.R", "finger3.R.001", "finger4.R",
			"finger4.R.001", "finger5.R", "finger5.R.001", "thigh.L", "shin.L", "foot.L", "heel.02.L", "toe.L", "thigh.R", "shin.R",
			"foot.R", "heel.02.R", "toe.R"
		};

		public GrabbablePropObject sourceGrabbableEmoteProp;

		public static EmoteControllerPlayer emoteControllerLocal => ((Object)(object)HelperTools.localPlayerController != (Object)null && allPlayerEmoteControllers.ContainsKey(HelperTools.localPlayerController)) ? allPlayerEmoteControllers[HelperTools.localPlayerController] : null;

		public bool isLocalPlayer => (Object)(object)playerController == (Object)(object)StartOfRound.Instance?.localPlayerController;

		public ulong clientId => playerController.actualClientId;

		public ulong playerId => playerController.playerClientId;

		public ulong steamId => playerController.playerSteamId;

		public string username => playerController.playerUsername;

		public float timeSinceStartingEmote
		{
			get
			{
				return (float)Traverse.Create((object)playerController).Field("timeSinceStartingEmote").GetValue();
			}
			set
			{
				Traverse.Create((object)playerController).Field("timeSinceStartingEmote").SetValue((object)value);
			}
		}

		public override void Initialize(string sourceRootBoneName = "metarig")
		{
			base.Initialize();
			if (initialized)
			{
				originalAnimator = ((Component)metarig).GetComponentInChildren<Animator>();
				playerController = ((Component)this).GetComponentInParent<PlayerControllerB>();
				if ((Object)(object)playerController == (Object)null)
				{
					CustomLogging.LogError("Failed to find PlayerControllerB component in parent of EmoteControllerPlayer.");
				}
				else
				{
					allPlayerEmoteControllers.Add(playerController, this);
				}
			}
		}

		protected override void Start()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			base.Start();
			if (initialized)
			{
				Transform val = FindChildRecursive("spine.004", metarig);
				if ((Object)(object)val != (Object)null)
				{
					cameraContainerTarget = new GameObject("CameraContainer_Target").transform;
					cameraContainerTarget.SetParent(val);
					cameraContainerTarget.localPosition = new Vector3(0f, 0.22f, 0f);
					cameraContainerTarget.localEulerAngles = new Vector3(-3f, 0f, 0f);
					cameraContainerLerp = new GameObject("CameraContainer_Lerp").transform;
					cameraContainerLerp.SetParent(humanoidSkeleton);
					cameraContainerLerp.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
				}
				humanoidHead = FindChildRecursive("head", humanoidSkeleton);
				if (!Object.op_Implicit((Object)(object)humanoidHead))
				{
					CustomLogging.LogError("Failed to find Head on: " + base.emoteControllerName);
				}
			}
		}

		protected override void OnDestroy()
		{
			base.OnDestroy();
			allPlayerEmoteControllers?.Remove(playerController);
		}

		protected override void Update()
		{
			if (initialized && !((Object)(object)playerController == (Object)null) && (!((Object)(object)playerController == (Object)(object)HelperTools.localPlayerController) || (!ConfigSettings.disableEmotesForSelf.Value && !LCVR_Compat.LoadedAndEnabled)))
			{
				base.Update();
			}
		}

		protected override void LateUpdate()
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			if (!initialized || (Object)(object)playerController == (Object)null || ((Object)(object)playerController == (Object)(object)HelperTools.localPlayerController && (ConfigSettings.disableEmotesForSelf.Value || LCVR_Compat.LoadedAndEnabled)))
			{
				return;
			}
			bool flag = isPerformingEmote;
			base.LateUpdate();
			if (flag && !isPerformingEmote && playerController.performingEmote)
			{
				playerController.performingEmote = false;
				originalAnimator.SetInteger("emoteNumber", 0);
				AnimatorStateInfo currentAnimatorStateInfo = originalAnimator.GetCurrentAnimatorStateInfo(0);
				animator.Play(((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash, 0, 0f);
				if (isLocalPlayer)
				{
					timeSinceStartingEmote = 0f;
					playerController.StopPerformingEmoteServerRpc();
				}
			}
		}

		protected override void TranslateAnimation()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: 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_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			if (!initialized || !isPerformingEmote || (Object)(object)playerController == (Object)null)
			{
				return;
			}
			base.TranslateAnimation();
			if (Object.op_Implicit((Object)(object)humanoidHead) && Object.op_Implicit((Object)(object)cameraContainerLerp) && Object.op_Implicit((Object)(object)cameraContainerTarget))
			{
				cameraContainerLerp.position = Vector3.Lerp(cameraContainerLerp.position, cameraContainerTarget.position, 25f * Time.deltaTime);
				cameraContainerLerp.rotation = Quaternion.Lerp(cameraContainerLerp.rotation, cameraContainerTarget.rotation, 25f * Time.deltaTime);
				if (!isLocalPlayer || !ThirdPersonEmoteController.firstPersonEmotesEnabled || !ThirdPersonEmoteController.isMovingWhileEmoting)
				{
					playerController.cameraContainerTransform.position = cameraContainerLerp.position;
					playerController.cameraContainerTransform.rotation = cameraContainerLerp.rotation;
				}
				if (isLocalPlayer)
				{
					playerController.localVisor.position = playerController.localVisorTargetPoint.position;
					playerController.localVisor.rotation = playerController.localVisorTargetPoint.rotation;
				}
			}
			if (!isLocalPlayer)
			{
				return;
			}
			playerController.playerModelArmsMetarig.rotation = playerController.localArmsRotationTarget.rotation;
			if (boneMapLocalPlayerArms == null)
			{
				return;
			}
			foreach (KeyValuePair<Transform, Transform> boneMapLocalPlayerArm in boneMapLocalPlayerArms)
			{
				Transform key = boneMapLocalPlayerArm.Key;
				Transform value = boneMapLocalPlayerArm.Value;
				if (!((Object)(object)key == (Object)null) && !((Object)(object)value == (Object)null))
				{
					((Component)value).transform.position = ((Component)key).transform.position;
					((Component)value).transform.rotation = ((Component)key).transform.rotation;
				}
			}
		}

		protected override bool CheckIfShouldStopEmoting()
		{
			if ((Object)(object)playerController == (Object)null || !isPerformingEmote)
			{
				return false;
			}
			if (base.CheckIfShouldStopEmoting() || !playerController.performingEmote || performingEmote == null)
			{
				return true;
			}
			GrabbableObject val = playerController.ItemSlots[playerController.currentItemSlot];
			if ((Object)(object)sourceGrabbableEmoteProp != (Object)null && (Object)(object)sourceGrabbableEmoteProp != (Object)(object)val)
			{
				return true;
			}
			return false;
		}

		public override bool IsPerformingCustomEmote()
		{
			return base.IsPerformingCustomEmote();
		}

		public bool TryPerformingEmoteLocal(UnlockableEmote emote, int overrideEmoteId = -1, GrabbablePropObject sourcePropObject = null)
		{
			if (!initialized || ConfigSettings.disableEmotesForSelf.Value || LCVR_Compat.LoadedAndEnabled)
			{
				return false;
			}
			if (!isLocalPlayer)
			{
				CustomLogging.LogWarning("Cannot run TryPerformEmoteLocal on a character who does not belong to the local player. This is not allowed.");
				return false;
			}
			CustomLogging.Log("Attempting to perform emote on local player.");
			if (!CanPerformEmote())
			{
				return false;
			}
			if (overrideEmoteId >= 0 && (emote.emoteSyncGroup == null || emote.emoteSyncGroup.Count <= 1 || overrideEmoteId < 0 || overrideEmoteId >= emote.emoteSyncGroup.Count))
			{
				overrideEmoteId = -1;
			}
			if (emote.emoteSyncGroup != null && emote.emoteSyncGroup.Count > 1)
			{
				if (emote.randomEmote)
				{
					if (overrideEmoteId < 0)
					{
						overrideEmoteId = Random.Range(0, emote.emoteSyncGroup.Count);
					}
				}
				else
				{
					emote = emote.emoteSyncGroup[0];
				}
			}
			if (overrideEmoteId >= 0 && emote.emoteSyncGroup != null && overrideEmoteId < emote.emoteSyncGroup.Count)
			{
				emote = emote.emoteSyncGroup[overrideEmoteId];
			}
			else
			{
				overrideEmoteId = -1;
			}
			EmoteController emoteController = null;
			if (isPerformingEmote && performingEmote.IsEmoteInEmoteGroup(emote) && (!performingEmote.randomEmote || performingEmote.loopable))
			{
				if (performingEmote.emoteSyncGroup != null && performingEmote.emoteSyncGroup.Count > 1)
				{
					overrideEmoteId = (performingEmote.emoteSyncGroup.IndexOf(performingEmote) + 1) % performingEmote.emoteSyncGroup.Count;
					if (performingEmote.emoteSyncGroup[overrideEmoteId] != null)
					{
						emote = performingEmote.emoteSyncGroup[overrideEmoteId];
					}
				}
				if (emoteSyncGroup?.syncGroup != null && emoteSyncGroup.syncGroup.Count > 1)
				{
					if (emoteSyncGroup.syncGroup.Count > 1 && (performingEmote?.emoteSyncGroup == null || performingEmote.emoteSyncGroup.Count <= 1))
					{
						return true;
					}
					foreach (EmoteController item in emoteSyncGroup.syncGroup)
					{
						if ((Object)(object)item != (Object)(object)this)
						{
							emoteController = item;
							break;
						}
					}
				}
			}
			if ((Object)(object)emoteController != (Object)null)
			{
				return TrySyncingEmoteWithEmoteController(emoteController, overrideEmoteId);
			}
			bool result = ((!((Object)(object)sourcePropObject != (Object)null) || !((Object)(object)sourcePropObject == (Object)(object)HelperTools.localPlayerController.ItemSlots[HelperTools.localPlayerController.currentItemSlot])) ? PerformEmote(emote, overrideEmoteId, AudioManager.emoteOnlyMode) : PerformEmote(emote, sourcePropObject, overrideEmoteId, AudioManager.emoteOnlyMode));
			playerController.StartPerformingEmoteServerRpc();
			SyncPerformingEmoteManager.SendPerformingEmoteUpdateToServer(emote, AudioManager.emoteOnlyMode);
			timeSinceStartingEmote = 0f;
			playerController.performingEmote = true;
			return result;
		}

		public bool TrySyncingEmoteWithEmoteController(EmoteController emoteController, int overrideEmoteId = -1)
		{
			if (!initialized || (Object)(object)emoteController == (Object)null || ConfigSettings.disableEmotesForSelf.Value || LCVR_Compat.LoadedAndEnabled)
			{
				return false;
			}
			if (!isLocalPlayer)
			{
				CustomLogging.LogWarning("Cannot run TrySyncingEmoteWithEmoteController on a character who does not belong to the local player. This is not allowed.");
				return false;
			}
			CustomLogging.Log("Attempting to sync emote for player: " + ((Object)playerController).name + " with emote controller with id: " + emoteController.emoteControllerId);
			if (!CanPerformEmote() || !emoteController.IsPerformingCustomEmote())
			{
				return false;
			}
			if (overrideEmoteId >= 0 && (emoteController.performingEmote?.emoteSyncGroup == null || overrideEmoteId >= emoteController.performingEmote.emoteSyncGroup.Count || emoteController.performingEmote.emoteSyncGroup[overrideEmoteId] == null))
			{
				overrideEmoteId = -1;
			}
			SyncWithEmoteController(emoteController, overrideEmoteId);
			if (performingEmote != null)
			{
				if (performingEmote.inEmoteSyncGroup)
				{
					overrideEmoteId = performingEmote.emoteSyncGroup.IndexOf(performingEmote);
				}
				playerController.StartPerformingEmoteServerRpc();
				SyncPerformingEmoteManager.SendSyncEmoteUpdateToServer(emoteController, overrideEmoteId);
				timeSinceStartingEmote = 0f;
				playerController.performingEmote = true;
				return true;
			}
			return false;
		}

		public override bool CanPerformEmote()
		{
			if (!isLocalPlayer)
			{
				return true;
			}
			if (!initialized || ConfigSettings.disableEmotesForSelf.Value || LCVR_Compat.LoadedAndEnabled)
			{
				return false;
			}
			bool flag = base.CanPerformEmote();
			MethodInfo method = ((object)playerController).GetType().GetMethod("CheckConditionsForEmote", BindingFlags.Instance | BindingFlags.NonPublic);
			flag &= (bool)method.Invoke(playerController, new object[0]);
			bool flag2 = (Object)(object)playerController.inAnimationWithEnemy == (Object)null && (!isLocalPlayer || !CentipedePatcher.IsCentipedeLatchedOntoLocalPlayer());
			return flag && flag2;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "SwitchToItemSlot")]
		[HarmonyPostfix]
		private static void OnSwapItem(int slot, PlayerControllerB __instance)
		{
			if (allPlayerEmoteControllers.TryGetValue(__instance, out var value) && value.IsPerformingCustomEmote())
			{
				GrabbableObject val = __instance.ItemSlots[slot];
				if ((Object)(object)value.sourceGrabbableEmoteProp != (Object)null && (Object)(object)value.sourceGrabbableEmoteProp != (Object)(object)val)
				{
					value.StopPerformingEmote();
				}
				else if (Object.op_Implicit((Object)(object)val) && value.emotingProps.Count > 0)
				{
					val.EnableItemMeshes(false);
				}
			}
		}

		public bool PerformEmote(UnlockableEmote emote, GrabbablePropObject sourcePropObject, int overrideEmoteId = -1, bool doNotTriggerAudio = false)
		{
			if ((Object)(object)sourcePropObject != (Object)null && (Object)(object)sourcePropObject == (Object)(object)playerController.ItemSlots[playerController.currentItemSlot])
			{
				sourceGrabbableEmoteProp = sourcePropObject;
			}
			bool result = PerformEmote(emote, overrideEmoteId, doNotTriggerAudio);
			if (isPerformingEmote)
			{
				if (!isLocalPlayer && SyncManager.isSynced && ConfigSync.instance.syncPersistentUnlocksGlobal && !SessionManager.unlockedEmotesByPlayer.TryGetValue(playerController.playerUsername, out var value) && !value.Contains(performingEmote))
				{
					SessionManager.UnlockEmoteLocal(emote.emoteId, purchased: false, playerController.playerUsername);
				}
			}
			else
			{
				StopPerformingEmote();
			}
			return result;
		}

		public override bool PerformEmote(UnlockableEmote emote, int overrideEmoteId = -1, bool doNotTriggerAudio = false)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)playerController == (Object)null || (isLocalPlayer && (ConfigSettings.disableEmotesForSelf.Value || LCVR_Compat.LoadedAndEnabled)))
			{
				return false;
			}
			bool result = base.PerformEmote(emote, overrideEmoteId, doNotTriggerAudio);
			if (isPerformingEmote)
			{
				cameraContainerLerp.SetPositionAndRotation(cameraContainerTarget.position, cameraContainerTarget.rotation);
				playerController.performingEmote = true;
				if (!isLocalPlayer)
				{
					originalAnimator.SetInteger("emoteNumber", 0);
				}
				GrabbableObject val = playerController.ItemSlots[playerController.currentItemSlot];
				if (Object.op_Implicit((Object)(object)val) && emotingProps.Count > 0)
				{
					val.EnableItemMeshes(false);
				}
				if (isLocalPlayer)
				{
					ThirdPersonEmoteController.OnStartCustomEmoteLocal();
				}
			}
			return result;
		}

		public override bool SyncWithEmoteController(EmoteController emoteController, int overrideEmoteId = -1)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)playerController == (Object)null || (isLocalPlayer && (ConfigSettings.disableEmotesForSelf.Value || LCVR_Compat.LoadedAndEnabled)))
			{
				return false;
			}
			bool result = base.SyncWithEmoteController(emoteController, overrideEmoteId);
			if (isPerformingEmote)
			{
				cameraContainerLerp.SetPositionAndRotation(cameraContainerTarget.position, cameraContainerTarget.rotation);
				playerController.performingEmote = true;
				if (!isLocalPlayer)
				{
					originalAnimator.SetInteger("emoteNumber", 0);
				}
				else
				{
					ThirdPersonEmoteController.OnStartCustomEmoteLocal();
					playerController.StartPerformingEmoteServerRpc();
				}
			}
			return result;
		}

		public override void StopPerformingEmote()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)playerController == (Object)null || (isLocalPlayer && ConfigSettings.disableEmotesForSelf.Value))
			{
				return;
			}
			base.StopPerformingEmote();
			cameraContainerLerp.SetPositionAndRotation(cameraContainerTarget.position, cameraContainerTarget.rotation);
			GrabbableObject val = playerController.ItemSlots[playerController.currentItemSlot];
			if (Object.op_Implicit((Object)(object)val))
			{
				val.EnableItemMeshes(true);
			}
			if ((Object)(object)sourceGrabbableEmoteProp != (Object)null)
			{
				if (sourceGrabbableEmoteProp.isPerformingEmote)
				{
					sourceGrabbableEmoteProp.StopEmote();
				}
				sourceGrabbableEmoteProp = null;
			}
			playerController.playerBodyAnimator.SetInteger("emote_number", 0);
			playerController.performingEmote = false;
			playerController.playerBodyAnimator.Update(0f);
			if (isLocalPlayer)
			{
				ThirdPersonEmoteController.OnStopCustomEmoteLocal();
				((Component)playerController.gameplayCamera).transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
				playerController.StopPerformingEmoteServerRpc();
			}
		}

		public override void ResetPerformingEmote()
		{
			if ((Object)(object)playerController == (Object)null || (isLocalPlayer && ConfigSettings.disableEmotesForSelf.Value))
			{
				return;
			}
			base.ResetPerformingEmote();
			if ((Object)(object)sourceGrabbableEmoteProp != (Object)null)
			{
				if (sourceGrabbableEmoteProp.isPerformingEmote)
				{
					sourceGrabbableEmoteProp.StopEmote();
				}
				sourceGrabbableEmoteProp = null;
			}
			GrabbableObject val = playerController.ItemSlots[playerController.currentItemSlot];
			if (Object.op_Implicit((Object)(object)val))
			{
				val.EnableItemMeshes(true);
			}
		}

		protected override void CreateBoneMap()
		{
			boneMap = BoneMapper.CreateBoneMap(humanoidSkeleton, metarig, sourceBoneNames);
			List<string> list = new List<string>
			{
				"arm.L_upper", "arm.L_lower", "hand.L", "finger1.L", "finger1.L.001", "finger2.L", "finger2.L.001", "finger3.L", "finger3.L.001", "finger4.L",
				"finger4.L.001", "finger5.L", "finger5.L.001", "arm.R_upper", "arm.R_lower", "hand.R", "finger1.R", "finger1.R.001", "finger2.R", "finger2.R.001",
				"finger3.R", "finger3.R.001", "finger4.R", "finger4.R.001", "finger5.R", "finger5.R.001"
			};
			boneMapLocalPlayerArms = BoneMapper.CreateBoneMap(humanoidSkeleton, playerController.localArmsTransform, list);
		}

		protected override ulong GetEmoteControllerId()
		{
			return ((Object)(object)playerController != (Object)null) ? ((NetworkBehaviour)playerController).NetworkObjectId : 0;
		}

		protected override string GetEmoteControllerName()
		{
			return ((Object)(object)playerController != (Object)null) ? playerController.playerUsername : base.GetEmoteControllerName();
		}
	}
	[HarmonyPatch]
	[DefaultExecutionOrder(-2)]
	public class EmoteController : MonoBehaviour
	{
		public static Dictionary<GameObject, EmoteController> allEmoteControllers = new Dictionary<GameObject, EmoteController>();

		public bool initialized = false;

		public Transform metarig;

		public Transform humanoidSkeleton;

		public Animator animator;

		public AnimatorOverrideController animatorController;

		public bool isPerformingEmote = false;

		public UnlockableEmote performingEmote;

		protected Dictionary<Transform, Transform> boneMap;

		public List<Transform> groundContactPoints = new List<Transform>();

		public Transform propsParent;

		public List<PropObject> emotingProps = new List<PropObject>();

		public Transform ikLeftHand;

		public Transform ikRightHand;

		public Transform ikLeftFoot;

		public Transform ikRightFoot;

		public Transform ikHead;

		public EmoteSyncGroup emoteSyncGroup;

		public EmoteAudioSource personalEmoteAudioSource;

		private float timePerformedEmote = 0f;

		public bool smoothTransitionToEmote = false;

		public ulong emoteControllerId => GetEmoteControllerId();

		public string emoteControllerName => GetEmoteControllerName();

		public float currentAnimationTimeNormalized
		{
			get
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0);
				return ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime;
			}
		}

		public float currentAnimationTime
		{
			get
			{
				AnimationClip currentAnimationClip = GetCurrentAnimationClip();
				return ((Object)(object)currentAnimationClip != (Object)null) ? (currentAnimationClip.length * (currentAnimationTimeNormalized % 1f)) : 0f;
			}
		}

		public int currentStateHash
		{
			get
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0);
				return ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).shortNameHash;
			}
		}

		public bool isLooping
		{
			get
			{
				return animator.GetBool("loop");
			}
			set
			{
				animator.SetBool("loop", value);
			}
		}

		public bool isAnimatorInLoopingState
		{
			get
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0);
				return ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("emote_loop");
			}
		}

		public bool isSimpleEmoteController => ((object)this).GetType() == typeof(EmoteController);

		public int emoteSyncId => (emoteSyncGroup != null) ? emoteSyncGroup.syncId : (-1);

		protected virtual void Awake()
		{
			if (!initialized)
			{
				Initialize();
			}
		}

		public virtual void Initialize(string sourceRootBoneName = "metarig")
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Expected O, but got Unknown
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			if (initialized || (Object)(object)Plugin.humanoidSkeletonPrefab == (Object)null || (Object)(object)Plugin.humanoidAnimatorController == (Object)null || (Object)(object)Plugin.humanoidAvatar == (Object)null)
			{
				return;
			}
			try
			{
				metarig = FindChildRecursive(sourceRootBoneName, ((Component)this).transform);
				humanoidSkeleton = Object.Instantiate<GameObject>(Plugin.humanoidSkeletonPrefab, metarig.parent).transform;
				((Object)humanoidSkeleton).name = "HumanoidSkeleton";
				humanoidSkeleton.SetSiblingIndex(metarig.GetSiblingIndex() + 1);
				animator = ((Component)humanoidSkeleton).GetComponent<Animator>();
				OnAnimatorIKHandler onAnimatorIKHandler = ((Component)animator).gameObject.AddComponent<OnAnimatorIKHandler>();
				onAnimatorIKHandler.SetParentEmoteController(this);
				animatorController = new AnimatorOverrideController(Plugin.humanoidAnimatorController);
				animator.runtimeAnimatorController = (RuntimeAnimatorController)(object)animatorController;
				humanoidSkeleton.SetLocalPositionAndRotation(metarig.localPosition + Vector3.down * 0.025f, Quaternion.identity);
				humanoidSkeleton.localScale = metarig.localScale;
				if (!isSimpleEmoteController)
				{
					allEmoteControllers.Add(((Component)this).gameObject, this);
					GameObject val = new GameObject("PersonalEmoteAudioSource");
					val.transform.SetParent(humanoidSkeleton);
					val.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
					val.transform.localScale = Vector3.one;
					personalEmoteAudioSource = val.AddComponent<EmoteAudioSource>();
				}
				if ((Object)(object)propsParent == (Object)null)
				{
					propsParent = ((Component)this).transform.Find("EmoteProps");
					if ((Object)(object)propsParent == (Object)null)
					{
						propsParent = new GameObject("EmoteProps").transform;
						propsParent.SetParent(humanoidSkeleton);
						propsParent.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
						propsParent.localScale = Vector3.one;
					}
				}
				initialized = true;
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Failed to initialize EmoteController. Error: " + ex));
			}
		}

		protected virtual void Start()
		{
			if (!initialized)
			{
				return;
			}
			if (boneMap == null)
			{
				if (!isSimpleEmoteController)
				{
					CreateBoneMap();
				}
				else
				{
					Debug.LogWarning((object)"Using the base emote controller. Remember that when doing this, the bonemap will need to be built manually.");
				}
			}
			FindIkBones();
		}

		protected virtual void OnEnable()
		{
		}

		protected virtual void OnDisable()
		{
			if (isPerformingEmote)
			{
				StopPerformingEmote();
			}
		}

		protected virtual void OnDestroy()
		{
			if (isPerformingEmote)
			{
				StopPerformingEmote();
			}
			allEmoteControllers?.Remove(((Component)this).gameObject);
			if (SyncPerformingEmoteManager.doNotTriggerAudioDict.ContainsKey(this))
			{
				SyncPerformingEmoteManager.doNotTriggerAudioDict.Remove(this);
			}
		}

		protected virtual void Update()
		{
			if (initialized)
			{
			}
		}

		protected virtual void LateUpdate()
		{
			if (initialized)
			{
				if (isPerformingEmote && CheckIfShouldStopEmoting())
				{
					StopPerformingEmote();
				}
				if (!((Object)(object)animator == (Object)null) && !((Object)(object)animatorController == (Object)null) && boneMap != null && isPerformingEmote)
				{
					TranslateAnimation();
				}
			}
		}

		protected virtual void TranslateAnimation()
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			if (performingEmote == null || boneMap == null || boneMap.Count <= 0)
			{
				return;
			}
			foreach (KeyValuePair<Transform, Transform> item in boneMap)
			{
				Transform key = item.Key;
				Transform value = item.Value;
				if (!((Object)(object)key == (Object)null) && !((Object)(object)value == (Object)null))
				{
					float num = Time.time - timePerformedEmote;
					float num2 = (smoothTransitionToEmote ? Mathf.Clamp01(num / 0.2f) : 1f);
					((Component)value).transform.position = Vector3.Lerp(((Component)value).transform.position, ((Component)key).transform.position, num2);
					((Component)value).transform.rotation = Quaternion.Slerp(((Component)value).transform.rotation, ((Component)key).transform.rotation, num2);
				}
			}
		}

		protected virtual bool CheckIfShouldStopEmoting()
		{
			if (isPerformingEmote)
			{
				return performingEmote == null || (!performingEmote.loopable && !performingEmote.isPose && currentAnimationTimeNormalized >= 1f);
			}
			return false;
		}

		protected virtual void CorrectVerticalPosition()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			if (groundContactPoints == null)
			{
				return;
			}
			float num = 0f;
			foreach (Transform groundContactPoint in groundContactPoints)
			{
				num = Mathf.Min(num, ((Component)groundContactPoint).transform.position.y - metarig.position.y);
			}
			if (num < 0f)
			{
				metarig.position = new Vector3(metarig.position.x, metarig.position.y - num, metarig.position.z);
			}
		}

		public virtual bool IsPerformingCustomEmote()
		{
			return isPerformingEmote && performingEmote != null;
		}

		public virtual bool CanPerformEmote()
		{
			return initialized && (Object)(object)animator != (Object)null && ((Behaviour)animator).enabled;
		}

		public virtual bool PerformEmote(UnlockableEmote emote, int overrideEmoteId = -1, bool doNotTriggerAudio = false)
		{
			if (!initialized || !CanPerformEmote())
			{
				return false;
			}
			if (!isSimpleEmoteController)
			{
				CustomLogging.Log("[" + emoteControllerName + "] Performing emote: " + emote.emoteName);
			}
			if (isPerformingEmote)
			{
				ResetPerformingEmote();
			}
			if (emote.emoteSyncGroup != null)
			{
				if (overrideEmoteId >= 0 && overrideEmoteId < emote.emoteSyncGroup.Count && emote.emoteSyncGroup[overrideEmoteId] != null)
				{
					emote = emote.emoteSyncGroup[overrideEmoteId];
				}
				else if (emote.randomEmote)
				{
					int index = Random.Range(0, emote.emoteSyncGroup.Count);
					UnlockableEmote unlockableEmote = emote.emoteSyncGroup[index];
					if (unlockableEmote != null)
					{
						emote = unlockableEmote;
					}
				}
			}
			animatorController["emote"] = emote.animationClip;
			if ((Object)(object)emote.transitionsToClip != (Object)null)
			{
				animatorController["emote_loop"] = emote.transitionsToClip;
			}
			animator.SetBool("loop", (Object)(object)emote.transitionsToClip != (Object)null);
			animator.Play("emote", 0, 0f);
			animator.Update(0f);
			performingEmote = emote;
			isPerformingEmote = true;
			timePerformedEmote = Time.time;
			RecordStartingBonePositions();
			PerformEmoteProps();
			if (!isSimpleEmoteController)
			{
				CreateEmoteSyncGroup(doNotTriggerAudio);
			}
			DiscoBallPatcher.OnPerformEmote(this);
			return true;
		}

		public virtual bool SyncWithEmoteController(EmoteController emoteController, int overrideEmoteId = -1)
		{
			if (!initialized || !CanPerformEmote() || (Object)(object)emoteController == (Object)null || !emoteController.IsPerformingCustomEmote())
			{
				return false;
			}
			if (!isSimpleEmoteController)
			{
				CustomLogging.Log("[" + emoteControllerName + "] Attempting to sync with emote controller: " + ((Object)emoteController).name + " Emote: " + emoteController.performingEmote.emoteName + " PlayEmoteAtTimeNormalized: " + emoteController.currentAnimationTimeNormalized % 1f);
			}
			if (isPerformingEmote)
			{
				ResetPerformingEmote();
			}
			EmoteSyncGroup emoteSyncGroup = emoteController.emoteSyncGroup;
			if (emoteSyncGroup == null)
			{
				CustomLogging.LogWarning("[" + emoteControllerName + "] Attempted to sync with emote controller who is not a part of an emote sync group. Continuing anyways.");
			}
			UnlockableEmote unlockableEmote = emoteController.performingEmote;
			if (unlockableEmote.emoteSyncGroup != null)
			{
				if (overrideEmoteId >= 0 && overrideEmoteId < unlockableEmote.emoteSyncGroup.Count && unlockableEmote.emoteSyncGroup[overrideEmoteId] != null)
				{
					unlockableEmote = unlockableEmote.emoteSyncGroup[overrideEmoteId];
				}
				else if (unlockableEmote.randomEmote)
				{
					if (unlockableEmote.hasAudio && !unlockableEmote.isBoomboxAudio)
					{
						unlockableEmote = emoteController.performingEmote;
					}
					else
					{
						int index = Random.Range(0, unlockableEmote.emoteSyncGroup.Count);
						UnlockableEmote unlockableEmote2 = unlockableEmote.emoteSyncGroup[index];
						if (unlockableEmote2 != null)
						{
							unlockableEmote = unlockableEmote2;
						}
					}
				}
				else
				{
					bool flag = false;
					foreach (UnlockableEmote item in unlockableEmote.emoteSyncGroup)
					{
						if (!emoteSyncGroup.leadEmoteControllerByEmote.ContainsKey(item) || (Object)(object)emoteSyncGroup.leadEmoteControllerByEmote[unlockableEmote] == (Object)null)
						{
							unlockableEmote = item;
							flag = true;
							break;
						}
					}
					if (!flag)
					{
						int num = unlockableEmote.emoteSyncGroup.IndexOf(unlockableEmote);
						if (num >= 0)
						{
							num = (num + 1) % unlockableEmote.emoteSyncGroup.Count;
							unlockableEmote = unlockableEmote.emoteSyncGroup[num];
						}
					}
				}
			}
			AnimationClip currentAnimationClip = emoteController.GetCurrentAnimationClip();
			if (!unlockableEmote.ClipIsInEmote(currentAnimationClip))
			{
				CustomLogging.LogError("[" + emoteControllerName + "] Attempted to sync with emote controller whose animation clip is not a part of their performing emote? Emote: " + emoteController.performingEmote?.ToString() + " AnimationClip: " + ((Object)currentAnimationClip).name);
				return false;
			}
			animatorController["emote"] = unlockableEmote.animationClip;
			if ((Object)(object)unlockableEmote.transitionsToClip != (Object)null)
			{
				animatorController["emote_loop"] = unlockableEmote.transitionsToClip;
			}
			float num2 = emoteController.currentAnimationTimeNormalized % 1f;
			animator.SetBool("loop", (Object)(object)unlockableEmote.transitionsToClip != (Object)null);
			animator.Play(((Object)(object)currentAnimationClip == (Object)(object)unlockableEmote.transitionsToClip) ? "emote_loop" : "emote", 0, num2);
			animator.Update(0f);
			performingEmote = unlockableEmote;
			isPerformingEmote = true;
			PerformEmoteProps();
			if (!isSimpleEmoteController && emoteController.emoteSyncGroup != null)
			{
				AddToEmoteSyncGroup(emoteController.emoteSyncGroup);
			}
			DiscoBallPatcher.OnPerformEmote(this);
			return true;
		}

		protected void PerformEmoteProps()
		{
			if ((Object)(object)propsParent != (Object)null && performingEmote.propNamesInEmote != null)
			{
				LoadEmoteProps();
			}
			if (emotingProps == null)
			{
				return;
			}
			foreach (PropObject emotingProp in emotingProps)
			{
				emotingProp.SyncWithEmoteController(this);
			}
		}

		protected void LoadEmoteProps()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			UnloadEmoteProps();
			if (performingEmote.propNamesInEmote == null)
			{
				return;
			}
			foreach (string item in performingEmote.propNamesInEmote)
			{
				PropObject propObject = EmotePropManager.LoadEmoteProp(item);
				propObject.SetPropLayer(6);
				emotingProps.Add(propObject);
				((Component)propObject).transform.SetParent(propsParent);
				((Component)propObject).transform.localPosition = Vector3.zero;
				((Component)propObject).transform.localRotation = Quaternion.identity;
			}
		}

		protected void UnloadEmoteProps()
		{
			if (emotingProps == null)
			{
				return;
			}
			foreach (PropObject emotingProp in emotingProps)
			{
				((Component)emotingProp).transform.SetParent(EmotePropManager.propPoolParent);
				emotingProp.active = false;
			}
			emotingProps.Clear();
		}

		public virtual void StopPerformingEmote()
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			if (initialized)
			{
				isPerformingEmote = false;
				if (!isSimpleEmoteController)
				{
					CustomLogging.Log(string.Format("[" + emoteControllerName + "] Stopping emote."));
				}
				animatorController["emote"] = null;
				animatorController["emote_loop"] = null;
				RemoveFromEmoteSyncGroup();
				UnloadEmoteProps();
				if ((Object)(object)ikLeftHand != (Object)null)
				{
					ikLeftHand.localPosition = Vector3.zero;
				}
				if ((Object)(object)ikRightHand != (Object)null)
				{
					ikRightHand.localPosition = Vector3.zero;
				}
				if ((Object)(object)ikLeftFoot != (Object)null)
				{
					ikLeftFoot.localPosition = Vector3.zero;
				}
				if ((Object)(object)ikRightFoot != (Object)null)
				{
					ikRightFoot.localPosition = Vector3.zero;
				}
				if ((Object)(object)ikHead != (Object)null)
				{
					ikHead.localPosition = Vector3.zero;
				}
				DiscoBallPatcher.OnStopPerformingEmote(this);
			}
		}

		public virtual void ResetPerformingEmote()
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			if (initialized)
			{
				isPerformingEmote = false;
				animatorController["emote"] = null;
				animatorController["emote_loop"] = null;
				RemoveFromEmoteSyncGroup();
				UnloadEmoteProps();
				if ((Object)(object)ikLeftHand != (Object)null)
				{
					ikLeftHand.localPosition = Vector3.zero;
				}
				if ((Object)(object)ikRightHand != (Object)null)
				{
					ikRightHand.localPosition = Vector3.zero;
				}
				if ((Object)(object)ikLeftFoot != (Object)null)
				{
					ikLeftFoot.localPosition = Vector3.zero;
				}
				if ((Object)(object)ikRightFoot != (Object)null)
				{
					ikRightFoot.localPosition = Vector3.zero;
				}
				if ((Object)(object)ikHead != (Object)null)
				{
					ikHead.localPosition = Vector3.zero;
				}
			}
		}

		public AnimationClip GetCurrentAnimationClip()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (!IsPerformingCustomEmote())
			{
				return null;
			}
			if (!animator.GetBool("loop"))
			{
				return animatorController["emote"];
			}
			AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0);
			return animatorController[((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("emote_loop") ? "emote_loop" : "emote"];
		}

		protected virtual void CreateBoneMap()
		{
		}

		public void CreateBoneMap(List<string> sourceBoneNames, List<string> targetBoneNames = null)
		{
			boneMap = BoneMapper.CreateBoneMap(humanoidSkeleton, metarig, sourceBoneNames, targetBoneNames);
		}

		protected virtual void FindIkBones()
		{
			Transform val = FindChildRecursive("root_ik");
			if ((Object)(object)val == (Object)null)
			{
				CustomLogging.LogError("Failed to find root ik bone called \"root_ik\" in humanoid skeleton: " + emoteControllerName);
				return;
			}
			ikLeftHand = val.Find("hand_ik_l");
			ikRightHand = val.Find("hand_ik_r");
			ikLeftFoot = val.Find("foot_ik_l");
			ikRightFoot = val.Find("foot_ik_r");
			ikHead = val.Find("head_ik");
		}

		protected virtual Transform FindChildRecursive(string objectName, Transform root = null)
		{
			if ((Object)(object)root == (Object)null)
			{
				root = humanoidSkeleton;
			}
			if (((Object)root).name == objectName)
			{
				return root;
			}
			for (int i = 0; i < root.childCount; i++)
			{
				Transform child = root.GetChild(i);
				Transform val = FindChildRecursive(objectName, child);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		protected virtual ulong GetEmoteControllerId()
		{
			return 0uL;
		}

		protected virtual string GetEmoteControllerName()
		{
			return ((Object)this).name;
		}

		protected void CreateEmoteSyncGroup(bool doNotTriggerAudio = false)
		{
			emoteSyncGroup = EmoteSyncGroup.CreateEmoteSyncGroup(this, !doNotTriggerAudio);
		}

		protected void AddToEmoteSyncGroup(EmoteSyncGroup emoteSyncGroup)
		{
			CustomLogging.Log("Adding to emote sync group with id: " + emoteSyncGroup.syncId);
			emoteSyncGroup.AddToEmoteSyncGroup(this);
			this.emoteSyncGroup = emoteSyncGroup;
		}

		protected void RemoveFromEmoteSyncGroup()
		{
			if (emoteSyncGroup != null)
			{
				emoteSyncGroup.RemoveFromEmoteSyncGroup(this);
			}
			emoteSyncGroup = null;
		}

		protected void RecordStartingBonePositions()
		{
		}
	}
	[HarmonyPatch]
	public static class EmotesManager
	{
		public static List<UnlockableEmote> allUnlockableEmotes;

		public static Dictionary<string, UnlockableEmote> allUnlockableEmotesDict;

		public static List<UnlockableEmote> complementaryEmotes;

		internal static List<UnlockableEmote> complementaryEmotesDefault;

		public static List<string> allFavoriteEmotes;

		public static List<string> allQuickEmotes;

		public static List<UnlockableEmote> allEmotesTier0;

		public static List<UnlockableEmote> allEmotesTier1;

		public static List<UnlockableEmote> allEmotesTier2;

		public static List<UnlockableEmote> allEmotesTier3;

		public static void BuildEmotesList()
		{
			allUnlockableEmotes = new List<UnlockableEmote>();
			allUnlockableEmotesDict = new Dictionary<string, UnlockableEmote>();
			complementaryEmotesDefault = new List<UnlockableEmote>();
			allFavoriteEmotes = new List<string>();
			allQuickEmotes = new List<string>(8);
			while (allQuickEmotes.Count < allQuickEmotes.Capacity)
			{
				allQuickEmotes.Add("");
			}
			allEmotesTier0 = new List<UnlockableEmote>();
			allEmotesTier1 = new List<UnlockableEmote>();
			allEmotesTier2 = new List<UnlockableEmote>();
			allEmotesTier3 = new List<UnlockableEmote>();
			Dictionary<string, List<UnlockableEmote>> dictionary = new Dictionary<string, List<UnlockableEmote>>();
			for (int i = 0; i < Plugin.customAnimationClips.Count; i++)
			{
				AnimationClip val = Plugin.customAnimationClips[i];
				UnlockableEmote unlockableEmote = new UnlockableEmote
				{
					emoteId = i,
					emoteName = ((Object)val).name,
					displayName = "",
					animationClip = val,
					rarity = 0
				};
				unlockableEmote.rarity = (Plugin.animationClipsTier1.Contains(val) ? 1 : (Plugin.animationClipsTier2.Contains(val) ? 2 : (Plugin.animationClipsTier3.Contains(val) ? 3 : 0)));
				if (Plugin.complementaryAnimationClips.Contains(val))
				{
					unlockableEmote.complementary = true;
				}
				if (unlockableEmote.emoteName.Contains("_start") && !unlockableEmote.emoteName.Contains("_start_"))
				{
					string key = unlockableEmote.emoteName.Replace("_start", "_loop");
					AnimationClip val2 = Plugin.customAnimationClipsLoopDict[key];
					if ((Object)(object)val2 != (Object)null)
					{
						unlockableEmote.transitionsToClip = val2;
						unlockableEmote.emoteName = unlockableEmote.emoteName.Replace("_start", "");
						((Object)unlockableEmote.animationClip).name = unlockableEmote.emoteName + "_start";
						((Object)unlockableEmote.transitionsToClip).name = unlockableEmote.emoteName + "_loop";
					}
				}
				else if (unlockableEmote.emoteName.Contains("_pose"))
				{
					unlockableEmote.isPose = true;
					unlockableEmote.emoteName = unlockableEmote.emoteName.Replace("_pose", "");
					((Object)unlockableEmote.animationClip).name = unlockableEmote.emoteName;
				}
				if (unlockableEmote.emoteName.Contains("."))
				{
					string[] array = unlockableEmote.emoteName.Split(new char[1] { '.' });
					if (array.Length != 0 && array[0].Length > 0)
					{
						if (array.Length > 3)
						{
							CustomLogging.LogError("Error parsing emote name: " + unlockableEmote.emoteName + ". Correct format: \"emote_group.optional_arg.emote_name\"");
							continue;
						}
						unlockableEmote.emoteSyncGroupName = array[0];
						unlockableEmote.emoteName = unlockableEmote.emoteSyncGroupName + "." + array[^1];
						unlockableEmote.displayName = unlockableEmote.emoteSyncGroupName;
						if ((Object)(object)unlockableEmote.transitionsToClip == (Object)null)
						{
							((Object)unlockableEmote.animationClip).name = unlockableEmote.emoteName;
						}
						else
						{
							((Object)unlockableEmote.animationClip).name = unlockableEmote.emoteName + "_start";
							((Object)unlockableEmote.transitionsToClip).name = unlockableEmote.emoteName + "_loop";
						}
						if (!dictionary.TryGetValue(unlockableEmote.emoteSyncGroupName, out unlockableEmote.emoteSyncGroup))
						{
							unlockableEmote.emoteSyncGroup = new List<UnlockableEmote>();
							dictionary.Add(unlockableEmote.emoteSyncGroupName, unlockableEmote.emoteSyncGroup);
						}
						if (array.Length == 3 && array[1].ToLower().Contains("layer_"))
						{
							((Object)val).name = ((Object)val).name.Replace("." + array[1], "");
							if ((Object)(object)unlockableEmote.transitionsToClip != (Object)null)
							{
								((Object)unlockableEmote.transitionsToClip).name = ((Object)unlockableEmote.transitionsToClip).name.Replace("." + array[1], "");
							}
							if (!int.TryParse(array[1].Substring(6), out var result))
							{
								CustomLogging.LogError("Failed to parse emote layer number in arg: " + array[1] + ". Emote will not be added.");
								continue;
							}
							unlockableEmote.purchasable = result == 0;
							while (unlockableEmote.emoteSyncGroup.Count <= result)
							{
								unlockableEmote.emoteSyncGroup.Add(null);
							}
							unlockableEmote.emoteSyncGroup[result] = unlockableEmote;
						}
						else
						{
							unlockableEmote.emoteSyncGroup.Add(unlockableEmote);
							unlockableEmote.purchasable = unlockableEmote.emoteSyncGroup.Count == 1;
							if (array.Length == 3 && array[1].ToLower() == "random")
							{
								unlockableEmote.randomEmote = true;
								((Object)val).name = ((Object)val).name.Replace("." + array[1], "");
								if ((Object)(object)unlockableEmote.transitionsToClip != (Object)null)
								{
									((Object)unlockableEmote.transitionsToClip).name = ((Object)unlockableEmote.transitionsToClip).name.Replace("." + array[1], "");
								}
							}
						}
					}
				}
				if (unlockableEmote.emoteName.Contains("_start") && !unlockableEmote.emoteName.Contains("_start_"))
				{
					string key2 = unlockableEmote.emoteName.Replace("_start", "_loop");
					AnimationClip val3 = Plugin.customAnimationClipsLoopDict[key2];
					if ((Object)(object)val3 != (Object)null)
					{
						unlockableEmote.transitionsToClip = val3;
						unlockableEmote.emoteName = unlockableEmote.emoteName.Replace("_start", "");
						((Object)unlockableEmote.animationClip).name = unlockableEmote.emoteName + "_start";
						((Object)unlockableEmote.transitionsToClip).name = unlockableEmote.emoteName + "_loop";
					}
				}
				else if (unlockableEmote.emoteName.Contains("_pose"))
				{
					unlockableEmote.isPose = true;
					unlockableEmote.emoteName = unlockableEmote.emoteName.Replace("_pose", "");
					((Object)unlockableEmote.animationClip).name = unlockableEmote.emoteName;
				}
				if ((!((Object)(object)unlockableEmote.transitionsToClip != (Object)null) && !((Motion)unlockableEmote.animationClip).isLooping && !unlockableEmote.isPose && unlockableEmote.emoteSyncGroup == null) || true)
				{
					unlockableEmote.canSyncEmote = true;
				}
				if (unlockableEmote.displayName == "")
				{
					unlockableEmote.displayName = unlockableEmote.emoteName;
				}
				unlockableEmote.displayName = unlockableEmote.displayName.Replace('_', ' ').Trim(new char[1] { ' ' });
				unlockableEmote.displayName = char.ToUpper(unlockableEmote.displayName[0]) + unlockableEmote.displayName.Substring(1).ToLower();
				if (!allUnlockableEmotes.Contains(unlockableEmote))
				{
					allUnlockableEmotes.Add(unlockableEmote);
					allUnlockableEmotesDict.Add(unlockableEmote.emoteName, unlockableEmote);
				}
				if (Plugin.complementaryAnimationClips.Contains(val) && unlockableEmote.purchasable)
				{
					unlockableEmote.complementary = true;
					complementaryEmotesDefault.Add(unlockableEmote);
				}
			}
			allUnlockableEmotes = allUnlockableEmotes.OrderBy((UnlockableEmote item) => item.emoteName).ToList();
			int num = 0;
			foreach (UnlockableEmote allUnlockableEmote in allUnlockableEmotes)
			{
				allUnlockableEmote.emoteId = num++;
				if (!allUnlockableEmote.complementary)
				{
					if (allUnlockableEmote.rarity == 0)
					{
						allEmotesTier0.Add(allUnlockableEmote);
					}
					else if (allUnlockableEmote.rarity == 1)
					{
						allEmotesTier1.Add(allUnlockableEmote);
					}
					else if (allUnlockableEmote.rarity == 2)
					{
						allEmotesTier2.Add(allUnlockableEmote);
					}
					else if (allUnlockableEmote.rarity == 3)
					{
						allEmotesTier3.Add(allUnlockableEmote);
					}
				}
			}
			complementaryEmotes = new List<UnlockableEmote>(complementaryEmotesDefault);
			SaveManager.LoadFavoritedEmotes();
			SaveManager.LoadQuickEmotes();
		}
	}
	[HarmonyPatch]
	public static class SessionManager
	{
		public static List<UnlockableEmote> unlockedEmotes = new List<UnlockableEmote>();

		public static List<UnlockableEmote> unlockedEmotesTier0 = new List<UnlockableEmote>();

		public static List<UnlockableEmote> unlockedEmotesTier1 = new List<UnlockableEmote>();

		public static List<UnlockableEmote> unlockedEmotesTier2 = new List<UnlockableEmote>();

		public static List<UnlockableEmote> unlockedEmotesTier3 = new List<UnlockableEmote>();

		internal static List<UnlockableEmote> emotesUnlockedThisSession = new List<UnlockableEmote>();

		public static Dictionary<string, List<UnlockableEmote>> unlockedEmotesByPlayer = new Dictionary<string, List<UnlockableEmote>>();

		public static List<UnlockableEmote> unlockedFavoriteEmotes = new List<UnlockableEmote>();

		public static string localPlayerUsername => GameNetworkManager.Instance?.username;

		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPrefix]
		private static void ResetGameValues()
		{
			EmoteController.allEmoteControllers?.Clear();
			EmoteControllerPlayer.allPlayerEmoteControllers?.Clear();
			EmoteControllerMaskedEnemy.allMaskedEnemyEmoteControllers?.Clear();
			EmoteAudioSource.allEmoteAudioSources?.Clear();
			EmotesManager.complementaryEmotes = new List<UnlockableEmote>(EmotesManager.complementaryEmotesDefault);
		}

		[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
		[HarmonyPostfix]
		private static void OnHostConnected(PlayerControllerB __instance)
		{
			if (!HelperTools.isServer)
			{
				return;
			}
			if (!unlockedEmotesByPlayer.ContainsKey(HelperTools.localPlayerController.playerUsername))
			{
				unlockedEmotesByPlayer.Add(HelperTools.localPlayerController.playerUsername, unlockedEmotes);
				TerminalPatcher.currentEmoteCreditsByPlayer.Add(HelperTools.localPlayerController.playerUsername, TerminalPatcher.currentEmoteCredits);
				return;
			}
			foreach (UnlockableEmote item in unlockedEmotesByPlayer[HelperTools.localPlayerController.playerUsername])
			{
				if (!IsEmoteUnlocked(item))
				{
					unlockedEmotes.Add(item);
				}
			}
			unlockedEmotesByPlayer[HelperTools.localPlayerController.playerUsername] = unlockedEmotes;
			TerminalPatcher.currentEmoteCreditsByPlayer[HelperTools.localPlayerController.playerUsername] = TerminalPatcher.currentEmoteCredits;
		}

		[HarmonyPatch(typeof(StartOfRound), "Start")]
		[HarmonyPostfix]
		private static void OnServerStart(StartOfRound __instance)
		{
			if (HelperTools.isServer)
			{
			}
			SyncManager.RotateEmoteSelectionServer(TerminalPatcher.emoteStoreSeed);
		}

		[HarmonyPatch(typeof(StartOfRound), "StartGame")]
		[HarmonyPostfix]
		private static void ResetOverrideSeedFlag(StartOfRound __instance)
		{
			__instance.overrideRandomSeed = false;
		}

		[HarmonyPatch(typeof(StartOfRound), "ResetShip")]
		[HarmonyPostfix]
		private static void ResetEmotesOnShipReset(StartOfRound __instance)
		{
			if (!ConfigSync.instance.syncUnlockEverything)
			{
				ResetProgressLocal();
			}
			if (HelperTools.isServer)
			{
				SyncManager.RotateEmoteSelectionServer();
			}
		}

		public static void ResetProgressLocal(bool forceResetAll = false)
		{
			CustomLogging.Log("Resetting progress.");
			if (!ConfigSync.instance.syncPersistentUnlocks || forceResetAll)
			{
				ResetEmotesLocal();
			}
			if (!ConfigSync.instance.syncPersistentEmoteCredits || forceResetAll)
			{
				TerminalPatcher.currentEmoteCredits = ConfigSync.instance.syncStartingEmoteCredits;
				List<string> list = new List<string>(TerminalPatcher.currentEmoteCreditsByPlayer.Keys);
				foreach (string item in list)
				{
					TerminalPatcher.currentEmoteCreditsByPlayer[item] = ConfigSync.instance.syncStartingEmoteCredits;
				}
			}
			TerminalPatcher.emoteStoreSeed = 0;
		}

		[HarmonyPatch(typeof(StartOfRound), "SyncShipUnlockablesServerRpc")]
		[HarmonyPostfix]
		private static void SyncUnlockedEmotesWithClients(StartOfRound __instance)
		{
			if (!HelperTools.isServer || ConfigSync.instance.syncUnlockEverything || ConfigSync.instance.syncPersistentUnlocksGlobal)
			{
				return;
			}
			if (ConfigSync.instance.syncShareEverything)
			{
				CustomLogging.Log("Syncing unlocked emotes with clients.");
				SyncManager.SendOnUnlockEmoteUpdateMulti(TerminalPatcher.currentEmoteCredits);
				return;
			}
			HashSet<ulong> hashSet = new HashSet<ulong>();
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (val.actualClientId != 0L && val.playerSteamId != 0)
				{
					hashSet.Add(val.actualClientId);
				}
			}
			foreach (ulong item in hashSet)
			{
				SyncManager.ServerSendSyncToClient(item);
			}
		}

		public static bool IsEmoteUnlocked(string emoteName, string playerUsername = "")
		{
			if (EmotesManager.allUnlockableEmotesDict.TryGetValue(emoteName, out var value))
			{
				return IsEmoteUnlocked(value, playerUsername);
			}
			return false;
		}

		public static bool IsEmoteUnlocked(UnlockableEmote emote, string playerUsername = "")
		{
			if (emote == null)
			{
				return false;
			}
			List<UnlockableEmote> value = unlockedEmotes;
			if (playerUsername != "" && !unlockedEmotesByPlayer.TryGetValue(playerUsername, out value))
			{
				return false;
			}
			if (emote.emoteSyncGroup != null && emote.emoteSyncGroup.Count > 0)
			{
				foreach (UnlockableEmote item in emote.emoteSyncGroup)
				{
					if (value.Contains(item))
					{
						return true;
					}
				}
			}
			return value.Contains(emote);
		}

		public static List<UnlockableEmote> GetUnlockedEmotes(PlayerControllerB playerController)
		{
			return GetUnlockedEmotes(((Object)(object)playerController != (Object)null) ? playerController.playerUsername : "");
		}

		public static List<UnlockableEmote> GetUnlockedEmotes(string playerUsername)
		{
			if (unlockedEmotesByPlayer.TryGetValue(playerUsername, out var value))
			{
				return value;
			}
			return null;
		}

		public static void UnlockEmotesLocal(IEnumerable<UnlockableEmote> emotes, bool purchased = false, string playerUsername = "")
		{
			foreach (UnlockableEmote emote in emotes)
			{
				UnlockEmoteLocal(emote, purchased, playerUsername);
			}
		}

		public static void UnlockEmoteLocal(int emoteId, bool purchased = false, string playerUsername = "")
		{
			UnlockEmoteLocal((emoteId >= 0 && emoteId < EmotesManager.allUnlockableEmotes.Count) ? EmotesManager.allUnlockableEmotes[emoteId] : null, purchased, playerUsername);
		}

		public static void UnlockEmoteLocal(UnlockableEmote emote, bool purchased = false, string playerUsername = "")
		{
			if (emote == null || (emote.requiresHeldProp && ConfigSync.instance.syncRemoveGrabbableEmotesPartyPooperMode))
			{
				return;
			}
			List<UnlockableEmote> list = unlockedEmotes;
			if (playerUsername != "" && playerUsername != localPlayerUsername)
			{
				if (!unlockedEmotesByPlayer.TryGetValue(playerUsername, out var value) && !ConfigSync.instance.syncShareEverything)
				{
					return;
				}
				if (value != null)
				{
					list = value;
				}
			}
			if (IsEmoteUnlocked(emote, playerUsername))
			{
				return;
			}
			if (emote.emoteSyncGroup != null)
			{
				foreach (UnlockableEmote item in emote.emoteSyncGroup)
				{
					if (list.Contains(item))
					{
						return;
					}
				}
			}
			if (!list.Contains(emote))
			{
				list.Add(emote);
			}
			if (list != unlockedEmotes)
			{
				return;
			}
			if (!emote.complementary)
			{
				if (emote.rarity == 3 && !unlockedEmotesTier3.Contains(emote))
				{
					unlockedEmotesTier3.Add(emote);
				}
				else if (emote.rarity == 2 && !unlockedEmotesTier2.Contains(emote))
				{
					unlockedEmotesTier2.Add(emote);
				}
				else if (emote.rarity == 1 && !unlockedEmotesTier1.Contains(emote))
				{
					unlockedEmotesTier1.Add(emote);
				}
				else if (emote.rarity == 0 && !unlockedEmotesTier0.Contains(emote))
				{
					unlockedEmotesTier0.Add(emote);
				}
			}
			if (EmotesManager.allFavoriteEmotes.Contains(emote.emoteName) && !unlockedFavoriteEmotes.Contains(emote))
			{
				unlockedFavoriteEmotes.Add(emote);
			}
			if (ConfigSync.instance.syncPersistentUnlocksGlobal && purchased && !emotesUnlockedThisSession.Contains(emote))
			{
				emotesUnlockedThisSession.Add(emote);
			}
		}

		public static void RemoveEmoteLocal(UnlockableEmote emote)
		{
			unlockedEmotes.Remove(emote);
			unlockedEmotesTier0.Remove(emote);
			unlockedEmotesTier1.Remove(emote);
			unlockedEmotesTier2.Remove(emote);
			unlockedEmotesTier3.Remove(emote);
			unlockedFavoriteEmotes.Remove(emote);
			emotesUnlockedThisSession.Remove(emote);
			foreach (List<UnlockableEmote> value in unlockedEmotesByPlayer.Values)
			{
				value.Remove(emote);
			}
		}

		public static void ResetEmotesLocal()
		{
			CustomLogging.Log("Resetting unlocked emotes.");
			unlockedEmotes.Clear();
			unlockedEmotesTier0.Clear();
			unlockedEmotesTier1.Clear();
			unlockedEmotesTier2.Clear();
			unlockedEmotesTier3.Clear();
			emotesUnlockedThisSession.Clear();
			unlockedEmotesByPlayer.Clear();
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (val.playerSteamId != 0)
				{
					unlockedEmotesByPlayer.Add(val.playerUsername, ((Object)(object)val == (Object)(object)HelperTools.localPlayerController || ConfigSync.instance.syncShareEverything) ? unlockedEmotes : new List<UnlockableEmote>());
				}
			}
			UnlockEmotesLocal(ConfigSync.instance.syncUnlockEverything ? EmotesManager.allUnlockableEmotes : EmotesManager.complementaryEmotes);
			UpdateUnlockedFavoriteEmotes();
		}

		public static void UpdateUnlockedFavoriteEmotes()
		{
			unlockedFavoriteEmotes?.Clear();
			if (EmotesManager.allFavoriteEmotes == null || EmotesManager.allUnlockableEmotesDict == null || unlockedFavoriteEmotes == null)
			{
				return;
			}
			foreach (string allFavoriteEmote in EmotesManager.allFavoriteEmotes)
			{
				if (EmotesManager.allUnlockableEmotesDict.TryGetValue(allFavoriteEmote, out var value))
				{
					if (value.emoteSyncGroup != null && value.emoteSyncGroup.Count > 0)
					{
						value = value.emoteSyncGroup[0];
					}
					if (IsEmoteUnlocked(value))
					{
						unlockedFavoriteEmotes.Add(value);
					}
				}
			}
		}
	}
	public class UnlockableEmote
	{
		public int emoteId;

		public string emoteName;

		public string displayName = "";

		public AnimationClip animationClip;

		public AnimationClip transitionsToClip = null;

		public bool purchasable = true;

		public bool requiresHeldProp = false;

		public GameObject requiredHeldPropPrefab = null;

		public bool complementary = false;

		public bool isPose = false;

		public bool canMoveWhileEmoting = false;

		private bool _isBoomboxAudio = true;

		public string overrideAudioClipName = "";

		public string overrideAudioLoopClipName = "";

		public string emoteSyncGroupName = "";

		public List<UnlockableEmote> emoteSyncGroup;

		public float recordSongLoopValue = 0f;

		public bool randomEmote = false;

		public List<string> propNamesInEmote;

		public bool canSyncEmote = false;

		public int rarity = 0;

		public static string[] rarityColorCodes = new string[4]
		{
			ConfigSettings.emoteNameColorTier0.Value,
			ConfigSettings.emoteNameColorTier1.Value,
			ConfigSettings.emoteNameColorTier2.Value,
			ConfigSettings.emoteNameColorTier3.Value
		};

		public string displayNameColorCoded => $"<color={nameColor}>{displayName}</color>";

		public bool humanoidAnimation => ((Motion)animationClip).isHumanMotion;

		public bool loopable => ((Motion)animationClip).isLooping || ((Object)(object)transitionsToClip != (Object)null && ((Motion)transitionsToClip).isLooping);

		public bool hasAudio => audioClipName != "" || audioLoopClipName != "";

		public bool isBoomboxAudio
		{
			get
			{
				return _isBoomboxAudio && !ConfigSettings.disableBoomboxRequirement.Value;
			}
			set
			{
				_isBoomboxAudio = value;
			}
		}

		public string audioClipName => ((Object)(object)animationClip != (Object)null && AudioManager.AudioExists(((Object)animationClip).name)) ? ((Object)animationClip).name : ((overrideAudioClipName != "" && AudioManager.AudioExists(overrideAudioClipName)) ? overrideAudioClipName : "");

		public string audioLoopClipName => ((Object)(object)transitionsToClip != (Object)null && AudioManager.AudioExists(((Object)transitionsToClip).name)) ? ((Object)transitionsToClip).name : ((overrideAudioLoopClipName != "" && AudioManager.AudioExists(overrideAudioLoopClipName)) ? overrideAudioLoopClipName : "");

		public bool inEmoteSyncGroup => emoteSyncGroup != null && !randomEmote;

		public bool favorite => EmotesManager.allFavoriteEmotes.Contains(emoteName);

		public string rarityText
		{
			get
			{
				if (rarity == 0)
				{
					return "Common";
				}
				if (rarity == 1)
				{
					return "Rare";
				}
				if (rarity == 2)
				{
					return "Epic";
				}
				if (rarity == 3)
				{
					return "Legendary";
				}
				return "Invalid";
			}
		}

		public int price
		{
			get
			{
				int num = -1;
				if (complementary)
				{
					num = 0;
				}
				else if (rarity == 0)
				{
					num = ConfigSync.instance.syncBasePriceEmoteTier0;
				}
				else if (rarity == 1)
				{
					num = ConfigSync.instance.syncBasePriceEmoteTier1;
				}
				else if (rarity == 2)
				{
					num = ConfigSync.instance.syncBasePriceEmoteTier2;
				}
				else if (rarity == 3)
				{
					num = ConfigSync.instance.syncBasePriceEmoteTier3;
				}
				return (int)Mathf.Max((float)num * ConfigSync.instance.syncPriceMultiplierEmotesStore, 0f);
			}
		}

		public string nameColor => rarityColorCodes[rarity];

		public bool IsEmoteInEmoteGroup(UnlockableEmote emote)
		{
			return this == emote || (emoteSyncGroup != null && emoteSyncGroup.Contains(emote));
		}

		public bool ClipIsInEmote(AnimationClip clip)
		{
			if ((Object)(object)clip == (Object)null)
			{
				return false;
			}
			if ((Object)(object)clip == (Object)(object)animationClip || (Object)(object)clip == (Object)(object)transitionsToClip)
			{
				return true;
			}
			if (emoteSyncGroup != null)
			{
				foreach (UnlockableEmote item in emoteSyncGroup)
				{
					if ((Object)(object)clip == (Object)(object)item.animationClip || (Object)(object)clip == (Object)(object)item.transitionsToClip)
					{
						return true;
					}
				}
			}
			return false;
		}

		public AudioClip LoadAudioClip()
		{
			if (hasAudio && audioClipName.Length > 0)
			{
				return AudioManager.LoadAudioClip(audioClipName);
			}
			return null;
		}

		public AudioClip LoadAudioLoopClip()
		{
			if (hasAudio && (Object)(object)transitionsToClip != (Object)null && audioLoopClipName.Length > 0)
			{
				return AudioManager.LoadAudioClip(audioLoopClipName);
			}
			return null;
		}
	}
	[HarmonyPatch]
	public static class SaveManager
	{
		public static string TooManyEmotesSaveFileName = "TooManyEmotes_LocalSaveData";

		private static List<string> globallyUnlockedEmoteNames = new List<string>();

		[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
		[HarmonyPrefix]
		private static void CheckIfShouldResetLocalSettings()
		{
			if (ConfigSettings.resetGloballyUnlockedEmotes)
			{
				ResetGloballyUnlockedEmotes();
			}
			if (ConfigSettings.resetFavoriteEmotes)
			{
				ResetFavoritedEmotes();
				ResetQuickEmotes();
			}
			ConfigSettings.resetGloballyUnlockedEmotes = false;
			ConfigSettings.resetFavoriteEmotes = false;
		}

		[HarmonyPatch(typeof(GameNetworkManager), "SaveGameValues")]
		[HarmonyPostfix]
		private static void SaveUnlockedEmotes(GameNetworkManager __instance)
		{
			if (!__instance.isHostingGame || !StartOfRound.Instance.inShipPhase)
			{
				return;
			}
			CustomLogging.Log("Saving game values.");
			try
			{
				HashSet<string> hashSet;
				try
				{
					hashSet = new HashSet<string>(ES3.Load<string[]>("TooManyEmotes.UnlockedEmotes.PlayersList", HelperTools.currentSaveFileName, new string[0]));
				}
				catch (Exception ex)
				{
					CustomLogging.LogErrorVerbose("Error loading previous users list. Deleting key: TooManyEmotes.UnlockedEmotes.PlayersList from file: " + HelperTools.currentSaveFileName);
					CustomLogging.LogErrorVerbose(ex.ToString());
					ES3.DeleteKey("TooManyEmotes.UnlockedEmotes.PlayersList", HelperTools.currentSaveFileName);
					hashSet = new HashSet<string>();
				}
				foreach (string key in SessionManager.unlockedEmotesByPlayer.Keys)
				{
					hashSet.Add(key);
				}
				ES3.Save<string[]>("TooManyEmotes.UnlockedEmotes.PlayersList", hashSet.ToArray(), HelperTools.currentSaveFileName);
				foreach (string item in hashSet)
				{
					if (!ConfigSync.instance.syncPersistentUnlocksGlobal)
					{
						if (!SessionManager.unlockedEmotesByPlayer.ContainsKey(item))
						{
							continue;
						}
						if (SessionManager.unlockedEmotesByPlayer.TryGetValue(item, out var value))
						{
							CustomLogging.Log("Saving " + value.Count + " unlocked emotes for player: " + item);
							string[] array = new string[value.Count];
							for (int i = 0; i < value.Count; i++)
							{
								array[i] = value[i].emoteName;
							}
							if (value == SessionManager.unlockedEmotes)
							{
								ES3.Save<string[]>("TooManyEmotes.UnlockedEmotes", array, HelperTools.currentSaveFileName);
							}
							else
							{
								ES3.Save<string[]>("TooManyEmotes.UnlockedEmotes.Player_" + item, array, HelperTools.currentSaveFileName);
							}
						}
					}
					if (TerminalPatcher.currentEmoteCreditsByPlayer.ContainsKey(item))
					{
						CustomLogging.Log("Saving " + TerminalPatcher.currentEmoteCreditsByPlayer[item] + " emote credits for player: " + item);
						string text = "TooManyEmotes.CurrentEmoteCredits" + (ConfigSync.instance.syncPersistentUnlocks ? ".Persistent" : "");
						if ((Object)(object)HelperTools.localPlayerController != (Object)null && HelperTools.localPlayerController.playerSteamId != 0L && item == HelperTools.localPlayerController.playerUsername)
						{
							ES3.Save<int>(text, TerminalPatcher.currentEmoteCredits, __instance.currentSaveFileName);
						}
						else
						{
							ES3.Save<int>(text + ".Player_" + item, TerminalPatcher.currentEmoteCreditsByPlayer[item], __instance.currentSaveFileName);
						}
					}
				}
				ES3.Save<int>("TooManyEmotes.EmoteStoreSeed", TerminalPatcher.emoteStoreSeed, __instance.currentSaveFileName);
				CustomLogging.Log("Saved Seed: " + TerminalPatcher.emoteStoreSeed);
			}
			catch (Exception ex2)
			{
				CustomLogging.LogError("Error while trying to save TooManyEmotes values when disconnecting as host.");
				CustomLogging.LogError(ex2.ToString());
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "LoadUnlockables")]
		[HarmonyPostfix]
		private static void LoadUnlockedEmotes(StartOfRound __instance)
		{
			if (!GameNetworkManager.Instance.isHostingGame)
			{
				return;
			}
			CustomLogging.Log("Loading game values.");
			try
			{
				if (!ConfigSync.instance.syncPersistentUnlocksGlobal)
				{
					SessionManager.ResetEmotesLocal();
					string[] array = ES3.Load<string[]>("TooManyEmotes.UnlockedEmotes", HelperTools.currentSaveFileName, new string[0]);
					string[] array2 = array;
					foreach (string key in array2)
					{
						if (EmotesManager.allUnlockableEmotesDict.TryGetValue(key, out var value))
						{
							SessionManager.UnlockEmoteLocal(value);
						}
					}
				}
				string text = "TooManyEmotes.CurrentEmoteCredits" + (ConfigSync.instance.syncPersistentUnlocks ? ".Persistent" : "");
				TerminalPatcher.currentEmoteCredits = ES3.Load<int>(text, HelperTools.currentSaveFileName, ConfigSync.instance.syncStartingEmoteCredits);
				string[] array3 = ES3.Load<string[]>("TooManyEmotes.UnlockedEmotes.PlayersList", HelperTools.currentSaveFileName, new string[0]);
				string[] array4 = array3;
				foreach (string text2 in array4)
				{
					if ((Object)(object)HelperTools.localPlayerController != (Object)null && HelperTools.localPlayerController.playerSteamId != 0L && text2 == HelperTools.localPlayerController.playerUsername)
					{
						continue;
					}
					if (!SessionManager.unlockedEmotesByPlayer.ContainsKey(text2))
					{
						S

plugins/TooManySuits.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LobbyCompatibility.Enums;
using LobbyCompatibility.Features;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
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("TooManySuits")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.0.1.0")]
[assembly: AssemblyInformationalVersion("2.0.1+85b6d88f27a7a790ab993a3962618a1602891367")]
[assembly: AssemblyProduct("TooManySuits")]
[assembly: AssemblyTitle("TooManySuits")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.1.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.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;
		}
	}
	[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 TooManySuits
{
	internal class AssetManager
	{
		public TMP_FontAsset VGA437Font { get; private set; }

		public AssetManager()
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			using Stream stream = executingAssembly.GetManifestResourceStream("TooManySuits.AssetBundle") ?? throw new InvalidOperationException("Failed to load AssetBundle");
			AssetBundle val = AssetBundle.LoadFromStream(stream);
			VGA437Font = val.LoadAsset<TMP_FontAsset>("Perfect DOS VGA 437 SDF") ?? throw new InvalidOperationException("Failed to load font 'Perfect DOS VGA 437 SDF' from AssetBundle");
		}
	}
	internal class Config
	{
		private readonly ConfigEntry<float> _configLabelScale;

		private readonly ConfigEntry<int> _configSuitsPerPage;

		public float LabelScale => _configLabelScale.Value;

		public int SuitsPerPage => _configSuitsPerPage.Value;

		public Config(ConfigFile cfg)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			_configSuitsPerPage = cfg.Bind<int>("Pagination", "SuitsPerPage", 13, new ConfigDescription("Number of suits per page in the suit rack.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(13, 20), Array.Empty<object>()));
			_configLabelScale = cfg.Bind<float>("UI", "LabelScale", 1f, new ConfigDescription("Size of the text above the suit rack.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>()));
			cfg.OrphanedEntries.Clear();
			cfg.Save();
		}
	}
	internal static class LobbyCompatibility
	{
		public static void Init()
		{
			TooManySuits.Logger.LogInfo((object)"Registering plugin with LobbyCompatibility.");
			Version version = Version.Parse("2.0.1");
			PluginHelper.RegisterPlugin("TooManySuits", version, (CompatibilityLevel)0, (VersionStrictness)0);
		}
	}
	public class PaginationController : MonoBehaviour
	{
		private UnlockableSuit[] _allSuits;

		private TextMeshPro _pageTextMesh;

		private GameObject _pageGO;

		private GameObject _previousGO;

		private GameObject _nextGO;

		private bool _shouldUpdate;

		public int SuitsPerPage { get; set; }

		private int CurrentPage { get; set; }

		private int PageCount { get; set; }

		private static Sprite FindInteractIcon()
		{
			Terminal val = Object.FindObjectOfType<Terminal>() ?? throw new InvalidOperationException("Can't find Terminal object");
			InteractTrigger val2 = ((Component)val).GetComponent<InteractTrigger>() ?? throw new InvalidOperationException("Can't find InteractTrigger component from Terminal object");
			return val2.hoverIcon;
		}

		private void Awake()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			//IL_00ea: 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_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Expected O, but got Unknown
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Expected O, but got Unknown
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			if (SuitsPerPage <= 0)
			{
				throw new InvalidOperationException("SuitsPerPage must be >= 0");
			}
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(10f, 10f);
			_pageGO = new GameObject("page");
			_pageGO.transform.SetParent(((Component)this).transform, false);
			_pageTextMesh = CreateTMP(_pageGO, "Page");
			_previousGO = new GameObject("previousButton");
			RectTransform val2 = _previousGO.AddComponent<RectTransform>();
			((Transform)val2).SetParent(((Component)this).transform, false);
			val2.anchorMax = new Vector2(0f, 0.5f);
			val2.anchorMin = new Vector2(0f, 0.5f);
			CreateTMP(_previousGO, "<");
			GameObject val3 = new GameObject("trigger");
			RectTransform val4 = val3.AddComponent<RectTransform>();
			((Transform)val4).SetParent((Transform)(object)val2, false);
			BoxCollider val5 = val3.AddComponent<BoxCollider>();
			val5.size = Vector2.op_Implicit(val);
			InteractTrigger val6 = CreateInteractTrigger(val3);
			((UnityEvent<PlayerControllerB>)(object)val6.onInteract).AddListener((UnityAction<PlayerControllerB>)delegate
			{
				PreviousPage();
			});
			_nextGO = new GameObject("nextButton");
			RectTransform val7 = _nextGO.AddComponent<RectTransform>();
			((Transform)val7).SetParent(((Component)this).transform, false);
			val7.anchorMax = new Vector2(1f, 0.5f);
			val7.anchorMin = new Vector2(1f, 0.5f);
			CreateTMP(_nextGO, ">");
			GameObject val8 = new GameObject("trigger");
			RectTransform val9 = val8.AddComponent<RectTransform>();
			((Transform)val9).SetParent((Transform)(object)val7, false);
			BoxCollider val10 = val8.AddComponent<BoxCollider>();
			val10.size = Vector2.op_Implicit(val);
			InteractTrigger val11 = CreateInteractTrigger(val8);
			((UnityEvent<PlayerControllerB>)(object)val11.onInteract).AddListener((UnityAction<PlayerControllerB>)delegate
			{
				NextPage();
			});
			static InteractTrigger CreateInteractTrigger(GameObject go)
			{
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: Expected O, but got Unknown
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0064: Expected O, but got Unknown
				//IL_0065: Unknown result type (might be due to invalid IL or missing references)
				//IL_006f: Expected O, but got Unknown
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Expected O, but got Unknown
				//IL_007b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0085: Expected O, but got Unknown
				Sprite val12 = FindInteractIcon();
				InteractTrigger val13 = go.AddComponent<InteractTrigger>();
				((Component)val13).gameObject.tag = "InteractTrigger";
				((Component)val13).gameObject.layer = LayerMask.NameToLayer("InteractableObject");
				val13.interactable = true;
				val13.oneHandedItemAllowed = true;
				val13.holdInteraction = false;
				val13.interactCooldown = false;
				val13.onInteract = new InteractEvent();
				val13.onInteractEarly = new InteractEvent();
				val13.onCancelAnimation = new InteractEvent();
				val13.onStopInteract = new InteractEvent();
				val13.holdingInteractEvent = new InteractEventFloat();
				val13.hoverTip = "";
				val13.disabledHoverTip = "";
				val13.hoverIcon = val12;
				val13.disabledHoverIcon = val12;
				return val13;
			}
			static TextMeshPro CreateTMP(GameObject go, string text)
			{
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0074: Unknown result type (might be due to invalid IL or missing references)
				TextMeshPro val14 = go.AddComponent<TextMeshPro>();
				((TMP_Text)val14).autoSizeTextContainer = true;
				((TMP_Text)val14).enableWordWrapping = false;
				((TMP_Text)val14).alignment = (TextAlignmentOptions)514;
				((TMP_Text)val14).text = text;
				((TMP_Text)val14).font = TooManySuits.AssetManager.VGA437Font;
				((TMP_Text)val14).fontMaterial = ((TMP_Asset)TooManySuits.AssetManager.VGA437Font).material;
				((Graphic)val14).color = new Color(255f, 255f, 255f, 255f);
				((TMP_Text)val14).outlineColor = new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue);
				((TMP_Text)val14).outlineWidth = 0.25f;
				return val14;
			}
		}

		private void Start()
		{
			TooManySuits.SuitManager.SuitsUpdated += OnSuitsUpdated;
			UpdateSuits();
		}

		private void Update()
		{
			if (_shouldUpdate)
			{
				_shouldUpdate = false;
				UpdateSuits();
			}
		}

		private void OnDestroy()
		{
			TooManySuits.SuitManager.SuitsUpdated -= OnSuitsUpdated;
		}

		private void OnSuitsUpdated()
		{
			_shouldUpdate = true;
		}

		private void UpdateSuits()
		{
			_allSuits = TooManySuits.SuitManager.GetUnlockedSuits().ToArray();
			PageCount = Mathf.CeilToInt((float)_allSuits.Length / (float)SuitsPerPage);
			if (CurrentPage > PageCount - 1)
			{
				CurrentPage = PageCount - 1;
			}
			DisplayCurrentPage();
		}

		private void NextPage()
		{
			if (CurrentPage < PageCount - 1)
			{
				CurrentPage++;
				DisplayCurrentPage();
			}
		}

		private void PreviousPage()
		{
			if (CurrentPage > 0)
			{
				CurrentPage--;
				DisplayCurrentPage();
			}
		}

		private void DisplayCurrentPage()
		{
			//IL_0143: 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_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			int num = CurrentPage * SuitsPerPage;
			int num2 = Mathf.Min(num + SuitsPerPage, _allSuits.Length);
			float num3 = 0.18f;
			if (TooManySuits.Config.SuitsPerPage > 13 && _allSuits.Length > 13)
			{
				num3 /= (float)Mathf.Min(_allSuits.Length, TooManySuits.Config.SuitsPerPage) / 12f;
			}
			int num4 = 0;
			for (int i = 0; i < _allSuits.Length; i++)
			{
				UnlockableSuit val = _allSuits[i];
				AutoParentToShip component = ((Component)val).gameObject.GetComponent<AutoParentToShip>();
				if (!((Object)(object)component == (Object)null))
				{
					bool flag = i >= num && i < num2;
					Renderer[] componentsInChildren = ((Component)val).gameObject.GetComponentsInChildren<Renderer>();
					foreach (Renderer val2 in componentsInChildren)
					{
						val2.enabled = flag;
					}
					Collider[] componentsInChildren2 = ((Component)val).gameObject.GetComponentsInChildren<Collider>();
					foreach (Collider val3 in componentsInChildren2)
					{
						val3.enabled = flag;
					}
					InteractTrigger component2 = ((Component)val).gameObject.GetComponent<InteractTrigger>();
					((Behaviour)component2).enabled = flag;
					component2.interactable = flag;
					if (flag)
					{
						component.overrideOffset = true;
						component.positionOffset = new Vector3(-2.45f, 2.75f, -8.41f) + StartOfRound.Instance.rightmostSuitPosition.forward * (num3 * (float)num4);
						component.rotationOffset = new Vector3(0f, 90f, 0f);
						num4++;
					}
				}
			}
			((MonoBehaviour)this).StartCoroutine(UpdateLabel());
		}

		private IEnumerator UpdateLabel()
		{
			((TMP_Text)_pageTextMesh).text = $"<b>{CurrentPage + 1}/{PageCount}</b>";
			yield return null;
			TMP_CharacterInfo[] characterInfo = ((TMP_Text)_pageTextMesh).textInfo.characterInfo;
			int characterCount = ((TMP_Text)_pageTextMesh).textInfo.characterCount;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(2f, 0f, 0f);
			Vector3 val2 = new Vector3(0f, 1f, 0f) * ((TMP_Text)_pageTextMesh).outlineWidth;
			_previousGO.transform.localPosition = characterInfo[0].topLeft - val2 * 2f - val + new Vector3(0f, characterInfo[0].baseLine, 0f);
			_nextGO.transform.localPosition = characterInfo[characterCount - 1].topRight - val2 * 2f + val + new Vector3(0f, characterInfo[characterCount - 1].baseLine, 0f);
			_previousGO.SetActive(PageCount > 0 && CurrentPage > 0);
			_nextGO.SetActive(PageCount > 0 && CurrentPage < PageCount - 1);
			_pageGO.SetActive(PageCount > 0);
		}
	}
	[HarmonyPatch]
	internal class Patches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartOfRound), "Start")]
		[HarmonyPriority(600)]
		[HarmonyAfter(new string[] { "x753.More_Suits" })]
		private static void StartPatch()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_002b: 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)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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)
			GameObject val = new GameObject("TooManySuitsPageLabel");
			val.SetActive(false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			((Transform)val2).SetParent(StartOfRound.Instance.rightmostSuitPosition, false);
			((Transform)val2).localPosition = Vector3.zero;
			((Transform)val2).localEulerAngles = Vector3.zero;
			((Transform)val2).localScale = Vector3.one * TooManySuits.Config.LabelScale * 0.05f;
			PaginationController paginationController = val.AddComponent<PaginationController>();
			paginationController.SuitsPerPage = TooManySuits.Config.SuitsPerPage;
			Vector3 val3 = StartOfRound.Instance.rightmostSuitPosition.forward * 2.0700002f / 2f;
			AutoParentToShip val4 = val.AddComponent<AutoParentToShip>();
			val4.overrideOffset = true;
			val4.positionOffset = new Vector3(-2.45f, 3f, -8.41f) + val3;
			val4.rotationOffset = new Vector3(0f, 180f, 0f);
			val.SetActive(true);
			TooManySuits.SuitManager.UpdateSuits();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartOfRound), "PositionSuitsOnRack")]
		[HarmonyPriority(600)]
		[HarmonyAfter(new string[] { "x753.More_Suits" })]
		private static void PositionSuitsOnRackPatch()
		{
			TooManySuits.SuitManager.UpdateSuits();
		}
	}
	internal class SuitManager
	{
		public event Action? SuitsUpdated;

		public IEnumerable<UnlockableSuit> GetUnlockedSuits()
		{
			return from suit in Resources.FindObjectsOfTypeAll<UnlockableSuit>()
				orderby suit.syncedSuitID.Value
				where ((NetworkBehaviour)suit).IsSpawned
				select suit;
		}

		internal void UpdateSuits()
		{
			this.SuitsUpdated?.Invoke();
		}
	}
	[BepInPlugin("TooManySuits", "TooManySuits", "2.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class TooManySuits : BaseUnityPlugin
	{
		internal const string MoreSuitsGuid = "x753.More_Suits";

		internal const int VanillaSuitsPerPage = 13;

		internal const float SuitThickness = 0.18f;

		private static readonly Harmony Harmony = new Harmony("TooManySuits");

		internal static SuitManager SuitManager { get; } = new SuitManager();


		internal static AssetManager AssetManager { get; } = new AssetManager();


		internal static ManualLogSource Logger { get; private set; } = null;


		internal static Config Config { get; private set; } = null;


		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Config = new Config(((BaseUnityPlugin)this).Config);
			Harmony.PatchAll();
			if (Chainloader.PluginInfos.ContainsKey("BMX.LobbyCompatibility"))
			{
				LobbyCompatibility.Init();
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "TooManySuits";

		public const string PLUGIN_NAME = "TooManySuits";

		public const string PLUGIN_VERSION = "2.0.1";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		internal IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}

plugins/VoiceHUD.dll

Decompiled 2 months ago
using System;
using System.Diagnostics;
using System.IO;
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 Dissonance;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;
using VoiceHUD.Configuration;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("VoiceHUD")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Displays push-to-talk icon on voice activation")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+f1e0a0cfa0a629002418c9e0aa3a753676e33192")]
[assembly: AssemblyProduct("VoiceHUD")]
[assembly: AssemblyTitle("VoiceHUD")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.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 VoiceHUD
{
	[BepInPlugin("5Bit.VoiceHUD", "VoiceHUD", "1.0.4")]
	public class VoiceHUD : BaseUnityPlugin
	{
		private const string modGUID = "5Bit.VoiceHUD";

		private const string modName = "VoiceHUD";

		private const string modVersion = "1.0.4";

		private readonly Harmony harmony = new Harmony("5Bit.VoiceHUD");

		private static VoiceHUD Instance;

		internal static ManualLogSource mls;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			mls = Logger.CreateLogSource("5Bit.VoiceHUD");
			Config.Init();
			harmony.PatchAll();
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "VoiceHUD";

		public const string PLUGIN_NAME = "VoiceHUD";

		public const string PLUGIN_VERSION = "1.0.1";
	}
}
namespace VoiceHUD.Patches
{
	[HarmonyPatch(typeof(HUDManager))]
	internal class VoiceHUDPatch
	{
		private static Color Start = new Color(0f, 255f, 0f, 255f);

		private static Color Center = new Color(165f, 255f, 0f, 255f);

		private static Color End = new Color(255f, 0f, 0f, 255f);

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void Update()
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			if (!IngamePlayerSettings.Instance.settings.micEnabled || IngamePlayerSettings.Instance.settings.pushToTalk || (Object)(object)StartOfRound.Instance.voiceChatModule == (Object)null)
			{
				return;
			}
			VoicePlayerState val = StartOfRound.Instance.voiceChatModule.FindPlayer(StartOfRound.Instance.voiceChatModule.LocalPlayerName);
			if (val.IsSpeaking)
			{
				float num = Mathf.Clamp(val.Amplitude * 35f, 0f, 1f);
				if (Config.ColorsEnabled)
				{
					((Graphic)HUDManager.Instance.PTTIcon).color = GetColorByVolume(num * 100f);
				}
				((Behaviour)HUDManager.Instance.PTTIcon).enabled = num > 0.01f;
			}
		}

		public static Color GetColorByVolume(float volume)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (volume < 20f)
			{
				return Start;
			}
			if (volume > 70f)
			{
				return End;
			}
			return Center;
		}
	}
}
namespace VoiceHUD.Configuration
{
	internal static class Config
	{
		private const string CONFIG_FILE_NAME = "VoiceHUD.cfg";

		private static ConfigFile config;

		private static ConfigEntry<bool> colorsEnabled;

		public static bool ColorsEnabled => colorsEnabled.Value;

		public static void Init()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			string text = Path.Combine(Paths.ConfigPath, "VoiceHUD.cfg");
			config = new ConfigFile(text, true);
			colorsEnabled = config.Bind<bool>("Config", "Colors enabled", false, "Change icon color based on volume.");
		}
	}
}

plugins/YippeeMod.dll

Decompiled 2 months ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using YippeeMod.Patches;

[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("YippeeMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("YippeeMod")]
[assembly: AssemblyTitle("YippeeMod")]
[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 YippeeMod
{
	[BepInPlugin("sunnobunno.YippeeMod", "Yippee tbh mod", "1.2.4")]
	public class YippeeModBase : BaseUnityPlugin
	{
		private const string modGUID = "sunnobunno.YippeeMod";

		private const string modName = "Yippee tbh mod";

		private const string modVersion = "1.2.4";

		private readonly Harmony harmony = new Harmony("sunnobunno.YippeeMod");

		private static YippeeModBase? Instance;

		internal ManualLogSource? mls;

		internal static AudioClip[]? newSFX;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			mls = Logger.CreateLogSource("sunnobunno.YippeeMod");
			mls.LogInfo((object)"sunnobunno.YippeeMod is loading.");
			string location = ((BaseUnityPlugin)Instance).Info.Location;
			string text = "YippeeMod.dll";
			string text2 = location.TrimEnd(text.ToCharArray());
			string text3 = text2 + "yippeesound";
			AssetBundle val = AssetBundle.LoadFromFile(text3);
			if ((Object)(object)val == (Object)null)
			{
				mls.LogError((object)"Failed to load audio assets!");
				return;
			}
			newSFX = val.LoadAssetWithSubAssets<AudioClip>("assets/yippee-tbh.mp3");
			harmony.PatchAll(typeof(HoarderBugPatch));
			mls.LogInfo((object)"sunnobunno.YippeeMod is loaded. Yippee!!!");
		}
	}
}
namespace YippeeMod.Patches
{
	[HarmonyPatch(typeof(HoarderBugAI))]
	internal class HoarderBugPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		public static void hoarderBugAudioPatch(ref AudioClip[] ___chitterSFX)
		{
			AudioClip[] newSFX = YippeeModBase.newSFX;
			___chitterSFX = newSFX;
		}
	}
}