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.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Logging; using CollectionWeaver.Core; using CollectionWeaver.IL; using EnhancedPrefabLoader.Prepatch.Extensions; using EnhancedPrefabLoader.Shared.Extensions; using EnhancedPrefabLoader.Shared.Models; using EnhancedPrefabLoader.Shared.Services; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using Newtonsoft.Json; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("EnhancedPrefabLoaderPrepatch")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("6.0.0.0")] [assembly: AssemblyInformationalVersion("6.0.0+cd7431ddc1ec5aac5b27bb4a89a6104e570aad10")] [assembly: AssemblyProduct("Enhanced Prefab Loader Prepatch")] [assembly: AssemblyTitle("EnhancedPrefabLoaderPrepatch")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("6.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [CompilerGenerated] internal sealed class <>z__ReadOnlySingleElementList : IEnumerable, ICollection, IList, IEnumerable, IReadOnlyCollection, IReadOnlyList, ICollection, IList { private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator { object IEnumerator.Current => _item; T IEnumerator.Current => _item; public Enumerator(T item) { _item = item; } bool IEnumerator.MoveNext() { if (!_moveNextCalled) { return _moveNextCalled = true; } return false; } void IEnumerator.Reset() { _moveNextCalled = false; } void IDisposable.Dispose() { } } int ICollection.Count => 1; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection.Count => 1; T IReadOnlyList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } } int ICollection.Count => 1; bool ICollection.IsReadOnly => true; T IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } public <>z__ReadOnlySingleElementList(T item) { _item = item; } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.CopyTo(Array array, int index) { array.SetValue(_item, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return EqualityComparer.Default.Equals(_item, (T)value); } int IList.IndexOf(object value) { if (!EqualityComparer.Default.Equals(_item, (T)value)) { return -1; } return 0; } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Contains(T item) { return EqualityComparer.Default.Equals(_item, item); } void ICollection.CopyTo(T[] array, int arrayIndex) { array[arrayIndex] = _item; } bool ICollection.Remove(T item) { throw new NotSupportedException(); } int IList.IndexOf(T item) { if (!EqualityComparer.Default.Equals(_item, item)) { return -1; } return 0; } void IList.Insert(int index, T item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 EnhancedPrefabLoader.Shared.Services { public class BundleDiscoveryService { public List DiscoverBundles(string basePath) { return Directory.EnumerateDirectories(basePath, "*_prefabloader", new EnumerationOptions { RecurseSubdirectories = true, MatchCasing = MatchCasing.CaseInsensitive }).ToList().SelectMany((string d) => Directory.GetFiles(d, "*.json", SearchOption.AllDirectories)) .ToList(); } } } namespace EnhancedPrefabLoader.Shared.Models { public class BundleDescriptor { public string BundleId { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public List Assemblies { get; set; } = new List(); public List CustomShops { get; set; } = new List(); public List Items { get; set; } = new List(); public List Prefabs { get; set; } = new List(); public List CardExpansions { get; set; } = new List(); public List Furniture => Prefabs.Where((PrefabInfo p) => p.AddItemToFurnitureShop).ToList(); public List Deco => Prefabs.Where((PrefabInfo p) => p.IsDecoObject || p.IsDecoFloorTexture || p.IsDecoCeilingTexture || p.IsDecoWallTexture).ToList(); public HashSet PrefabNames { get { HashSet hashSet = new HashSet(); foreach (string item in (from p in Prefabs?.Where((PrefabInfo p) => !string.IsNullOrWhiteSpace(p.PrefabName)) select p.PrefabName) ?? Array.Empty()) { hashSet.Add(item); } return hashSet; } } public HashSet MeshNames { get { HashSet hashSet = new HashSet(); foreach (string item in (from i in Items?.Where((ItemInfo i) => !string.IsNullOrWhiteSpace(i.Mesh)) select i.Mesh) ?? Array.Empty()) { hashSet.Add(item); } return hashSet; } } public HashSet MaterialNames { get { HashSet hashSet = new HashSet(); foreach (string item in (from i in Items?.Where((ItemInfo i) => !string.IsNullOrWhiteSpace(i.Material)) select i.Material) ?? Array.Empty()) { hashSet.Add(item); } return hashSet; } } } public class CardExpansionInfo { public string Name { get; set; } = string.Empty; public string MenuCategory { get; set; } = string.Empty; public string CardExpansion { get; set; } = string.Empty; [JsonProperty("CardbackSprite")] public string Cardback { get; set; } = string.Empty; public string FoilMask { get; set; } = string.Empty; public bool HasRandomFoils { get; set; } public float FoilChance { get; set; } public List Rarities { get; set; } = new List(); public List Cards { get; set; } = new List(); public string CardPriceStrategy { get; set; } = string.Empty; public float DefaultBorderMultiplierBase { get; set; } = 3.15f; public float DefaultFoilMultiplier { get; set; } = 2.9f; public float RarityDrivenFloor { get; set; } = 4f; public float RarityDrivenStepSize { get; set; } = 1026f; public float RarityDrivenBorderMultiplierBase { get; set; } = 1.15f; public float RarityDrivenFoilMultiplier { get; set; } = 1.4f; public int TradeUnlockLevel { get; set; } public List PlayCardMaterials { get; set; } = new List(); public bool IsValid { get; set; } = true; } public class CardExpansionMetadata { public string ExpansionName { get; set; } = string.Empty; public int CardCount { get; set; } } public class CardInfo { public string Name { get; set; } = string.Empty; public string ElementType { get; set; } = string.Empty; public string Rarity { get; set; } = string.Empty; public int CardNumber { get; set; } public string Sprite { get; set; } = string.Empty; public string BorderType { get; set; } = string.Empty; public bool IsFoil { get; set; } public string FoilMask { get; set; } = string.Empty; public string Cardback { get; set; } = string.Empty; } [Serializable] public struct ColorData { public float R { get; set; } public float G { get; set; } public float B { get; set; } public float A { get; set; } } public class CustomShopInfo { public string PhoneAppId { get; set; } = string.Empty; public string AppDisplayName { get; set; } = string.Empty; public string AppIcon { get; set; } = string.Empty; public string AppInnerBGImage { get; set; } = string.Empty; public string AppOuterBGImage { get; set; } = string.Empty; public string SiteLogo { get; set; } = string.Empty; public string SiteHeader { get; set; } = string.Empty; public string SiteBackground { get; set; } = string.Empty; public bool IsValid { get; internal set; } = true; } public class ItemInfo { public string Name { get; set; } = string.Empty; public string ItemCategory { get; set; } = string.Empty; public string SpriteName { get; set; } = string.Empty; public float BaseCost { get; set; } public bool AddItemAsAccessory { get; set; } public bool AddItemAsFigurine { get; set; } public bool AddItemAsBoardGame { get; set; } public string PhoneAppId { get; set; } = string.Empty; public string ItemType { get; set; } = string.Empty; public bool UsesBaseGameMesh { get; set; } public string MeshToUse { get; set; } = string.Empty; public string Mesh { get; set; } = string.Empty; public string MeshSecondary { get; set; } = string.Empty; public string Material { get; set; } = string.Empty; public string MaterialSecondary { get; set; } = string.Empty; public List MaterialList { get; set; } = new List(); [JsonProperty("IsBigBox")] public bool HasBigBox { get; set; } public bool HasSmallBox { get; set; } [JsonProperty("HideTillUnlocked")] public bool BigBoxHideTillUnlocked { get; set; } public bool SmallBoxHideTillUnlocked { get; set; } [JsonProperty("LicensePrice")] public float BigBoxLicensePrice { get; set; } public float SmallBoxLicensePrice { get; set; } [JsonProperty("LicenseLevelRequirement")] public int BigBoxLicenseLevelRequirement { get; set; } public int SmallBoxLicenseLevelRequirement { get; set; } [JsonProperty("IgnoreDoubleImage")] public bool BigBoxIgnoreDoubleImage { get; set; } public bool SmallBoxIgnoreDoubleImage { get; set; } public float MinMarketPricePercent { get; set; } public float MaxMarketPricePercent { get; set; } public string FollowItemPrice { get; set; } = string.Empty; public bool AutoSetBoxPrice { get; set; } public bool IsTallItem { get; set; } public float InBoxOffsetY { get; set; } public float InBoxOffsetScale { get; set; } public Vector3Data ItemDeminsion { get; set; } public Vector3Data CollidorPosOffset { get; set; } public Vector3Data ColliderScale { get; set; } public List PriceAffectedBy { get; set; } = new List(); public bool IsSprayCan { get; set; } public bool IsCardPack { get; set; } public bool IsCardBox { get; set; } public bool IsBulkBox { get; set; } public int MinValue { get; set; } public string CardExpansion { get; set; } = string.Empty; public bool CanHaveDuplicates { get; set; } public bool CanHaveGodPacks { get; set; } public string PackGenerationStrategy { get; set; } = string.Empty; public Dictionary NormalWeights { get; set; } = new Dictionary(); public Dictionary GodWeights { get; set; } = new Dictionary(); public Dictionary> SlotWeights { get; set; } = new Dictionary>(); [Obsolete("Use NormalWeights, GodWeights, and SlotWeights instead. This field exists for backwards compatibility with older descriptors.")] public List GenerationWeights { get; set; } = new List(); public string SpawnsPackType { get; set; } = string.Empty; public string PackType { get; set; } = string.Empty; public float GodPackPercentage { get; set; } public bool IsValid { get; set; } = true; } public class ModManifest { public string ModId { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public string Directory { get; set; } = string.Empty; public string BundlePath { get; set; } = string.Empty; public string JsonPath { get; set; } = string.Empty; public bool IsValid { get; set; } = true; public bool IsLoaded { get; set; } = true; public List Errors { get; set; } = new List(); public int ItemCount { get; set; } public int FurnitureCount { get; set; } public int CustomShopCount { get; set; } public int DecoCount { get; set; } public List CardExpansions { get; set; } = new List(); } public class PrefabInfo { public string Name { get; set; } = string.Empty; public string PrefabName { get; set; } = string.Empty; public string SpriteName { get; set; } = string.Empty; public float Price { get; set; } public int LevelRequirement { get; set; } public bool AddItemToFurnitureShop { get; set; } public string Description { get; set; } = string.Empty; public string ObjectType { get; set; } public List VideoClips { get; set; } = new List(); public float DecoBonus { get; set; } public bool IsDecoWallTexture { get; set; } public bool IsDecoFloorTexture { get; set; } public bool IsDecoCeilingTexture { get; set; } public bool IsDecoObject { get; set; } public string DecoObject { get; set; } = string.Empty; public string DecoType { get; set; } = string.Empty; public string Texture { get; set; } = string.Empty; public string RoughnessMap { get; set; } = string.Empty; public string NormalMap { get; set; } = string.Empty; public float Smoothness { get; set; } public ColorData Color { get; set; } public bool IsValid { get; set; } = true; } public class RarityWeightInfo { public string Rarity { get; set; } = string.Empty; [Obsolete("Use SlotWeights instead. This field exists for backwards compatibility with older descriptors.")] public string GuaranteedSlots { get; set; } = string.Empty; public float NormalWeight { get; set; } public float GodPackWeight { get; set; } } [Serializable] public struct Vector3Data { public float X { get; set; } public float Y { get; set; } public float Z { get; set; } } public class VideoClipInfo { public string Name { get; set; } = string.Empty; public string VideoPlayerName { get; set; } = string.Empty; } } namespace EnhancedPrefabLoader.Shared.Helpers { public static class FileHelper { public static List GetAllJsonFilesIn(string basePath, string folderPattern) { return Directory.EnumerateDirectories(basePath, folderPattern, new EnumerationOptions { RecurseSubdirectories = true, MatchCasing = MatchCasing.CaseInsensitive }).SelectMany((string d) => Directory.GetFiles(d, "*.json", SearchOption.AllDirectories)).ToList(); } } public static class ModIdGenerator { public static string GenerateFromDirectory(string directory) { DirectoryInfo directoryInfo = new DirectoryInfo(Path.GetDirectoryName(directory)); string fullName = directoryInfo.FullName; string name = directoryInfo.Name; using SHA1 sHA = SHA1.Create(); string text = BitConverter.ToString(sHA.ComputeHash(Encoding.UTF8.GetBytes(fullName.ToLowerInvariant()))).Replace("-", "").Substring(0, 8); return name + "_" + text; } } } namespace EnhancedPrefabLoader.Shared.Extensions { public static class DictionaryExtensions { public static TValue GetOrDefault(this Dictionary dict, TKey key) { if (!dict.TryGetValue(key, out TValue value)) { return default(TValue); } return value; } public static TValue GetOrAdd(this Dictionary dict, TKey key, Func factory) { if (!dict.TryGetValue(key, out TValue value)) { value = (dict[key] = factory(key)); } return value; } public static void MergeAdd(this Dictionary dict, IEnumerable<(TKey key, int amount)> items) { foreach (var item3 in items) { TKey item = item3.key; int item2 = item3.amount; dict[item] = dict.GetOrAdd(item, (TKey _) => 0) + item2; } } public static void AddRange(this Dictionary dict, IEnumerable> items) { foreach (KeyValuePair item in items) { dict[item.Key] = item.Value; } } } public static class ListExtensions { public static List Shuffle(this List list) where T : class { for (int num = list.Count - 1; num > 0; num--) { int num2 = Random.Range(0, num + 1); int index = num; int index2 = num2; T value = list[num2]; T value2 = list[num]; list[index] = value; list[index2] = value2; } return list; } public static List SwapAndRemove(this List list, int index) { int num = list.Count - 1; if (index != num) { int index2 = num; T value = list[num]; T value2 = list[index]; list[index] = value; list[index2] = value2; } list.RemoveAt(num); return list; } } } namespace EnhancedPrefabLoader.Shared.Enums { [Flags] public enum ItemFlags : byte { None = 0, BoardGame = 1, Accessory = 2, Figurine = 4, TCG = 8 } } namespace EnhancedPrefabLoader.Prepatch { public class BepInExLogger : ILogger { private readonly ManualLogSource logSource; public BepInExLogger(string sourceName) { logSource = Logger.CreateLogSource(sourceName); } public void Log(LogLevel logLevel, string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected I4, but got Unknown switch ((int)logLevel) { case 0: logSource.LogDebug((object)message); break; case 1: logSource.LogInfo((object)message); break; case 2: logSource.LogWarning((object)message); break; case 3: logSource.LogError((object)message); break; } } } public class EnumPatcher { public void PatchEnums(AssemblyDefinition assembly, int startingValue, Dictionary> userData, Dictionary> savedData) { //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Expected O, but got Unknown //IL_0429: Unknown result type (might be due to invalid IL or missing references) //IL_042f: Unknown result type (might be due to invalid IL or missing references) //IL_0434: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Expected O, but got Unknown foreach (string enumName in userData.Keys) { int i = startingValue; TypeDefinition val = ((IEnumerable)assembly.MainModule.Types).FirstOrDefault((Func)((TypeDefinition t) => ((MemberReference)t).Name == enumName)); if (val == null || !val.IsEnum) { Patcher.Log.LogWarning((object)("Enum type " + enumName + " not found in assembly.")); continue; } FieldDefinition val2 = ((IEnumerable)val.Fields).FirstOrDefault((Func)((FieldDefinition f) => f.HasConstant && f.IsStatic && f.IsLiteral)); if (val2 == null) { Patcher.Log.LogWarning((object)("No valid enum fields found in " + enumName + ".")); continue; } HashSet hashSet = new HashSet(from f in (IEnumerable)val.Fields where f.HasConstant && f.IsStatic && f.IsLiteral select ((MemberReference)f).Name); HashSet hashSet2 = new HashSet(from f in (IEnumerable)val.Fields where f.HasConstant && f.IsStatic && f.IsLiteral select (int)f.Constant); SortedDictionary sortedDictionary = new SortedDictionary(); HashSet hashSet3 = (from f in userData[enumName] select f.Sanitize() into f where !string.IsNullOrWhiteSpace(f) select f).ToHashSet(); if (savedData.TryGetValue(enumName, out Dictionary value)) { List list = new List(); foreach (KeyValuePair item in value) { string text = item.Key.Sanitize(); if (hashSet.Contains(text)) { Patcher.Log.LogWarning((object)("Field name '" + text + "' already exists in enum " + enumName + ". Skipping.")); list.Add(item.Key); } else if (hashSet2.Contains(item.Value)) { Patcher.Log.LogWarning((object)$"Field value {item.Value} already exists in enum {enumName} for saved field '{text}'. Assigning new value."); list.Add(item.Key); } else { sortedDictionary[item.Value] = new FieldDefinition(text, val2.Attributes, (TypeReference)(object)val) { Constant = item.Value }; hashSet.Add(text); hashSet2.Add(item.Value); } } foreach (string item2 in list) { value.Remove(item2); Patcher.Log.LogDebug((object)("Removed obsolete/conflicting saved field " + item2 + " from enum " + enumName)); } } foreach (string fieldName in hashSet3) { if (sortedDictionary.Values.Any((FieldDefinition f) => ((MemberReference)f).Name == fieldName)) { continue; } if (hashSet.Contains(fieldName)) { Patcher.Log.LogWarning((object)("Field name '" + fieldName + "' already exists in enum " + enumName + ". Skipping.")); continue; } for (; hashSet2.Contains(i) || sortedDictionary.ContainsKey(i); i++) { } sortedDictionary[i] = new FieldDefinition(fieldName, val2.Attributes, (TypeReference)(object)val) { Constant = i }; savedData.GetOrAdd(enumName, (string _) => new Dictionary())[fieldName] = i; hashSet.Add(fieldName); hashSet2.Add(i); } foreach (KeyValuePair item3 in sortedDictionary) { val.Fields.Add(item3.Value); Patcher.Log.LogDebug((object)$"Added field {((MemberReference)item3.Value).Name} with value {item3.Key} to enum {((MemberReference)val).Name}"); } Patcher.Log.LogInfo((object)$"Patching for enum {enumName} complete. {sortedDictionary.Count} fields added."); } } } public class PatchDataManager { private static readonly string SaveDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "Low", "OPNeonGames", "Card Shop Simulator", "PrefabLoader"); private readonly BundleDiscoveryService bundleDiscoveryService = new BundleDiscoveryService(); private bool initialized; private readonly Dictionary keyMapping = new Dictionary { { "FurnitureObjectTypes", "EObjectType" }, { "ItemTypes", "EItemType" }, { "FurnitureTypes", "EObjectType" }, { "DecoTypes", "EDecoObject" }, { "DecoObject", "EDecoObject" }, { "PackType", "ECollectionPackType" }, { "Rarity", "ERarity" }, { "CardExpansions", "ECardExpansionType" } }; public Dictionary> SavedData { get; private set; } = new Dictionary>(); public Dictionary> UserData { get; private set; } = new Dictionary>(); public void Initialize() { if (!initialized) { LoadSavedEnumValues(); LoadNewEnumEntries(); initialized = true; } } public void SaveEnumValues() { if (!initialized) { Patcher.Log.LogError((object)"Cannot save - not initialized"); return; } try { if (!Directory.Exists(SaveDirectory)) { Directory.CreateDirectory(SaveDirectory); } string contents = JsonConvert.SerializeObject((object)SavedData, (Formatting)1); File.WriteAllText(Path.Combine(SaveDirectory, "enum_values.json"), contents); Patcher.Log.LogInfo((object)$"Saved values for {SavedData.Count} enums"); } catch (Exception ex) { Patcher.Log.LogError((object)("Error saving values: " + ex.Message)); } } private string MapLegacyKey(string key) { if (!keyMapping.TryGetValue(key, out string value)) { return key; } return value; } private void LoadSavedEnumValues() { List obj = new List(3) { Path.Combine(SaveDirectory, "enum_values.json"), Paths.PatcherPluginPath + "/EnhancedPrefabLoader/savedTypes", Paths.PatcherPluginPath + "/EnhancedPrefabLoader/enum_values.json" }; Dictionary> dictionary = new Dictionary>(); string text = obj[0]; foreach (string item in obj) { if (!File.Exists(item)) { continue; } try { string text2 = File.ReadAllText(item); dictionary.AddRange(JsonConvert.DeserializeObject>>(text2) ?? new Dictionary>()); if (item != text) { File.Delete(item); Patcher.Log.LogInfo((object)("Migrated and removed legacy enum values from " + item)); } } catch (Exception ex) { Patcher.Log.LogError((object)("Failed to load saved enum values from " + item + ": " + ex.Message + ".")); } } foreach (KeyValuePair> item2 in dictionary) { SavedData[MapLegacyKey(item2.Key)] = item2.Value; } } private void LoadNewEnumEntries() { List list = bundleDiscoveryService.DiscoverBundles(Paths.PluginPath); UserData["EObjectType"] = new HashSet(); UserData["EDecoObject"] = new HashSet(); UserData["EItemType"] = new HashSet(); UserData["ECardExpansionType"] = new HashSet(); UserData["ERarity"] = new HashSet(); UserData["ECollectionPackType"] = new HashSet(); foreach (string item in list) { try { BundleDescriptor bundleDescriptor = JsonConvert.DeserializeObject(File.ReadAllText(item)); if (bundleDescriptor != null) { UserData["EObjectType"].UnionWith(bundleDescriptor.Furniture.Select((PrefabInfo f) => f.ObjectType)); UserData["EDecoObject"].UnionWith(bundleDescriptor.Deco.Select((PrefabInfo d) => d.DecoObject)); UserData["EItemType"].UnionWith(bundleDescriptor.Items.Select((ItemInfo i) => i.ItemType)); UserData["ECardExpansionType"].UnionWith(bundleDescriptor.CardExpansions.Select((CardExpansionInfo c) => c.CardExpansion)); UserData["ERarity"].UnionWith(bundleDescriptor.CardExpansions.SelectMany((CardExpansionInfo c) => c.Rarities)); UserData["ECollectionPackType"].UnionWith(from i in bundleDescriptor.Items where i.IsCardPack select i.PackType); } } catch (Exception ex) { Patcher.Log.LogError((object)("Failed to load bundle descriptor from " + item + ": " + ex.Message)); } } } } public class Patcher { private static ILWeaver weaver = null; private static EnumPatcher enumPatcher = null; private static PatchDataManager patchDataManager = null; public static ManualLogSource Log { get; private set; } = Logger.CreateLogSource("EnhancedPrefabLoader"); public static IEnumerable TargetDLLs { get; } = new <>z__ReadOnlySingleElementList("Assembly-CSharp.dll"); public static void Initialize() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected O, but got Unknown Log.Logger = (ILogger)(object)new BepInExLogger("CollectionWeaver"); Log.LogLevel = (LogLevel)3; WeaverOptions val = new WeaverOptions(); val.IncludeField("CPlayerData.m_CurrentTotalItemCountList").IncludeField("CPlayerData.m_GeneratedMarketPriceList").IncludeField("CPlayerData.m_GeneratedCostPriceList") .IncludeField("CPlayerData.m_ItemPricePercentChangeList") .IncludeField("CPlayerData.m_AverageItemCostList") .IncludeField("CPlayerData.m_SetItemPriceList") .IncludeField("CPlayerData.m_ItemPricePercentPastChangeList") .IncludeField("CPlayerData.m_IsItemLicenseUnlocked") .IncludeField("CPlayerData.m_DecorationInventoryList") .IncludeField("CPlayerData.m_CollectionSortingMethodIndexList") .IncludeField("StockItemData_ScriptableObject.m_ItemDataList") .IncludeField("StockItemData_ScriptableObject.m_ItemMeshDataList") .IncludeField("StockItemData_ScriptableObject.m_RestockDataList") .IncludeField("StockItemData_ScriptableObject.m_CardPackItemTypeList") .IncludeField("ShelfData_ScriptableObject.m_DecoDataList") .IncludeField("ShelfData_ScriptableObject.m_DecoPurchaseDataList") .IncludeField("ShelfData_ScriptableObject.m_WallDecoDataList") .IncludeField("ShelfData_ScriptableObject.m_FloorDecoDataList") .IncludeField("ShelfData_ScriptableObject.m_CeilingDecoDataList") .IncludeField("MonsterData_ScriptableObject.m_CardBackImageList") .IncludeField("MonsterData_ScriptableObject.m_CardFoilMaskImageList") .IncludeField("MonsterData_ScriptableObject.m_CardUISettingList") .IncludeField("CardUI.m_CardRaritySpriteList"); if (weaver == null) { weaver = new ILWeaver(val); } if (enumPatcher == null) { enumPatcher = new EnumPatcher(); } if (patchDataManager == null) { patchDataManager = new PatchDataManager(); } patchDataManager.Initialize(); } public static void Patch(AssemblyDefinition assembly) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) BaseAssemblyResolver val = (BaseAssemblyResolver)assembly.MainModule.AssemblyResolver; val.AddSearchDirectory(Path.GetDirectoryName(typeof(Patcher).Assembly.Location)); val.AddSearchDirectory(Paths.PatcherPluginPath); Log.LogInfo((object)"Starting Enhanced Prefab Loader PrePatching"); ILWeaver obj = weaver; WeaverResult val2 = ((obj != null) ? obj.Weave(assembly) : null); Log.LogInfo((object)$"Collection weaving complete. Weaved: {((val2 != null) ? new int?(val2.PatchedCount) : null)}, Skipped: {((val2 != null) ? new int?(val2.SkippedCount) : null)}"); enumPatcher?.PatchEnums(assembly, 200000, patchDataManager.UserData, patchDataManager.SavedData); patchDataManager.SaveEnumValues(); Log.LogInfo((object)"Enhanced Prefab Loader PrePatching complete"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "EnhancedPrefabLoaderPrepatch"; public const string PLUGIN_NAME = "Enhanced Prefab Loader Prepatch"; public const string PLUGIN_VERSION = "6.0.0"; } } namespace EnhancedPrefabLoader.Prepatch.Extensions { public static class CicelExtensions { public static bool IsLoadCode(this OpCode opCode) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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) if (!opCode.IsLdloc() && !opCode.IsLdarg() && !opCode.IsLdc() && !opCode.IsLdelem() && !opCode.IsFieldLoad() && !opCode.IsLdNullOrStr()) { return opCode.IsLdind(); } return true; } public static bool IsFieldLoad(this OpCode opCode) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 Code code = ((OpCode)(ref opCode)).Code; if ((int)code == 120 || (int)code == 123) { return true; } return false; } public static bool IsLdloc(this OpCode opCode) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 Code code = ((OpCode)(ref opCode)).Code; if (code - 6 <= 3 || (int)code == 17 || (int)code == 202) { return true; } return false; } public static bool IsLdarg(this OpCode opCode) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 Code code = ((OpCode)(ref opCode)).Code; if (code - 2 <= 3 || code - 14 <= 1 || code - 199 <= 1) { return true; } return false; } public static bool IsLdc(this OpCode opCode) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 Code code = ((OpCode)(ref opCode)).Code; if (code - 21 <= 14) { return true; } return false; } public static bool IsLdelem(this OpCode opCode) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 Code code = ((OpCode)(ref opCode)).Code; if ((int)code == 145 || (int)code == 151 || (int)code == 160) { return true; } return false; } public static bool IsLdind(this OpCode opCode) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 Code code = ((OpCode)(ref opCode)).Code; if (code - 69 <= 6 || code - 77 <= 2) { return true; } return false; } public static bool IsLdNullOrStr(this OpCode opCode) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 Code code = ((OpCode)(ref opCode)).Code; if ((int)code == 20 || (int)code == 113) { return true; } return false; } public static bool IsStloc(this OpCode opCode) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 Code code = ((OpCode)(ref opCode)).Code; if (code - 10 <= 3 || (int)code == 19 || (int)code == 204) { return true; } return false; } public static bool IsComplimentaryStOf(this Instruction stInstruction, Instruction ldInstruction) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (stInstruction.OpCode.IsStloc() && ldInstruction.OpCode.IsLdloc()) { return stInstruction.GetLocalCodeIndex() == ldInstruction.GetLocalCodeIndex(); } return false; } public static int? GetLocalCodeIndex(this Instruction instr) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected I4, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Invalid comparison between Unknown and I4 //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Invalid comparison between Unknown and I4 OpCode opCode = instr.OpCode; Code code = ((OpCode)(ref opCode)).Code; switch (code - 6) { default: if ((int)code != 202 && (int)code != 204) { break; } goto case 11; case 0: case 4: return 0; case 1: case 5: return 1; case 2: case 6: return 2; case 3: case 7: return 3; case 11: case 13: { object operand = instr.Operand; object obj = ((operand is VariableReference) ? operand : null); return (obj != null) ? new int?(((VariableReference)obj).Index) : null; } case 8: case 9: case 10: case 12: break; } return null; } public static bool IsListType(this TypeReference typeRef) { if (((typeRef != null) ? ((MemberReference)typeRef).Name : null) == "List`1" && ((typeRef != null) ? typeRef.Namespace : null) == "System.Collections.Generic") { if (!(typeRef is GenericInstanceType)) { TypeDefinition obj = typeRef.Resolve(); object obj2; if (obj == null) { obj2 = null; } else { TypeReference baseType = obj.BaseType; obj2 = ((baseType != null) ? ((MemberReference)baseType).Name : null); } return (string?)obj2 == "List`1"; } return true; } return false; } public static bool IsListAccessor(this MethodReference methodRef) { if (methodRef != null) { if (!methodRef.IsListGetItemCall() && !methodRef.IsListSetItemCall()) { return methodRef.IsListGetCountCall(); } return true; } return false; } public static bool IsListGetItemCall(this MethodReference methodRef) { if (methodRef != null && ((MemberReference)methodRef).DeclaringType.IsListType()) { return ((MemberReference)methodRef).Name == "get_Item"; } return false; } public static bool IsListSetItemCall(this MethodReference methodRef) { if (methodRef != null && ((MemberReference)methodRef).DeclaringType.IsListType()) { return ((MemberReference)methodRef).Name == "set_Item"; } return false; } public static bool IsListGetCountCall(this MethodReference methodRef) { if (methodRef != null && ((MemberReference)methodRef).DeclaringType.IsListType()) { return ((MemberReference)methodRef).Name == "get_Count"; } return false; } public static bool MatchListLoad(this Instruction instr, MethodBody methodBody, out TypeReference elementType) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Invalid comparison between Unknown and I4 //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Invalid comparison between Unknown and I4 //IL_0046: 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_008e: Expected I4, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Invalid comparison between Unknown and I4 //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Invalid comparison between Unknown and I4 //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Invalid comparison between Unknown and I4 elementType = null; if (instr != null) { _ = instr.OpCode; if (0 == 0 && ((methodBody != null) ? methodBody.Method : null) != null && instr.OpCode.IsLoadCode()) { try { OpCode opCode = instr.OpCode; Code code = ((OpCode)(ref opCode)).Code; if ((int)code <= 120) { switch (code - 2) { case 4: goto IL_00bb; case 5: goto IL_00d2; case 6: goto IL_00e9; case 7: goto IL_0100; case 15: goto IL_0117; case 0: goto IL_0134; case 1: goto IL_0171; case 2: goto IL_019a; case 3: goto IL_01c3; case 12: goto IL_01ec; case 8: case 9: case 10: case 11: case 13: case 14: goto IL_0220; } if ((int)code == 120) { goto IL_0206; } } else { if ((int)code == 123) { goto IL_0206; } if ((int)code == 199) { goto IL_01ec; } if ((int)code == 202) { goto IL_0117; } } goto IL_0220; IL_0220: TypeReference val = null; goto IL_0222; IL_0134: object obj2; if (!((MethodReference)methodBody.Method).HasThis) { ParameterDefinition obj = ((MethodReference)methodBody.Method).Parameters[0]; obj2 = ((obj != null) ? ((ParameterReference)obj).ParameterType : null); } else { obj2 = methodBody.Method.DeclaringType; } val = (TypeReference)obj2; goto IL_0222; IL_0100: val = ((VariableReference)methodBody.Variables[3]).VariableType; goto IL_0222; IL_00e9: val = ((VariableReference)methodBody.Variables[2]).VariableType; goto IL_0222; IL_00d2: val = ((VariableReference)methodBody.Variables[1]).VariableType; goto IL_0222; IL_00bb: val = ((VariableReference)methodBody.Variables[0]).VariableType; goto IL_0222; IL_01c3: val = ((ParameterReference)((MethodReference)methodBody.Method).Parameters[((MethodReference)methodBody.Method).HasThis ? 2 : 3]).ParameterType; goto IL_0222; IL_0117: object operand = instr.Operand; object obj3 = ((operand is VariableReference) ? operand : null); val = ((obj3 != null) ? ((VariableReference)obj3).VariableType : null); goto IL_0222; IL_0206: object operand2 = instr.Operand; object obj4 = ((operand2 is FieldReference) ? operand2 : null); val = ((obj4 != null) ? ((FieldReference)obj4).FieldType : null); goto IL_0222; IL_01ec: object operand3 = instr.Operand; object obj5 = ((operand3 is ParameterReference) ? operand3 : null); val = ((obj5 != null) ? ((ParameterReference)obj5).ParameterType : null); goto IL_0222; IL_019a: val = ((ParameterReference)((MethodReference)methodBody.Method).Parameters[((MethodReference)methodBody.Method).HasThis ? 1 : 2]).ParameterType; goto IL_0222; IL_0222: TypeReference val2 = val; GenericInstanceType val3 = (GenericInstanceType)(object)((val2 is GenericInstanceType) ? val2 : null); if (val3 != null && val2.IsListType() && val3.GenericArguments.Count > 0) { elementType = val3.GenericArguments[0]; return true; } return false; IL_0171: val = ((ParameterReference)((MethodReference)methodBody.Method).Parameters[(!((MethodReference)methodBody.Method).HasThis) ? 1 : 0]).ParameterType; goto IL_0222; } catch (Exception ex) when (((ex is ArgumentOutOfRangeException || ex is NullReferenceException) ? 1 : 0) != 0) { elementType = null; return false; } } } return false; } } internal static class StringExtensions { public static string Sanitize(this string value) { if (string.IsNullOrWhiteSpace(value)) { return "_Invalid"; } string input = Regex.Replace(value, "\\s", ""); input = Regex.Replace(input, "[^\\w]", "_"); if (!string.IsNullOrEmpty(input) && !char.IsDigit(input[0])) { return input; } return "_" + (input ?? "Invalid"); } } }