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());
}
}
}
}