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 _pendingSoldCardIds = new List(); [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 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 dictionary = source.Where((KeyValuePair kvp) => !ConfigManager.Moons.Any((MoonEntry m) => m.PlanetName == kvp.Key)).ToDictionary((KeyValuePair kvp) => kvp.Key, (KeyValuePair 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(); 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|]"; } 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 enumerable = ModCardDatabase.Sets[set.Key].Cards.Select((KeyValuePair 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 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 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 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 _rarities; private Dictionary _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("Assets/LethalCardLoader/CardBase_Item.asset"); _cardBaseItem.saveItemVariable = true; ((Object)_cardBaseItem).name = "BaseCard"; _cardBaseItem.itemName = "BaseCard"; _cardBaseItem.isScrap = true; BaseCardProp baseCardProp = _cardBaseItem.spawnPrefab.AddComponent(); ((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, Dictionary) tuple = SplitLevelRarity(ConfigManager.Moons.ToDictionary((MoonEntry a) => a.InternalName, (MoonEntry a) => a.CardScrapRarity)); Items.RegisterScrap(_cardBaseItem, tuple.Item1, tuple.Item2); _cardPackBaseItem = val.LoadAsset("Assets/LethalCardLoader/CardPackBase_Item.asset"); _cardPackBaseItem.saveItemVariable = true; ((Object)_cardPackBaseItem).name = "BasePack"; _cardPackBaseItem.itemName = "BasePack"; _cardPackBaseItem.isScrap = true; BoosterPackProp boosterPackProp = _cardPackBaseItem.spawnPrefab.AddComponent(); ((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, Dictionary) tuple2 = SplitLevelRarity(ConfigManager.Moons.ToDictionary((MoonEntry a) => a.InternalName, (MoonEntry a) => a.PackScrapRarity)); Items.RegisterScrap(_cardPackBaseItem, tuple2.Item1, tuple2.Item2); return true; } public (Dictionary vanilla, Dictionary modded) SplitLevelRarity(Dictionary levels) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); Dictionary dictionary2 = new Dictionary(); foreach (KeyValuePair 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(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 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 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 BuildMoonSpawnWeights(string spawnGroupName, int spawnWeight, SpawnGroupEntry setSpawnGroup) { Dictionary dictionary = new Dictionary(); 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(_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(_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(string path) where T : class { if (!File.Exists(path)) { _logger.LogError((object)("JSON file not found: " + path)); return null; } try { T val = JsonConvert.DeserializeObject(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().Count((BaseCardProp c) => c.TemplateId == cardId && ((GrabbableObject)c).isInShipRoom); } public static int GetSold(int cardId) { return ES3.Load($"sold_{cardId}", _saveFilePath, 0); } public static void IncrementSold(int cardId) { int sold = GetSold(cardId); ES3.Save($"sold_{cardId}", sold + 1, _saveFilePath); Log.LogInfo((object)$"[CollectionTracker] Card {cardId} Sold → {sold + 1}"); } public static (int owned, int sold) GetTotalsForSet(IEnumerable 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 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 MoonSpawnWeights; public List BlacklistedCardIds = new List(); public Texture2D ItemTexture; public Item Item; } public class SetInfo { public string Key; public Dictionary Cards = new Dictionary(); public Dictionary Packs = new Dictionary(); } 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 Sets = new Dictionary(StringComparer.OrdinalIgnoreCase); public static readonly Dictionary Cards = new Dictionary(); public static readonly Dictionary Packs = new Dictionary(); private static Dictionary> packSpawnWeights = new Dictionary>(); private static Dictionary> moonCardSpawnWeights = new Dictionary>(StringComparer.OrdinalIgnoreCase); private static Dictionary> moonPackSpawnWeights = new Dictionary>(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(); 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(); 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 rarities) { packSpawnWeights.Clear(); foreach (PackLocator value2 in Packs.Values) { SetInfo setInfo = Sets[value2.SetKey]; PackInfo packInfo = setInfo.Packs[value2.PackKey]; Dictionary dictionary = new Dictionary(); 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(Dictionary pool) { double num = pool.Values.Sum(); double num2 = _rng.NextDouble() * num; double num3 = 0.0; foreach (KeyValuePair 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 Packs { get; set; } public List Cards { get; set; } } public class PackEntry { public string Key { get; set; } public string Name { get; set; } public List BlacklistedCardIds { get; set; } = new List(); 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(); 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(); 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 d__19 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GrabbableObject gObject; public BoosterPackProp <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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 d__17 : IEnumerator, 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 5__1; private float 5__2; private BaseCardProp 5__3; private Transform 5__4; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__17(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__1 = null; 5__3 = null; 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; 5__1 = null; 5__2 = Time.realtimeSinceStartup; goto IL_0062; case 1: <>1__state = -1; goto IL_0062; case 2: { <>1__state = -1; 5__3 = ((Component)5__1).GetComponent(); if ((Object)(object)5__3 == (Object)null) { return false; } 5__3.ApplyProperties(); RoundManager instance = RoundManager.Instance; instance.totalScrapValueInLevel -= (float)((GrabbableObject)<>4__this).scrapValue; RoundManager instance2 = RoundManager.Instance; instance2.totalScrapValueInLevel += (float)cardValue; 5__4 = <>4__this.GetParentOfGiftObject(); ((Component)5__3).transform.SetParent(5__4, true); ((GrabbableObject)5__3).startFallingPosition = (((Object)(object)5__4 != (Object)null) ? 5__4.InverseTransformPoint(spawnPos) : spawnPos); ((GrabbableObject)5__3).targetFloorPosition = (((Object)(object)((Component)5__3).transform.parent != (Object)null) ? ((Component)5__3).transform.parent.InverseTransformPoint(((GrabbableObject)5__3).GetItemFloorPosition(spawnPos)) : ((GrabbableObject)5__3).GetItemFloorPosition(spawnPos)); ((GrabbableObject)5__3).fallTime = 0f; ((GrabbableObject)5__3).hasHitGround = false; ((GrabbableObject)5__3).reachedFloorTarget = false; if ((Object)(object)<>4__this._previousPlayerHeldBy != (Object)null && <>4__this._previousPlayerHeldBy.isInHangarShipRoom) { <>4__this._previousPlayerHeldBy.SetItemInElevator(true, true, (GrabbableObject)(object)5__3); } return false; } IL_0062: if (Time.realtimeSinceStartup - 5__2 < 8f && !((NetworkObjectReference)(ref netObjectRef)).TryGet(ref 5__1, (NetworkManager)null)) { <>2__current = (object)new WaitForSeconds(0.03f); <>1__state = 1; return true; } if ((Object)(object)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(); 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(); 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(cardInfo.Item.spawnPrefab, val3, Quaternion.identity, parentOfGiftObject); BaseCardProp component = val4.GetComponent(); if ((Object)(object)component != (Object)null) { ((GrabbableObject)component).SetScrapValue(num); component.CardInfo = cardInfo; component.TemplateId = cardInfo.Id; } NetworkObject component2 = val4.GetComponent(); 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(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(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 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(d__19))] private IEnumerator SetObjectFallSFX(GrabbableObject gObject) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new 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(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 Moons = new List(); public static List Sets = new List(); public static List SpawnGroups = new List(); public static List RarityConfigs = new List(); private static Dictionary _levelNamesMap = new Dictionary(); 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 LevelNamesMap => _levelNamesMap; public static void LoadMoonConfigs() { if (_moonsLoaded) { Plugin.logger.LogWarning((object)"[ConfigManager] LoadMoonConfigs called more than once — skipping."); return; } _moonsLoaded = true; List 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 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 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 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 levelNameMap) { if (_missingMoonsCreated) { Plugin.logger.LogWarning((object)"[ConfigManager] CreateMissingMoonConfigs called more than once — skipping."); return; } _missingMoonsCreated = true; List list = new List(); foreach (KeyValuePair 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 GetHeaderValues(string prefix) { string path = Path.Combine(Paths.ConfigPath, "com.sholiver.lethalcardloader.cfg"); List list = new List(); 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 _planetName; private ConfigEntry _internalName; private ConfigEntry _cardScrapRarity; private ConfigEntry _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(text, "Planet Name", planetName, "Auto-managed — do not edit manually."); _internalName = config.Bind(text, "Internal Name", internalName, "Auto-managed — do not edit manually."); _cardScrapRarity = config.Bind(text, "Card Scrap Rarity", cardRarity, "Rarity of card scrap spawning on this moon (0-100)."); _packScrapRarity = config.Bind(text, "Pack Scrap Rarity", packRarity, "Rarity of pack scrap spawning on this moon (0-100)."); } } public class RarityEntry { private ConfigEntry _key; private ConfigEntry _value; private ConfigEntry _spawnWeight; private ConfigEntry _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(text, "Key", key, "The unique key for this rarity tier."); _value = config.Bind(text, "Value", value, "The scrap value multiplier for this rarity tier."); _spawnWeight = config.Bind(text, "Spawn Weight", spawnWeight, "The relative weight of this rarity tier when spawning scrap."); _cardPackWeight = config.Bind(text, "Card Pack Weight", cardPackWeight, "The relative weight of this rarity tier when opening a card pack."); } } public class SetEntry { private ConfigEntry _name; private ConfigEntry _key; private ConfigEntry _id; private ConfigEntry _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(text, "Name", name, "The display name of this set."); _key = config.Bind(text, "Key", string.IsNullOrEmpty(key) ? name.Replace(" ", "") : key, "Used to derive the manifest filename (e.g. \"BaseSet\" → \"BaseSet.json\")."); _id = config.Bind(text, "Id", id, "Unique numeric identifier for this set."); _spawnGroup = config.Bind(text, "Spawn Group", spawnGroup, "The spawn group this set belongs to."); } } public class SpawnGroupEntry { private ConfigEntry _key; private List> _moonWeights = new List>(); private Dictionary _moonWeightOverrides = new Dictionary(); public string Key => _key.Value; public Dictionary MoonWeightOverrides => _moonWeightOverrides; public void Bind(string key, List moons) { ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config; string text = "Spawn Group: " + key; _key = config.Bind(text, "Key", key, "The unique key for this spawn group."); foreach (MoonEntry moon in moons) { _moonWeights.Add(config.Bind(text, moon.InternalName, 1f, "Weight multiplier for this moon. (0.0 = never spawns, 1.0 = normal weight)")); } RebuildMoonWeightOverrides(); } public void AddMissingMoons(List 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 e) => ((ConfigEntryBase)e).Definition.Key == moon.InternalName)) { _moonWeights.Add(config.Bind(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 e) => ((ConfigEntryBase)e).Definition.Key, (ConfigEntry e) => e.Value); } } } namespace __GEN { internal class NetworkVariableSerializationHelper { [RuntimeInitializeOnLoadMethod] internal static void InitializeSerialization() { } } } namespace LethalCardLoader.NetcodePatcher { [AttributeUsage(AttributeTargets.Module)] internal class NetcodePatchedAssemblyAttribute : Attribute { } }