Decompiled source of CustomItemSpawner v1.1.1

CustomItemSpawner/CustomItemSpawner.dll

Decompiled 6 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("CustomItemSpawner")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CustomItemSpawner")]
[assembly: AssemblyTitle("CustomItemSpawner")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 CustomItemSpawner
{
	internal struct ItemDirectoryEntry
	{
		internal int Index;

		internal string Name;
	}
	internal static class CreateItemDirectory
	{
		internal static ItemDirectoryEntry[] Create()
		{
			GameObject[] array = (((Object)(object)PrefabsDirectory.instance == (Object)null) ? null : PrefabsDirectory.instance.directory);
			if (array == null)
			{
				return new ItemDirectoryEntry[0];
			}
			ItemDirectoryEntry[] array2 = new ItemDirectoryEntry[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				GameObject val = array[i];
				array2[i] = new ItemDirectoryEntry
				{
					Index = i,
					Name = (((Object)(object)val == (Object)null) ? null : ((Object)val).name)
				};
			}
			return array2;
		}
	}
	[BepInPlugin("com.Exocet.customitemspawner", "Custom Item Spawner", "1.1.0")]
	public sealed class CustomItemSpawnerPlugin : BaseUnityPlugin
	{
		internal static ConfigEntry<string> CrateDirectoryItem;

		internal static ConfigEntry<KeyCode> SpawnKey;

		internal static ConfigEntry<bool> CustomBallastObject;

		internal static ConfigEntry<int> CustomObjectMass;

		internal static ManualLogSource Log;

		internal static ConfigFile PluginConfig;

		internal static ItemDirectoryEntry[] ItemDirectory;

		internal static Dictionary<string, int> ItemIndices;

		private static bool itemDirectoryCreated;

		private void Awake()
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			PluginConfig = ((BaseUnityPlugin)this).Config;
			SpawnKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "Spawn Key", (KeyCode)287, "Key used to spawn the custom object.");
			CustomBallastObject = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Custom Ballast Object", true, "Apply the custom mass and name to spawned objects.");
			CustomObjectMass = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Custom Object Mass", 10000, new ConfigDescription("User defined mass value for this spawned object.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1000, 100000), Array.Empty<object>()));
			CrateDirectoryItem = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Game Item Directory", "(Loading item directory...)", new ConfigDescription("Prefab name from PrefabsDirectory.directory used as the custom object.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[1] { "(Loading item directory...)" }), Array.Empty<object>()));
			new Harmony("com.Exocet.customitemspawner").PatchAll();
			((MonoBehaviour)this).StartCoroutine(InitializeItemDirectoryWhenReady());
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Custom object spawner loaded.");
		}

		private void Update()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(SpawnKey.Value))
			{
				CustomItemSpawner.Spawn();
			}
		}

		internal static void CreateItemDirectoryOnce()
		{
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Expected O, but got Unknown
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Expected O, but got Unknown
			if (itemDirectoryCreated || (Object)(object)PrefabsDirectory.instance == (Object)null || PrefabsDirectory.instance.directory == null || PrefabsDirectory.instance.directory.Length == 0)
			{
				return;
			}
			ItemDirectory = CreateItemDirectory.Create();
			Log.LogDebug((object)$"Created item directory with {ItemDirectory.Length} entries.");
			List<string> list = new List<string>();
			ItemIndices = new Dictionary<string, int>();
			for (int i = 0; i < ItemDirectory.Length; i++)
			{
				string name = ItemDirectory[i].Name;
				if (name != null && !ItemIndices.ContainsKey(name))
				{
					list.Add(name);
					ItemIndices.Add(name, ItemDirectory[i].Index);
				}
			}
			if (list.Count != 0)
			{
				itemDirectoryCreated = true;
				string text = ((ItemDirectory.Length > 23) ? ItemDirectory[23].Name : null);
				if (text == null || !ItemIndices.ContainsKey(text))
				{
					text = list[0];
				}
				if (!ItemIndices.ContainsKey(CrateDirectoryItem.Value))
				{
					CrateDirectoryItem.Value = text;
				}
				PluginConfig.Remove(new ConfigDefinition("General", "Game Item Directory"));
				CrateDirectoryItem = PluginConfig.Bind<string>("General", "Game Item Directory", text, new ConfigDescription("Prefab name from PrefabsDirectory.directory used as the custom object.", (AcceptableValueBase)(object)new AcceptableValueList<string>(list.ToArray()), Array.Empty<object>()));
			}
		}

		private static IEnumerator InitializeItemDirectoryWhenReady()
		{
			while (!itemDirectoryCreated)
			{
				CreateItemDirectoryOnce();
				yield return null;
			}
		}
	}
	internal static class CustomItemSpawner
	{
		private const string ModDataPrefix = "CustomItemSpawner.item.";

		private const string MarkerSuffix = ".customObject";

		private const string MassSuffix = ".mass";

		private const string NameSuffix = ".name";

		internal static void Spawn()
		{
			//IL_0103: 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_0112: 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)
			PrefabsDirectory val = (((Object)(object)SaveLoadManager.instance == (Object)null) ? null : ((Component)SaveLoadManager.instance).GetComponent<PrefabsDirectory>());
			string text = ((CustomItemSpawnerPlugin.CrateDirectoryItem == null) ? null : CustomItemSpawnerPlugin.CrateDirectoryItem.Value);
			int value;
			int num = ((CustomItemSpawnerPlugin.ItemIndices == null || text == null || !CustomItemSpawnerPlugin.ItemIndices.TryGetValue(text, out value)) ? (-1) : value);
			if ((Object)(object)val == (Object)null || val.directory == null || num < 0 || num >= val.directory.Length)
			{
				CustomItemSpawnerPlugin.Log.LogError((object)("Cannot spawn custom object: prefab '" + text + "' is unavailable."));
				return;
			}
			GameObject val2 = val.directory[num];
			if ((Object)(object)val2 == (Object)null)
			{
				CustomItemSpawnerPlugin.Log.LogError((object)$"Cannot spawn custom object: PrefabsDirectory index {num} is empty.");
				return;
			}
			if ((Object)(object)Refs.ovrCameraRig == (Object)null)
			{
				CustomItemSpawnerPlugin.Log.LogError((object)"Cannot spawn custom object: the camera rig is unavailable.");
				return;
			}
			GameObject val3 = Object.Instantiate<GameObject>(val2, Refs.ovrCameraRig.position + Refs.ovrCameraRig.forward, Refs.ovrCameraRig.rotation);
			ShipItem component = val3.GetComponent<ShipItem>();
			SaveablePrefab component2 = val3.GetComponent<SaveablePrefab>();
			Good component3 = val3.GetComponent<Good>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
			{
				Object.Destroy((Object)(object)val3);
				CustomItemSpawnerPlugin.Log.LogError((object)"Cannot spawn custom object: the selected prefab is missing required components.");
				return;
			}
			component.sold = true;
			component2.RegisterToSave();
			if (CustomItemSpawnerPlugin.CustomBallastObject.Value)
			{
				int value2 = CustomItemSpawnerPlugin.CustomObjectMass.Value;
				component.mass = value2;
				component.name = $"{value2} Mass Custom Object";
				SaveCustomObjectProperties(component2.instanceId, component);
			}
			if ((Object)(object)component3 != (Object)null)
			{
				component3.RegisterAsMissionless();
			}
			CustomItemSpawnerPlugin.Log.LogInfo((object)$"Spawned custom object '{((Object)val2).name}' from PrefabsDirectory index {num}.");
		}

		internal static void RestoreLoadedCustomObject(ShipItem item)
		{
			if ((Object)(object)item == (Object)null || !CustomItemSpawnerPlugin.CustomBallastObject.Value)
			{
				return;
			}
			SaveablePrefab component = ((Component)item).GetComponent<SaveablePrefab>();
			if (!((Object)(object)component == (Object)null) && IsCustomObject(component.instanceId))
			{
				string modDataKey = GetModDataKey(component.instanceId);
				if (int.TryParse(GetModDataValue(modDataKey + ".mass", ((int)item.mass).ToString(CultureInfo.InvariantCulture)), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
				{
					item.mass = result;
				}
				item.name = GetModDataValue(modDataKey + ".name", item.name);
			}
		}

		internal static void RestoreLoadedCustomObjects()
		{
			if (!CustomItemSpawnerPlugin.CustomBallastObject.Value || (Object)(object)SaveLoadManager.instance == (Object)null)
			{
				return;
			}
			List<SaveablePrefab> currentPrefabs = SaveLoadManager.instance.GetCurrentPrefabs();
			if (currentPrefabs == null)
			{
				return;
			}
			foreach (SaveablePrefab item in currentPrefabs)
			{
				if (!((Object)(object)item == (Object)null))
				{
					RestoreLoadedCustomObject(((Component)item).GetComponent<ShipItem>());
				}
			}
		}

		internal static IEnumerator RestoreLoadedCustomObjectsAfterLoad()
		{
			for (int frame = 0; frame < 2; frame++)
			{
				yield return null;
				RestoreLoadedCustomObjects();
			}
		}

		private static void SaveCustomObjectProperties(int instanceId, ShipItem item)
		{
			if (GameState.modData == null)
			{
				CustomItemSpawnerPlugin.Log.LogWarning((object)"Custom object spawned, but save data is unavailable; custom properties cannot persist.");
				return;
			}
			string modDataKey = GetModDataKey(instanceId);
			GameState.modData[modDataKey + ".customObject"] = "1";
			GameState.modData[modDataKey + ".mass"] = item.mass.ToString(CultureInfo.InvariantCulture);
			GameState.modData[modDataKey + ".name"] = item.name;
		}

		private static bool IsCustomObject(int instanceId)
		{
			return GameState.modData != null && GameState.modData.ContainsKey(GetModDataKey(instanceId) + ".customObject");
		}

		private static string GetModDataKey(int instanceId)
		{
			return "CustomItemSpawner.item." + instanceId;
		}

		private static string GetModDataValue(string key, string fallback)
		{
			string value;
			return GameState.modData.TryGetValue(key, out value) ? value : fallback;
		}
	}
	[HarmonyPatch(typeof(SaveLoadManager), "LoadModData")]
	internal static class CustomObjectLoadPatch
	{
		private static void Postfix()
		{
			CustomItemSpawnerPlugin.CreateItemDirectoryOnce();
			CustomItemSpawner.RestoreLoadedCustomObjects();
			if ((Object)(object)SaveLoadManager.instance != (Object)null)
			{
				((MonoBehaviour)SaveLoadManager.instance).StartCoroutine(CustomItemSpawner.RestoreLoadedCustomObjectsAfterLoad());
			}
			CustomItemSpawnerPlugin.Log.LogDebug((object)"Save data loaded; item directory initialized and custom object properties restored.");
		}
	}
	[HarmonyPatch(typeof(ShipItem), "OnLoad")]
	internal static class CustomObjectShipItemLoadPatch
	{
		private static void Postfix(ShipItem __instance)
		{
			CustomItemSpawner.RestoreLoadedCustomObject(__instance);
		}
	}
	[HarmonyPatch(typeof(ItemRigidbody), "UpdateMass")]
	internal static class CustomObjectMassUpdatePatch
	{
		private static void Prefix(ItemRigidbody __instance)
		{
			if ((Object)(object)__instance != (Object)null)
			{
				CustomItemSpawner.RestoreLoadedCustomObject(__instance.GetShipItem());
			}
		}
	}
}