Decompiled source of LethalCardLoader v0.2.0

LethalCardLoader.dll

Decompiled 8 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalCardLoader.Config;
using LethalCardLoader.CustomProps;
using LethalCardLoader.ModLoading;
using LethalCardLoader.Models;
using LethalCardLoader.NetcodePatcher;
using LethalLib;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using TMPro;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LethalCardLoader")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Trading Cards for Lethal Company")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0+0973080823146e5b641a5d6f62a6afe9237984d4")]
[assembly: AssemblyProduct("LethalCardLoader")]
[assembly: AssemblyTitle("LethalCardLoader")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 LethalCardLoader
{
	[BepInPlugin("com.sholiver.lethalcardloader", "LethalCardLoader", "0.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string modGUID = "com.sholiver.lethalcardloader";

		public const string modName = "LethalCardLoader";

		public const string modVersion = "0.2.0";

		public static Plugin Instance;

		public static ManualLogSource logger;

		private void Awake()
		{
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
			Instance = this;
			logger = ((BaseUnityPlugin)this).Logger;
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			ConfigManager.LoadMoonConfigs();
			ConfigManager.CreateDefaults();
			ConfigManager.LoadSetConfigs();
			ConfigManager.LoadSpawnGroupConfigs();
			ConfigManager.LoadRarityConfigs();
			CardRegistryHelper cardRegistryHelper = new CardRegistryHelper(logger, directoryName);
			cardRegistryHelper.RegisterAllCards();
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "com.sholiver.lethalcardloader");
			logger.LogInfo((object)"Plugin com.sholiver.lethalcardloader is loaded!");
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "LethalCardLoader";

		public const string PLUGIN_NAME = "LethalCardLoader";

		public const string PLUGIN_VERSION = "0.2.0";
	}
}
namespace LethalCardLoader.Patches
{
	[HarmonyPatch(typeof(DepositItemsDesk), "SellItemsOnServer")]
	internal static class DepositItemsDeskPatch
	{
		private static readonly List<int> _pendingSoldCardIds = new List<int>();

		[HarmonyPrefix]
		private static void BeforeSell(DepositItemsDesk __instance)
		{
			_pendingSoldCardIds.Clear();
			foreach (GrabbableObject item in __instance.itemsOnCounter)
			{
				if (item is BaseCardProp baseCardProp)
				{
					_pendingSoldCardIds.Add(baseCardProp.TemplateId);
				}
			}
		}

		[HarmonyPostfix]
		private static void AfterSell()
		{
			foreach (int pendingSoldCardId in _pendingSoldCardIds)
			{
				CollectionTracker.IncrementSold(pendingSoldCardId);
			}
			_pendingSoldCardIds.Clear();
		}
	}
	[HarmonyPatch(typeof(GrabbableObject))]
	internal static class GrabbableObjectPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("SetScrapValue")]
		public static bool SetScrapValuePrefix(GrabbableObject __instance, int setValueTo)
		{
			TemplatableProp templatableProp = __instance as TemplatableProp;
			if ((Object)(object)templatableProp == (Object)null)
			{
				return true;
			}
			return !templatableProp.isSynced;
		}

		[HarmonyPostfix]
		[HarmonyPatch("SetScrapValue")]
		public static void SetScrapValuePostfix(GrabbableObject __instance, int setValueTo)
		{
			TemplatableProp templatableProp = __instance as TemplatableProp;
			if (!((Object)(object)templatableProp == (Object)null))
			{
				templatableProp.isSynced = true;
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal static class StartOfRoundPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void StartPostfix(StartOfRound __instance)
		{
			Dictionary<string, string> source = __instance.levels.Where((SelectableLevel l) => (Object)(object)l != (Object)null && !string.IsNullOrWhiteSpace(l.PlanetName)).ToDictionary((SelectableLevel l) => l.PlanetName, (SelectableLevel l) => ((Object)l).name);
			Dictionary<string, string> dictionary = source.Where((KeyValuePair<string, string> kvp) => !ConfigManager.Moons.Any((MoonEntry m) => m.PlanetName == kvp.Key)).ToDictionary((KeyValuePair<string, string> kvp) => kvp.Key, (KeyValuePair<string, string> kvp) => kvp.Value);
			if (dictionary.Count > 0)
			{
				ConfigManager.CreateMissingMoonConfigs(dictionary);
			}
			else
			{
				Plugin.logger.LogInfo((object)"[StartOfRoundPatch] No missing moons to register.");
			}
			CollectionTracker.Initialise();
		}
	}
	[HarmonyPatch(typeof(Terminal))]
	internal static class TerminalPatch
	{
		private static Terminal _terminalInstance;

		[HarmonyPatch("OnSubmit")]
		[HarmonyPrefix]
		private static void OnSubmit(Terminal __instance)
		{
			TMP_InputField screenText = __instance.screenText;
			if ((Object)(object)screenText == (Object)null)
			{
				return;
			}
			string text = screenText.text;
			if (!string.IsNullOrWhiteSpace(text))
			{
				string[] source = text.Split('\n');
				string text2 = source.LastOrDefault()?.Trim().ToLower();
				if (!string.IsNullOrWhiteSpace(text2) && text2.StartsWith("cards"))
				{
					string[] source2 = text2.Split(' ', StringSplitOptions.RemoveEmptyEntries);
					string[] args = source2.Skip(1).ToArray();
					string text3 = CardCommand.Execute(args);
					__instance.LoadNewNode(CreateTextNode(text3));
					screenText.text = "";
				}
			}
		}

		private static TerminalNode CreateTextNode(string text)
		{
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			val.displayText = text + "\n\n";
			val.clearPreviousText = true;
			val.terminalEvent = "";
			return val;
		}
	}
}
namespace LethalCardLoader.ModLoading
{
	public class CardCommand
	{
		private const int MaxNameDisplayLength = 15;

		private const int CardsPerPage = 15;

		public static string Execute(string[] args)
		{
			if (args.Length == 0)
			{
				return GetOverview();
			}
			string setKey = args[0];
			if (args.Length == 1)
			{
				return GetSetListView(setKey, 1);
			}
			string text = args[1].ToLower();
			if (text.Length > 1 && text[0] == 'p' && int.TryParse(text.Substring(1), out var result))
			{
				return GetSetListView(setKey, result);
			}
			if (int.TryParse(text, out var result2))
			{
				return GetCardView(setKey, result2);
			}
			return "Usage: cards [setKey] [p<pageNumber>|<cardNumber>]";
		}

		private static string GetOverview()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("╔════════════════════════════════════════════════╗");
			stringBuilder.AppendLine("║            LETHAL CARD COLLECTION              ║");
			stringBuilder.AppendLine("╚════════════════════════════════════════════════╝\n");
			foreach (SetEntry set in ConfigManager.Sets)
			{
				IEnumerable<int> enumerable = ModCardDatabase.Sets[set.Key].Cards.Select((KeyValuePair<int, ModCardDatabase.CardInfo> a) => a.Value.Id);
				(int owned, int sold) totalsForSet = CollectionTracker.GetTotalsForSet(enumerable);
				int item = totalsForSet.owned;
				int item2 = totalsForSet.sold;
				int num = enumerable.Count();
				stringBuilder.AppendLine($"{set.Name,-10} ({set.Key}): {item,3} / {num,-3} found ({item2} sold)");
			}
			stringBuilder.AppendLine("\nUse 'cards [setKey]' to view cards in a set.");
			return stringBuilder.ToString();
		}

		private static string GetSetListView(string setKey, int page)
		{
			SetEntry setEntry = ConfigManager.Sets.FirstOrDefault((SetEntry s) => s.Key.Equals(setKey, StringComparison.OrdinalIgnoreCase));
			if (setEntry == null)
			{
				return "Set '" + setKey + "' not found.";
			}
			List<ModCardDatabase.CardInfo> list = ModCardDatabase.Sets[setKey].Cards.Values.OrderBy((ModCardDatabase.CardInfo a) => a.Number).ToList();
			if (list.Count() == 0)
			{
				return "No cards found in set '" + setEntry.Name + "'.";
			}
			int num = (list.Count + 15 - 1) / 15;
			if (page < 1)
			{
				page = 1;
			}
			if (page > num)
			{
				page = num;
			}
			List<ModCardDatabase.CardInfo> list2 = list.Skip((page - 1) * 15).Take(15).ToList();
			int num2 = 3;
			int num3 = 15;
			int num4 = 9;
			int num5 = 5;
			int num6 = 4;
			StringBuilder stringBuilder = new StringBuilder();
			string text = $"=== {setEntry.Name.ToUpper()} (Page {page}/{num}) ===";
			stringBuilder.AppendLine(text);
			stringBuilder.AppendLine(new string('═', text.Length));
			stringBuilder.Append("No.".PadRight(num2) + " │ ");
			stringBuilder.Append("Name".PadRight(num3) + " │ ");
			stringBuilder.Append("Status".PadRight(num4) + " │ ");
			stringBuilder.Append("Owned".PadLeft(num5) + " │ ");
			stringBuilder.AppendLine("Sold".PadLeft(num6) ?? "");
			int count = num2 + 3 + num3 + 3 + num4 + 3 + num5 + 3 + num6;
			stringBuilder.AppendLine(new string('─', count));
			foreach (ModCardDatabase.CardInfo item in list2)
			{
				int owned = CollectionTracker.GetOwned(item.Id);
				int sold = CollectionTracker.GetSold(item.Id);
				string text2 = ((owned > 0) ? "Collected" : "Missing");
				string text3 = ((item.Name.Length > 15) ? (item.Name.Substring(0, 12) + "...") : item.Name);
				stringBuilder.Append(item.Number.ToString().PadRight(num2) + " │ ");
				stringBuilder.Append(text3.PadRight(num3) + " │ ");
				stringBuilder.Append(text2.PadRight(num4) + " │ ");
				stringBuilder.Append(owned.ToString().PadLeft(num5) + " │ ");
				stringBuilder.AppendLine(sold.ToString().PadLeft(num6) ?? "");
			}
			stringBuilder.AppendLine();
			if (num > 1)
			{
				if (page < num)
				{
					stringBuilder.AppendLine($"Next: cards {setKey} p{page + 1}");
				}
				if (page > 1)
				{
					stringBuilder.AppendLine($"Prev: cards {setKey} p{page - 1}");
				}
			}
			stringBuilder.AppendLine("Detail: cards " + setKey + " [number]");
			return stringBuilder.ToString();
		}

		private static string GetCardView(string setKey, int cardNumber)
		{
			if (!ModCardDatabase.Sets.TryGetValue(setKey, out var value))
			{
				return "Set '" + setKey + "' not found.";
			}
			if (!value.Cards.TryGetValue(cardNumber, out var card))
			{
				return $"Card #{cardNumber} not found in set '{setKey}'.";
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("=== CARD DETAILS ===\n");
			stringBuilder.AppendLine("Name: " + card.Name);
			stringBuilder.AppendLine("Set: " + ConfigManager.Sets.First((SetEntry s) => s.Key == card.SetKey).Name);
			stringBuilder.AppendLine($"Number: {card.Number:D3}");
			stringBuilder.AppendLine("Rarity: " + card.Rarity);
			stringBuilder.AppendLine("Metallic: " + (card.Metallic ? "Yes" : "No"));
			stringBuilder.AppendLine($"Value: {card.MinValue} - {card.MaxValue}");
			stringBuilder.AppendLine($"Owned: {CollectionTracker.GetOwned(card.Id)}");
			stringBuilder.AppendLine($"Sold: {CollectionTracker.GetSold(card.Id)}");
			var list = (from kvp in card.MoonSpawnWeights
				where kvp.Value > 0.0
				orderby kvp.Value descending
				select new
				{
					InternalName = kvp.Key,
					Weight = kvp.Value,
					PlanetName = ConfigManager.LevelNamesMap.FirstOrDefault((KeyValuePair<string, string> a) => a.Value == kvp.Key).Key
				}).ToList();
			if (list.Count > 0)
			{
				stringBuilder.AppendLine("\n=== SPAWN LOCATIONS ===");
				foreach (var item in list)
				{
					stringBuilder.AppendLine($"{item.PlanetName,-20} | Weight: {item.Weight:F2}");
				}
			}
			else
			{
				stringBuilder.AppendLine("\nNo spawn locations configured for this card.");
			}
			return stringBuilder.ToString();
		}
	}
	public class CardRegistryHelper
	{
		private readonly ManualLogSource _logger;

		private readonly string _pluginDir;

		private readonly string _contentDir;

		private Item _cardBaseItem;

		private Item _cardPackBaseItem;

		private Dictionary<string, RarityEntry> _rarities;

		private Dictionary<string, SpawnGroupEntry> _spawnGroups;

		public CardRegistryHelper(ManualLogSource logger, string pluginDir)
		{
			_logger = logger;
			_pluginDir = pluginDir;
			_contentDir = Path.Combine(_pluginDir, "Content");
		}

		public void RegisterAllCards()
		{
			_spawnGroups = ConfigManager.SpawnGroups.ToDictionary((SpawnGroupEntry s) => s.Key, (SpawnGroupEntry s) => s);
			_rarities = ConfigManager.RarityConfigs.ToDictionary((RarityEntry r) => r.Key, (RarityEntry r) => r);
			if (LoadBundle())
			{
				LoadAndRegisterSets();
				ModCardDatabase.CalculateMoonSpawnWeightsForCards();
				ModCardDatabase.CalculateMoonSpawnWeightsForPacks();
				ModCardDatabase.CalculatePackDropRates(_rarities);
			}
		}

		private bool LoadBundle()
		{
			string text = Path.Combine(_pluginDir, "lethalcardloader");
			AssetBundle val = AssetBundle.LoadFromFile(text);
			if ((Object)(object)val == (Object)null)
			{
				_logger.LogError((object)("Failed to load asset bundle from " + text));
				return false;
			}
			_cardBaseItem = val.LoadAsset<Item>("Assets/LethalCardLoader/CardBase_Item.asset");
			_cardBaseItem.saveItemVariable = true;
			((Object)_cardBaseItem).name = "BaseCard";
			_cardBaseItem.itemName = "BaseCard";
			_cardBaseItem.isScrap = true;
			BaseCardProp baseCardProp = _cardBaseItem.spawnPrefab.AddComponent<BaseCardProp>();
			((GrabbableObject)baseCardProp).grabbable = true;
			((GrabbableObject)baseCardProp).grabbableToEnemies = true;
			((GrabbableObject)baseCardProp).itemProperties = _cardBaseItem;
			((Object)baseCardProp).name = "BaseCard";
			NetworkPrefabs.RegisterNetworkPrefab(_cardBaseItem.spawnPrefab);
			Utilities.FixMixerGroups(_cardBaseItem.spawnPrefab);
			(Dictionary<LevelTypes, int>, Dictionary<string, int>) tuple = SplitLevelRarity(ConfigManager.Moons.ToDictionary((MoonEntry a) => a.InternalName, (MoonEntry a) => a.CardScrapRarity));
			Items.RegisterScrap(_cardBaseItem, tuple.Item1, tuple.Item2);
			_cardPackBaseItem = val.LoadAsset<Item>("Assets/LethalCardLoader/CardPackBase_Item.asset");
			_cardPackBaseItem.saveItemVariable = true;
			((Object)_cardPackBaseItem).name = "BasePack";
			_cardPackBaseItem.itemName = "BasePack";
			_cardPackBaseItem.isScrap = true;
			BoosterPackProp boosterPackProp = _cardPackBaseItem.spawnPrefab.AddComponent<BoosterPackProp>();
			((GrabbableObject)boosterPackProp).grabbable = true;
			((GrabbableObject)boosterPackProp).grabbableToEnemies = true;
			((GrabbableObject)boosterPackProp).itemProperties = _cardPackBaseItem;
			((Object)boosterPackProp).name = "BasePack";
			NetworkPrefabs.RegisterNetworkPrefab(_cardPackBaseItem.spawnPrefab);
			Utilities.FixMixerGroups(_cardPackBaseItem.spawnPrefab);
			(Dictionary<LevelTypes, int>, Dictionary<string, int>) tuple2 = SplitLevelRarity(ConfigManager.Moons.ToDictionary((MoonEntry a) => a.InternalName, (MoonEntry a) => a.PackScrapRarity));
			Items.RegisterScrap(_cardPackBaseItem, tuple2.Item1, tuple2.Item2);
			return true;
		}

		public (Dictionary<LevelTypes, int> vanilla, Dictionary<string, int> modded) SplitLevelRarity(Dictionary<string, int> levels)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<LevelTypes, int> dictionary = new Dictionary<LevelTypes, int>();
			Dictionary<string, int> dictionary2 = new Dictionary<string, int>();
			foreach (KeyValuePair<string, int> level in levels)
			{
				if (Enum.TryParse(typeof(LevelTypes), level.Key, out object result))
				{
					dictionary[(LevelTypes)result] = level.Value;
				}
				else
				{
					dictionary2[level.Key] = level.Value;
				}
			}
			return (dictionary, dictionary2);
		}

		private void LoadAndRegisterSets()
		{
			foreach (SetEntry set in ConfigManager.Sets)
			{
				LoadAndRegisterSet(set);
			}
		}

		private void LoadAndRegisterSet(SetEntry setEntry)
		{
			string path = Path.Combine(_contentDir, setEntry.Key, setEntry.Key + ".json");
			SetManifest setManifest = LoadJson<SetManifest>(path);
			if (setManifest == null)
			{
				_logger.LogWarning((object)("Skipping set '" + setEntry.Key + "' — manifest failed to load."));
				return;
			}
			string key = ResolveSpawnGroup(setEntry.SpawnGroup);
			SpawnGroupEntry setSpawnGroup = _spawnGroups[key];
			Texture2D val = null;
			if (!string.IsNullOrEmpty(setManifest.CardBackTexturePath))
			{
				val = LoadTexture(Path.Combine("Shared", setManifest.CardBackTexturePath));
				if ((Object)(object)val == (Object)null)
				{
					_logger.LogWarning((object)("Card back texture not found for set '" + setEntry.Key + "'."));
				}
			}
			_logger.LogInfo((object)$"Loading set '{setEntry.Key}' ({setManifest.Cards.Count} cards).");
			foreach (CardEntry card in setManifest.Cards)
			{
				RegisterCard(setEntry.Key, card, val, setSpawnGroup, setManifest.Number);
			}
			foreach (PackEntry pack in setManifest.Packs)
			{
				RegisterPack(setEntry.Key, pack, setSpawnGroup);
			}
		}

		private void RegisterCard(string setKey, CardEntry cardEntry, Texture2D cardBackTexture, SpawnGroupEntry setSpawnGroup, int totalInSet)
		{
			if (!_rarities.TryGetValue(cardEntry.Rarity, out var value))
			{
				_logger.LogWarning((object)("Card '" + cardEntry.Name + "' has unknown rarity '" + cardEntry.Rarity + "', skipping."));
				return;
			}
			cardEntry.SpawnGroup = ResolveSpawnGroup(cardEntry.SpawnGroup, cardEntry.Rarity);
			Dictionary<string, double> moonSpawnWeights = BuildMoonSpawnWeights(cardEntry.SpawnGroup, value.SpawnWeight, setSpawnGroup);
			Texture2D val = LoadTexture(Path.Combine(setKey, "Cards", cardEntry.ItemTexturePath));
			Item item = CreateCardItem(cardEntry, val, totalInSet);
			int num = (int)(cardEntry.ValueMultiplier * (double)value.Value);
			int maxValue = (int)(1.5 * (double)num);
			ModCardDatabase.CardInfo card = new ModCardDatabase.CardInfo
			{
				SetKey = setKey,
				Number = cardEntry.Number,
				Name = cardEntry.Name,
				Rarity = cardEntry.Rarity,
				Enabled = cardEntry.Enabled,
				Metallic = cardEntry.Metallic,
				MinValue = num,
				MaxValue = maxValue,
				ItemTexture = val,
				CardBackTexture = cardBackTexture,
				Item = item,
				MoonSpawnWeights = moonSpawnWeights
			};
			ModCardDatabase.RegisterCard(setKey, card);
		}

		private void RegisterPack(string setKey, PackEntry packEntry, SpawnGroupEntry setSpawnGroup)
		{
			Texture2D val = LoadTexture(Path.Combine("Shared", packEntry.ItemTexturePath));
			Item item = CreateCardPackItem(packEntry, val);
			packEntry.SpawnGroup = ResolveSpawnGroup(packEntry.SpawnGroup);
			Dictionary<string, double> moonSpawnWeights = BuildMoonSpawnWeights(packEntry.SpawnGroup, 1, setSpawnGroup);
			ModCardDatabase.PackInfo pack = new ModCardDatabase.PackInfo
			{
				SetKey = setKey,
				Key = packEntry.Key,
				Name = packEntry.Name,
				BlacklistedCardIds = packEntry.BlacklistedCardIds,
				ItemTexture = val,
				Item = item,
				MoonSpawnWeights = moonSpawnWeights
			};
			ModCardDatabase.RegisterPack(setKey, pack);
		}

		private string ResolveSpawnGroup(string spawnGroup, string rarity = null)
		{
			if (!string.IsNullOrEmpty(spawnGroup))
			{
				if (_spawnGroups.ContainsKey(spawnGroup))
				{
					return spawnGroup;
				}
				_logger.LogWarning((object)("SpawnGroup '" + spawnGroup + "' not found, falling back."));
			}
			if (rarity != null && _spawnGroups.ContainsKey(rarity))
			{
				return rarity;
			}
			if (_spawnGroups.ContainsKey("Default"))
			{
				return "Default";
			}
			_logger.LogWarning((object)"No resolvable SpawnGroup.");
			return null;
		}

		private Dictionary<string, double> BuildMoonSpawnWeights(string spawnGroupName, int spawnWeight, SpawnGroupEntry setSpawnGroup)
		{
			Dictionary<string, double> dictionary = new Dictionary<string, double>();
			if (spawnGroupName == null || !_spawnGroups.TryGetValue(spawnGroupName, out var value))
			{
				return dictionary;
			}
			foreach (var (key, num2) in value.MoonWeightOverrides)
			{
				if (setSpawnGroup.MoonWeightOverrides.TryGetValue(key, out var value2))
				{
					dictionary[key] = (float)spawnWeight * num2 * value2;
				}
			}
			return dictionary;
		}

		private Item CreateCardItem(CardEntry cardEntry, Texture2D texture, int totalInSet)
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			Item val = Object.Instantiate<Item>(_cardBaseItem);
			val.itemName = cardEntry.Name;
			val.isConductiveMetal = cardEntry.Metallic;
			val.toolTips = new string[4]
			{
				cardEntry.Name ?? "",
				$"({cardEntry.Number} of {totalInSet})",
				cardEntry.Rarity ?? "",
				"Inspect: [Z]"
			};
			if ((Object)(object)texture != (Object)null)
			{
				val.itemIcon = Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f));
			}
			Items.RegisterItem(val);
			return val;
		}

		private Item CreateCardPackItem(PackEntry packEntry, Texture2D texture)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			Item val = Object.Instantiate<Item>(_cardPackBaseItem);
			val.itemName = packEntry.Name;
			val.isConductiveMetal = true;
			if ((Object)(object)texture != (Object)null)
			{
				val.itemIcon = Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f));
			}
			Items.RegisterItem(val);
			return val;
		}

		private Texture2D LoadTexture(string relativePath)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			string text = Path.Combine(_contentDir, relativePath);
			if (!File.Exists(text))
			{
				Plugin.logger.LogWarning((object)("Card texture not found at: " + text));
				return null;
			}
			byte[] array = File.ReadAllBytes(text);
			Texture2D val = new Texture2D(2, 2);
			ImageConversion.LoadImage(val, array);
			return val;
		}

		private T LoadJson<T>(string path) where T : class
		{
			if (!File.Exists(path))
			{
				_logger.LogError((object)("JSON file not found: " + path));
				return null;
			}
			try
			{
				T val = JsonConvert.DeserializeObject<T>(File.ReadAllText(path));
				if (val == null)
				{
					_logger.LogError((object)("Deserialization returned null for " + typeof(T).Name + " from " + path));
				}
				return val;
			}
			catch (Exception arg)
			{
				_logger.LogError((object)$"Failed to deserialize {path} into {typeof(T).Name}: {arg}");
				return null;
			}
		}
	}
	public static class CollectionTracker
	{
		private static string _saveFilePath;

		private static bool _initialised;

		private static ManualLogSource Log => Plugin.logger;

		public static void Initialise()
		{
			if (_initialised)
			{
				Log.LogWarning((object)"[CollectionTracker] Already initialised — skipping.");
				return;
			}
			string text = GameNetworkManager.Instance?.currentSaveFileName;
			if (string.IsNullOrWhiteSpace(text))
			{
				Log.LogError((object)"[CollectionTracker] Could not retrieve save file name — collection tracking unavailable.");
				return;
			}
			_saveFilePath = text + "_LethalCardLoader.es3";
			_initialised = true;
			Log.LogInfo((object)("[CollectionTracker] Initialised — save file: " + _saveFilePath));
		}

		public static int GetOwned(int cardId)
		{
			return Object.FindObjectsOfType<BaseCardProp>().Count((BaseCardProp c) => c.TemplateId == cardId && ((GrabbableObject)c).isInShipRoom);
		}

		public static int GetSold(int cardId)
		{
			return ES3.Load<int>($"sold_{cardId}", _saveFilePath, 0);
		}

		public static void IncrementSold(int cardId)
		{
			int sold = GetSold(cardId);
			ES3.Save<int>($"sold_{cardId}", sold + 1, _saveFilePath);
			Log.LogInfo((object)$"[CollectionTracker] Card {cardId} Sold → {sold + 1}");
		}

		public static (int owned, int sold) GetTotalsForSet(IEnumerable<int> cardIds)
		{
			int num = 0;
			int num2 = 0;
			foreach (int cardId in cardIds)
			{
				num += ((GetOwned(cardId) > 0) ? 1 : 0);
				num2 += GetSold(cardId);
			}
			return (num, num2);
		}
	}
	public static class ModCardDatabase
	{
		public class CardInfo
		{
			public int Id;

			public string SetKey;

			public int Number;

			public string Name;

			public string Rarity;

			public Dictionary<string, double> MoonSpawnWeights;

			public int MinValue;

			public int MaxValue;

			public bool Metallic;

			public Texture2D ItemTexture;

			public Texture2D CardBackTexture;

			public Item Item;

			public bool Enabled;
		}

		public class PackInfo
		{
			public int Id;

			public string SetKey;

			public string Key;

			public string Name;

			public Dictionary<string, double> MoonSpawnWeights;

			public List<int> BlacklistedCardIds = new List<int>();

			public Texture2D ItemTexture;

			public Item Item;
		}

		public class SetInfo
		{
			public string Key;

			public Dictionary<int, CardInfo> Cards = new Dictionary<int, CardInfo>();

			public Dictionary<string, PackInfo> Packs = new Dictionary<string, PackInfo>();
		}

		public class CardLocator
		{
			public string SetKey;

			public int CardNumber;
		}

		public class PackLocator
		{
			public string SetKey;

			public string PackKey;
		}

		private static readonly Random _rng = new Random();

		public static readonly Dictionary<string, SetInfo> Sets = new Dictionary<string, SetInfo>(StringComparer.OrdinalIgnoreCase);

		public static readonly Dictionary<int, CardLocator> Cards = new Dictionary<int, CardLocator>();

		public static readonly Dictionary<int, PackLocator> Packs = new Dictionary<int, PackLocator>();

		private static Dictionary<int, Dictionary<int, double>> packSpawnWeights = new Dictionary<int, Dictionary<int, double>>();

		private static Dictionary<string, Dictionary<int, double>> moonCardSpawnWeights = new Dictionary<string, Dictionary<int, double>>(StringComparer.OrdinalIgnoreCase);

		private static Dictionary<string, Dictionary<int, double>> moonPackSpawnWeights = new Dictionary<string, Dictionary<int, double>>(StringComparer.OrdinalIgnoreCase);

		public static void RegisterCard(string setKey, CardInfo card)
		{
			if (!Sets.TryGetValue(setKey, out var value))
			{
				Plugin.logger.LogInfo((object)("Registering new set '" + setKey + "'."));
				value = new SetInfo
				{
					Key = setKey
				};
				Sets[setKey] = value;
			}
			card.Id = Cards.Count + 1;
			Cards[card.Id] = new CardLocator
			{
				CardNumber = card.Number,
				SetKey = setKey
			};
			value.Cards[card.Number] = card;
		}

		public static void RegisterPack(string setKey, PackInfo pack)
		{
			if (!Sets.TryGetValue(setKey, out var value))
			{
				Plugin.logger.LogInfo((object)("Registering new set '" + setKey + "'."));
				value = new SetInfo
				{
					Key = setKey
				};
				Sets[setKey] = value;
			}
			pack.Id = Packs.Count + 1;
			Packs[pack.Id] = new PackLocator
			{
				PackKey = pack.Key,
				SetKey = setKey
			};
			value.Packs[pack.Key] = pack;
		}

		public static void CalculateMoonSpawnWeightsForCards()
		{
			moonCardSpawnWeights.Clear();
			foreach (CardLocator value2 in Cards.Values)
			{
				CardInfo cardInfo = Sets[value2.SetKey].Cards[value2.CardNumber];
				if (!cardInfo.Enabled)
				{
					continue;
				}
				foreach (var (key, num2) in cardInfo.MoonSpawnWeights)
				{
					if (!(num2 <= 0.0))
					{
						if (!moonCardSpawnWeights.TryGetValue(key, out var value))
						{
							value = new Dictionary<int, double>();
							moonCardSpawnWeights[key] = value;
						}
						value[cardInfo.Id] = num2;
					}
				}
			}
			Plugin.logger.LogInfo((object)$"Moon spawn weights calculated: {moonCardSpawnWeights.Count} moons, {Cards.Count} cards registered.");
		}

		public static void CalculateMoonSpawnWeightsForPacks()
		{
			moonPackSpawnWeights.Clear();
			foreach (PackLocator value2 in Packs.Values)
			{
				PackInfo packInfo = Sets[value2.SetKey].Packs[value2.PackKey];
				foreach (var (key, num2) in packInfo.MoonSpawnWeights)
				{
					if (!(num2 <= 0.0))
					{
						if (!moonPackSpawnWeights.TryGetValue(key, out var value))
						{
							value = new Dictionary<int, double>();
							moonPackSpawnWeights[key] = value;
						}
						value[packInfo.Id] = num2;
					}
				}
			}
			Plugin.logger.LogInfo((object)$"Moon spawn weights calculated: {moonPackSpawnWeights.Count} moons, {Packs.Count} packs registered.");
		}

		public static void CalculatePackDropRates(Dictionary<string, RarityEntry> rarities)
		{
			packSpawnWeights.Clear();
			foreach (PackLocator value2 in Packs.Values)
			{
				SetInfo setInfo = Sets[value2.SetKey];
				PackInfo packInfo = setInfo.Packs[value2.PackKey];
				Dictionary<int, double> dictionary = new Dictionary<int, double>();
				foreach (CardInfo value3 in setInfo.Cards.Values)
				{
					if (value3.Enabled && !packInfo.BlacklistedCardIds.Contains(value3.Number) && rarities.TryGetValue(value3.Rarity ?? "", out var value) && value.CardPackWeight > 0)
					{
						dictionary[value3.Id] = value.CardPackWeight;
					}
				}
				packSpawnWeights[packInfo.Id] = dictionary;
				Plugin.logger.LogInfo((object)$"Pack '{packInfo.Key}': {dictionary.Count} eligible cards.");
			}
		}

		public static CardInfo RetrieveCardById(int cardId)
		{
			if (!Cards.TryGetValue(cardId, out var value))
			{
				Plugin.logger.LogWarning((object)$"No card registered with id {cardId}");
				return null;
			}
			return Sets[value.SetKey].Cards[value.CardNumber];
		}

		public static SetInfo RetrieveSetByCardId(int cardId)
		{
			if (!Cards.TryGetValue(cardId, out var value))
			{
				Plugin.logger.LogWarning((object)$"No card registered with id {cardId}");
				return null;
			}
			return Sets[value.SetKey];
		}

		public static PackInfo RetrievePackById(int packId)
		{
			if (!Packs.TryGetValue(packId, out var value))
			{
				Plugin.logger.LogWarning((object)$"No pack registered with id {packId}");
				return null;
			}
			return Sets[value.SetKey].Packs[value.PackKey];
		}

		public static SetInfo RetrieveSetByPackId(int packId)
		{
			if (!Packs.TryGetValue(packId, out var value))
			{
				Plugin.logger.LogWarning((object)$"No pack registered with id {packId}");
				return null;
			}
			return Sets[value.SetKey];
		}

		private static TKey WeightedRandom<TKey>(Dictionary<TKey, double> pool)
		{
			double num = pool.Values.Sum();
			double num2 = _rng.NextDouble() * num;
			double num3 = 0.0;
			foreach (KeyValuePair<TKey, double> item in pool)
			{
				item.Deconstruct(out var key, out var value);
				TKey result = key;
				double num4 = value;
				num3 += num4;
				if (num2 < num3)
				{
					return result;
				}
			}
			return pool.Keys.Last();
		}

		public static CardInfo SelectCardForMoon(string moonName)
		{
			string value;
			string key = (ConfigManager.LevelNamesMap.TryGetValue(moonName, out value) ? value : moonName);
			if (!moonCardSpawnWeights.TryGetValue(key, out var value2))
			{
				Plugin.logger.LogWarning((object)("No spawn pool found for moon '" + moonName + "'."));
				return null;
			}
			if (value2.Count == 0)
			{
				Plugin.logger.LogWarning((object)("Spawn pool for moon '" + moonName + "' is empty."));
				return null;
			}
			return RetrieveCardById(WeightedRandom(value2));
		}

		public static CardInfo SelectCardForPack(int packId)
		{
			if (!packSpawnWeights.TryGetValue(packId, out var value) || value.Count == 0)
			{
				Plugin.logger.LogWarning((object)$"No spawn pool for pack id {packId}.");
				return null;
			}
			return RetrieveCardById(WeightedRandom(value));
		}

		public static PackInfo SelectPackForMoon(string moonName)
		{
			string value;
			string key = (ConfigManager.LevelNamesMap.TryGetValue(moonName, out value) ? value : moonName);
			if (!moonPackSpawnWeights.TryGetValue(key, out var value2))
			{
				Plugin.logger.LogWarning((object)("No pack spawn pool found for moon '" + moonName + "'."));
				return null;
			}
			if (value2.Count == 0)
			{
				Plugin.logger.LogWarning((object)("Spawn pool for moon '" + moonName + "' is empty."));
				return null;
			}
			return RetrievePackById(WeightedRandom(value2));
		}
	}
}
namespace LethalCardLoader.Models
{
	public class SetManifest
	{
		public int Id { get; set; }

