Decompiled source of ToilHead v1.7.2

com.github.zehsteam.ToilHead.dll

Decompiled 4 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 LethalLib.Modules;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using com.github.zehsteam.ToilHead.Compatibility;
using com.github.zehsteam.ToilHead.MonoBehaviours;
using com.github.zehsteam.ToilHead.MonoBehaviours.TurretHeads;
using com.github.zehsteam.ToilHead.NetcodePatcher;
using com.github.zehsteam.ToilHead.Patches;

[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("com.github.zehsteam.ToilHead")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("CoilHeads, Manticoils, and other entities can sometimes spawn with a turret on their head. Highly Configurable.")]
[assembly: AssemblyFileVersion("1.7.2.0")]
[assembly: AssemblyInformationalVersion("1.7.2+13ae783a09c02f93fd4ce1f29c4c3515ccdfa834")]
[assembly: AssemblyProduct("ToilHead")]
[assembly: AssemblyTitle("com.github.zehsteam.ToilHead")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.7.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
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 com.github.zehsteam.ToilHead
{
	public class Api
	{
		public static Dictionary<EnemyAI, TurretHeadControllerBehaviour> EnemyTurretHeadControllerPairs => TurretHeadManager.EnemyTurretHeadControllerPairs;

		public static Dictionary<PlayerControllerB, TurretHeadControllerBehaviour> PlayerTurretHeadControllerPairs => TurretHeadManager.PlayerTurretHeadControllerPairs;

		public static Dictionary<PlayerControllerB, TurretHeadControllerBehaviour> DeadBodyTurretHeadControllerPairs => TurretHeadManager.DeadBodyTurretHeadControllerPairs;

		public static TurretHeadData ToilHeadData => TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false);

		public static bool ForceToilHeadSpawns
		{
			get
			{
				return ToilHeadData.ForceSpawns;
			}
			set
			{
				ToilHeadData.ForceSpawns = value;
			}
		}

		public static int ForceToilHeadMaxSpawnCount
		{
			get
			{
				return ToilHeadData.ForceMaxSpawnCount;
			}
			set
			{
				ToilHeadData.ForceMaxSpawnCount = value;
			}
		}

		public static TurretHeadData MantiToilData => TurretHeadManager.GetEnemyTurretHeadData("Manticoil", isSlayer: false);

		public static bool ForceMantiToilSpawns
		{
			get
			{
				return MantiToilData.ForceSpawns;
			}
			set
			{
				MantiToilData.ForceSpawns = value;
			}
		}

		public static int ForceMantiToilMaxSpawnCount
		{
			get
			{
				return MantiToilData.ForceMaxSpawnCount;
			}
			set
			{
				MantiToilData.ForceMaxSpawnCount = value;
			}
		}

		public static TurretHeadData ToilSlayerData => TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: true);

		public static bool ForceToilSlayerSpawns
		{
			get
			{
				return ToilSlayerData.ForceSpawns;
			}
			set
			{
				ToilSlayerData.ForceSpawns = value;
			}
		}

		public static int ForceToilSlayerMaxSpawnCount
		{
			get
			{
				return ToilSlayerData.ForceMaxSpawnCount;
			}
			set
			{
				ToilSlayerData.ForceMaxSpawnCount = value;
			}
		}

		public static TurretHeadData MantiSlayerData => TurretHeadManager.GetEnemyTurretHeadData("Manticoil", isSlayer: true);

		public static bool ForceMantiSlayerSpawns
		{
			get
			{
				return MantiSlayerData.ForceSpawns;
			}
			set
			{
				MantiSlayerData.ForceSpawns = value;
			}
		}

		public static int ForceMantiSlayerMaxSpawnCount
		{
			get
			{
				return MantiSlayerData.ForceMaxSpawnCount;
			}
			set
			{
				MantiSlayerData.ForceMaxSpawnCount = value;
			}
		}

		public static TurretHeadData ToilPlayerData => TurretHeadManager.PlayerTurretHeadData;

		public static bool ForceToilPlayerSpawns
		{
			get
			{
				return ToilPlayerData.ForceSpawns;
			}
			set
			{
				ToilPlayerData.ForceSpawns = value;
			}
		}

		public static int ForceToilPlayerMaxSpawnCount
		{
			get
			{
				return ToilPlayerData.ForceMaxSpawnCount;
			}
			set
			{
				ToilPlayerData.ForceMaxSpawnCount = value;
			}
		}

		public static TurretHeadData ToilMaskedData => TurretHeadManager.GetEnemyTurretHeadData("Masked", isSlayer: false);

		public static bool ForceToilMaskedSpawns
		{
			get
			{
				return ToilMaskedData.ForceSpawns;
			}
			set
			{
				ToilMaskedData.ForceSpawns = value;
			}
		}

		public static int ForceToilMaskedMaxSpawnCount
		{
			get
			{
				return ToilMaskedData.ForceMaxSpawnCount;
			}
			set
			{
				ToilMaskedData.ForceMaxSpawnCount = value;
			}
		}

		public static TurretHeadData SlayerMaskedData => TurretHeadManager.GetEnemyTurretHeadData("Masked", isSlayer: true);

		public static bool ForceSlayerMaskedSpawns
		{
			get
			{
				return SlayerMaskedData.ForceSpawns;
			}
			set
			{
				SlayerMaskedData.ForceSpawns = value;
			}
		}

		public static int ForceSlayerMaskedMaxSpawnCount
		{
			get
			{
				return SlayerMaskedData.ForceMaxSpawnCount;
			}
			set
			{
				SlayerMaskedData.ForceMaxSpawnCount = value;
			}
		}

		[Obsolete("EnemyTurretPairs is deprecated, please use EnemyTurretHeadControllerPairs instead.", true)]
		public static Dictionary<EnemyAI, ToilHeadTurretBehaviour> EnemyTurretPairs => new Dictionary<EnemyAI, ToilHeadTurretBehaviour>();

		[Obsolete("PlayerTurretPairs is deprecated, please use PlayerTurretHeadControllerPairs instead.", true)]
		public static Dictionary<PlayerControllerB, ToilHeadTurretBehaviour> PlayerTurretPairs => new Dictionary<PlayerControllerB, ToilHeadTurretBehaviour>();

		[Obsolete("enemyTurretPairs is deprecated, please use EnemyTurretHeadControllerPairs instead.", true)]
		public static Dictionary<NetworkObject, NetworkObject> enemyTurretPairs => new Dictionary<NetworkObject, NetworkObject>();

		[Obsolete("MaxSpawnCount is deprecated, please use ToilHeadMaxSpawnCount instead.", true)]
		public static int MaxSpawnCount => TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false).GetSpawnDataForCurrentMoon().MaxSpawnCount;

		[Obsolete("SpawnChance is deprecated, please use ToilHeadSpawnChance instead.", true)]
		public static float SpawnChance => TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false).GetSpawnDataForCurrentMoon().SpawnChance;

		[Obsolete("spawnCount is deprecated, please use ToilHeadSpawnCount instead.", true)]
		public static int spawnCount => TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false).SpawnCount;

		[Obsolete("forceSpawns is deprecated, please use ForceToilHeadSpawns instead.", true)]
		public static bool forceSpawns
		{
			get
			{
				return TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false).ForceSpawns;
			}
			set
			{
				TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false).ForceSpawns = value;
			}
		}

		[Obsolete("forceMaxSpawnCount is deprecated, please use ForceToilHeadMaxSpawnCount instead.", true)]
		public static int forceMaxSpawnCount
		{
			get
			{
				return TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false).ForceMaxSpawnCount;
			}
			set
			{
				TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false).ForceMaxSpawnCount = value;
			}
		}

		[Obsolete("mantiToilSpawnCount is deprecated, please use MantiToilSpawnCount instead.", true)]
		public static int mantiToilSpawnCount => TurretHeadManager.GetEnemyTurretHeadData("Manticoil", isSlayer: false).SpawnCount;

		[Obsolete("forceMantiToilSpawns is deprecated, please use ForceMantiToilSpawns instead.", true)]
		public static bool forceMantiToilSpawns
		{
			get
			{
				return TurretHeadManager.GetEnemyTurretHeadData("Manticoil", isSlayer: false).ForceSpawns;
			}
			set
			{
				TurretHeadManager.GetEnemyTurretHeadData("Manticoil", isSlayer: false).ForceSpawns = value;
			}
		}

		[Obsolete("forceMantiToilMaxSpawnCount is deprecated, please use ForceMantiToilMaxSpawnCount instead.", true)]
		public static int forceMantiToilMaxSpawnCount
		{
			get
			{
				return TurretHeadManager.GetEnemyTurretHeadData("Manticoil", isSlayer: false).ForceMaxSpawnCount;
			}
			set
			{
				TurretHeadManager.GetEnemyTurretHeadData("Manticoil", isSlayer: false).ForceMaxSpawnCount = value;
			}
		}

		[Obsolete("toilSlayerSpawnCount is deprecated, please use ToilSlayerSpawnCount instead.", true)]
		public static int toilSlayerSpawnCount => TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: true).SpawnCount;

		[Obsolete("forceToilSlayerSpawns is deprecated, please use ForceToilSlayerSpawns instead.", true)]
		public static bool forceToilSlayerSpawns
		{
			get
			{
				return TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: true).ForceSpawns;
			}
			set
			{
				TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: true).ForceSpawns = value;
			}
		}

		[Obsolete("forceToilSlayerMaxSpawnCount is deprecated, please use ForceToilSlayerMaxSpawnCount instead.", true)]
		public static int forceToilSlayerMaxSpawnCount
		{
			get
			{
				return TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: true).ForceMaxSpawnCount;
			}
			set
			{
				TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: true).ForceMaxSpawnCount = value;
			}
		}

		public static bool SetToilHeadOnServer(EnemyAI enemyScript)
		{
			return TurretHeadManager.SetEnemyTurretHeadOnServer(enemyScript, isSlayer: false);
		}

		public static bool SetMantiToilOnServer(EnemyAI enemyScript)
		{
			return TurretHeadManager.SetEnemyTurretHeadOnServer(enemyScript, isSlayer: false);
		}

		public static bool SetToilSlayerOnServer(EnemyAI enemyScript)
		{
			return TurretHeadManager.SetEnemyTurretHeadOnServer(enemyScript, isSlayer: true);
		}

		public static bool SetMantiSlayerOnServer(EnemyAI enemyScript)
		{
			return TurretHeadManager.SetEnemyTurretHeadOnServer(enemyScript, isSlayer: true);
		}

		public static bool SetToilPlayerOnServer(PlayerControllerB playerScript, bool isSlayer = false)
		{
			return TurretHeadManager.SetPlayerTurretHeadOnServer(playerScript, isSlayer);
		}

		public static bool SetToilMaskedOnServer(EnemyAI enemyScript)
		{
			return TurretHeadManager.SetEnemyTurretHeadOnServer(enemyScript, isSlayer: false);
		}

		public static bool SetSlayerMaskedOnServer(EnemyAI enemyScript)
		{
			return TurretHeadManager.SetEnemyTurretHeadOnServer(enemyScript, isSlayer: true);
		}
	}
	internal class Content
	{
		public static GameObject NetworkHandlerPrefab;

		public static GameObject TurretPropPrefab;

		public static GameObject MinigunPropPrefab;

		public static GameObject ToilPlayerControllerPrefab;

		public static GameObject SlayerPlayerControllerPrefab;

		public static GameObject ToiledDeadBodyControllerPrefab;

		public static GameObject SlayedDeadBodyControllerPrefab;

		public static GameObject ToilHeadControllerPrefab;

		public static GameObject ToilSlayerControllerPrefab;

		public static GameObject MantiToilControllerPrefab;

		public static GameObject MantiSlayerControllerPrefab;

		public static GameObject ToilMaskedControllerPrefab;

		public static GameObject SlayerMaskedControllerPrefab;

		public static Item ToilHeadPlush;

		public static Item ToilSlayerPlush;

		public static void Load()
		{
			LoadAssetsFromAssetBundle();
		}

		private static void LoadAssetsFromAssetBundle()
		{
			try
			{
				string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location);
				string text = Path.Combine(directoryName, "toilhead_assets");
				AssetBundle val = AssetBundle.LoadFromFile(text);
				NetworkHandlerPrefab = val.LoadAsset<GameObject>("NetworkHandler");
				NetworkHandlerPrefab.AddComponent<PluginNetworkBehaviour>();
				TurretPropPrefab = val.LoadAsset<GameObject>("TurretHeadTurretProp");
				MinigunPropPrefab = val.LoadAsset<GameObject>("MinigunTurretHeadTurretProp");
				ToilPlayerControllerPrefab = val.LoadAsset<GameObject>("ToilPlayerController");
				SlayerPlayerControllerPrefab = val.LoadAsset<GameObject>("SlayerPlayerController");
				ToiledDeadBodyControllerPrefab = val.LoadAsset<GameObject>("ToiledDeadBodyController");
				SlayedDeadBodyControllerPrefab = val.LoadAsset<GameObject>("SlayedDeadBodyController");
				ToilHeadControllerPrefab = val.LoadAsset<GameObject>("ToilHeadController");
				ToilSlayerControllerPrefab = val.LoadAsset<GameObject>("ToilSlayerController");
				MantiToilControllerPrefab = val.LoadAsset<GameObject>("MantiToilController");
				MantiSlayerControllerPrefab = val.LoadAsset<GameObject>("MantiSlayerController");
				ToilMaskedControllerPrefab = val.LoadAsset<GameObject>("ToilMaskedController");
				SlayerMaskedControllerPrefab = val.LoadAsset<GameObject>("SlayerMaskedController");
				ToilHeadPlush = val.LoadAsset<Item>("ToilHeadPlush");
				ToilSlayerPlush = val.LoadAsset<Item>("ToilSlayerPlush");
				Plugin.logger.LogInfo((object)"Successfully loaded assets from AssetBundle!");
			}
			catch (Exception arg)
			{
				Plugin.logger.LogError((object)$"Error: Failed to load assets from AssetBundle.\n\n{arg}");
			}
		}
	}
	public class ExtendedConfigEntry<T>
	{
		public ConfigEntry<T> ConfigEntry;

		public Func<T> GetValue;

		public Action<T> SetValue;

		public bool UseEnableConfiguration = true;

		public T DefaultValue => (T)((ConfigEntryBase)ConfigEntry).DefaultValue;

		public T Value
		{
			get
			{
				return GetValue();
			}
			set
			{
				SetValue(value);
			}
		}

		public ExtendedConfigEntry(string section, string key, T defaultValue, string description, bool useEnableConfiguration = true)
		{
			ConfigEntry = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<T>(section, key, defaultValue, description);
			UseEnableConfiguration = useEnableConfiguration;
			Initialize();
		}

		public ExtendedConfigEntry(string section, string key, T defaultValue, ConfigDescription configDescription = null, bool useEnableConfiguration = true)
		{
			ConfigEntry = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<T>(section, key, defaultValue, configDescription);
			UseEnableConfiguration = useEnableConfiguration;
			Initialize();
		}

		private void Initialize()
		{
			if (GetValue == null)
			{
				GetValue = () => (UseEnableConfiguration && !Plugin.ConfigManager.EnableConfiguration.Value) ? DefaultValue : ConfigEntry.Value;
			}
			if (SetValue == null)
			{
				SetValue = delegate(T value)
				{
					ConfigEntry.Value = value;
				};
			}
		}

		public void ResetToDefault()
		{
			ConfigEntry.Value = (T)((ConfigEntryBase)ConfigEntry).DefaultValue;
		}
	}
	internal class PlayerUtils
	{
		public static bool IsLocalPlayer(PlayerControllerB playerScript)
		{
			return (Object)(object)playerScript == (Object)(object)GetLocalPlayerScript();
		}

		public static int GetPlayerId(PlayerControllerB playerScript)
		{
			return (int)playerScript.playerClientId;
		}

		public static int GetLocalPlayerId()
		{
			return (int)GetLocalPlayerScript().playerClientId;
		}

		public static PlayerControllerB GetPlayerScript(int playerId)
		{
			try
			{
				return StartOfRound.Instance.allPlayerScripts[playerId];
			}
			catch
			{
				return null;
			}
		}

		public static PlayerControllerB GetLocalPlayerScript()
		{
			return GameNetworkManager.Instance.localPlayerController;
		}
	}
	[BepInPlugin("com.github.zehsteam.ToilHead", "ToilHead", "1.7.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal class Plugin : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("com.github.zehsteam.ToilHead");

		internal static Plugin Instance;

		internal static ManualLogSource logger;

		internal static SyncedConfigManager ConfigManager;

		public static bool IsHostOrServer => NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			logger = Logger.CreateLogSource("com.github.zehsteam.ToilHead");
			logger.LogInfo((object)"ToilHead has awoken!");
			harmony.PatchAll(typeof(GameNetworkManagerPatch));
			harmony.PatchAll(typeof(StartOfRoundPatch));
			harmony.PatchAll(typeof(RoundManagerPatch));
			harmony.PatchAll(typeof(TerminalPatch));
			harmony.PatchAll(typeof(PlayerControllerBPatch));
			harmony.PatchAll(typeof(RagdollGrabbableObjectPatch));
			harmony.PatchAll(typeof(EnemyAIPatch));
			harmony.PatchAll(typeof(SpringManAIPatch));
			harmony.PatchAll(typeof(MaskedPlayerEnemyPatch));
			harmony.PatchAll(typeof(TurretPatch));
			ConfigManager = new SyncedConfigManager();
			Content.Load();
			TurretHeadManager.Initialize();
			RegisterScrapItems();
			NetcodePatcherAwake();
		}

		private void NetcodePatcherAwake()
		{
			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 void OnLocalDisconnect()
		{
			logger.LogInfo((object)"Local player disconnected. Removing hostConfigData.");
			ConfigManager.SetHostConfigData(null);
			TurretHeadManager.Reset();
		}

		public void OnNewLevelLoaded()
		{
			Secret.SpawnSecrets();
		}

		public void OnNewLevelFinishedLoading()
		{
			TurretHeadManager.TrySetPlayerTurretHeadsOnServer();
		}

		public void OnShipHasLeft()
		{
			TurretHeadManager.Reset();
		}

		private void RegisterScrapItems()
		{
			if (!LethalLibCompat.HasMod || !MonsterPlushiesCompat.HasMod)
			{
				return;
			}
			try
			{
				ScrapHelper.RegisterScrap(Content.ToilHeadPlush, ConfigManager.ToilHeadPlushieSpawnWeight.Value, ConfigManager.ToilHeadPlushieSpawnAllMoons.Value, ConfigManager.ToilHeadPlushieMoonSpawnList.Value, twoHanded: false, ConfigManager.ToilHeadPlushieCarryWeight.Value, ConfigManager.ToilHeadPlushieMinValue.Value, ConfigManager.ToilHeadPlushieMaxValue.Value);
				ScrapHelper.RegisterScrap(Content.ToilSlayerPlush, ConfigManager.ToilSlayerPlushieSpawnWeight.Value, ConfigManager.ToilSlayerPlushieSpawnAllMoons.Value, ConfigManager.ToilSlayerPlushieMoonSpawnList.Value, twoHanded: false, ConfigManager.ToilSlayerPlushieCarryWeight.Value, ConfigManager.ToilSlayerPlushieMinValue.Value, ConfigManager.ToilSlayerPlushieMaxValue.Value);
			}
			catch (Exception arg)
			{
				logger.LogWarning((object)$"Warning: Failed to register scrap items.\n\n{arg}");
			}
		}

		public void LogInfoExtended(object data)
		{
			if (ConfigManager.ExtendedLogging.Value)
			{
				logger.LogInfo(data);
			}
		}

		public void LogWarningExtended(object data)
		{
			if (ConfigManager.ExtendedLogging.Value)
			{
				logger.LogWarning(data);
			}
		}

		public void LogErrorExtended(object data)
		{
			if (ConfigManager.ExtendedLogging.Value)
			{
				logger.LogError(data);
			}
		}
	}
	internal class ScrapHelper
	{
		public static void RegisterScrap(Item item, int iRarity, bool spawnAllMoons, string moonSpawnList, bool twoHanded, int carryWeight, int minValue, int maxValue)
		{
			if (!LethalLibCompat.HasMod)
			{
				return;
			}
			try
			{
				item.twoHanded = twoHanded;
				item.weight = (float)carryWeight / 105f + 1f;
				item.minValue = minValue;
				item.maxValue = maxValue;
				Utilities.FixMixerGroups(item.spawnPrefab);
				NetworkPrefabs.RegisterNetworkPrefab(item.spawnPrefab);
				if (spawnAllMoons)
				{
					Items.RegisterScrap(item, iRarity, (LevelTypes)(-1));
					Plugin.logger.LogInfo((object)$"Registered \"{item.itemName}\" scrap item with {iRarity} rarity.");
				}
				else
				{
					RegisterScrapForMoons(item, iRarity, moonSpawnList);
				}
			}
			catch (Exception arg)
			{
				Plugin.logger.LogError((object)$"Error: Failed to register \"{item.itemName}\" scrap item.\n\n{arg}");
			}
		}

		private static void RegisterScrapForMoons(Item item, int iRarity, string moonSpawnList)
		{
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, LevelTypes> dictionary = new Dictionary<string, LevelTypes>();
			dictionary.Add("Experimentation", (LevelTypes)4);
			dictionary.Add("Assurance", (LevelTypes)8);
			dictionary.Add("Vow", (LevelTypes)16);
			dictionary.Add("Offense", (LevelTypes)32);
			dictionary.Add("March", (LevelTypes)64);
			dictionary.Add("Adamance", (LevelTypes)2048);
			dictionary.Add("Rend", (LevelTypes)128);
			dictionary.Add("Dine", (LevelTypes)256);
			dictionary.Add("Titan", (LevelTypes)512);
			dictionary.Add("Artifice", (LevelTypes)4096);
			dictionary.Add("Embrion", (LevelTypes)8192);
			foreach (string item2 in from _ in moonSpawnList.Split(',')
				select GetFormattedSting(_.Trim()))
			{
				if (dictionary.TryGetValue(item2, out var value))
				{
					Items.RegisterScrap(item, iRarity, value);
					Plugin.logger.LogInfo((object)$"Registered \"{item.itemName}\" scrap item on moon \"{item2}\" with {iRarity} rarity.");
				}
			}
		}

		private static string GetFormattedSting(string value)
		{
			if (value.Length <= 1)
			{
				return value.ToUpper();
			}
			return value.Substring(0, 1).ToUpper() + value.Substring(1, value.Length - 1).ToLower();
		}
	}
	internal class Secret
	{
		public static void SpawnSecrets()
		{
			string planetName = StartOfRound.Instance.currentLevel.PlanetName;
			if (planetName == "57 Asteroid-13")
			{
				SpawnAsteroid13Secrets();
			}
		}

		public static void SpawnAsteroid13Secrets()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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)
			//IL_0089: 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_00a6: 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_00ae: 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_00bb: 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_00bf: 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_00d5: 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_00d7: 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_00e4: 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)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: 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_00ff: 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_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: 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_0153: 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_0161: 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_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: 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_0171: 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_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: 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_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: 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_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: 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_01d1: 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_01d3: 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_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: 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_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: 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_020a: 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_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: 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_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: 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_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: 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_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Content.TurretPropPrefab == (Object)null)
			{
				Plugin.Instance.LogWarningExtended("Warning: Failed to spawn Asteroid13 secrets. turretPropPrefab is null.");
				return;
			}
			Vector3 val = Content.TurretPropPrefab.transform.localScale * 1.3f;
			Vector3 positionOffset = default(Vector3);
			((Vector3)(ref positionOffset))..ctor(0f, 3.031f, -0.464f);
			Vector3 rotationOffset = default(Vector3);
			((Vector3)(ref rotationOffset))..ctor(-27.2f, 0f, 0f);
			Vector3 positionOffset2 = default(Vector3);
			((Vector3)(ref positionOffset2))..ctor(0f, 3.105f, -0.11f);
			Vector3 zero = Vector3.zero;
			Vector3 positionOffset3 = default(Vector3);
			((Vector3)(ref positionOffset3))..ctor(0f, 6.217f, -0.225f);
			Vector3 zero2 = Vector3.zero;
			SpawnTurretProp("coilheadstuck_model", positionOffset, rotationOffset, val);
			SpawnTurretProp("coilheadrigged", positionOffset3, zero2, val * 2f);
			SpawnTurretProp("coilheadstuck_model (5)", positionOffset, rotationOffset, val);
			SpawnTurretProp("coilheadstuck_model (7)", positionOffset, rotationOffset, val);
			SpawnTurretProp("coilheadstuck_model (8)", positionOffset, rotationOffset, val);
			SpawnTurretProp("coilheadstuck_model (9)", positionOffset, rotationOffset, val);
			SpawnTurretProp("coilheadstuck_model (10)", positionOffset, rotationOffset, val);
			SpawnTurretProp("coilheadstuck_model (6)", positionOffset, rotationOffset, val);
			SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (29)", positionOffset, rotationOffset, val);
			SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (24)", positionOffset, rotationOffset, val);
			SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (25)", positionOffset, rotationOffset, val);
			SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (26)", positionOffset, rotationOffset, val);
			SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (27)", positionOffset, rotationOffset, val);
			SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (28)", positionOffset, rotationOffset, val);
			SpawnTurretProp("coilheadstuck_model (23)", positionOffset, rotationOffset, val);
			SpawnTurretProp("coilheadstuck_model (18)", positionOffset, rotationOffset, val);
			SpawnTurretProp("coilheadstuck_model (19)", positionOffset, rotationOffset, val);
			SpawnTurretProp("coilheadstuck_model (20)", positionOffset, rotationOffset, val);
			SpawnTurretProp("coilheadstuck_model (21)", positionOffset, rotationOffset, val);
			SpawnTurretProp("coilheadstuck_model (22)", positionOffset, rotationOffset, val);
			SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (17)", positionOffset, rotationOffset, val);
			SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (12)", positionOffset, rotationOffset, val);
			SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (13)", positionOffset, rotationOffset, val);
			SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (14)", positionOffset, rotationOffset, val);
			SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (15)", positionOffset, rotationOffset, val);
			SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (16)", positionOffset, rotationOffset, val);
			SpawnTurretProp("asteroid(Clone)/coilheadstuck_2_model (7)", positionOffset2, zero, val);
			SpawnTurretProp("coilheadstuck_2_model (1)", positionOffset2, zero, val);
			SpawnTurretProp("coilheadstuck_model (11)", positionOffset, rotationOffset, val);
			SpawnTurretProp("coilheadrigged (1)", positionOffset3, zero2, val * 2f);
			Plugin.Instance.LogInfoExtended("Spawned Asteroid13 secrets.");
		}

		private static void SpawnTurretProp(string parentName, Vector3 positionOffset, Vector3 rotationOffset)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			SpawnTurretProp(parentName, positionOffset, rotationOffset, Content.TurretPropPrefab.transform.localScale);
		}

		private static void SpawnTurretProp(string parentName, Vector3 positionOffset, Vector3 rotationOffset, Vector3 scale)
		{
			//IL_004d: 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_0069: 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_007d: 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)
			if ((Object)(object)Content.TurretPropPrefab == (Object)null)
			{
				Plugin.Instance.LogWarningExtended("Warning: Failed to Instantiate turretPropPrefab. turretPropPrefab is null.");
				return;
			}
			GameObject val = GameObject.Find(parentName);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Instance.LogWarningExtended("Warning: Failed to Instantiate turretPropPrefab. Parent GameObject is null.");
				return;
			}
			Transform transform = Object.Instantiate<GameObject>(Content.TurretPropPrefab, Vector3.zero, Quaternion.identity, val.transform).transform;
			transform.localScale = scale;
			transform.localRotation = Quaternion.identity;
			transform.Rotate(rotationOffset, (Space)1);
			transform.localPosition = positionOffset;
			Utils.DisableColliders(((Component)transform).gameObject);
		}
	}
	public class SpawnData
	{
		public int MaxSpawnCount;

		public float SpawnChance;

		public SpawnData(string value)
		{
			ParseValue(value);
		}

		protected virtual void ParseValue(string value)
		{
			string[] array = (from _ in value.Split(':')
				select _.Trim()).ToArray();
			int num = 2;
			if (array.Length != num)
			{
				Plugin.logger.LogError((object)$"ParseValue Error: Invalid item length for string \"{value}\". Length is {array.Length} but should have been {num}.");
				return;
			}
			TryParseInt(array[0], out MaxSpawnCount);
			TryParseFloat(array[1], out SpawnChance);
			Plugin.Instance.LogInfoExtended($"Parsed SpawnData value string. MaxSpawnCount: {MaxSpawnCount}, SpawnChance: {SpawnChance}");
		}

		protected bool TryParseInt(string value, out int parsedInt)
		{
			if (int.TryParse(value, out parsedInt))
			{
				return true;
			}
			Plugin.logger.LogError((object)("TryParseItem Error: Failed to parse int from string \"" + value + "\"."));
			return false;
		}

		protected bool TryParseFloat(string value, out float parsedFloat)
		{
			if (float.TryParse(value, out parsedFloat))
			{
				return true;
			}
			Plugin.logger.LogError((object)("TryParseItem Error: Failed to parse float from string \"" + value + "\"."));
			return false;
		}
	}
	public class MoonSpawnData : SpawnData
	{
		public string PlanetName;

		public MoonSpawnData(string value)
			: base(value)
		{
		}

		protected override void ParseValue(string value)
		{
			string[] array = (from _ in value.Split(':')
				select _.Trim()).ToArray();
			int num = 3;
			if (array.Length != num)
			{
				Plugin.logger.LogError((object)$"ParseValue Error: Invalid item length for string \"{value}\". Length is {array.Length} but should have been {num}.");
				return;
			}
			PlanetName = array[0];
			TryParseInt(array[1], out MaxSpawnCount);
			TryParseFloat(array[2], out SpawnChance);
			Plugin.Instance.LogInfoExtended($"Parsed MoonSpawnData value string. PlanetName: \"{PlanetName}\", MaxSpawnCount: {MaxSpawnCount}, SpawnChance: {SpawnChance}");
		}
	}
	public class MoonSpawnDataList
	{
		public List<MoonSpawnData> List = new List<MoonSpawnData>();

		public SpawnData DefaultSpawnData;

		public MoonSpawnDataList(string value)
		{
			ParseValue(value);
		}

		public MoonSpawnDataList(string value, SpawnData defaultSpawnData)
		{
			ParseValue(value);
			DefaultSpawnData = defaultSpawnData;
		}

		private void ParseValue(string value)
		{
			if (value == string.Empty)
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(value))
			{
				Plugin.logger.LogError((object)"ParseValue Error: MoonSpawnDataList value is null or whitespace.");
				return;
			}
			string[] array = (from _ in value.Split(',')
				select _.Trim()).ToArray();
			List = new List<MoonSpawnData>();
			string[] array2 = array;
			foreach (string value2 in array2)
			{
				List.Add(new MoonSpawnData(value2));
			}
		}

		public SpawnData GetSpawnDataForCurrentMoon()
		{
			if ((Object)(object)StartOfRound.Instance == (Object)null)
			{
				return DefaultSpawnData;
			}
			return GetSpawnDataForMoon(StartOfRound.Instance.currentLevel.PlanetName);
		}

		public SpawnData GetSpawnDataForMoon(string planetName)
		{
			foreach (MoonSpawnData item in List)
			{
				if (item.PlanetName == planetName)
				{
					return item;
				}
			}
			return DefaultSpawnData;
		}
	}
	[Serializable]
	public class SyncedConfigData : INetworkSerializable
	{
		public float TurretLostLOSDuration;

		public float TurretRotationRange;

		public float TurretCodeAccessCooldownDuration;

		public bool TurretDetectionRotation;

		public float TurretDetectionRotationSpeed;

		public float TurretChargingDuration;

		public float TurretChargingRotationSpeed;

		public float TurretFiringRotationSpeed;

		public float TurretBerserkDuration;

		public float TurretBerserkRotationSpeed;

		public SyncedConfigData()
		{
		}

		public SyncedConfigData(SyncedConfigManager configManager)
		{
			TurretLostLOSDuration = configManager.TurretLostLOSDuration.Value;
			TurretRotationRange = configManager.TurretRotationRange.Value;
			TurretCodeAccessCooldownDuration = configManager.TurretCodeAccessCooldownDuration.Value;
			TurretDetectionRotation = configManager.TurretDetectionRotation.Value;
			TurretDetectionRotationSpeed = configManager.TurretDetectionRotationSpeed.Value;
			TurretChargingDuration = configManager.TurretChargingDuration.Value;
			TurretChargingRotationSpeed = configManager.TurretChargingRotationSpeed.Value;
			TurretFiringRotationSpeed = configManager.TurretFiringRotationSpeed.Value;
			TurretBerserkDuration = configManager.TurretBerserkDuration.Value;
			TurretBerserkRotationSpeed = configManager.TurretBerserkRotationSpeed.Value;
		}

		public unsafe void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
		{
			//IL_000b: 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_0022: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_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_007e: 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)
			//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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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)
			//IL_00da: 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)
			((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretLostLOSDuration, default(ForPrimitives));
			((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretRotationRange, default(ForPrimitives));
			((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretCodeAccessCooldownDuration, default(ForPrimitives));
			((BufferSerializer<bool>*)(&serializer))->SerializeValue<bool>(ref TurretDetectionRotation, default(ForPrimitives));
			((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretDetectionRotationSpeed, default(ForPrimitives));
			((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretChargingDuration, default(ForPrimitives));
			((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretChargingRotationSpeed, default(ForPrimitives));
			((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretFiringRotationSpeed, default(ForPrimitives));
			((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretBerserkDuration, default(ForPrimitives));
			((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretBerserkRotationSpeed, default(ForPrimitives));
		}
	}
	public class SyncedConfigManager
	{
		public SyncedConfigData HostConfigData { get; private set; }

		public ExtendedConfigEntry<bool> EnableConfiguration { get; private set; }

		public ExtendedConfigEntry<bool> ExtendedLogging { get; private set; }

		public ExtendedConfigEntry<string> ToilationToilPlayerSpawnSettings { get; private set; }

		public ExtendedConfigEntry<float> ToilationToilPlayerSlayerChance { get; private set; }

		public ExtendedConfigEntry<string> ToilationToilHeadSpawnSettings { get; private set; }

		public ExtendedConfigEntry<string> ToilationToilSlayerSpawnSettings { get; private set; }

		public ExtendedConfigEntry<string> ToilationMantiToilSpawnSettings { get; private set; }

		public ExtendedConfigEntry<string> ToilationMantiSlayerSpawnSettings { get; private set; }

		public ExtendedConfigEntry<string> ToilationToilMaskedSpawnSettings { get; private set; }

		public ExtendedConfigEntry<string> ToilationSlayerMaskedSpawnSettings { get; private set; }

		public ExtendedConfigEntry<string> ToilPlayerDefaultSpawnSettings { get; private set; }

		public ExtendedConfigEntry<string> ToilPlayerSpawnSettingsMoonList { get; private set; }

		public ExtendedConfigEntry<float> ToilPlayerSlayerChance { get; private set; }

		public ExtendedConfigEntry<bool> SpawnToiledPlayerRagdolls { get; private set; }

		public ExtendedConfigEntry<bool> SpawnRealToiledPlayerRagdolls { get; private set; }

		public ExtendedConfigEntry<string> ToilHeadDefaultSpawnSettings { get; private set; }

		public ExtendedConfigEntry<string> ToilHeadSpawnSettingsMoonList { get; private set; }

		public ExtendedConfigEntry<string> MantiToilDefaultSpawnSettings { get; private set; }

		public ExtendedConfigEntry<string> MantiToilSpawnSettingsMoonList { get; private set; }

		public ExtendedConfigEntry<string> ToilSlayerDefaultSpawnSettings { get; private set; }

		public ExtendedConfigEntry<string> ToilSlayerSpawnSettingsMoonList { get; private set; }

		public ExtendedConfigEntry<string> MantiSlayerDefaultSpawnSettings { get; private set; }

		public ExtendedConfigEntry<string> MantiSlayerSpawnSettingsMoonList { get; private set; }

		public ExtendedConfigEntry<string> ToilMaskedDefaultSpawnSettings { get; private set; }

		public ExtendedConfigEntry<string> ToilMaskedSpawnSettingsMoonList { get; private set; }

		public ExtendedConfigEntry<string> SlayerMaskedDefaultSpawnSettings { get; private set; }

		public ExtendedConfigEntry<string> SlayerMaskedSpawnSettingsMoonList { get; private set; }

		public ExtendedConfigEntry<int> ToilHeadPlushieSpawnWeight { get; private set; }

		public ExtendedConfigEntry<bool> ToilHeadPlushieSpawnAllMoons { get; private set; }

		public ExtendedConfigEntry<string> ToilHeadPlushieMoonSpawnList { get; private set; }

		public ExtendedConfigEntry<int> ToilHeadPlushieCarryWeight { get; private set; }

		public ExtendedConfigEntry<int> ToilHeadPlushieMinValue { get; private set; }

		public ExtendedConfigEntry<int> ToilHeadPlushieMaxValue { get; private set; }

		public ExtendedConfigEntry<int> ToilSlayerPlushieSpawnWeight { get; private set; }

		public ExtendedConfigEntry<bool> ToilSlayerPlushieSpawnAllMoons { get; private set; }

		public ExtendedConfigEntry<string> ToilSlayerPlushieMoonSpawnList { get; private set; }

		public ExtendedConfigEntry<int> ToilSlayerPlushieCarryWeight { get; private set; }

		public ExtendedConfigEntry<int> ToilSlayerPlushieMinValue { get; private set; }

		public ExtendedConfigEntry<int> ToilSlayerPlushieMaxValue { get; private set; }

		public ExtendedConfigEntry<float> TurretLostLOSDuration { get; private set; }

		public ExtendedConfigEntry<float> TurretRotationRange { get; private set; }

		public ExtendedConfigEntry<float> TurretCodeAccessCooldownDuration { get; private set; }

		public ExtendedConfigEntry<bool> TurretDetectionRotation { get; private set; }

		public ExtendedConfigEntry<float> TurretDetectionRotationSpeed { get; private set; }

		public ExtendedConfigEntry<float> TurretChargingDuration { get; private set; }

		public ExtendedConfigEntry<float> TurretChargingRotationSpeed { get; private set; }

		public ExtendedConfigEntry<float> TurretFiringRotationSpeed { get; private set; }

		public ExtendedConfigEntry<float> TurretBerserkDuration { get; private set; }

		public ExtendedConfigEntry<float> TurretBerserkRotationSpeed { get; private set; }

		public SyncedConfigManager()
		{
			BindConfigs();
			ClearUnusedEntries();
		}

		private void BindConfigs()
		{
			EnableConfiguration = new ExtendedConfigEntry<bool>("General Settings", "EnableConfiguration", defaultValue: false, "Enable if you want to use custom set config setting values. If disabled, the default config setting values will be used.", useEnableConfiguration: false);
			ExtendedLogging = new ExtendedConfigEntry<bool>("General Settings", "ExtendedLogging", defaultValue: false, "Enable extended logging.", useEnableConfiguration: false);
			ToilationToilPlayerSpawnSettings = new ExtendedConfigEntry<string>("Toilation Settings", "ToilPlayerSpawnSettings", "1:7", GetDescriptionForMoonSpawnSettings("Toil-Player", "69-Toilation"));
			ToilationToilPlayerSlayerChance = new ExtendedConfigEntry<float>("Toilation Settings", "ToilPlayerSlayerChance", 20f, "The percent chance a Toil-Player will become a Slayer-Player for 69-Toilation.");
			ToilationToilHeadSpawnSettings = new ExtendedConfigEntry<string>("Toilation Settings", "ToilHeadSpawnSettings", "6:75", GetDescriptionForMoonSpawnSettings("Toil-Head", "69-Toilation"));
			ToilationMantiToilSpawnSettings = new ExtendedConfigEntry<string>("Toilation Settings", "MantiToilSpawnSettings", "50:90", GetDescriptionForMoonSpawnSettings("Manti-Toil", "69-Toilation"));
			ToilationToilSlayerSpawnSettings = new ExtendedConfigEntry<string>("Toilation Settings", "ToilSlayerSpawnSettings", "2:10", GetDescriptionForMoonSpawnSettings("Toil-Slayer", "69-Toilation"));
			ToilationMantiSlayerSpawnSettings = new ExtendedConfigEntry<string>("Toilation Settings", "MantiSlayerSpawnSettings", "2:20", GetDescriptionForMoonSpawnSettings("Manti-Slayer", "69-Toilation"));
			ToilationToilMaskedSpawnSettings = new ExtendedConfigEntry<string>("Toilation Settings", "ToilMaskedSpawnSettings", "2:15", GetDescriptionForMoonSpawnSettings("Toil-Masked", "69-Toilation"));
			ToilationSlayerMaskedSpawnSettings = new ExtendedConfigEntry<string>("Toilation Settings", "SlayerMaskedSpawnSettings", "1:5", GetDescriptionForMoonSpawnSettings("Slayer-Masked", "69-Toilation"));
			ToilPlayerDefaultSpawnSettings = new ExtendedConfigEntry<string>("Toil-Player Settings", "ToilPlayerDefaultSpawnSettings", "1:3", GetDescriptionForDefaultSpawnSettings("Toil-Player"));
			string defaultValue = "85 Rend:1:4, 7 Dine:1:4, 8 Titan:1:5, 68 Artifice:1:5, 57 Asteroid-13:1:5, 523 Ooblterra:1:6";
			ToilPlayerSpawnSettingsMoonList = new ExtendedConfigEntry<string>("Toil-Player Settings", "ToilPlayerSpawnSettingsMoonList", defaultValue, GetDescriptionForMoonSpawnSettingsList("Toil-Player"));
			ToilPlayerSlayerChance = new ExtendedConfigEntry<float>("Toil-Player Settings", "ToilPlayerSlayerChance", 10f, "The percent chance a Toil-Player will become a Slayer-Player.");
			SpawnToiledPlayerRagdolls = new ExtendedConfigEntry<bool>("Player Ragdoll Settings", "SpawnToiledPlayerRagdolls", defaultValue: true, "If enabled, will spawn a Toiled player ragdoll when a player dies to a Turret-Head in any way.");
			SpawnRealToiledPlayerRagdolls = new ExtendedConfigEntry<bool>("Player Ragdoll Settings", "SpawnRealToiledPlayerRagdolls", defaultValue: true, "If enabled, will spawn a real turret on the Toiled player ragdoll.");
			ToilHeadDefaultSpawnSettings = new ExtendedConfigEntry<string>("Toil-Head Settings", "ToilHeadDefaultSpawnSettings", "1:30", GetDescriptionForDefaultSpawnSettings("Toil-Head"));
			string defaultValue2 = "41 Experimentation:1:10, 220 Assurance:1:20, 56 Vow:1:20, 21 Offense:1:20, 61 March:1:20, 20 Adamance:1:30, 85 Rend:1:40, 7 Dine:1:45, 8 Titan:1:50, 68 Artifice:2:70, 5 Embrion:1:30, 57 Asteroid-13:2:30, 523 Ooblterra:2:70";
			ToilHeadSpawnSettingsMoonList = new ExtendedConfigEntry<string>("Toil-Head Settings", "ToilHeadSpawnSettingsMoonList", defaultValue2, GetDescriptionForMoonSpawnSettingsList("Toil-Head"));
			MantiToilDefaultSpawnSettings = new ExtendedConfigEntry<string>("Manti-Toil Settings", "MantiToilDefaultSpawnSettings", "5:50", GetDescriptionForDefaultSpawnSettings("Manti-Toil"));
			string defaultValue3 = "20 Adamance:5:60, 85 Rend:5:60, 7 Dine:5:65, 8 Titan:5:70, 68 Artifice:8:75";
			MantiToilSpawnSettingsMoonList = new ExtendedConfigEntry<string>("Manti-Toil Settings", "MantiToilSpawnSettingsMoonList", defaultValue3, GetDescriptionForMoonSpawnSettingsList("Manti-Toil"));
			ToilSlayerDefaultSpawnSettings = new ExtendedConfigEntry<string>("Toil-Slayer Settings", "ToilSlayerDefaultSpawnSettings", "1:10", GetDescriptionForDefaultSpawnSettings("Toil-Slayer"));
			string defaultValue4 = "20 Adamance:1:15, 85 Rend:1:15, 7 Dine:1:15, 8 Titan:1:20, 68 Artifice:1:20, 57 Asteroid-13:1:15, 523 Ooblterra:1:25";
			ToilSlayerSpawnSettingsMoonList = new ExtendedConfigEntry<string>("Toil-Slayer Settings", "ToilSlayerSpawnSettingsMoonList", defaultValue4, GetDescriptionForMoonSpawnSettingsList("Toil-Slayer"));
			MantiSlayerDefaultSpawnSettings = new ExtendedConfigEntry<string>("Manti-Slayer Settings", "MantiSlayerDefaultSpawnSettings", "1:10", GetDescriptionForDefaultSpawnSettings("Manti-Slayer"));
			string defaultValue5 = "20 Adamance:1:15, 85 Rend:1:15, 7 Dine:1:15, 8 Titan:1:20, 68 Artifice:1:20, 57 Asteroid-13:1:15, 523 Ooblterra:1:25";
			MantiSlayerSpawnSettingsMoonList = new ExtendedConfigEntry<string>("Manti-Slayer Settings", "MantiSlayerSpawnSettingsMoonList", defaultValue5, GetDescriptionForMoonSpawnSettingsList("Manti-Slayer"));
			ToilMaskedDefaultSpawnSettings = new ExtendedConfigEntry<string>("Toil-Masked Settings", "ToilMaskedDefaultSpawnSettings", "1:10", GetDescriptionForDefaultSpawnSettings("Toil-Masked"));
			string defaultValue6 = "";
			ToilMaskedSpawnSettingsMoonList = new ExtendedConfigEntry<string>("Toil-Masked Settings", "ToilMaskedSpawnSettingsMoonList", defaultValue6, GetDescriptionForMoonSpawnSettingsList("Toil-Masked"));
			SlayerMaskedDefaultSpawnSettings = new ExtendedConfigEntry<string>("Slayer-Masked Settings", "SlayerMaskedDefaultSpawnSettings", "1:5", GetDescriptionForDefaultSpawnSettings("Slayer-Masked"));
			string defaultValue7 = "";
			SlayerMaskedSpawnSettingsMoonList = new ExtendedConfigEntry<string>("Slayer-Masked Settings", "SlayerMaskedSpawnSettingsMoonList", defaultValue7, GetDescriptionForMoonSpawnSettingsList("Slayer-Masked"));
			ToilHeadPlushieSpawnWeight = new ExtendedConfigEntry<int>("Toil-Head Plushie Settings", "SpawnWeight", 10, "Toil-Head plushie spawn chance weight.");
			ToilHeadPlushieSpawnAllMoons = new ExtendedConfigEntry<bool>("Toil-Head Plushie Settings", "SpawnAllMoons", defaultValue: true, "If true, the Toil-Head plushie will spawn on all moons. If false, the Toil-Head plushie will only spawn on moons set in the moons list.");
			ToilHeadPlushieMoonSpawnList = new ExtendedConfigEntry<string>("Toil-Head Plushie Settings", "MoonSpawnList", "Experimentation, Assurance, Vow, Offense, March, Adamance, Rend, Dine, Titan, Artifice, Embrion", "The list of moons the Toil-Head plushie will spawn on.\nCurrently only works for vanilla moons.\nOnly works if PlushieSpawnAllMoons is false.");
			ToilHeadPlushieCarryWeight = new ExtendedConfigEntry<int>("Toil-Head Plushie Settings", "CarryWeight", 6, "Toil-Head plushie carry weight in pounds.");
			ToilHeadPlushieMinValue = new ExtendedConfigEntry<int>("Toil-Head Plushie Settings", "MinValue", 80, "Toil-Head plushie min scrap value.");
			ToilHeadPlushieMaxValue = new ExtendedConfigEntry<int>("Toil-Head Plushie Settings", "MaxValue", 250, "Toil-Head plushie max scrap value.");
			ToilSlayerPlushieSpawnWeight = new ExtendedConfigEntry<int>("Toil-Slayer Plushie Settings", "SpawnWeight", 5, "Toil-Slayer plushie spawn chance weight.");
			ToilSlayerPlushieSpawnAllMoons = new ExtendedConfigEntry<bool>("Toil-Slayer Plushie Settings", "SpawnAllMoons", defaultValue: true, "If true, the Toil-Slayer plushie will spawn on all moons. If false, the Toil-Slayer plushie will only spawn on moons set in the moons list.");
			ToilSlayerPlushieMoonSpawnList = new ExtendedConfigEntry<string>("Toil-Slayer Plushie Settings", "MoonSpawnList", "Experimentation, Assurance, Vow, Offense, March, Adamance, Rend, Dine, Titan, Artifice, Embrion", "The list of moons the Toil-Slayer plushie will spawn on.\nCurrently only works for vanilla moons.\nOnly works if PlushieSpawnAllMoons is false.");
			ToilSlayerPlushieCarryWeight = new ExtendedConfigEntry<int>("Toil-Slayer Plushie Settings", "CarryWeight", 12, "Toil-Slayer plushie carry weight in pounds.");
			ToilSlayerPlushieMinValue = new ExtendedConfigEntry<int>("Toil-Slayer Plushie Settings", "MinValue", 150, "Toil-Slayer plushie min scrap value.");
			ToilSlayerPlushieMaxValue = new ExtendedConfigEntry<int>("Toil-Slayer Plushie Settings", "MaxValue", 380, "Toil-Slayer plushie max scrap value.");
			TurretLostLOSDuration = new ExtendedConfigEntry<float>("Turret Settings", "LostLOSDuration", 0.75f, "The duration until the turret loses the target player when not in line of sight.\nVanilla Turret Default value: 2");
			TurretLostLOSDuration.GetValue = () => (HostConfigData == null) ? TurretLostLOSDuration.ConfigEntry.Value : HostConfigData.TurretLostLOSDuration;
			TurretRotationRange = new ExtendedConfigEntry<float>("Turret Settings", "RotationRange", 75f, "The rotation range of the turret in degrees.\nVanilla Turret Default value: 75");
			TurretRotationRange.GetValue = () => (HostConfigData == null) ? TurretRotationRange.ConfigEntry.Value : HostConfigData.TurretRotationRange;
			TurretCodeAccessCooldownDuration = new ExtendedConfigEntry<float>("Turret Settings", "CodeAccessCooldownDuration", 7f, "The duration of the turret being disabled from the terminal in seconds.\nVanilla Turret Default value: 7");
			TurretCodeAccessCooldownDuration.GetValue = () => (HostConfigData == null) ? TurretCodeAccessCooldownDuration.ConfigEntry.Value : HostConfigData.TurretCodeAccessCooldownDuration;
			TurretDetectionRotation = new ExtendedConfigEntry<bool>("Turret Detection Settings", "Rotation", defaultValue: false, "If enabled, the turret will rotate when searching for players.\nVanilla Turret Default value: true");
			TurretDetectionRotation.GetValue = () => (HostConfigData == null) ? TurretDetectionRotation.ConfigEntry.Value : HostConfigData.TurretDetectionRotation;
			TurretDetectionRotationSpeed = new ExtendedConfigEntry<float>("Turret Detection Settings", "RotationSpeed", 28f, "The rotation speed of the turret when in detection state.\nVanilla Turret Default value: 28");
			TurretDetectionRotationSpeed.GetValue = () => (HostConfigData == null) ? TurretDetectionRotationSpeed.ConfigEntry.Value : HostConfigData.TurretDetectionRotationSpeed;
			TurretChargingDuration = new ExtendedConfigEntry<float>("Turret Charging Settings", "ChargingDuration", 2f, "The duration of the turret charging state.\nVanilla Turret Default value: 1.5");
			TurretChargingDuration.GetValue = () => (HostConfigData == null) ? TurretChargingDuration.ConfigEntry.Value : HostConfigData.TurretChargingDuration;
			TurretChargingRotationSpeed = new ExtendedConfigEntry<float>("Turret Charging Settings", "RotationSpeed", 95f, "The rotation speed of the turret when in charging state.\nVanilla Turret Default value: 95");
			TurretChargingRotationSpeed.GetValue = () => (HostConfigData == null) ? TurretChargingRotationSpeed.ConfigEntry.Value : HostConfigData.TurretChargingRotationSpeed;
			TurretFiringRotationSpeed = new ExtendedConfigEntry<float>("Turret Firing Settings", "RotationSpeed", 95f, "The rotation speed of the turret when in firing state.\nVanilla Turret Default value: 95");
			TurretFiringRotationSpeed.GetValue = () => (HostConfigData == null) ? TurretFiringRotationSpeed.ConfigEntry.Value : HostConfigData.TurretFiringRotationSpeed;
			TurretBerserkDuration = new ExtendedConfigEntry<float>("Turret Berserk Settings", "BerserkDuration", 9f, "The duration of the turret berserk state.\nVanilla Turret Default value: 9");
			TurretBerserkDuration.GetValue = () => (HostConfigData == null) ? TurretBerserkDuration.ConfigEntry.Value : HostConfigData.TurretBerserkDuration;
			TurretBerserkRotationSpeed = new ExtendedConfigEntry<float>("Turret Berserk Settings", "RotationSpeed", 77f, "The rotation speed of the turret when in berserk state.\nVanilla Turret Default value: 77");
			TurretBerserkRotationSpeed.GetValue = () => (HostConfigData == null) ? TurretBerserkRotationSpeed.ConfigEntry.Value : HostConfigData.TurretBerserkRotationSpeed;
		}

		private string GetDescriptionForSpawnSettings(string enemyName)
		{
			string text = enemyName + " spawn settings.\n";
			text += "MaxSpawnCount,SpawnChance\n";
			return text + "<int>,<float>";
		}

		private string GetDescriptionForMoonSpawnSettings(string enemyName, string planetName)
		{
			string text = enemyName + " spawn settings for " + planetName + ".\n";
			text += "MaxSpawnCount,SpawnChance\n";
			return text + "<int>,<float>";
		}

		private string GetDescriptionForMoonSpawnSettingsList(string enemyName)
		{
			string text = enemyName + " spawn settings list for moons.\n";
			text += "Separate each entry with a comma.\n";
			text += "PlanetName:MaxSpawnCount:SpawnChance\n";
			return text + "<string>:<int>:<float>";
		}

		private string GetDescriptionForDefaultSpawnSettings(string enemyName)
		{
			string text = enemyName + " default spawn settings for all moons.\n";
			text += "MaxSpawnCount:SpawnChance\n";
			return text + "<int>:<float>";
		}

		private void ClearUnusedEntries()
		{
			ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config;
			PropertyInfo property = ((object)config).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic);
			Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(config, null);
			dictionary.Clear();
			config.Save();
		}

		internal void SetHostConfigData(SyncedConfigData syncedConfigData)
		{
			HostConfigData = syncedConfigData;
		}

		private void SyncedConfigsChanged()
		{
			//IL_001c: 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)
			if (Plugin.IsHostOrServer)
			{
				PluginNetworkBehaviour.Instance.SendConfigToPlayerClientRpc(new SyncedConfigData(this));
			}
		}
	}
	public class TurretHeadData
	{
		public bool ForceSpawns = false;

		public int ForceMaxSpawnCount = -1;

		public string EnemyName { get; private set; }

		public bool IsSlayer { get; private set; }

		public GameObject ControllerPrefab { get; private set; }

		public MoonSpawnDataList MoonSpawnDataList { get; private set; }

		public SpawnData ToilationSpawnData { get; private set; }

		public int SpawnCount { get; private set; }

		public TurretHeadData(string enemyName, bool isSlayer, GameObject controllerPrefab, MoonSpawnDataList moonSpawnDataList, SpawnData toilationSpawnData)
		{
			EnemyName = enemyName;
			IsSlayer = isSlayer;
			ControllerPrefab = controllerPrefab;
			MoonSpawnDataList = moonSpawnDataList;
			ToilationSpawnData = toilationSpawnData;
		}

		public void Reset()
		{
			SpawnCount = 0;
			ForceSpawns = false;
			ForceMaxSpawnCount = -1;
		}

		public void AddToSpawnCount()
		{
			SpawnCount++;
		}

		public SpawnData GetSpawnDataForCurrentMoon()
		{
			if (Utils.IsCurrentMoonToilation())
			{
				return ToilationSpawnData;
			}
			return MoonSpawnDataList.GetSpawnDataForCurrentMoon();
		}
	}
	public class TurretHeadManager
	{
		private static Coroutine _setDeadBodyTurretHeadOnServerCoroutine;

		public static List<TurretHeadData> TurretHeadDataList { get; private set; } = new List<TurretHeadData>();


		public static TurretHeadData PlayerTurretHeadData { get; private set; }

		public static Dictionary<EnemyAI, TurretHeadControllerBehaviour> EnemyTurretHeadControllerPairs { get; private set; } = new Dictionary<EnemyAI, TurretHeadControllerBehaviour>();


		public static Dictionary<PlayerControllerB, TurretHeadControllerBehaviour> PlayerTurretHeadControllerPairs { get; private set; } = new Dictionary<PlayerControllerB, TurretHeadControllerBehaviour>();


		public static Dictionary<PlayerControllerB, TurretHeadControllerBehaviour> DeadBodyTurretHeadControllerPairs { get; private set; } = new Dictionary<PlayerControllerB, TurretHeadControllerBehaviour>();


		internal static void Initialize()
		{
			TurretHeadDataList = new List<TurretHeadData>(6)
			{
				new TurretHeadData("Spring", isSlayer: false, Content.ToilHeadControllerPrefab, new MoonSpawnDataList(Plugin.ConfigManager.ToilHeadSpawnSettingsMoonList.Value, new SpawnData(Plugin.ConfigManager.ToilHeadDefaultSpawnSettings.Value)), new SpawnData(Plugin.ConfigManager.ToilationToilHeadSpawnSettings.Value)),
				new TurretHeadData("Spring", isSlayer: true, Content.ToilSlayerControllerPrefab, new MoonSpawnDataList(Plugin.ConfigManager.ToilSlayerSpawnSettingsMoonList.Value, new SpawnData(Plugin.ConfigManager.ToilSlayerDefaultSpawnSettings.Value)), new SpawnData(Plugin.ConfigManager.ToilationToilSlayerSpawnSettings.Value)),
				new TurretHeadData("Manticoil", isSlayer: false, Content.MantiToilControllerPrefab, new MoonSpawnDataList(Plugin.ConfigManager.MantiToilSpawnSettingsMoonList.Value, new SpawnData(Plugin.ConfigManager.MantiToilDefaultSpawnSettings.Value)), new SpawnData(Plugin.ConfigManager.ToilationMantiToilSpawnSettings.Value)),
				new TurretHeadData("Manticoil", isSlayer: true, Content.MantiSlayerControllerPrefab, new MoonSpawnDataList(Plugin.ConfigManager.MantiSlayerSpawnSettingsMoonList.Value, new SpawnData(Plugin.ConfigManager.MantiSlayerDefaultSpawnSettings.Value)), new SpawnData(Plugin.ConfigManager.ToilationMantiSlayerSpawnSettings.Value)),
				new TurretHeadData("Masked", isSlayer: false, Content.ToilMaskedControllerPrefab, new MoonSpawnDataList(Plugin.ConfigManager.ToilMaskedSpawnSettingsMoonList.Value, new SpawnData(Plugin.ConfigManager.ToilMaskedDefaultSpawnSettings.Value)), new SpawnData(Plugin.ConfigManager.ToilationToilMaskedSpawnSettings.Value)),
				new TurretHeadData("Masked", isSlayer: true, Content.SlayerMaskedControllerPrefab, new MoonSpawnDataList(Plugin.ConfigManager.SlayerMaskedSpawnSettingsMoonList.Value, new SpawnData(Plugin.ConfigManager.SlayerMaskedDefaultSpawnSettings.Value)), new SpawnData(Plugin.ConfigManager.ToilationSlayerMaskedSpawnSettings.Value))
			};
			PlayerTurretHeadData = new TurretHeadData(string.Empty, isSlayer: false, null, new MoonSpawnDataList(Plugin.ConfigManager.ToilPlayerSpawnSettingsMoonList.Value, new SpawnData(Plugin.ConfigManager.ToilPlayerDefaultSpawnSettings.Value)), new SpawnData(Plugin.ConfigManager.ToilationToilPlayerSpawnSettings.Value));
			EnemyTurretHeadControllerPairs = new Dictionary<EnemyAI, TurretHeadControllerBehaviour>();
			PlayerTurretHeadControllerPairs = new Dictionary<PlayerControllerB, TurretHeadControllerBehaviour>();
			DeadBodyTurretHeadControllerPairs = new Dictionary<PlayerControllerB, TurretHeadControllerBehaviour>();
			_setDeadBodyTurretHeadOnServerCoroutine = null;
		}

		internal static void Reset()
		{
			TurretHeadDataList.ForEach(delegate(TurretHeadData _)
			{
				_.Reset();
			});
			PlayerTurretHeadData.Reset();
			EnemyTurretHeadControllerPairs.Clear();
			PlayerTurretHeadControllerPairs.Clear();
			DeadBodyTurretHeadControllerPairs.Clear();
			_setDeadBodyTurretHeadOnServerCoroutine = null;
			DespawnAllControllersOnServer();
		}

		internal static bool TrySetEnemyTurretHeadOnServer(EnemyAI enemyScript, bool isSlayer)
		{
			if (!Plugin.IsHostOrServer)
			{
				return false;
			}
			string enemyName = enemyScript.enemyType.enemyName;
			TurretHeadData enemyTurretHeadData = GetEnemyTurretHeadData(enemyName, isSlayer);
			if (enemyTurretHeadData == null)
			{
				Plugin.logger.LogError((object)("Error: Failed to try set \"" + enemyName + "\" Turret-Head on server. TurretHeadData is null."));
				return false;
			}
			SpawnData spawnDataForCurrentMoon = enemyTurretHeadData.GetSpawnDataForCurrentMoon();
			int num = spawnDataForCurrentMoon.MaxSpawnCount;
			if (enemyTurretHeadData.ForceMaxSpawnCount > -1)
			{
				num = enemyTurretHeadData.ForceMaxSpawnCount;
			}
			if (!enemyTurretHeadData.ForceSpawns)
			{
				if (enemyTurretHeadData.SpawnCount >= num)
				{
					return false;
				}
				if (!Utils.RandomPercent(spawnDataForCurrentMoon.SpawnChance))
				{
					return false;
				}
			}
			return SetEnemyTurretHeadOnServer(enemyScript, isSlayer);
		}

		internal static void TrySetPlayerTurretHeadsOnServer()
		{
			if (!Plugin.IsHostOrServer || !StartOfRound.Instance.currentLevel.spawnEnemiesAndScrap || GameNetworkManager.Instance.connectedPlayers == 1)
			{
				return;
			}
			List<PlayerControllerB> list = StartOfRound.Instance.allPlayerScripts.ToList();
			for (int num = list.Count - 1; num >= 0; num--)
			{
				int index = Random.Range(0, num);
				bool isSlayer = Utils.RandomPercent(Plugin.ConfigManager.ToilPlayerSlayerChance.Value);
				PlayerControllerB val = list[index];
				if (((Component)val).gameObject.activeSelf && val.isPlayerControlled)
				{
					TrySetPlayerTurretHeadOnServer(val, isSlayer);
					list.RemoveAt(index);
				}
			}
		}

		internal static bool TrySetPlayerTurretHeadOnServer(PlayerControllerB playerScript, bool isSlayer)
		{
			if (!Plugin.IsHostOrServer)
			{
				return false;
			}
			TurretHeadData playerTurretHeadData = PlayerTurretHeadData;
			SpawnData spawnDataForCurrentMoon = playerTurretHeadData.GetSpawnDataForCurrentMoon();
			int num = spawnDataForCurrentMoon.MaxSpawnCount;
			if (playerTurretHeadData.ForceMaxSpawnCount > -1)
			{
				num = playerTurretHeadData.ForceMaxSpawnCount;
			}
			if (!playerTurretHeadData.ForceSpawns)
			{
				if (playerTurretHeadData.SpawnCount >= num)
				{
					return false;
				}
				if (!Utils.RandomPercent(spawnDataForCurrentMoon.SpawnChance))
				{
					return false;
				}
			}
			return SetPlayerTurretHeadOnServer(playerScript, isSlayer);
		}

		public static bool SetEnemyTurretHeadOnServer(EnemyAI enemyScript, bool isSlayer)
		{
			if (!Plugin.IsHostOrServer)
			{
				return false;
			}
			if ((Object)(object)enemyScript == (Object)null)
			{
				Plugin.logger.LogError((object)$"Error: Failed to set enemy Turret-Head (isSlayer? {isSlayer}) on server. EnemyAI is null.");
				return false;
			}
			string enemyName = enemyScript.enemyType.enemyName;
			if (enemyScript.isEnemyDead)
			{
				Plugin.logger.LogError((object)$"Error: Failed to set enemy \"{enemyName}\" Turret-Head (isSlayer? {isSlayer}) on server. Enemy is already dead.");
				return false;
			}
			if (Utils.IsTurretHead(enemyScript))
			{
				Plugin.logger.LogError((object)$"Error: Failed to set enemy \"{enemyName}\" Turret-Head (isSlayer? {isSlayer}) on server. Enemy is already a Turret-Head.");
				return false;
			}
			TurretHeadData enemyTurretHeadData = GetEnemyTurretHeadData(enemyName, isSlayer);
			if (enemyTurretHeadData == null)
			{
				Plugin.logger.LogError((object)$"Error: Failed to set enemy \"{enemyName}\" Turret-Head (isSlayer? {isSlayer}) on server. TurretHeadData is null.");
				return false;
			}
			SpawnTurretHeadControllerOnServer(enemyTurretHeadData.ControllerPrefab, ((Component)enemyScript).transform);
			Plugin.Instance.LogInfoExtended($"Set enemy \"{enemyName}\" Turret-Head (isSlayer? {isSlayer}) on server.");
			return true;
		}

		public static bool SetPlayerTurretHeadOnServer(PlayerControllerB playerScript, bool isSlayer)
		{
			if (!Plugin.IsHostOrServer)
			{
				return false;
			}
			string playerUsername = playerScript.playerUsername;
			if ((Object)(object)playerScript == (Object)null)
			{
				Plugin.logger.LogError((object)$"Error: Failed to set player \"{playerUsername}\" Turret-Head (isSlayer? {isSlayer}) on server. PlayerControllerB is null.");
				return false;
			}
			if (playerScript.isPlayerDead)
			{
				Plugin.logger.LogError((object)$"Error: Failed to set player \"{playerUsername}\" Turret-Head (isSlayer? {isSlayer}) on server. Player is already dead.");
				return false;
			}
			if (Utils.IsTurretHead(playerScript))
			{
				Plugin.logger.LogError((object)$"Error: Failed to set player \"{playerUsername}\" Turret-Head (isSlayer? {isSlayer}) on server. Player is already a Turret-Head.");
				return false;
			}
			GameObject controllerPrefab = (isSlayer ? Content.SlayerPlayerControllerPrefab : Content.ToilPlayerControllerPrefab);
			SpawnTurretHeadControllerOnServer(controllerPrefab, ((Component)playerScript).transform);
			Plugin.Instance.LogInfoExtended($"Set player \"{playerUsername}\" Turret-Head (isSlayer? {isSlayer}) on server.");
			return true;
		}

		public static void SetDeadBodyTurretHead(PlayerControllerB playerScript, bool isSlayer)
		{
			if (Plugin.IsHostOrServer)
			{
				SetDeadBodyTurretHeadOnServer(playerScript, isSlayer);
			}
			else
			{
				PluginNetworkBehaviour.Instance.SetToilHeadPlayerRagdollServerRpc(PlayerUtils.GetPlayerId(playerScript), isSlayer);
			}
		}

		public static void SetDeadBodyTurretHeadOnServer(PlayerControllerB playerScript, bool isSlayer)
		{
			if (!Plugin.IsHostOrServer)
			{
				return;
			}
			bool value = Plugin.ConfigManager.SpawnRealToiledPlayerRagdolls.Value;
			if (!Plugin.ConfigManager.SpawnToiledPlayerRagdolls.Value)
			{
				Plugin.Instance.LogErrorExtended($"Error: Failed to set player ragdoll Turret-Head (isSlayer? {isSlayer}, isReal? {value}) on server. Spawning player ragdoll Turret-Heads is disabled in the config settings.");
				return;
			}
			if ((Object)(object)playerScript == (Object)null)
			{
				Plugin.logger.LogError((object)$"Error: Failed to set player ragdoll Turret-Head (isSlayer? {isSlayer}, isReal? {value}) on server. PlayerControllerB is null.");
				return;
			}
			if (_setDeadBodyTurretHeadOnServerCoroutine != null)
			{
				((MonoBehaviour)StartOfRound.Instance).StopCoroutine(_setDeadBodyTurretHeadOnServerCoroutine);
			}
			_setDeadBodyTurretHeadOnServerCoroutine = ((MonoBehaviour)StartOfRound.Instance).StartCoroutine(SetDeadBodyTurretHeadOnServerCO(playerScript, isSlayer, value));
		}

		private static IEnumerator SetDeadBodyTurretHeadOnServerCO(PlayerControllerB playerScript, bool isSlayer, bool isReal)
		{
			if (!Plugin.IsHostOrServer)
			{
				yield break;
			}
			string playerUsername = playerScript.playerUsername;
			yield return Utils.WaitUntil(() => (Object)(object)playerScript.deadBody != (Object)null);
			DeadBodyInfo deadBodyScript = playerScript.deadBody;
			if ((Object)(object)deadBodyScript == (Object)null)
			{
				Plugin.logger.LogError((object)$"Error: Failed to set player \"{playerUsername}\" ragdoll Turret-Head (isSlayer? {isSlayer}, isReal? {isReal}) on server. DeadBodyInfo is null.");
				yield break;
			}
			GameObject ragdollObject = ((Component)deadBodyScript).gameObject;
			if (((Object)ragdollObject).name != "PlayerRagdollSpring Variant(Clone)")
			{
				Plugin.logger.LogError((object)$"Error: Failed to set player \"{playerUsername}\" ragdoll Turret-Head (isSlayer? {isSlayer}, isReal? {isReal}) on server. Player ragdoll is not of type \"PlayerRagdollSpring Variant\".");
				yield break;
			}
			yield return Utils.WaitUntil(() => (Object)(object)ragdollObject.GetComponentInChildren<NetworkObject>() != (Object)null);
			NetworkObject ragdollNetworkObject = ragdollObject.GetComponentInChildren<NetworkObject>();
			if ((Object)(object)ragdollNetworkObject == (Object)null)
			{
				Plugin.logger.LogError((object)$"Error: Failed to set player \"{playerUsername}\" ragdoll Turret-Head (isSlayer? {isSlayer}, isReal? {isReal}) on server. NetworkObject is null.");
				yield break;
			}
			if (Utils.IsTurretHead(deadBodyScript))
			{
				Plugin.logger.LogError((object)$"Error: Failed to set player \"{playerUsername}\" ragdoll Turret-Head (isSlayer? {isSlayer}, isReal? {isReal}) on server. Player is already a player ragdoll Turret-Head.");
				yield break;
			}
			GameObject controllerPrefab = (isSlayer ? Content.SlayedDeadBodyControllerPrefab : Content.ToiledDeadBodyControllerPrefab);
			SpawnTurretHeadControllerOnServer(controllerPrefab, ((Component)ragdollNetworkObject).transform);
			Plugin.Instance.LogInfoExtended($"Set player \"{playerUsername}\" ragdoll Turret-Head (isSlayer? {isSlayer}, isReal? {isReal}) on server.");
		}

		private static void SpawnTurretHeadControllerOnServer(GameObject controllerPrefab, Transform parentTransform)
		{
			if (Plugin.IsHostOrServer)
			{
				GameObject val = Object.Instantiate<GameObject>(controllerPrefab, parentTransform);
				val.GetComponent<NetworkObject>().Spawn(false);
				val.transform.SetParent(parentTransform);
				val.GetComponent<TurretHeadControllerBehaviour>().SetupTurret();
			}
		}

		public static void AddEnemyTurretHeadControllerPair(EnemyAI enemyScript, TurretHeadControllerBehaviour behaviour)
		{
			EnemyTurretHeadControllerPairs.Add(enemyScript, behaviour);
		}

		public static void AddPlayerTurretHeadControllerPair(PlayerControllerB playerScript, TurretHeadControllerBehaviour behaviour)
		{
			PlayerTurretHeadControllerPairs.Add(playerScript, behaviour);
		}

		public static void AddDeadBodyTurretHeadControllerPair(PlayerControllerB playerScript, TurretHeadControllerBehaviour behaviour)
		{
			DeadBodyTurretHeadControllerPairs.Add(playerScript, behaviour);
		}

		internal static void AddToEnemySpawnCount(EnemyAI enemyScript, bool isSlayer)
		{
			string enemyName = enemyScript.enemyType.enemyName;
			TurretHeadData enemyTurretHeadData = GetEnemyTurretHeadData(enemyName, isSlayer);
			if (enemyTurretHeadData == null)
			{
				Plugin.logger.LogError((object)("Error: Failed to add to spawn count for enemy \"" + enemyName + "\". TurretHeadData is null."));
				return;
			}
			enemyTurretHeadData.AddToSpawnCount();
			Plugin.Instance.LogInfoExtended($"AddToEnemySpawnCount(); Enemy \"{enemyName}\" SpawnCount: {enemyTurretHeadData.SpawnCount}, MaxSpawnCount: {enemyTurretHeadData.GetSpawnDataForCurrentMoon().MaxSpawnCount}, SpawnChance: {enemyTurretHeadData.GetSpawnDataForCurrentMoon().SpawnChance}");
		}

		internal static void AddToPlayerSpawnCount()
		{
			TurretHeadData playerTurretHeadData = PlayerTurretHeadData;
			playerTurretHeadData.AddToSpawnCount();
		}

		public static TurretHeadData GetEnemyTurretHeadData(string enemyName, bool isSlayer)
		{
			foreach (TurretHeadData turretHeadData in TurretHeadDataList)
			{
				if (!turretHeadData.EnemyName.Equals(enemyName, StringComparison.OrdinalIgnoreCase) || turretHeadData.IsSlayer != isSlayer)
				{
					continue;
				}
				return turretHeadData;
			}
			return null;
		}

		public static void DespawnEnemyControllerOnServer(EnemyAI enemyScript)
		{
			if (!Plugin.IsHostOrServer)
			{
				return;
			}
			string enemyName = enemyScript.enemyType.enemyName;
			if (EnemyTurretHeadControllerPairs.TryGetValue(enemyScript, out var value))
			{
				NetworkObject val = default(NetworkObject);
				if (((Component)value).TryGetComponent<NetworkObject>(ref val))
				{
					val.Despawn(true);
					Plugin.Instance.LogInfoExtended("Despawned enemy \"" + enemyName + "\" Turret-Head controller.");
				}
				else
				{
					Plugin.logger.LogError((object)("Error: Failed to despawn enemy \"" + enemyName + "\" Turret-Head controller. NetworkObject is null."));
				}
				EnemyTurretHeadControllerPairs.Remove(enemyScript);
			}
			else
			{
				Plugin.logger.LogError((object)("Error: Failed to despawn enemy \"" + enemyName + "\" Turret-Head controller. Could not find value from key."));
			}
		}

		public static void DespawnPlayerControllerOnServer(PlayerControllerB playerScript)
		{
			if (!Plugin.IsHostOrServer)
			{
				return;
			}
			string playerUsername = playerScript.playerUsername;
			if (PlayerTurretHeadControllerPairs.TryGetValue(playerScript, out var value))
			{
				NetworkObject val = default(NetworkObject);
				if (((Component)value).TryGetComponent<NetworkObject>(ref val))
				{
					val.Despawn(true);
					Plugin.Instance.LogInfoExtended("Despawned player \"" + playerUsername + "\" Turret-Head controller.");
				}
				else
				{
					Plugin.logger.LogError((object)("Error: Failed to despawn player \"" + playerUsername + "\" Turret-Head controller. NetworkObject is null."));
				}
				PlayerTurretHeadControllerPairs.Remove(playerScript);
			}
			else
			{
				Plugin.logger.LogError((object)("Error: Failed to despawn player \"" + playerUsername + "\" Turret-Head controller. Could not find value from key."));
			}
		}

		public static void DespawnDeadBodyControllerOnServer(PlayerControllerB playerScript)
		{
			if (!Plugin.IsHostOrServer)
			{
				return;
			}
			string playerUsername = playerScript.playerUsername;
			if (DeadBodyTurretHeadControllerPairs.TryGetValue(playerScript, out var value))
			{
				NetworkObject val = default(NetworkObject);
				if (((Component)value).TryGetComponent<NetworkObject>(ref val))
				{
					val.Despawn(true);
					Plugin.Instance.LogInfoExtended("Despawned player \"" + playerUsername + "\" ragdoll Turret-Head controller.");
				}
				else
				{
					Plugin.logger.LogError((object)("Error: Failed to despawn player \"" + playerUsername + "\" ragdoll Turret-Head controller. NetworkObject is null."));
				}
				DeadBodyTurretHeadControllerPairs.Remove(playerScript);
			}
			else
			{
				Plugin.logger.LogError((object)("Error: Failed to despawn player \"" + playerUsername + "\" ragdoll Turret-Head controller. Could not find value from key."));
			}
		}

		private static void DespawnAllControllersOnServer()
		{
			if (!Plugin.IsHostOrServer)
			{
				return;
			}
			try
			{
				TurretHeadControllerBehaviour[] array = Object.FindObjectsByType<TurretHeadControllerBehaviour>((FindObjectsSortMode)0);
				NetworkObject val = default(NetworkObject);
				foreach (TurretHeadControllerBehaviour turretHeadControllerBehaviour in array)
				{
					if (!((Component)turretHeadControllerBehaviour).TryGetComponent<NetworkObject>(ref val))
					{
						Plugin.logger.LogError((object)"Error: Failed to despawn TurretHeadBehaviour. NetworkObject is null.");
					}
					else
					{
						val.Despawn(true);
					}
				}
				Plugin.Instance.LogInfoExtended("Finished despawning all TurretHeadBehaviour(s).");
			}
			catch (Exception arg)
			{
				Plugin.logger.LogError((object)$"Error: Failed to despawn all TurretHeadBehaviour(s).\n\n{arg}");
			}
		}

		public static bool IsEnemyTurretHead(EnemyAI enemyScript)
		{
			return EnemyTurretHeadControllerPairs.ContainsKey(enemyScript);
		}

		public static bool IsPlayerTurretHead(PlayerControllerB playerScript)
		{
			return PlayerTurretHeadControllerPairs.ContainsKey(playerScript);
		}

		public static bool IsDeadBodyTurretHead(PlayerControllerB playerScript)
		{
			return DeadBodyTurretHeadControllerPairs.ContainsKey(playerScript);
		}
	}
	public class Utils
	{
		public static bool RandomPercent(float percent)
		{
			if (percent <= 0f)
			{
				return false;
			}
			if (percent >= 100f)
			{
				return true;
			}
			return Random.value <= percent * 0.01f;
		}

		public static void DisableColliders(GameObject gameObject, bool keepScanNodeEnabled = false)
		{
			Collider[] componentsInChildren = gameObject.GetComponentsInChildren<Collider>();
			Collider[] array = componentsInChildren;
			foreach (Collider val in array)
			{
				if (!keepScanNodeEnabled || !(((Object)((Component)val).gameObject).name == "ScanNode"))
				{
					val.enabled = false;
				}
			}
		}

		public static void DisableRenderers(GameObject gameObject)
		{
			MeshRenderer[] componentsInChildren = gameObject.GetComponentsInChildren<MeshRenderer>();
			foreach (MeshRenderer val in componentsInChildren)
			{
				((Renderer)val).enabled = false;
			}
			SkinnedMeshRenderer[] componentsInChildren2 = gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();
			foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
			{
				((Renderer)val2).enabled = false;
			}
		}

		public static IEnumerator WaitUntil(Func<bool> predicate, float maxDuration = 5f, int iterationsPerSecond = 10)
		{
			float timer = 0f;
			float timePerIteration = 1f / (float)iterationsPerSecond;
			for (; timer < maxDuration; timer += Time.deltaTime)
			{
				if (predicate())
				{
					break;
				}
				yield return (object)new WaitForSeconds(timePerIteration);
			}
		}

		public static bool IsValidEnemy(EnemyAI enemyScript)
		{
			if (IsSpring(enemyScript))
			{
				return true;
			}
			if (IsManticoil(enemyScript))
			{
				return true;
			}
			if (IsMasked(enemyScript))
			{
				return true;
			}
			return false;
		}

		public static bool IsSpring(EnemyAI enemyScript)
		{
			return enemyScript.enemyType.enemyName == "Spring";
		}

		public static bool IsManticoil(EnemyAI enemyScript)
		{
			return enemyScript.enemyType.enemyName == "Manticoil";
		}

		public static bool IsMasked(EnemyAI enemyScript)
		{
			return enemyScript.enemyType.enemyName == "Masked";
		}

		public static bool IsTurretHead(EnemyAI enemyScript)
		{
			return (Object)(object)((Component)enemyScript).GetComponentInChildren<TurretHeadControllerBehaviour>() != (Object)null;
		}

		public static bool IsTurretHead(PlayerControllerB playerScript)
		{
			return (Object)(object)((Component)playerScript).GetComponentInChildren<TurretHeadControllerBehaviour>() != (Object)null;
		}

		public static bool IsTurretHead(DeadBodyInfo deadBodyScript)
		{
			return (Object)(object)((Component)deadBodyScript).GetComponentInChildren<TurretHeadControllerBehaviour>() != (Object)null;
		}

		public static bool IsCurrentMoonToilation()
		{
			if ((Object)(object)StartOfRound.Instance == (Object)null)
			{
				return false;
			}
			string planetName = StartOfRound.Instance.currentLevel.PlanetName;
			if (planetName.Equals("69 Toilation", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (planetName.Contains("Toilation", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "com.github.zehsteam.ToilHead";

		public const string PLUGIN_NAME = "ToilHead";

		public const string PLUGIN_VERSION = "1.7.2";
	}
}
namespace com.github.zehsteam.ToilHead.Patches
{
	[HarmonyPatch(typeof(EnemyAI))]
	internal class EnemyAIPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPatch(ref EnemyAI __instance)
		{
			if (Utils.IsValidEnemy(__instance) && !TurretHeadManager.TrySetEnemyTurretHeadOnServer(__instance, isSlayer: true))
			{
				TurretHeadManager.TrySetEnemyTurretHeadOnServer(__instance, isSlayer: false);
			}
		}

		[HarmonyPatch("HitEnemyServerRpc")]
		[HarmonyPostfix]
		private static void HitEnemyServerRpcPatch(ref EnemyAI __instance, int playerWhoHit)
		{
			if (!__instance.isEnemyDead && TurretHeadManager.EnemyTurretHeadControllerPairs.TryGetValue(__instance, out var value) && value.TurretBehaviour.turretActive)
			{
				value.TurretBehaviour.EnterBerserkModeClientRpc();
			}
		}

		[HarmonyPatch("KillEnemy")]
		[HarmonyPrefix]
		private static void KillEnemyPatch(ref EnemyAI __instance, bool destroy)
		{
			if (Plugin.IsHostOrServer && destroy && TurretHeadManager.IsEnemyTurretHead(__instance))
			{
				TurretHeadManager.DespawnEnemyControllerOnServer(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal class GameNetworkManagerPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPatch()
		{
			AddNetworkPrefabs();
		}

		private static void AddNetworkPrefabs()
		{
			AddNetworkPrefab(Content.NetworkHandlerPrefab);
			AddNetworkPrefab(Content.ToilHeadControllerPrefab);
			AddNetworkPrefab(Content.ToilSlayerControllerPrefab);
			AddNetworkPrefab(Content.MantiToilControllerPrefab);
			AddNetworkPrefab(Content.MantiSlayerControllerPrefab);
			AddNetworkPrefab(Content.ToilPlayerControllerPrefab);
			AddNetworkPrefab(Content.SlayerPlayerControllerPrefab);
			AddNetworkPrefab(Content.ToiledDeadBodyControllerPrefab);
			AddNetworkPrefab(Content.SlayedDeadBodyControllerPrefab);
			AddNetworkPrefab(Content.ToilMaskedControllerPrefab);
			AddNetworkPrefab(Content.SlayerMaskedControllerPrefab);
		}

		private static void AddNetworkPrefab(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				Plugin.logger.LogError((object)"Error: Failed to register network prefab. Prefab is null.");
				return;
			}
			NetworkManager.Singleton.AddNetworkPrefab(prefab);
			Plugin.logger.LogInfo((object)("Registered \"" + ((Object)prefab).name + "\" network prefab."));
		}
	}
	[HarmonyPatch(typeof(MaskedPlayerEnemy))]
	internal class MaskedPlayerEnemyPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPatch(ref EnemyAI __instance)
		{
			if (!TurretHeadManager.TrySetEnemyTurretHeadOnServer(__instance, isSlayer: true))
			{
				TurretHeadManager.TrySetEnemyTurretHeadOnServer(__instance, isSlayer: false);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class PlayerControllerBPatch
	{
		[HarmonyPatch("KillPlayerServerRpc")]
		[HarmonyPrefix]
		private static void KillPlayerServerRpcPatch(ref PlayerControllerB __instance)
		{
			if (TurretHeadManager.IsPlayerTurretHead(__instance))
			{
				TurretHeadManager.DespawnPlayerControllerOnServer(__instance);
			}
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroyPatch(ref PlayerControllerB __instance)
		{
			if (Plugin.IsHostOrServer && TurretHeadManager.IsPlayerTurretHead(__instance))
			{
				TurretHeadManager.DespawnPlayerControllerOnServer(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(RagdollGrabbableObject))]
	internal class RagdollGrabbableObjectPatch
	{
		[HarmonyPatch("OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroyPatch(ref RagdollGrabbableObject __instance)
		{
			if (Plugin.IsHostOrServer)
			{
				PlayerControllerB playerScript = __instance.ragdoll.playerScript;
				if (TurretHeadManager.IsDeadBodyTurretHead(playerScript))
				{
					TurretHeadManager.DespawnDeadBodyControllerOnServer(playerScript);
				}
			}
		}
	}
	[HarmonyPatch(typeof(RoundManager))]
	internal class RoundManagerPatch
	{
		[HarmonyPatch("LoadNewLevel")]
		[HarmonyPostfix]
		private static void LoadNewLevelPatch()
		{
			Plugin.Instance.OnNewLevelLoaded();
		}

		[HarmonyPatch("GenerateNewLevelClientRpc")]
		[HarmonyPrefix]
		private static void GenerateNewLevelClientRpcPatch()
		{
			if (!Plugin.IsHostOrServer)
			{
				Plugin.Instance.OnNewLevelLoaded();
			}
		}

		[HarmonyPatch("FinishGeneratingNewLevelClientRpc")]
		[HarmonyPostfix]
		private static void FinishGeneratingNewLevelClientRpcPatch()
		{
			Plugin.Instance.OnNewLevelFinishedLoading();
		}
	}
	[HarmonyPatch(typeof(SpringManAI))]
	internal class SpringManAIPatch
	{
		[HarmonyPatch("OnCollideWithPlayer")]
		[HarmonyPostfix]
		private static void OnCollideWithPlayerPatch(ref SpringManAI __instance, ref Collider other)
		{
			TurretHeadControllerBehaviour componentInChildren = ((Component)__instance).GetComponentInChildren<TurretHeadControllerBehaviour>();
			if (!((Object)(object)componentInChildren == (Object)null))
			{
				PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>();
				if (!((Object)(object)component == (Object)null) && PlayerUtils.IsLocalPlayer(component) && component.AllowPlayerDeath())
				{
					bool isMinigun = componentInChildren.TurretBehaviour.IsMinigun;
					Plugin.Instance.LogInfoExtended($"SpringManAI OnCollideWithPlayer \"{component.playerUsername}\" isSlayer? {isMinigun}");
					TurretHeadManager.SetDeadBodyTurretHead(component, isMinigun);
				}
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal class StartOfRoundPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePatch()
		{
			SpawnNetworkHandler();
		}

		private static void SpawnNetworkHandler()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.IsHostOrServer)
			{
				GameObject val = Object.Instantiate<GameObject>(Content.NetworkHandlerPrefab, Vector3.zero, Quaternion.identity);
				val.GetComponent<NetworkObject>().Spawn(false);
			}
		}

		[HarmonyPatch("OnClientConnect")]
		[HarmonyPrefix]
		private static void OnClientConnectPatch(ref ulong clientId)
		{
			SendConfigToNewConnectedPlayer(clientId);
		}

		private static void SendConfigToNewConnectedPlayer(ulong clientId)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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)
			if (Plugin.IsHostOrServer)
			{
				ClientRpcParams val = default(ClientRpcParams);
				val.Send = new ClientRpcSendParams
				{
					TargetClientIds = new <>z__ReadOnlyArray<ulong>(new ulong[1] { clientId })
				};
				ClientRpcParams clientRpcParams = val;
				Plugin.logger.LogInfo((object)$"Sending config to client: {clientId}");
				PluginNetworkBehaviour.Instance.SendConfigToPlayerClientRpc(new SyncedConfigData(Plugin.ConfigManager), clientRpcParams);
			}
		}

		[HarmonyPatch("ShipHasLeft")]
		[HarmonyPostfix]
		private static void ShipHasLeftPatch()
		{
			Plugin.Instance.OnShipHasLeft();
		}

		[HarmonyPatch("OnLocalDisconnect")]
		[HarmonyPrefix]
		private static void OnLocalDisconnectPatch()
		{
			Plugin.Instance.OnLocalDisconnect();
		}
	}
	[HarmonyPatch(typeof(Terminal))]
	internal class TerminalPatch
	{
		[HarmonyPatch("CallFunctionInAccessibleTerminalObject")]
		[HarmonyPostfix]
		private static void CallFunctionInAccessibleTerminalObjectPatch(string word, ref bool ___broadcastedCodeThisFrame)
		{
			FollowTerminalAccessibleObjectBehaviour[] array = Object.FindObjectsByType<FollowTerminalAccessibleObjectBehaviour>((FindObjectsSortMode)0);
			FollowTerminalAccessibleObjectBehaviour[] array2 = array;
			foreach (FollowTerminalAccessibleObjectBehaviour followTerminalAccessibleObjectBehaviour in array2)
			{
				if (!(followTerminalAccessibleObjectBehaviour.objectCode != word))
				{
					Plugin.Instance.LogInfoExtended("Found accessible terminal object with corresponding string, calling function.");
					___broadcastedCodeThisFrame = true;
					followTerminalAccessibleObjectBehaviour.CallFunctionFromTerminal();
				}
			}
		}
	}
	[HarmonyPatch(typeof(Turret))]
	internal class TurretPatch
	{
		[HarmonyPatch("CheckForPlayersInLineOfSight")]
		[HarmonyPostfix]
		private static void CheckForPlayersInLineOfSightPatch(ref PlayerControllerB __result)
		{
			if ((Object)(object)__result != (Object)null && TurretHeadManager.IsPlayerTurretHead(__result))
			{
				__result = null;
			}
		}
	}
}
namespace com.github.zehsteam.ToilHead.MonoBehaviours
{
	public class FollowTerminalAccessibleObjectBehaviour : NetworkBehaviour
	{
		[HideInInspector]
		public string objectCode;

		[HideInInspector]
		public float codeAccessCooldownTimer = 7f;

		public InteractEvent terminalCodeEvent;

		public InteractEvent terminalCodeCooldownEvent;

		[Space(3f)]
		[HideInInspector]
		public MeshRenderer[] codeMaterials;

		[HideInInspector]
		public int rows;

		[HideInInspector]
		public int columns;

		private bool initializedValues;

		private TextMeshProUGUI mapRadarText;

		private Image mapRadarBox;

		[HideInInspector]
		public bool inCooldown { get; private set; }

		[HideInInspector]
		public float currentCooldownTimer { get; private set; }

		[HideInInspector]
		public RectTransform mapRadarRectTransform { get; private set; }

		private void Start()
		{
			InitializeValues();
			codeAccessCooldownTimer = Plugin.ConfigManager.TurretCodeAccessCooldownDuration.Value;
		}

		public void InitializeValues()
		{
			//IL_0050: 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_005f: 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)
			//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_008b: 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)
			//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_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (!initializedValues)
			{
				initializedValues = true;
				GameObject val = Object.Instantiate<GameObject>(StartOfRound.Instance.objectCodePrefab, StartOfRound.Instance.mapScreen.mapCameraStationaryUI, false);
				mapRadarRectTransform = val.GetComponent<RectTransform>();
				((Transform)mapRadarRectTransform).position = ((Component)this).transform.position + Vector3.up * 4.35f;
				RectTransform obj = mapRadarRectTransform;
				((Transform)obj).position = ((Transform)obj).position + (((Transform)mapRadarRectTransform).up * 1.2f - ((Transform)mapRadarRectTransform).right * 1.2f);
				mapRadarText = val.GetComponentInChildren<TextMeshProUGUI>();
				((TMP_Text)mapRadarText).text = objectCode;
				mapRadarBox = val.GetComponentInChildren<Image>();
			}
		}

		private void Update()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_0045: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)mapRadarRectTransform == (Object)null))
			{
				((Transform)mapRadarRectTransform).position = ((Component)this).transform.position + Vector3.up * 4.35f;
				RectTransform obj = mapRadarRectTransform;
				((Transform)obj).position = ((Transform)obj).position + (((Transform)mapRadarRectTransform).up * 1.2f - ((Transform)mapRadarRectTransform).right * 1.2f);
			}
		}

		public void CallFunctionFromTerminal()
		{
			if (!inCooldown)
			{
				((UnityEvent<PlayerControllerB>)(object)terminalCodeEvent).Invoke(GameNetworkManager.Instance.localPlayerController);
				if (codeAccessCooldownTimer > 0f)
				{
					currentCooldownTimer = codeAccessCooldownTimer;
					((MonoBehaviour)this).StartCoroutine(countCodeAccessCooldown());
				}
				Plugin.Instance.LogInfoExtended("calling terminal function for code : " + objectCode + "; object name: " + ((Object)((Component)this).gameObject).name);
			}
		}

		public void TerminalCodeCooldownReached()
		{
			((UnityEvent<PlayerControllerB>)(object)terminalCodeCooldownEvent).Invoke((PlayerControllerB)null);
			Plugin.Instance.LogInfoExtended("cooldown reached for object with code : " + objectCode + "; object name: " + ((Object)((Component)this).gameObject).name);
		}

		private IEnumerator countCodeAccessCooldown()
		{
			inCooldown = true;
			if (!initializedValues)
			{
				InitializeValues();
			}
			Image cooldownBar = mapRadarBox;
			Image[] componentsInChildren = ((Component)mapRadarText).gameObject.GetComponentsInChildren<Image>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((int)componentsInChildren[i].type == 3)
				{
					cooldownBar = componentsInChildren[i];
				}
			}
			((Behaviour)cooldownBar).enabled = true;
			((Graphic)mapRadarText).color = Color.red;
			((Graphic)mapRadarBox).color = Color.red;
			while (currentCooldownTimer > 0f)
			{
				yield return null;
				currentCooldownTimer -= Time.deltaTime;
				cooldownBar.fillAmount = currentCooldownTimer / codeAccessCooldownTimer;
			}
			TerminalCodeCooldownReached();
			((Graphic)mapRadarText).color = Color.green;
			((Graphic)mapRadarBox).color = Color.green;
			currentCooldownTimer = 1.5f;
			int frameNum = 0;
			while (currentCooldownTimer > 0f)
			{
				yield return null;
				currentCooldownTimer -= Time.deltaTime;
				cooldownBar.fillAmount = Mathf.Abs(currentCooldownTimer / 1.5f - 1f);
				frameNum++;
				if (frameNum % 7 == 0)
				{
					((Behaviour)mapRadarText).enabled = !((Behaviour)mapRadarText).enabled;
				}
			}
			((Behaviour)mapRadarText).enabled = true;
			((Behaviour)cooldownBar).enabled = false;
			inCooldown = false;
		}

		public voi