using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BoneLib;
using BoneLib.BoneMenu;
using BoneLib.Notifications;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.Pool;
using Il2CppSLZ.Marrow.Warehouse;
using MelonLoader;
using MelonLoader.Preferences;
using Newtonsoft.Json;
using SpawnLoadout;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Main), "SpawnLoadout", "1.0.0", "zekeg", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace SpawnLoadout;
public class Main : MelonMod
{
internal static Main Instance;
internal static MelonPreferences_Category PrefCategory;
internal static MelonPreferences_Entry<bool> PrefAutoLoad;
internal static MelonPreferences_Entry<string> PrefActivePreset;
private Page _mainPage;
private Page _presetsPage;
private bool _isDead;
private bool _respawnWatcherRunning;
public override void OnInitializeMelon()
{
Instance = this;
PrefCategory = MelonPreferences.CreateCategory("SpawnLoadout");
PrefAutoLoad = PrefCategory.CreateEntry<bool>("AutoLoad", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
PrefActivePreset = PrefCategory.CreateEntry<string>("ActivePreset", "", (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
PresetManager.Initialize();
SetupBoneMenu();
Hooking.OnLevelLoaded += delegate
{
if (PrefAutoLoad.Value && !string.IsNullOrEmpty(PrefActivePreset.Value))
{
MelonCoroutines.Start(DelayedLoad(3f));
}
};
Hooking.OnPlayerDeath += delegate
{
_isDead = true;
if (!_respawnWatcherRunning)
{
_respawnWatcherRunning = true;
MelonCoroutines.Start(RespawnWatcher());
}
};
}
private IEnumerator RespawnWatcher()
{
while (_isDead)
{
yield return (object)new WaitForSeconds(0.5f);
if (!PrefAutoLoad.Value || string.IsNullOrEmpty(PrefActivePreset.Value))
{
_isDead = false;
break;
}
bool ready = false;
try
{
ready = (Object)(object)Player.RigManager != (Object)null && (Object)(object)Player.RigManager.inventory != (Object)null && (Object)(object)Player.Head != (Object)null;
}
catch
{
}
if (ready)
{
_isDead = false;
yield return (object)new WaitForSeconds(1.5f);
TryLoadActivePreset();
break;
}
}
_respawnWatcherRunning = false;
}
private void SetupBoneMenu()
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
_mainPage = Page.Root.CreatePage("SpawnLoadout", new Color(0.2f, 0.6f, 1f), 0, true);
_mainPage.CreateBool("Auto Load", Color.green, PrefAutoLoad.Value, (Action<bool>)delegate(bool val)
{
PrefAutoLoad.Value = val;
});
StringElement nameElement = _mainPage.CreateString("Preset Name", Color.white, "", (Action<string>)null);
_mainPage.CreateFunction("Save Current as Preset", Color.cyan, (Action)delegate
{
string text = nameElement.Value.Trim();
if (string.IsNullOrEmpty(text))
{
SendNotification("Error", "Enter a name first", (NotificationType)2);
}
else if (PresetManager.PresetExists(text))
{
SendNotification("Error", "Preset name already exists", (NotificationType)2);
}
else
{
PresetManager.SavePreset(text);
RefreshPresetsPage();
SendNotification("Saved", "Preset \"" + text + "\" saved", (NotificationType)3);
}
});
_mainPage.CreateFunction("Load Active Preset Now", Color.yellow, (Action)delegate
{
TryLoadActivePreset();
});
_presetsPage = _mainPage.CreatePage("Presets", Color.cyan, 0, true);
RefreshPresetsPage();
}
private void RefreshPresetsPage()
{
//IL_002c: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
_presetsPage.RemoveAll();
List<Preset> allPresets = PresetManager.GetAllPresets();
if (allPresets.Count == 0)
{
_presetsPage.CreateFunction("(no presets saved)", Color.gray, (Action)delegate
{
});
return;
}
foreach (Preset preset in allPresets)
{
bool flag = preset.Name == PrefActivePreset.Value;
Page val = _presetsPage.CreatePage(preset.Name, flag ? Color.green : Color.white, 0, true);
val.CreateFunction("Load Now", Color.green, (Action)delegate
{
PresetManager.LoadPreset(preset);
SendNotification("Loaded", "Preset \"" + preset.Name + "\" loaded", (NotificationType)3);
});
if (!flag)
{
val.CreateFunction("Set as Auto Load", Color.yellow, (Action)delegate
{
PrefActivePreset.Value = preset.Name;
RefreshPresetsPage();
SendNotification("Active", "\"" + preset.Name + "\" set as auto-load", (NotificationType)0);
});
}
else
{
val.CreateFunction("(active)", Color.green, (Action)delegate
{
});
}
val.CreateFunction("Delete", Color.red, (Action)delegate
{
Menu.DisplayDialog("Delete Preset", "Delete \"" + preset.Name + "\"?", Dialog.WarningIcon, (Action)delegate
{
bool flag2 = preset.Name == PrefActivePreset.Value;
PresetManager.DeletePreset(preset.Name);
if (flag2)
{
PrefActivePreset.Value = "";
}
RefreshPresetsPage();
SendNotification("Deleted", "\"" + preset.Name + "\" deleted", (NotificationType)1);
}, (Action)null);
});
}
}
private IEnumerator DelayedLoad(float delay)
{
yield return (object)new WaitForSeconds(delay);
TryLoadActivePreset();
}
private void TryLoadActivePreset()
{
if (!string.IsNullOrEmpty(PrefActivePreset.Value))
{
Preset preset = PresetManager.GetPreset(PrefActivePreset.Value);
if (preset == null)
{
SendNotification("Error", "Preset \"" + PrefActivePreset.Value + "\" not found", (NotificationType)2);
}
else
{
PresetManager.LoadPreset(preset);
}
}
}
internal static void SendNotification(string title, string message, NotificationType type)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//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)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected O, but got Unknown
Notifier.Send(new Notification
{
Title = NotificationText.op_Implicit(title),
Message = NotificationText.op_Implicit(message),
Type = type,
PopupLength = 3f,
ShowTitleOnPopup = true
});
}
}
public class Preset
{
public string Name;
public Dictionary<string, string> Slots = new Dictionary<string, string>();
}
public static class PresetManager
{
private static string _presetsDir;
public static void Initialize()
{
_presetsDir = Path.Combine(Directory.GetCurrentDirectory(), "UserData", "SpawnLoadout", "Presets");
Directory.CreateDirectory(_presetsDir);
}
private static string GetFilePath(string presetName)
{
string text = string.Join("_", presetName.Split(Path.GetInvalidFileNameChars()));
return Path.Combine(_presetsDir, text + ".json");
}
public static bool PresetExists(string name)
{
return File.Exists(GetFilePath(name));
}
public static List<Preset> GetAllPresets()
{
if (!Directory.Exists(_presetsDir))
{
return new List<Preset>();
}
List<Preset> list = new List<Preset>();
string[] files = Directory.GetFiles(_presetsDir, "*.json");
foreach (string path in files)
{
try
{
Preset preset = JsonConvert.DeserializeObject<Preset>(File.ReadAllText(path));
if (preset != null && !string.IsNullOrEmpty(preset.Name))
{
list.Add(preset);
}
}
catch
{
}
}
return list;
}
public static Preset GetPreset(string name)
{
string filePath = GetFilePath(name);
if (!File.Exists(filePath))
{
return null;
}
try
{
return JsonConvert.DeserializeObject<Preset>(File.ReadAllText(filePath));
}
catch
{
return null;
}
}
public static void SavePreset(string name)
{
Dictionary<string, string> currentInventoryBarcodes = GetCurrentInventoryBarcodes();
string contents = JsonConvert.SerializeObject((object)new Preset
{
Name = name,
Slots = currentInventoryBarcodes
}, (Formatting)1);
File.WriteAllText(GetFilePath(name), contents);
}
public static void DeletePreset(string name)
{
string filePath = GetFilePath(name);
if (File.Exists(filePath))
{
File.Delete(filePath);
}
}
public static Dictionary<string, string> GetCurrentInventoryBarcodes()
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
try
{
RigManager rigManager = Player.RigManager;
if ((Object)(object)rigManager == (Object)null || (Object)(object)rigManager.inventory == (Object)null)
{
return dictionary;
}
foreach (SlotContainer item in (Il2CppArrayBase<SlotContainer>)(object)rigManager.inventory.bodySlots)
{
if ((Object)(object)((item != null) ? item.inventorySlotReceiver : null) == (Object)null)
{
continue;
}
WeaponSlot slottedWeapon = item.inventorySlotReceiver._slottedWeapon;
if ((Object)(object)((slottedWeapon != null) ? slottedWeapon.interactableHost : null) == (Object)null)
{
continue;
}
Poolee val = (((Object)(object)slottedWeapon.interactableHost.manager != (Object)null) ? ((Component)slottedWeapon.interactableHost.manager).GetComponent<Poolee>() : ((Component)slottedWeapon.interactableHost).GetComponent<Poolee>());
if (!((Object)(object)((val != null) ? val.SpawnableCrate : null) == (Object)null))
{
string iD = ((Scannable)val.SpawnableCrate).Barcode.ID;
if (!string.IsNullOrEmpty(iD) && !dictionary.ContainsKey(((Object)item).name))
{
dictionary[((Object)item).name] = iD;
}
}
}
}
catch (Exception ex)
{
Main instance = Main.Instance;
if (instance != null)
{
((MelonBase)instance).LoggerInstance.Error("GetInventory: " + ex.Message);
}
}
return dictionary;
}
public static void LoadPreset(Preset preset)
{
//IL_0167: Unknown result type (might be due to invalid IL or missing references)
//IL_0169: Unknown result type (might be due to invalid IL or missing references)
//IL_0176: Unknown result type (might be due to invalid IL or missing references)
//IL_017b: Unknown result type (might be due to invalid IL or missing references)
//IL_0180: Unknown result type (might be due to invalid IL or missing references)
//IL_0185: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: Unknown result type (might be due to invalid IL or missing references)
//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
//IL_01c2: Expected O, but got Unknown
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_0131: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
if (preset?.Slots == null || preset.Slots.Count == 0)
{
return;
}
try
{
RigManager rigManager = Player.RigManager;
if ((Object)(object)rigManager == (Object)null)
{
Main instance = Main.Instance;
if (instance != null)
{
((MelonBase)instance).LoggerInstance.Error("RigManager null");
}
return;
}
int num = 0;
foreach (KeyValuePair<string, string> slot in preset.Slots)
{
string value = slot.Value;
string key = slot.Key;
if (string.IsNullOrEmpty(value))
{
continue;
}
InventorySlotReceiver val = null;
foreach (SlotContainer item in (Il2CppArrayBase<SlotContainer>)(object)rigManager.inventory.bodySlots)
{
if ((Object)(object)item != (Object)null && ((Object)item).name == key)
{
val = item.inventorySlotReceiver;
break;
}
}
if ((Object)(object)val == (Object)null)
{
Vector3 val2 = Vector3.zero;
try
{
val2 = Player.Head.position + Player.Head.forward * 1.5f;
}
catch
{
((Vector3)(ref val2))..ctor(0f, 1.5f, 0f);
}
HelperMethods.SpawnCrate(value, val2 + Vector3.right * ((float)num * 0.3f), Quaternion.identity, Vector3.one, true, (Action<GameObject>)null, (Action<GameObject>)null);
num++;
}
else
{
if ((Object)(object)val._slottedWeapon != (Object)null)
{
val.DespawnContents();
}
val.SpawnInSlotAsync(new Barcode(value));
num++;
}
}
if (num > 0)
{
Main.SendNotification("SpawnLoadout", $"Loaded {num} items", (NotificationType)3);
}
}
catch (Exception ex)
{
Main instance2 = Main.Instance;
if (instance2 != null)
{
((MelonBase)instance2).LoggerInstance.Error("LoadPreset: " + ex.Message);
}
}
}
}