		public string Key { get; set; }

		public string Name { get; set; }

		public int Number { get; set; }

		public int CardSpawnWeight { get; set; }

		public string CardBackTexturePath { get; set; }

		public List<PackEntry> Packs { get; set; }

		public List<CardEntry> Cards { get; set; }
	}
	public class PackEntry
	{
		public string Key { get; set; }

		public string Name { get; set; }

		public List<int> BlacklistedCardIds { get; set; } = new List<int>();


		public string ItemTexturePath { get; set; }

		public string SpawnGroup { get; set; } = string.Empty;

	}
	public class CardEntry
	{
		public int Number { get; set; }

		public string Name { get; set; }

		public string ItemTexturePath { get; set; }

		public string Rarity { get; set; }

		public bool Enabled { get; set; } = true;


		public bool Metallic { get; set; } = false;


		public string SpawnGroup { get; set; } = string.Empty;


		public double ValueMultiplier { get; set; } = 1.0;

	}
}
namespace LethalCardLoader.CustomProps
{
	internal class BaseCardProp : TemplatableProp
	{
		public ModCardDatabase.CardInfo CardInfo;

		public bool hasBeenRecordedInCollection = false;

		public override void AssignTemplateData()
		{
			string planetName = StartOfRound.Instance.currentLevel.PlanetName;
			CardInfo = ModCardDatabase.SelectCardForMoon(planetName);
			if (CardInfo == null)
			{
				Plugin.logger.LogWarning((object)"No card could be selected for moon, aborting.");
				return;
			}
			((GrabbableObject)this).SetScrapValue(Random.Range(CardInfo.MinValue, CardInfo.MaxValue));
			base.TemplateId = CardInfo.Id;
			Plugin.logger.LogInfo((object)$"Assigned card '{CardInfo.Name}' (id: {base.TemplateId})");
		}

