Decompiled source of TooManyEmotesScrap v1.0.8

TooManyEmotesScrap.dll

Decompiled 3 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TooManyEmotes;
using TooManyEmotes.Networking;
using TooManyEmotes.Props;
using TooManyEmotesScrap.Config;
using TooManyEmotesScrap.Props;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("TooManyEmotesScrap")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TooManyEmotesScrap")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("287f3e6e-43aa-427d-85bc-6abfb6cdf356")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: InternalsVisibleTo("TooManyEmotes")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace TooManyEmotesScrap
{
	internal static class CustomLogging
	{
		private static ManualLogSource logger;

		public static void InitLogger()
		{
			try
			{
				logger = Logger.CreateLogSource(string.Format("{0}-{1}", "TooManyEmotesScrap", "1.0.6"));
			}
			catch
			{
				logger = Plugin.defaultLogger;
			}
		}

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

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

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

		public static bool Assert(bool condition, string failMessage)
		{
			if (!condition)
			{
				LogWarning(failMessage);
			}
			return condition;
		}
	}
	[BepInPlugin("FlipMods.TooManyEmotesScrap", "TooManyEmotesScrap", "1.0.6")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private Harmony _harmony;

		public static Plugin instance;

		public static string recommendedTMEVersion = "2.2.0";

		public static ManualLogSource defaultLogger => ((BaseUnityPlugin)instance).Logger;

		private void Awake()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			instance = this;
			CustomLogging.InitLogger();
			ConfigSettings.BindConfigSettings();
			_harmony = new Harmony("TooManyEmotesScrap");
			CustomLogging.Log("Recommended minimum TooManyEmotes version: " + recommendedTMEVersion + " - Current version: " + ((BaseUnityPlugin)Plugin.instance).Info.Metadata.Version);
			PatchAll();
			CustomLogging.Log("TooManyEmotesScrap finished loading!");
			CustomLogging.LogWarning("NOTE: You will be unable to join other players (and they will be unable to join you) unless you either both have this mod enabled, or both have this mod disabled.\nIf you are hosting a lobby for random players to join, or you are looking to join random servers, it might be best to disable this mod for the best compatibility.");
		}

		private void PatchAll()
		{
			IEnumerable<Type> enumerable;
			try
			{
				enumerable = Assembly.GetExecutingAssembly().GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				enumerable = ex.Types.Where((Type t) => t != null);
			}
			foreach (Type item in enumerable)
			{
				try
				{
					_harmony.PatchAll(item);
				}
				catch
				{
					if (item == typeof(TooManyEmotesEvents))
					{
						CustomLogging.LogError("Error initializing mod with TooManyEmotes. Maybe you aren't running the minimum version of TME that this mod's version requires?");
					}
				}
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "FlipMods.TooManyEmotesScrap";

		public const string PLUGIN_NAME = "TooManyEmotesScrap";

		public const string PLUGIN_VERSION = "1.0.6";
	}
	[HarmonyPatch]
	public static class TooManyEmotesEvents
	{
		[HarmonyPatch(typeof(ConfigSync), "OnSynced")]
		[HarmonyPostfix]
		private static void OnConfigSynced()
		{
			GrabbableEmotePropManager.AddGrabbableEmotePropsMoons();
			GrabbableEmotePropManager.CheckIfShouldRemovePropEmotesFromUnlockedEmotes();
		}
	}
}
namespace TooManyEmotesScrap.Props
{
	public static class GrabbableEmotePropManager
	{
		private static Dictionary<string, Item> originalItems = new Dictionary<string, Item>();

		public static List<EmotePropData> grabbableEmotePropsData = new List<EmotePropData>();

		private static string defaultItemName = "dust pan";

		private static string defaultTwoHandedItemName = "v-type engine";

		private static Item defaultPropItemData;

		private static Item defaultPropItemDataTwoHanded;

		private static GameObject scanNodePrefab;

		public static List<EmotePropData> emotePropsData => EmotePropManager.emotePropsData;

		public static Dictionary<string, EmotePropData> emotePropsDataDict => EmotePropManager.emotePropsDataDict;

		public static int startGrabbableItemId => (HelperTools.allItems != null && numGrabbableEmoteProps > 0 && grabbableEmotePropsData[0] != null) ? HelperTools.allItems.IndexOf(grabbableEmotePropsData[0].itemData) : (-1);

		public static int numGrabbableEmoteProps => (grabbableEmotePropsData != null) ? grabbableEmotePropsData.Count : 0;

		[HarmonyPatch(typeof(StartOfRound), "OnDisable")]
		[HarmonyPrefix]
		private static void Reset()
		{
			UnregisterGrabbableEmoteProps();
			RemoveGrabbableEmotePropsMoons();
		}

		[HarmonyPatch(typeof(GameNetworkManager), "Start")]
		[HarmonyPostfix]
		private static void CreateAllGrabbablePropsData(GameNetworkManager __instance)
		{
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0380: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_0438: Unknown result type (might be due to invalid IL or missing references)
			//IL_044c: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0490: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0504: Unknown result type (might be due to invalid IL or missing references)
			//IL_0518: Unknown result type (might be due to invalid IL or missing references)
			//IL_0548: Unknown result type (might be due to invalid IL or missing references)
			//IL_055c: Unknown result type (might be due to invalid IL or missing references)
			//IL_058b: Unknown result type (might be due to invalid IL or missing references)
			//IL_059f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0611: Unknown result type (might be due to invalid IL or missing references)
			//IL_0625: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)defaultPropItemData == (Object)null || (Object)(object)defaultPropItemDataTwoHanded == (Object)null)
			{
				NetworkManager singleton = NetworkManager.Singleton;
				object obj;
				if (singleton == null)
				{
					obj = null;
				}
				else
				{
					NetworkConfig networkConfig = singleton.NetworkConfig;
					if (networkConfig == null)
					{
						obj = null;
					}
					else
					{
						NetworkPrefabs prefabs = networkConfig.Prefabs;
						obj = ((prefabs != null) ? prefabs.Prefabs : null);
					}
				}
				if (obj != null)
				{
					GrabbableObject val = default(GrabbableObject);
					foreach (NetworkPrefab prefab in NetworkManager.Singleton.NetworkConfig.Prefabs.Prefabs)
					{
						if (!((Object)(object)prefab?.Prefab != (Object)null) || !prefab.Prefab.TryGetComponent<GrabbableObject>(ref val) || !((Object)(object)val?.itemProperties != (Object)null) || string.IsNullOrEmpty(val.itemProperties.itemName))
						{
							continue;
						}
						string text = val.itemProperties.itemName.ToLower();
						if (!originalItems.ContainsKey(text))
						{
							originalItems.Add(text, val.itemProperties);
						}
						if (!(text == defaultItemName) && !(text == defaultTwoHandedItemName))
						{
							continue;
						}
						Item val2 = Object.Instantiate<Item>(val.itemProperties);
						val2.itemName = "";
						val2.spawnPrefab = null;
						val2.isScrap = true;
						val2.itemSpawnsOnGround = true;
						val2.isConductiveMetal = false;
						val2.canBeGrabbedBeforeGameStart = true;
						val2.requiresBattery = false;
						val2.creditsWorth = 100;
						val2.minValue = 80;
						val2.maxValue = 120;
						val2.weight = 1f;
						val2.toolTips = new string[1] { "Perform emote [RMB]" };
						if (text == defaultItemName && (Object)(object)defaultPropItemData == (Object)null)
						{
							val2.twoHanded = false;
							defaultPropItemData = val2;
							if ((Object)(object)scanNodePrefab == (Object)null)
							{
								ScanNodeProperties componentInChildren = ((Component)val).GetComponentInChildren<ScanNodeProperties>();
								scanNodePrefab = ((componentInChildren != null) ? ((Component)componentInChildren).gameObject : null);
								if ((Object)(object)scanNodePrefab != (Object)null)
								{
									scanNodePrefab = Object.Instantiate<GameObject>(scanNodePrefab);
									((Object)scanNodePrefab).name = "ScanNode";
									scanNodePrefab.layer = 22;
									ScanNodeProperties componentInChildren2 = scanNodePrefab.GetComponentInChildren<ScanNodeProperties>();
									componentInChildren2.headerText = "Prop";
									componentInChildren2.subText = "Value:";
									componentInChildren2.minRange = 1;
									componentInChildren2.maxRange = 15;
									componentInChildren2.scrapValue = 0;
								}
							}
						}
						else if (text == defaultTwoHandedItemName && (Object)(object)defaultPropItemDataTwoHanded == (Object)null)
						{
							val2.twoHanded = true;
							defaultPropItemDataTwoHanded = val2;
						}
					}
					if ((Object)(object)scanNodePrefab == (Object)null)
					{
						CustomLogging.LogError("Failed to create ScanNode prefab.");
					}
					if (!Object.op_Implicit((Object)(object)defaultPropItemData))
					{
						CustomLogging.LogError("Failed to create default prop item data.");
					}
					if (!Object.op_Implicit((Object)(object)defaultPropItemDataTwoHanded))
					{
						CustomLogging.LogError("Failed to create default two-handed prop item data.");
					}
				}
			}
			CreateGrabbablePropData("sexy_saxophone.sexy_sax.prop", isScrap: true, 0, 120, 8, 1.05f, two_handed: false, new Vector3(-0.15f, 0.08f, -0.055f), new Vector3(0f, 100f, 80f), "big bolt");
			CreateGrabbablePropData("trombone.prop", isScrap: true, 0, 80, 10, 1.05f, two_handed: false, new Vector3(-0.155f, 0.325f, -0.015f), new Vector3(-90f, -80f, 0f), "big bolt");
			CreateGrabbablePropData("baseball_bat.prop", isScrap: true, 0, 80, 10, 1.03f, two_handed: false, new Vector3(0.3f, 0.2f, 0.02f), new Vector3(0f, 0f, -160f), "dust pan");
			CreateGrabbablePropData("junk_food.prop", isScrap: true, 0, 60, 13, 0f, two_handed: false, new Vector3(-0.02f, 0.05f, -0.03f), new Vector3(-10f, 110f, -10f));
			CreateGrabbablePropData("red_card.prop", isScrap: true, 0, 60, 13, 0f, two_handed: false, new Vector3(0.08f, 0.075f, -0.075f), new Vector3(-10f, 100f, -10f));
			CreateGrabbablePropData("perfect_score.prop", isScrap: true, 0, 60, 13, 1.05f, two_handed: false, new Vector3(-0.1f, 0.025f, -0.027f), new Vector3(-10f, 110f, -10f), "toy robot");
			CreateGrabbablePropData("old_chair.prop", isScrap: true, 0, 100, 10, 1.15f, two_handed: true, new Vector3(0f, 0.1f, 0.6f), new Vector3(85f, 180f, 0f), "toy robot");
			CreateGrabbablePropData("paddle.prop", isScrap: true, 0, 60, 13, 1.01f, two_handed: false, new Vector3(0.15f, 0.08f, -0.01f), new Vector3(0f, 95f, -10f), "airhorn");
			CreateGrabbablePropData("dumbbell.prop", isScrap: true, 0, 120, 8, 1.2f, two_handed: false, new Vector3(0.015f, -0.08f, 0.02f), new Vector3(0f, 10f, 0f), "big bolt");
			CreateGrabbablePropData("gamepad.prop", isScrap: true, 0, 120, 8, 1.01f, two_handed: false, new Vector3(-0.03f, 0.15f, -0.09f), new Vector3(160f, 104f, 0f), "airhorn");
			CreateGrabbablePropData("jar_of_dirt.prop", isScrap: true, 0, 120, 8, 1.05f, two_handed: false, new Vector3(-0.2f, 0.15f, -0.07f), new Vector3(100f, 104f, 0f), "magnifying glass");
		}

		private static void CreateGrabbablePropData(string propName, bool isScrap = true, int purchasePrice = 0, int value = 100, int rarity = 10, float weight = 1f, bool two_handed = false, Vector3 positionOffset = default(Vector3), Vector3 rotationOffset = default(Vector3), string copySfxFromItem = "")
		{
			//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0391: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0600: Unknown result type (might be due to invalid IL or missing references)
			//IL_0605: Unknown result type (might be due to invalid IL or missing references)
			//IL_060d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0612: Unknown result type (might be due to invalid IL or missing references)
			if (!emotePropsDataDict.TryGetValue(propName, out var value2))
			{
				CustomLogging.LogWarning("Failed to assign prop as scrap: " + propName + ". Prop does not exist!");
				return;
			}
			if (value2.isGrabbableObject || grabbableEmotePropsData.Contains(value2))
			{
				if (!grabbableEmotePropsData.Contains(value2))
				{
					grabbableEmotePropsData.Add(value2);
				}
				return;
			}
			AudioClip grabSFX = null;
			AudioClip dropSFX = null;
			AudioClip pocketSFX = null;
			AudioClip throwSFX = null;
			if (copySfxFromItem != "")
			{
				if (originalItems.TryGetValue(copySfxFromItem, out var value3))
				{
					grabSFX = value3.grabSFX;
					dropSFX = value3.dropSFX;
					pocketSFX = value3.pocketSFX;
					throwSFX = value3.throwSFX;
				}
				else
				{
					CustomLogging.LogError("Could not copy item SFX from item: \"" + copySfxFromItem + "\". Item does not exist? This is okay.");
				}
			}
			value2.isGrabbableObject = false;
			if (value2.parentEmotes != null && value2.parentEmotes.Count > 0)
			{
				foreach (UnlockableEmote parentEmote in value2.parentEmotes)
				{
					parentEmote.requiredHeldPropPrefab = value2.propPrefab;
				}
				try
				{
					CustomLogging.Log("Creating item data for emote prop: " + propName + ". Assigned emote: " + value2.parentEmotes[0].emoteName);
					NetworkObject component = value2.propPrefab.GetComponent<NetworkObject>();
					if ((Object)(object)component == (Object)null)
					{
						CustomLogging.LogError("Cannot register grabbable emote prop prefab without a NetworkObject component.");
						return;
					}
					component.AutoObjectParentSync = false;
					component.DontDestroyWithOwner = true;
					string text = propName.Split(new char[1] { '.' })[0].Replace('_', ' ');
					text = char.ToUpper(text[0]) + text.Substring(1).ToLower();
					GrabbablePropObject val = value2.propPrefab.GetComponent<GrabbablePropObject>();
					if ((Object)(object)val == (Object)null)
					{
						val = value2.propPrefab.AddComponent<GrabbablePropObject>();
					}
					val.emotePropData = value2;
					((GrabbableObject)val).itemProperties = null;
					((GrabbableObject)val).grabbable = true;
					((GrabbableObject)val).mainObjectRenderer = value2.propPrefab.GetComponentInChildren<MeshRenderer>();
					((Component)val).tag = "PhysicsProp";
					((Component)val).gameObject.layer = 6;
					val.sfxAudioSource = value2.propPrefab.AddComponent<AudioSource>();
					val.sfxAudioSource.minDistance = 4f;
					val.sfxAudioSource.maxDistance = 18f;
					val.sfxAudioSource.spatialBlend = 1f;
					val.sfxAudioSource.dopplerLevel = 0f;
					ScanNodeProperties val2 = value2.propPrefab.GetComponentInChildren<ScanNodeProperties>();
					if ((Object)(object)val2 == (Object)null)
					{
						GameObject val3 = Object.Instantiate<GameObject>(scanNodePrefab);
						((Object)val3).name = "ScanNode";
						BoxCollider component2 = val3.GetComponent<BoxCollider>();
						BoxCollider componentInChildren = ((Component)val).GetComponentInChildren<BoxCollider>();
						component2.center = componentInChildren.center;
						component2.size = componentInChildren.size;
						val3.transform.SetParent(value2.propPrefab.transform);
						val3.transform.position = val3.transform.parent.position + Vector3.up * component2.size.y;
						component2.center = new Vector3(component2.center.x, 0f, component2.center.z);
						val3.transform.localRotation = Quaternion.identity;
						val3.transform.localScale = Vector3.one;
						val2 = val3.GetComponent<ScanNodeProperties>();
					}
					val.scanNodeProperties = val2;
					val2.scrapValue = value;
					val2.headerText = text;
					val2.subText = "Value:";
					val2.creatureScanID = -1;
					val2.requiresLineOfSight = true;
					val2.maxRange = 15;
					val2.minRange = 0;
					val2.nodeType = 2;
					value2.itemName = text;
					value2.grabbablePropObject = val;
					value2.isScrap = isScrap;
					value2.rarity = rarity;
					value2.twoHanded = two_handed;
					value2.minValue = Mathf.Max(value - 20, 0);
					value2.maxValue = Mathf.Max(value + 20, 0);
					value2.weight = Mathf.Clamp(weight, 1f, 10f);
					value2.positionOffset = positionOffset;
					value2.rotationOffset = rotationOffset;
					value2.restingRotation = value2.propPrefab.transform.eulerAngles;
					value2.verticalOffset = value2.propPrefab.transform.position.y;
					Item val4 = (value2.twoHanded ? defaultPropItemDataTwoHanded : defaultPropItemData);
					if ((Object)(object)val4 == (Object)null)
					{
						CustomLogging.LogError("Failed to create ItemData for prop: " + value2.propName);
						return;
					}
					Item val5 = value2.itemData;
					if ((Object)(object)val5 == (Object)null)
					{
						val5 = (value2.itemData = Object.Instantiate<Item>(val4));
						if (Object.op_Implicit((Object)(object)value2.grabbablePropObject))
						{
							((GrabbableObject)value2.grabbablePropObject).itemProperties = val5;
						}
					}
					((Object)val5).name = value2.itemName + ".prop";
					val5.itemName = value2.itemName;
					val5.spawnPrefab = value2.propPrefab;
					val5.saveItemVariable = false;
					val5.weight = value2.weight;
					val5.isScrap = value2.isScrap;
					val5.twoHanded = value2.twoHanded;
					val5.minValue = Mathf.Max(value2.minValue, 0);
					val5.maxValue = Mathf.Max(value2.maxValue, 0);
					val5.positionOffset = value2.positionOffset;
					val5.rotationOffset = value2.rotationOffset;
					val5.restingRotation = value2.restingRotation;
					val5.verticalOffset = value2.verticalOffset;
					val5.grabSFX = grabSFX;
					val5.dropSFX = dropSFX;
					val5.pocketSFX = pocketSFX;
					val5.throwSFX = throwSFX;
					NetworkManager.Singleton.AddNetworkPrefab(value2.propPrefab);
					value2.isGrabbableObject = true;
					if (!grabbableEmotePropsData.Contains(value2))
					{
						grabbableEmotePropsData.Add(value2);
					}
					return;
				}
				catch (Exception ex)
				{
					CustomLogging.LogError("Failed to create item data for emote prop: " + propName + ". Error: " + ex);
					value2.isGrabbableObject = false;
					return;
				}
			}
			CustomLogging.LogError("Failed to assign emote to emote prop. Could not find emote for prop: " + propName + ". Continuing anyways.");
			value2.isGrabbableObject = false;
		}

		[HarmonyPatch(typeof(StartOfRound), "Start")]
		[HarmonyPrefix]
		private static void RegisterGrabbableEmoteProps(StartOfRound __instance)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			if (grabbableEmotePropsData == null)
			{
				CustomLogging.LogError("Failed to register grabbable emote props.");
				return;
			}
			foreach (EmotePropData grabbableEmotePropsDatum in grabbableEmotePropsData)
			{
				if (grabbableEmotePropsDatum.isGrabbableObject)
				{
					CustomLogging.Log("Registering grabbable emote prop: " + grabbableEmotePropsDatum.propName);
					if (!HelperTools.allItems.Contains(grabbableEmotePropsDatum.itemData))
					{
						HelperTools.allItems.Add(grabbableEmotePropsDatum.itemData);
					}
					SpawnableItemWithRarity itemRarityData = grabbableEmotePropsDatum.itemRarityData;
					if (itemRarityData == null)
					{
						itemRarityData = (grabbableEmotePropsDatum.itemRarityData = new SpawnableItemWithRarity());
						itemRarityData.spawnableItem = grabbableEmotePropsDatum.itemData;
						itemRarityData.rarity = grabbableEmotePropsDatum.rarity;
					}
				}
			}
		}

		public static void UnregisterGrabbableEmoteProps()
		{
			if (grabbableEmotePropsData == null || HelperTools.allItems == null)
			{
				return;
			}
			foreach (EmotePropData grabbableEmotePropsDatum in grabbableEmotePropsData)
			{
				if ((Object)(object)grabbableEmotePropsDatum?.itemData != (Object)null)
				{
					HelperTools.allItems.Remove(grabbableEmotePropsDatum.itemData);
				}
			}
		}

		public static void AddGrabbableEmotePropsMoons()
		{
			if (grabbableEmotePropsData == null || HelperTools.selectableLevels == null)
			{
				CustomLogging.LogError("Error adding grabbable emote props to moons.");
				return;
			}
			foreach (EmotePropData grabbableEmotePropsDatum in grabbableEmotePropsData)
			{
				if (grabbableEmotePropsDatum.parentEmotes != null)
				{
					foreach (UnlockableEmote parentEmote in grabbableEmotePropsDatum.parentEmotes)
					{
						parentEmote.purchasable = false;
						parentEmote.requiresHeldProp = true;
						if (parentEmote.emoteSyncGroup == null)
						{
							continue;
						}
						foreach (UnlockableEmote item in parentEmote.emoteSyncGroup)
						{
							if (item != parentEmote)
							{
								item.purchasable = false;
							}
						}
					}
				}
				SelectableLevel[] selectableLevels = HelperTools.selectableLevels;
				foreach (SelectableLevel val in selectableLevels)
				{
					if (!val.spawnableScrap.Contains(grabbableEmotePropsDatum.itemRarityData))
					{
						val.spawnableScrap.Add(grabbableEmotePropsDatum.itemRarityData);
					}
				}
			}
		}

		public static void RemoveGrabbableEmotePropsMoons()
		{
			if (emotePropsData == null || HelperTools.selectableLevels == null)
			{
				CustomLogging.LogError("Error removing grabbable emote props from moons.");
				return;
			}
			foreach (EmotePropData emotePropsDatum in emotePropsData)
			{
				foreach (UnlockableEmote parentEmote in emotePropsDatum.parentEmotes)
				{
					parentEmote.purchasable = true;
					parentEmote.requiresHeldProp = false;
				}
				SelectableLevel[] selectableLevels = HelperTools.selectableLevels;
				foreach (SelectableLevel val in selectableLevels)
				{
					if (val.spawnableScrap.Contains(emotePropsDatum.itemRarityData))
					{
						val.spawnableScrap.Remove(emotePropsDatum.itemRarityData);
					}
				}
			}
		}

		public static void CheckIfShouldRemovePropEmotesFromUnlockedEmotes()
		{
			if (ConfigSync.instance.syncUnlockEverything && !ConfigSync.instance.syncRemoveGrabbableEmotesPartyPooperMode)
			{
				return;
			}
			foreach (EmotePropData grabbableEmotePropsDatum in grabbableEmotePropsData)
			{
				if (grabbableEmotePropsDatum.parentEmotes == null)
				{
					continue;
				}
				foreach (UnlockableEmote parentEmote in grabbableEmotePropsDatum.parentEmotes)
				{
					if (parentEmote == null || !parentEmote.requiresHeldProp)
					{
						continue;
					}
					SessionManager.RemoveEmoteLocal(parentEmote);
					if (parentEmote.complementary)
					{
						EmotesManager.complementaryEmotes.Remove(parentEmote);
					}
					if (parentEmote.emoteSyncGroup == null)
					{
						continue;
					}
					foreach (UnlockableEmote item in parentEmote.emoteSyncGroup)
					{
						if (item != parentEmote)
						{
							SessionManager.RemoveEmoteLocal(item);
							if (item.complementary)
							{
								EmotesManager.complementaryEmotes.Remove(item);
							}
						}
					}
				}
			}
		}

		[HarmonyPatch(typeof(GameNetworkManager), "SaveItemsInShip")]
		[HarmonyPostfix]
		private static void OnSaveGrabbableShipObjects(GameNetworkManager __instance)
		{
			if (HelperTools.allItems != null && startGrabbableItemId >= 0 && numGrabbableEmoteProps > 0)
			{
				int[] array = ES3.Load<int[]>("shipGrabbableItemIDs", HelperTools.currentSaveFileName, new int[0]);
				if (array.Length != 0)
				{
					List<int> list = new List<int>();
					for (int i = 0; i < array.Length; i++)
					{
						int num = array[i];
						if (num >= startGrabbableItemId && num < startGrabbableItemId + numGrabbableEmoteProps)
						{
							list.Add(i);
						}
					}
					if (list.Count > 0)
					{
						CustomLogging.Log("Saving " + list.Count + " grabbable prop items on ship. Grabbable props start id: " + startGrabbableItemId + " Num grabbable prop ids: " + numGrabbableEmoteProps);
						ES3.Save<int[]>("TooManyEmotes.GrabbablePropIndexes", list.ToArray(), HelperTools.currentSaveFileName);
						ES3.Save<int>("TooManyEmotes.StartGrabbablePropItemId", startGrabbableItemId, HelperTools.currentSaveFileName);
						ES3.Save<int>("TooManyEmotes.NumGrabbableProps", numGrabbableEmoteProps, HelperTools.currentSaveFileName);
						return;
					}
				}
			}
			ES3.DeleteKey("TooManyEmotes.GrabbablePropIndexes", HelperTools.currentSaveFileName);
			ES3.DeleteKey("TooManyEmotes.StartGrabbablePropItemId", HelperTools.currentSaveFileName);
			ES3.DeleteKey("TooManyEmotes.NumGrabbableProps", HelperTools.currentSaveFileName);
		}

		[HarmonyPatch(typeof(StartOfRound), "LoadShipGrabbableItems")]
		[HarmonyPrefix]
		private static void OnLoadGrabbableShipObjects(StartOfRound __instance)
		{
			if (HelperTools.allItems == null || grabbableEmotePropsData == null || startGrabbableItemId < 0 || numGrabbableEmoteProps <= 0 || !ES3.KeyExists("shipGrabbableItemIDs", HelperTools.currentSaveFileName) || !ES3.KeyExists("TooManyEmotes.GrabbablePropIndexes", HelperTools.currentSaveFileName))
			{
				return;
			}
			int[] array = ES3.Load<int[]>("shipGrabbableItemIDs", HelperTools.currentSaveFileName);
			int[] array2 = ES3.Load<int[]>("TooManyEmotes.GrabbablePropIndexes", HelperTools.currentSaveFileName);
			int num = ES3.Load<int>("TooManyEmotes.StartGrabbablePropItemId", HelperTools.currentSaveFileName);
			int num2 = ES3.Load<int>("TooManyEmotes.NumGrabbableProps", HelperTools.currentSaveFileName);
			if (num == startGrabbableItemId && num2 == numGrabbableEmoteProps)
			{
				return;
			}
			int num3 = 0;
			int[] array3 = array2;
			foreach (int num4 in array3)
			{
				if (num4 < 0 || num4 >= array.Length)
				{
					continue;
				}
				int num5 = array[num4];
				int num6 = num5;
				if (num5 >= num && num5 < num + num2)
				{
					num6 = num5 - num + startGrabbableItemId;
					if (num6 >= startGrabbableItemId + numGrabbableEmoteProps)
					{
						num6 = startGrabbableItemId;
					}
					array[num4] = num6;
					num3++;
				}
			}
			if (num3 > 0)
			{
				ES3.Save<int[]>("shipGrabbableItemIDs", array, HelperTools.currentSaveFileName);
				CustomLogging.LogWarning("Item list has changed since last session. Updating grabbable emote prop start id from: " + num + " to: " + startGrabbableItemId);
			}
		}
	}
}
namespace TooManyEmotesScrap.Config
{
	public static class ConfigSettings
	{
		public static ConfigEntry<bool> dummyConfig;

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

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

		public static void BindConfigSettings()
		{
		}

		public static ConfigEntry<T> AddConfigEntry<T>(string section, string name, T defaultValue, string description)
		{
			ConfigEntry<T> val = ((BaseUnityPlugin)Plugin.instance).Config.Bind<T>(section, name, defaultValue, description);
			currentConfigEntries.Add(((ConfigEntryBase)val).Definition.Key, (ConfigEntryBase)(object)val);
			return val;
		}

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