using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("IDDumper")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ItemIDDumper")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("18a719a3-8c77-4e67-a21e-e2eaff7f43f7")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ItemIDDumper;
internal static class Dumper
{
internal static readonly string dumpFileName = "itemID_dump.txt";
private static readonly string OutputPath = Path.Combine(Paths.ConfigPath, dumpFileName);
internal static void DumpIDs(StartOfRound instance)
{
HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
HashSet<string> hashSet2 = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
HashSet<string> hashSet3 = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
HashSet<string> hashSet4 = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
HashSet<string> seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("--- Lethal Company ID Dump ---");
stringBuilder.AppendLine($"Generated: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
stringBuilder.AppendLine();
stringBuilder.AppendLine("--- ITEMS ---");
List<Item> list = instance.allItemsList?.itemsList;
if (list != null)
{
stringBuilder.AppendLine(string.Format("{0,-5} {1,-35} {2,-10} {3}", "ID", "Name", "2-Handed", "IsScrap"));
stringBuilder.AppendLine(new string('-', 60));
for (int i = 0; i < list.Count; i++)
{
Item val = list[i];
if (!((Object)(object)val == (Object)null) && hashSet.Add(val.itemName))
{
stringBuilder.AppendLine($"{i,-5} {val.itemName,-35} {val.twoHanded,-10} {val.isScrap}");
}
}
}
else
{
stringBuilder.AppendLine("(itemsList not available)");
}
stringBuilder.AppendLine();
StringBuilder stringBuilder2 = new StringBuilder();
StringBuilder stringBuilder3 = new StringBuilder();
stringBuilder2.AppendLine("--- SUITS ---");
stringBuilder3.AppendLine("--- UNLOCKABLES (furniture, upgrades, etc.) ---");
List<UnlockableItem> list2 = instance.unlockablesList?.unlockables;
if (list2 != null)
{
stringBuilder2.AppendLine(string.Format("{0,-5} {1}", "ID", "Name"));
stringBuilder2.AppendLine(new string('-', 40));
stringBuilder3.AppendLine(string.Format("{0,-5} {1,-35} {2}", "ID", "Name", "UnlockableType"));
stringBuilder3.AppendLine(new string('-', 60));
for (int j = 0; j < list2.Count; j++)
{
UnlockableItem val2 = list2[j];
if (val2 == null)
{
continue;
}
bool flag = (Object)(object)val2.suitMaterial != (Object)null;
if ((flag ? hashSet2 : hashSet3).Add(val2.unlockableName))
{
if (flag)
{
stringBuilder2.AppendLine($"{j,-5} {val2.unlockableName}");
}
else
{
stringBuilder3.AppendLine($"{j,-5} {val2.unlockableName,-35} {val2.unlockableType}");
}
}
}
}
else
{
stringBuilder2.AppendLine("(unlockables not available)");
stringBuilder3.AppendLine("(unlockables not available)");
}
stringBuilder2.AppendLine();
stringBuilder3.AppendLine();
stringBuilder.Append((object?)stringBuilder2);
stringBuilder.Append((object?)stringBuilder3);
stringBuilder.AppendLine("--- MOONS ---");
if (instance.levels != null)
{
stringBuilder.AppendLine(string.Format("{0,-5} {1,-30} {2,-25} {3}", "ID", "Name", "Scene Name", "Risk Level"));
stringBuilder.AppendLine(new string('-', 75));
for (int k = 0; k < instance.levels.Length; k++)
{
SelectableLevel val3 = instance.levels[k];
if (!((Object)(object)val3 == (Object)null) && hashSet4.Add(val3.PlanetName))
{
stringBuilder.AppendLine($"{k,-5} {val3.PlanetName,-30} {val3.sceneName,-25} {val3.riskLevel}");
}
}
}
else
{
stringBuilder.AppendLine("(moons not available)");
}
stringBuilder.AppendLine();
stringBuilder.AppendLine("--- ENEMIES ---");
stringBuilder.AppendLine(string.Format("{0,-5} {1}", "ID", "Name"));
stringBuilder.AppendLine(new string('-', 40));
SortedDictionary<string, int> sortedDictionary = new SortedDictionary<string, int>(StringComparer.OrdinalIgnoreCase);
int nextId = 0;
if (instance.levels != null)
{
SelectableLevel[] levels = instance.levels;
foreach (SelectableLevel val4 in levels)
{
if (!((Object)(object)val4 == (Object)null))
{
RegisterEnemies(val4.Enemies, seen, sortedDictionary, ref nextId);
RegisterEnemies(val4.OutsideEnemies, seen, sortedDictionary, ref nextId);
RegisterEnemies(val4.DaytimeEnemies, seen, sortedDictionary, ref nextId);
}
}
foreach (KeyValuePair<string, int> item in sortedDictionary)
{
stringBuilder.AppendLine($"{item.Value,-5} {item.Key}");
}
}
if (nextId == 0)
{
stringBuilder.AppendLine("(enemies not available)");
}
stringBuilder.AppendLine();
try
{
File.WriteAllText(OutputPath, stringBuilder.ToString());
ItemIDPatchBase.logSource.LogInfo((object)("Full ID dump written to: " + OutputPath));
}
catch (Exception ex)
{
ItemIDPatchBase.logSource.LogError((object)("Failed to write ID dump: " + ex.Message));
}
}
private static void RegisterEnemies(List<SpawnableEnemyWithRarity> list, HashSet<string> seen, SortedDictionary<string, int> output, ref int nextId)
{
if (list == null)
{
return;
}
foreach (SpawnableEnemyWithRarity item in list)
{
string text = item?.enemyType?.enemyName;
if (text != null && seen.Add(text))
{
output[text] = nextId++;
}
}
}
}
internal static class ModInfo
{
internal const string modGUID = "PixelIndieDev_IDDumper";
internal const string modName = "ID Dumper";
internal const string modVersion = "1.0.1.0";
}
[BepInPlugin("PixelIndieDev_IDDumper", "ID Dumper", "1.0.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class ItemIDPatchBase : BaseUnityPlugin
{
private readonly Harmony harmony = new Harmony("PixelIndieDev_IDDumper");
internal static ItemIDPatchBase instance;
internal static ManualLogSource logSource;
internal static ConfigEntry<bool> DumpEntry;
private void Awake()
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Expected O, but got Unknown
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Expected O, but got Unknown
if ((Object)(object)instance == (Object)null)
{
instance = this;
}
logSource = Logger.CreateLogSource("PixelIndieDev_IDDumper");
DumpEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Dump IDs", false, "Set to true to dump all IDs to BepInEx/config/" + Dumper.dumpFileName + ".\nResets to false automatically.\n\nONLY WORKS WHEN IN_GAME!!!");
LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(DumpEntry, new BoolCheckBoxOptions
{
RequiresRestart = false
}));
DumpEntry.SettingChanged += OnDumpNowChanged;
harmony.PatchAll(typeof(ItemIDPatchBase));
logSource.LogInfo((object)"ID Dumper (version - 1.0.1.0): patches applied successfully");
}
private void OnDumpNowChanged(object sender, EventArgs e)
{
if (DumpEntry.Value)
{
StartOfRound val = StartOfRound.Instance;
if ((Object)(object)val == (Object)null)
{
logSource.LogWarning((object)"Cannot dump");
DumpEntry.Value = false;
}
else
{
Dumper.DumpIDs(val);
DumpEntry.Value = false;
}
}
}
}