		public override void ApplyProperties()
		{
			if (CardInfo == null)
			{
				CardInfo = ModCardDatabase.RetrieveCardById(base.TemplateId);
			}
			if (CardInfo == null)
			{
				Plugin.logger.LogWarning((object)$"No card found in database for id {base.TemplateId}.");
				return;
			}
			((GrabbableObject)this).itemProperties = CardInfo.Item;
			ScanNodeProperties componentInChildren = ((Component)this).GetComponentInChildren<ScanNodeProperties>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.headerText = CardInfo.Name;
				componentInChildren.subText = $"Value: {((GrabbableObject)this).scrapValue}";
			}
			if ((Object)(object)CardInfo.ItemTexture != (Object)null)
			{
				ApplyCardTexture();
			}
		}

		private void ApplyCardTexture()
		{
			Transform val = ((Component)this).transform.Find("CardBase");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.logger.LogWarning((object)"Could not find 'CardBase' mesh on card.");
				return;
			}
			Renderer component = ((Component)val).GetComponent<Renderer>();
			Material[] materials = component.materials;
			if ((Object)(object)CardInfo.CardBackTexture != (Object)null)
			{
				materials[0].mainTexture = (Texture)(object)CardInfo.CardBackTexture;
			}
			if ((Object)(object)CardInfo.ItemTexture != (Object)null)
			{
				materials[1].mainTexture = (Texture)(object)CardInfo.ItemTexture;
			}
			component.materials = materials;
		}

		protected override void __initializeVariables()
		{
			base.__initializeVariables();
		}

		protected override void __initializeRpcs()
		{
			base.__initializeRpcs();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string __getTypeName()
		{
			return "BaseCardProp";
		}
	}
	internal class BoosterPackProp : TemplatableProp
	{
		[CompilerGenerated]
		private sealed class <SetObjectFallSFX>d__19 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public GrabbableObject gObject;

			public BoosterPackProp <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SetObjectFallSFX>d__19(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForEndOfFrame();
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if ((Object)(object)gObject != (Object)null)
					{
						gObject.reachedFloorTarget = false;
						gObject.hasHitGround = false;
						gObject.fallTime = 0f;
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <WaitForCardOnClient>d__17 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public NetworkObjectReference netObjectRef;

			public int cardValue;

			public Vector3 spawnPos;

			public BoosterPackProp <>4__this;

			private NetworkObject <netObject>5__1;

			private float <startTime>5__2;

			private BaseCardProp <card>5__3;

			private Transform <parent>5__4;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitForCardOnClient>d__17(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<netObject>5__1 = null;
				<card>5__3 = null;
				<parent>5__4 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_017f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0184: Unknown result type (might be due to invalid IL or missing references)
				//IL_0171: Unknown result type (might be due to invalid IL or missing references)
				//IL_0189: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Expected O, but got Unknown
				//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
				//IL_01db: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b3: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bf: Expected O, but got Unknown
				//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<netObject>5__1 = null;
					<startTime>5__2 = Time.realtimeSinceStartup;
					goto IL_0062;
				case 1:
					<>1__state = -1;
					goto IL_0062;
				case 2:
					{
						<>1__state = -1;
						<card>5__3 = ((Component)<netObject>5__1).GetComponent<BaseCardProp>();
						if ((Object)(object)<card>5__3 == (Object)null)
						{
							return false;
						}
						<card>5__3.ApplyProperties();
						RoundManager instance = RoundManager.Instance;
						instance.totalScrapValueInLevel -= (float)((GrabbableObject)<>4__this).scrapValue;
						RoundManager instance2 = RoundManager.Instance;
						instance2.totalScrapValueInLevel += (float)cardValue;
						<parent>5__4 = <>4__this.GetParentOfGiftObject();
						((Component)<card>5__3).transform.SetParent(<parent>5__4, true);
						((GrabbableObject)<card>5__3).startFallingPosition = (((Object)(object)<parent>5__4 != (Object)null) ? <parent>5__4.InverseTransformPoint(spawnPos) : spawnPos);
						((GrabbableObject)<card>5__3).targetFloorPosition = (((Object)(object)((Component)<card>5__3).transform.parent != (Object)null) ? ((Component)<card>5__3).transform.parent.InverseTransformPoint(((GrabbableObject)<card>5__3).GetItemFloorPosition(spawnPos)) : ((GrabbableObject)<card>5__3).GetItemFloorPosition(spawnPos));
						((GrabbableObject)<card>5__3).fallTime = 0f;
						((GrabbableObject)<card>5__3).hasHitGround = false;
						((GrabbableObject)<card>5__3).reachedFloorTarget = false;
						if ((Object)(object)<>4__this._previousPlayerHeldBy != (Object)null && <>4__this._previousPlayerHeldBy.isInHangarShipRoom)
						{
							<>4__this._previousPlayerHeldBy.SetItemInElevator(true, true, (GrabbableObject)(object)<card>5__3);
						}
						return false;
					}
					IL_0062:
					if (Time.realtimeSinceStartup - <startTime>5__2 < 8f && !((NetworkObjectReference)(ref netObjectRef)).TryGet(ref <netObject>5__1, (NetworkManager)null))
					{
						<>2__current = (object)new WaitForSeconds(0.03f);
						<>1__state = 1;
						return true;
					}
					if ((Object)(object)<netObject>5__1 == (Object)null)
					{
						Plugin.logger.LogWarning((object)"BoosterPack: card NetworkObject not found on client.");
						return false;
					}
					<>2__current = (object)new WaitForEndOfFrame();
					<>1__state = 2;
					return true;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public ParticleSystem PoofParticle;

		public AudioSource presentAudio;

		public AudioClip openGiftAudio;

		private PlayerControllerB _previousPlayerHeldBy;

		private bool _hasOpened;

		public ModCardDatabase.PackInfo PackInfo { get; private set; }

		public override void AssignTemplateData()
		{
			string planetName = StartOfRound.Instance.currentLevel.PlanetName;
			PackInfo = ModCardDatabase.SelectPackForMoon(planetName);
			if (PackInfo == null)
			{
				Plugin.logger.LogWarning((object)"No pack could be selected for moon, aborting.");
				return;
			}
			base.TemplateId = PackInfo.Id;
			Plugin.logger.LogInfo((object)$"Assigned pack '{PackInfo.Name}' (id: {base.TemplateId})");
		}

		public override void ApplyProperties()
		{
			if (PackInfo == null)
			{
				PackInfo = ModCardDatabase.RetrievePackById(base.TemplateId);
			}
			if (PackInfo == null)
			{
				Plugin.logger.LogWarning((object)$"No pack found in database for id {base.TemplateId}.");
				return;
			}
			((GrabbableObject)this).itemProperties = PackInfo.Item;
			ScanNodeProperties componentInChildren = ((Component)this).GetComponentInChildren<ScanNodeProperties>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.headerText = PackInfo.Name;
				componentInChildren.subText = $"Value: {((GrabbableObject)this).scrapValue}";
			}
			if ((Object)(object)PackInfo.ItemTexture != (Object)null)
			{
				ApplyPackTexture();
			}
		}

		private void ApplyPackTexture()
		{
			Transform val = ((Component)this).transform.Find("CardPackBase");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.logger.LogWarning((object)"Could not find 'CardPackBase' mesh on pack.");
				return;
			}
			Renderer component = ((Component)val).GetComponent<Renderer>();
			Material[] materials = component.materials;
			if ((Object)(object)PackInfo.ItemTexture != (Object)null)
			{
				materials[0].mainTexture = (Texture)(object)PackInfo.ItemTexture;
			}
			component.materials = materials;
		}

		public override void EquipItem()
		{
			((PhysicsProp)this).EquipItem();
			_previousPlayerHeldBy = ((GrabbableObject)this).playerHeldBy;
		}

		public override void PocketItem()
		{
			((GrabbableObject)this).PocketItem();
			if ((Object)(object)((GrabbableObject)this).playerHeldBy != (Object)null)
			{
				((GrabbableObject)this).playerHeldBy.activatingItem = false;
			}
		}

		public override void ItemActivate(bool used, bool buttonDown = true)
		{
			((GrabbableObject)this).ItemActivate(used, buttonDown);
			if (!((Object)(object)((GrabbableObject)this).playerHeldBy == (Object)null) && !_hasOpened)
			{
				_hasOpened = true;
				((GrabbableObject)this).playerHeldBy.activatingItem = true;
				OpenBoosterServerRpc();
			}
		}

		[ServerRpc(RequireOwnership = false)]
		public void OpenBoosterServerRpc()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: 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_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				ServerRpcParams val = default(ServerRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(2302076414u, val, (RpcDelivery)0);
				((NetworkBehaviour)this).__endSendServerRpc(ref val2, 2302076414u, val, (RpcDelivery)0);
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 1 || (!networkManager.IsServer && !networkManager.IsHost))
			{
				return;
			}
			((NetworkBehaviour)this).__rpc_exec_stage = (__RpcExecStage)0;
			if (!((NetworkBehaviour)this).IsServer)
			{
				return;
			}
			ModCardDatabase.CardInfo cardInfo = ModCardDatabase.SelectCardForPack(base.TemplateId);
			if (cardInfo == null)
			{
				Plugin.logger.LogWarning((object)("Pack '" + PackInfo?.Name + "' could not select a card."));
				OpenBoosterClientRpc(default(NetworkObjectReference), 0, ((Component)this).transform.position);
				return;
			}
			int num = Random.Range(cardInfo.MinValue, cardInfo.MaxValue);
			Vector3 val3 = ((Component)this).transform.position + Vector3.up * 0.25f;
			Transform parentOfGiftObject = GetParentOfGiftObject();
			GameObject val4 = Object.Instantiate<GameObject>(cardInfo.Item.spawnPrefab, val3, Quaternion.identity, parentOfGiftObject);
			BaseCardProp component = val4.GetComponent<BaseCardProp>();
			if ((Object)(object)component != (Object)null)
			{
				((GrabbableObject)component).SetScrapValue(num);
				component.CardInfo = cardInfo;
				component.TemplateId = cardInfo.Id;
			}
			NetworkObject component2 = val4.GetComponent<NetworkObject>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.Spawn(false);
				((MonoBehaviour)this).StartCoroutine(SetObjectFallSFX((GrabbableObject)(object)component));
				OpenBoosterClientRpc(new NetworkObjectReference(component2), num, val3);
			}
			else
			{
				Plugin.logger.LogWarning((object)"Spawned card has no NetworkObject.");
				OpenBoosterClientRpc(default(NetworkObjectReference), 0, val3);
			}
		}

		[ClientRpc]
		public void OpenBoosterClientRpc(NetworkObjectReference netObjectRef, int cardValue, Vector3 spawnPos)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2979095893u, val, (RpcDelivery)0);
				((FastBufferWriter)(ref val2)).WriteValueSafe<NetworkObjectReference>(ref netObjectRef, default(ForNetworkSerializable));
				BytePacker.WriteValueBitPacked(val2, cardValue);
				((FastBufferWriter)(ref val2)).WriteValueSafe(ref spawnPos);
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2979095893u, val, (RpcDelivery)0);
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				((NetworkBehaviour)this).__rpc_exec_stage = (__RpcExecStage)0;
				PlayOpenEffects();
				if ((Object)(object)((GrabbableObject)this).playerHeldBy != (Object)null)
				{
					((GrabbableObject)this).playerHeldBy.activatingItem = false;
					((GrabbableObject)this).DestroyObjectInHand(((GrabbableObject)this).playerHeldBy);
				}
				if (!((NetworkBehaviour)this).IsServer)
				{
					((MonoBehaviour)this).StartCoroutine(WaitForCardOnClient(netObjectRef, cardValue, spawnPos));
				}
			}
		}

		[IteratorStateMachine(typeof(<WaitForCardOnClient>d__17))]
		private IEnumerator WaitForCardOnClient(NetworkObjectReference netObjectRef, int cardValue, Vector3 spawnPos)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForCardOnClient>d__17(0)
			{
				<>4__this = this,
				netObjectRef = netObjectRef,
				cardValue = cardValue,
				spawnPos = spawnPos
			};
		}

		private void PlayOpenEffects()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)PoofParticle != (Object)null)
			{
				PoofParticle.Play();
			}
			if ((Object)(object)presentAudio != (Object)null && (Object)(object)openGiftAudio != (Object)null)
			{
				presentAudio.PlayOneShot(openGiftAudio);
				WalkieTalkie.TransmitOneShotAudio(presentAudio, openGiftAudio, 1f);
				RoundManager.Instance.PlayAudibleNoise(((Component)presentAudio).transform.position, 8f, 0.5f, 0, ((GrabbableObject)this).isInShipRoom && StartOfRound.Instance.hangarDoorsClosed, 0);
			}
		}

		[IteratorStateMachine(typeof(<SetObjectFallSFX>d__19))]
		private IEnumerator SetObjectFallSFX(GrabbableObject gObject)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SetObjectFallSFX>d__19(0)
			{
				<>4__this = this,
				gObject = gObject
			};
		}

		private Transform GetParentOfGiftObject()
		{
			if (((Object)(object)_previousPlayerHeldBy != (Object)null && _previousPlayerHeldBy.isInElevator) || StartOfRound.Instance.inShipPhase)
			{
				return StartOfRound.Instance.elevatorTransform;
			}
			return null;
		}

		protected override void __initializeVariables()
		{
			base.__initializeVariables();
		}

		protected override void __initializeRpcs()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			((NetworkBehaviour)this).__registerRpc(2302076414u, new RpcReceiveHandler(__rpc_handler_2302076414), "OpenBoosterServerRpc");
			((NetworkBehaviour)this).__registerRpc(2979095893u, new RpcReceiveHandler(__rpc_handler_2979095893), "OpenBoosterClientRpc");
			base.__initializeRpcs();
		}

		private static void __rpc_handler_2302076414(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((BoosterPackProp)(object)target).OpenBoosterServerRpc();
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_2979095893(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				NetworkObjectReference netObjectRef = default(NetworkObjectReference);
				((FastBufferReader)(ref reader)).ReadValueSafe<NetworkObjectReference>(ref netObjectRef, default(ForNetworkSerializable));
				int cardValue = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref cardValue);
				Vector3 spawnPos = default(Vector3);
				((FastBufferReader)(ref reader)).ReadValueSafe(ref spawnPos);
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((BoosterPackProp)(object)target).OpenBoosterClientRpc(netObjectRef, cardValue, spawnPos);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string __getTypeName()
		{
			return "BoosterPackProp";
		}
	}
	internal abstract class TemplatableProp : PhysicsProp
	{
		public bool isSynced = false;

		public bool isLoaded = false;

		public int TemplateId { get; set; }

		public abstract void AssignTemplateData();

		public abstract void ApplyProperties();

		public override void OnNetworkSpawn()
		{
			((NetworkBehaviour)this).OnNetworkSpawn();
			if (((NetworkBehaviour)this).IsServer)
			{
				if (TemplateId == 0)
				{
					AssignTemplateData();
				}
				SyncDataClientRpc(TemplateId, ((GrabbableObject)this).scrapValue);
			}
		}

		[ClientRpc]
		public void SyncDataClientRpc(int id, int value)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(796621470u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, id);
				BytePacker.WriteValueBitPacked(val2, value);
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 796621470u, val, (RpcDelivery)0);
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				((NetworkBehaviour)this).__rpc_exec_stage = (__RpcExecStage)0;
				((GrabbableObject)this).SetScrapValue(value);
				TemplateId = id;
				if (TemplateId >= 0)
				{
					ApplyProperties();
				}
			}
		}

		public override int GetItemDataToSave()
		{
			return TemplateId;
		}

		public override void LoadItemSaveData(int saveData)
		{
			if (saveData > 0)
			{
				TemplateId = saveData;
				isLoaded = true;
				if (((NetworkBehaviour)this).IsServer)
				{
					isSynced = true;
				}
				ApplyProperties();
			}
		}

		protected override void __initializeVariables()
		{
			((PhysicsProp)this).__initializeVariables();
		}

		protected override void __initializeRpcs()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			((NetworkBehaviour)this).__registerRpc(796621470u, new RpcReceiveHandler(__rpc_handler_796621470), "SyncDataClientRpc");
			((PhysicsProp)this).__initializeRpcs();
		}

		private static void __rpc_handler_796621470(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				int id = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref id);
				int value = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref value);
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((TemplatableProp)(object)target).SyncDataClientRpc(id, value);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string __getTypeName()
		{
			return "TemplatableProp";
		}
	}
}
namespace LethalCardLoader.Config
{
	public static class ConfigManager
	{
		public static List<MoonEntry> Moons = new List<MoonEntry>();

		public static List<SetEntry> Sets = new List<SetEntry>();

		public static List<SpawnGroupEntry> SpawnGroups = new List<SpawnGroupEntry>();

		public static List<RarityEntry> RarityConfigs = new List<RarityEntry>();

		private static Dictionary<string, string> _levelNamesMap = new Dictionary<string, string>();

		private static bool _moonsLoaded = false;

		private static bool _setsLoaded = false;

		private static bool _spawnGroupsLoaded = false;

		private static bool _raritiesLoaded = false;

		private static bool _missingMoonsCreated = false;

		public static Dictionary<string, string> LevelNamesMap => _levelNamesMap;

		public static void LoadMoonConfigs()
		{
			if (_moonsLoaded)
			{
				Plugin.logger.LogWarning((object)"[ConfigManager] LoadMoonConfigs called more than once — skipping.");
				return;
			}
			_moonsLoaded = true;
			List<string> headerValues = GetHeaderValues("Moon");
			foreach (string item in headerValues)
			{
				MoonEntry moonEntry = new MoonEntry();
				moonEntry.Bind(item, string.Empty);
				Moons.Add(moonEntry);
				if (string.IsNullOrWhiteSpace(moonEntry.InternalName))
				{
					Plugin.logger.LogWarning((object)("[ConfigManager] Moon '" + item + "' has no Internal Name — it will be populated on next game load."));
				}
			}
			RebuildLevelNamesMap();
		}

		public static void CreateDefaults()
		{
			new RarityEntry().Bind("Common", 30, 80, 70);
			new RarityEntry().Bind("Uncommon", 50, 15, 20);
			new RarityEntry().Bind("Rare", 80, 5, 10);
			new SpawnGroupEntry().Bind("Default", Moons);
		}

		public static void LoadSetConfigs()
		{
			if (_setsLoaded)
			{
				Plugin.logger.LogWarning((object)"[ConfigManager] LoadSetConfigs called more than once — skipping.");
				return;
			}
			_setsLoaded = true;
			List<string> headerValues = GetHeaderValues("Set");
			foreach (string item in headerValues)
			{
				SetEntry setEntry = new SetEntry();
				setEntry.Bind(item, Sets.Count + 1);
				Sets.Add(setEntry);
			}
		}

		public static void LoadSpawnGroupConfigs()
		{
			if (_spawnGroupsLoaded)
			{
				Plugin.logger.LogWarning((object)"[ConfigManager] LoadSpawnGroupConfigs called more than once — skipping.");
				return;
			}
			_spawnGroupsLoaded = true;
			List<string> headerValues = GetHeaderValues("Spawn Group");
			foreach (string item in headerValues)
			{
				SpawnGroupEntry spawnGroupEntry = new SpawnGroupEntry();
				spawnGroupEntry.Bind(item, Moons);
				SpawnGroups.Add(spawnGroupEntry);
			}
		}

		public static void LoadRarityConfigs()
		{
			if (_raritiesLoaded)
			{
				Plugin.logger.LogWarning((object)"[ConfigManager] LoadRarityConfigs called more than once — skipping.");
				return;
			}
			_raritiesLoaded = true;
			List<string> headerValues = GetHeaderValues("Rarity");
			foreach (string item in headerValues)
			{
				RarityEntry rarityEntry = new RarityEntry();
				rarityEntry.Bind(item);
				RarityConfigs.Add(rarityEntry);
				Plugin.logger.LogInfo((object)("[ConfigManager] Loaded rarity: " + item));
			}
			Plugin.logger.LogInfo((object)$"[ConfigManager] Loaded {RarityConfigs.Count} rarity/rarities.");
		}

		private static void RebuildLevelNamesMap()
		{
			_levelNamesMap = Moons.ToDictionary((MoonEntry a) => a.PlanetName, (MoonEntry a) => a.InternalName);
		}

		public static void CreateMissingMoonConfigs(Dictionary<string, string> levelNameMap)
		{
			if (_missingMoonsCreated)
			{
				Plugin.logger.LogWarning((object)"[ConfigManager] CreateMissingMoonConfigs called more than once — skipping.");
				return;
			}
			_missingMoonsCreated = true;
			List<MoonEntry> list = new List<MoonEntry>();
			foreach (KeyValuePair<string, string> levelName in levelNameMap)
			{
				if (Moons.Any((MoonEntry m) => m.PlanetName == levelName.Key))
				{
					Plugin.logger.LogWarning((object)("[ConfigManager] Moon '" + levelName.Key + "' already exists — skipping."));
					continue;
				}
				MoonEntry moonEntry = new MoonEntry();
				moonEntry.Bind(levelName.Key, levelName.Value);
				Moons.Add(moonEntry);
				list.Add(moonEntry);
				Plugin.logger.LogInfo((object)("[ConfigManager] Registered new moon: " + levelName.Key + " (" + levelName.Value + ")"));
			}
			if (list.Count == 0)
			{
				return;
			}
			foreach (SpawnGroupEntry spawnGroup in SpawnGroups)
			{
				spawnGroup.AddMissingMoons(list);
			}
			RebuildLevelNamesMap();
		}

		public static List<string> GetHeaderValues(string prefix)
		{
			string path = Path.Combine(Paths.ConfigPath, "com.sholiver.lethalcardloader.cfg");
			List<string> list = new List<string>();
			if (!File.Exists(path))
			{
				Plugin.logger.LogWarning((object)("[ConfigManager] Config file not found when reading " + prefix + " names."));
				return list;
			}
			foreach (string item in File.ReadLines(path))
			{
				string text = item.Trim();
				if (!text.StartsWith("[") || !text.EndsWith("]"))
				{
					continue;
				}
				string text2 = text.Substring(1, text.Length - 2).Trim();
				if (text2.StartsWith(prefix + ":", StringComparison.OrdinalIgnoreCase))
				{
					string text3 = text2.Substring(prefix.Length + 1).Trim();
					if (!string.IsNullOrWhiteSpace(text3))
					{
						list.Add(text3);
					}
				}
			}
			Plugin.logger.LogInfo((object)$"[ConfigManager] Found {list.Count} existing {prefix}(s) in config.");
			return list;
		}
	}
	public class MoonEntry
	{
		private ConfigEntry<string> _planetName;

		private ConfigEntry<string> _internalName;

		private ConfigEntry<int> _cardScrapRarity;

		private ConfigEntry<int> _packScrapRarity;

		public string PlanetName => _planetName.Value;

		public string InternalName => _internalName.Value;

		public int CardScrapRarity => _cardScrapRarity.Value;

		public int PackScrapRarity => _packScrapRarity.Value;

		public void Bind(string planetName, string internalName, int cardRarity = 100, int packRarity = 100)
		{
			ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config;
			string text = "Moon: " + planetName;
			_planetName = config.Bind<string>(text, "Planet Name", planetName, "Auto-managed — do not edit manually.");
			_internalName = config.Bind<string>(text, "Internal Name", internalName, "Auto-managed — do not edit manually.");
			_cardScrapRarity = config.Bind<int>(text, "Card Scrap Rarity", cardRarity, "Rarity of card scrap spawning on this moon (0-100).");
			_packScrapRarity = config.Bind<int>(text, "Pack Scrap Rarity", packRarity, "Rarity of pack scrap spawning on this moon (0-100).");
		}
	}
	public class RarityEntry
	{
		private ConfigEntry<string> _key;

		private ConfigEntry<int> _value;

		private ConfigEntry<int> _spawnWeight;

		private ConfigEntry<int> _cardPackWeight;

		public string Key => _key.Value;

		public int Value => _value.Value;

		public int SpawnWeight => _spawnWeight.Value;

		public int CardPackWeight => _cardPackWeight.Value;

		public void Bind(string key, int value = 100, int spawnWeight = 50, int cardPackWeight = 50)
		{
			ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config;
			string text = "Rarity: " + key;
			_key = config.Bind<string>(text, "Key", key, "The unique key for this rarity tier.");
			_value = config.Bind<int>(text, "Value", value, "The scrap value multiplier for this rarity tier.");
			_spawnWeight = config.Bind<int>(text, "Spawn Weight", spawnWeight, "The relative weight of this rarity tier when spawning scrap.");
			_cardPackWeight = config.Bind<int>(text, "Card Pack Weight", cardPackWeight, "The relative weight of this rarity tier when opening a card pack.");
		}
	}
	public class SetEntry
	{
		private ConfigEntry<string> _name;

		private ConfigEntry<string> _key;

		private ConfigEntry<int> _id;

		private ConfigEntry<string> _spawnGroup;

		public string Name => _name.Value;

		public string Key => _key.Value;

		public int Id => _id.Value;

		public string SpawnGroup => _spawnGroup.Value;

		public void Bind(string name, int id, string key = "", string spawnGroup = "Default")
		{
			ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config;
			string text = "Set: " + name;
			_name = config.Bind<string>(text, "Name", name, "The display name of this set.");
			_key = config.Bind<string>(text, "Key", string.IsNullOrEmpty(key) ? name.Replace(" ", "") : key, "Used to derive the manifest filename (e.g. \"BaseSet\" → \"BaseSet.json\").");
			_id = config.Bind<int>(text, "Id", id, "Unique numeric identifier for this set.");
			_spawnGroup = config.Bind<string>(text, "Spawn Group", spawnGroup, "The spawn group this set belongs to.");
		}
	}
	public class SpawnGroupEntry
	{
		private ConfigEntry<string> _key;

		private List<ConfigEntry<float>> _moonWeights = new List<ConfigEntry<float>>();

		private Dictionary<string, float> _moonWeightOverrides = new Dictionary<string, float>();

		public string Key => _key.Value;

		public Dictionary<string, float> MoonWeightOverrides => _moonWeightOverrides;

		public void Bind(string key, List<MoonEntry> moons)
		{
			ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config;
			string text = "Spawn Group: " + key;
			_key = config.Bind<string>(text, "Key", key, "The unique key for this spawn group.");
			foreach (MoonEntry moon in moons)
			{
				_moonWeights.Add(config.Bind<float>(text, moon.InternalName, 1f, "Weight multiplier for this moon. (0.0 = never spawns, 1.0 = normal weight)"));
			}
			RebuildMoonWeightOverrides();
		}

		public void AddMissingMoons(List<MoonEntry> newMoons)
		{
			ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config;
			string text = "Spawn Group: " + Key;
			foreach (MoonEntry moon in newMoons)
			{
				if (string.IsNullOrWhiteSpace(moon.InternalName))
				{
					Plugin.logger.LogWarning((object)("[SpawnGroupEntry] Skipping moon '" + moon.PlanetName + "' — InternalName is empty."));
				}
				else if (!_moonWeights.Any((ConfigEntry<float> e) => ((ConfigEntryBase)e).Definition.Key == moon.InternalName))
				{
					_moonWeights.Add(config.Bind<float>(text, moon.InternalName, 1f, "Weight multiplier for this moon. (0.0 = never spawns, 1.0 = normal weight)"));
				}
			}
			RebuildMoonWeightOverrides();
		}

		private void RebuildMoonWeightOverrides()
		{
			_moonWeightOverrides = _moonWeights.ToDictionary((ConfigEntry<float> e) => ((ConfigEntryBase)e).Definition.Key, (ConfigEntry<float> e) => e.Value);
		}
	}
}
namespace __GEN
{
	internal class NetworkVariableSerializationHelper
	{
		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeSerialization()
		{
		}
	}
}
namespace LethalCardLoader.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}