Decompiled source of Enhanced Prefab Loader v6.2.3
BepInEx/patchers/EnhancedPrefabLoader/CollectionWeaver.dll
Decompiled 3 weeks agousing System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using CollectionWeaver.Core; using CollectionWeaver.Extensions; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Cecil.Rocks; using Mono.Collections.Generic; using MonoMod.Cil; [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("CollectionWeaver")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+5deed880084a3d484759676f86ade5aaab95e104")] [assembly: AssemblyProduct("CollectionWeaver")] [assembly: AssemblyTitle("CollectionWeaver")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 CollectionWeaver { public static class ListInterceptor<T> { private static readonly ConcurrentDictionary<string, ListInterceptorHandler<T>> handlerCache = new ConcurrentDictionary<string, ListInterceptorHandler<T>>(); public static List<ListInterceptorHandler<T>> Handlers { get; private set; } = new List<ListInterceptorHandler<T>>(); public static void RegisterHandler(ListInterceptorHandler<T> handler) { Handlers.Add(handler); handlerCache.Clear(); } public static void InvokeInsert(List<T> list, int index, T value, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { handler.Insert(list, index, value, fieldName); return; } try { list.Insert(index, value); } catch (Exception ex) { throw new Exception("Error in Insert for field '" + fieldName + "': " + ex.Message, ex); } } public static int InvokeIndexOf(List<T> list, T value, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.IndexOf(list, value, fieldName); } try { return list.IndexOf(value); } catch (Exception ex) { throw new Exception("Error in IndexOf for field '" + fieldName + "': " + ex.Message, ex); } } public static void InvokeRemoveAt(List<T> list, int index, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { handler.RemoveAt(list, index, fieldName); return; } try { list.RemoveAt(index); } catch (Exception ex) { throw new Exception("Error in RemoveAt for field '" + fieldName + "': " + ex.Message, ex); } } public static T InvokeGet_Item(List<T> list, int index, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.GetItem(list, index, fieldName); } try { return list[index]; } catch (Exception ex) { throw new Exception("Error in Get_Item for field '" + fieldName + "': " + ex.Message, ex); } } public static void InvokeSet_Item(List<T> list, int index, T value, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { handler.SetItem(list, index, value, fieldName); return; } try { list[index] = value; } catch (Exception ex) { throw new Exception("Error in Set_Item for field '" + fieldName + "': " + ex.Message, ex); } } public static List<T>.Enumerator InvokeGetEnumerator(List<T> list, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.GetEnumerator(list, fieldName); } try { return list.GetEnumerator(); } catch (Exception ex) { throw new Exception("Error in GetEnumerator for field '" + fieldName + "': " + ex.Message, ex); } } public static void InvokeAdd(List<T> list, T value, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { handler.Add(list, value, fieldName); return; } try { list.Add(value); } catch (Exception ex) { throw new Exception("Error in Add for field '" + fieldName + "': " + ex.Message, ex); } } public static bool InvokeRemove(List<T> list, T value, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.Remove(list, value, fieldName); } try { return list.Remove(value); } catch (Exception ex) { throw new Exception("Error in Remove for field '" + fieldName + "': " + ex.Message, ex); } } public static int InvokeGet_Count(List<T> list, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.Count(list, fieldName); } try { return list.Count; } catch (Exception ex) { throw new Exception("Error in Get_Count for field '" + fieldName + "': " + ex.Message, ex); } } public static void InvokeClear(List<T> list, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { handler.Clear(list, fieldName); return; } try { list.Clear(); } catch (Exception ex) { throw new Exception("Error in Clear for field '" + fieldName + "': " + ex.Message, ex); } } public static bool InvokeContains(List<T> list, T value, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.Contains(list, value, fieldName); } try { return list.Contains(value); } catch (Exception ex) { throw new Exception("Error in Contains for field '" + fieldName + "': " + ex.Message, ex); } } public static void InvokeCopyTo(List<T> list, T[] array, int arrayIndex, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { handler.CopyTo(list, array, arrayIndex, fieldName); return; } try { list.CopyTo(array, arrayIndex); } catch (Exception ex) { throw new Exception("Error in CopyTo for field '" + fieldName + "': " + ex.Message, ex); } } public static void InvokeAddRange(List<T> list, IEnumerable<T> values, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { handler.AddRange(list, values, fieldName); return; } try { list.AddRange(values); } catch (Exception ex) { throw new Exception("Error in AddRange for field '" + fieldName + "': " + ex.Message, ex); } } public static void InvokeInsertRange(List<T> list, int index, IEnumerable<T> values, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { handler.InsertRange(list, index, values, fieldName); return; } try { list.InsertRange(index, values); } catch (Exception ex) { throw new Exception("Error in InsertRange for field '" + fieldName + "': " + ex.Message, ex); } } public static void InvokeRemoveRange(List<T> list, int index, int count, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { handler.RemoveRange(list, index, count, fieldName); return; } try { list.RemoveRange(index, count); } catch (Exception ex) { throw new Exception("Error in RemoveRange for field '" + fieldName + "': " + ex.Message, ex); } } public static int InvokeLastIndexOf(List<T> list, T value, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.LastIndexOf(list, value, fieldName); } try { return list.LastIndexOf(value); } catch (Exception ex) { throw new Exception("Error in LastIndexOf for field '" + fieldName + "': " + ex.Message, ex); } } public static void InvokeSort(List<T> list, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { handler.Sort(list, fieldName); return; } try { list.Sort(); } catch (Exception ex) { throw new Exception("Error in Sort for field '" + fieldName + "': " + ex.Message, ex); } } public static void InvokeSort(List<T> list, Comparison<T> comparison, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { handler.Sort(list, comparison, fieldName); return; } try { list.Sort(comparison); } catch (Exception ex) { throw new Exception("Error in Sort(Comparison) for field '" + fieldName + "': " + ex.Message, ex); } } public static void InvokeSort(List<T> list, IComparer<T> comparer, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { handler.Sort(list, comparer, fieldName); return; } try { list.Sort(comparer); } catch (Exception ex) { throw new Exception("Error in Sort(IComparer) for field '" + fieldName + "': " + ex.Message, ex); } } public static void InvokeReverse(List<T> list, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { handler.Reverse(list, fieldName); return; } try { list.Reverse(); } catch (Exception ex) { throw new Exception("Error in Reverse for field '" + fieldName + "': " + ex.Message, ex); } } public static void InvokeReverse(List<T> list, int index, int count, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { handler.Reverse(list, index, count, fieldName); return; } try { list.Reverse(index, count); } catch (Exception ex) { throw new Exception("Error in Reverse(int, int) for field '" + fieldName + "': " + ex.Message, ex); } } public static bool InvokeExists(List<T> list, Predicate<T> predicate, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.Exists(list, predicate, fieldName); } try { return list.Exists(predicate); } catch (Exception ex) { throw new Exception("Error in Exists for field '" + fieldName + "': " + ex.Message, ex); } } public static T InvokeFind(List<T> list, Predicate<T> predicate, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.Find(list, predicate, fieldName); } try { return list.Find(predicate); } catch (Exception ex) { throw new Exception("Error in Find for field '" + fieldName + "': " + ex.Message, ex); } } public static int InvokeFindIndex(List<T> list, Predicate<T> predicate, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.FindIndex(list, predicate, fieldName); } try { return list.FindIndex(predicate); } catch (Exception ex) { throw new Exception("Error in FindIndex for field '" + fieldName + "': " + ex.Message, ex); } } public static int InvokeFindIndex(List<T> list, int index, Predicate<T> predicate, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.FindIndex(list, index, predicate, fieldName); } try { return list.FindIndex(index, predicate); } catch (Exception ex) { throw new Exception("Error in FindIndex(int) for field '" + fieldName + "': " + ex.Message, ex); } } public static int InvokeFindIndex(List<T> list, int index, int count, Predicate<T> predicate, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.FindIndex(list, index, count, predicate, fieldName); } try { return list.FindIndex(index, count, predicate); } catch (Exception ex) { throw new Exception("Error in FindIndex(int, int) for field '" + fieldName + "': " + ex.Message, ex); } } public static T InvokeFindLast(List<T> list, Predicate<T> predicate, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.FindLast(list, predicate, fieldName); } try { return list.FindLast(predicate); } catch (Exception ex) { throw new Exception("Error in FindLast for field '" + fieldName + "': " + ex.Message, ex); } } public static int InvokeFindLastIndex(List<T> list, Predicate<T> predicate, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.FindLastIndex(list, predicate, fieldName); } try { return list.FindLastIndex(predicate); } catch (Exception ex) { throw new Exception("Error in FindLastIndex for field '" + fieldName + "': " + ex.Message, ex); } } public static int InvokeFindLastIndex(List<T> list, int index, Predicate<T> predicate, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.FindLastIndex(list, index, predicate, fieldName); } try { return list.FindLastIndex(index, predicate); } catch (Exception ex) { throw new Exception("Error in FindLastIndex(int) for field '" + fieldName + "': " + ex.Message, ex); } } public static int InvokeFindLastIndex(List<T> list, int index, int count, Predicate<T> predicate, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.FindLastIndex(list, index, count, predicate, fieldName); } try { return list.FindLastIndex(index, count, predicate); } catch (Exception ex) { throw new Exception("Error in FindLastIndex(int, int) for field '" + fieldName + "': " + ex.Message, ex); } } public static bool InvokeTrueForAll(List<T> list, Predicate<T> predicate, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.TrueForAll(list, predicate, fieldName); } try { return list.TrueForAll(predicate); } catch (Exception ex) { throw new Exception("Error in TrueForAll for field '" + fieldName + "': " + ex.Message, ex); } } public static T[] InvokeToArray(List<T> list, string fieldName) { ListInterceptorHandler<T> handler = GetHandler(fieldName); if (handler != null) { return handler.ToArray(list, fieldName); } try { return list.ToArray(); } catch (Exception ex) { throw new Exception("Error in ToArray for field '" + fieldName + "': " + ex.Message, ex); } } private static ListInterceptorHandler<T>? GetHandler(string fieldName) { return handlerCache.GetOrAdd(fieldName, (string fn) => Handlers.FirstOrDefault((ListInterceptorHandler<T> h) => h.ShouldHandleCall(fn))); } } } namespace CollectionWeaver.IL { public class ILWeaver { private readonly WeaverOptions weaverOptions; private readonly MethodWeaver methodWeaver; public ILWeaver(WeaverOptions weaverOptions) { this.weaverOptions = weaverOptions; methodWeaver = new MethodWeaver(this.weaverOptions); } public WeaverResult Weave(AssemblyDefinition assembly) { ModuleDefinition mainModule = assembly.MainModule; WeaverResult weaverResult = new WeaverResult(); foreach (TypeDefinition item in from t in ModuleDefinitionRocks.GetAllTypes(mainModule) where t.IsClassType() select t) { foreach (MethodDefinition item2 in ((IEnumerable<MethodDefinition>)item.Methods).Where((MethodDefinition m) => m.HasBody)) { weaverResult.Merge(methodWeaver.Weave(item2)); } } return weaverResult; } } public class MethodWeaver(WeaverOptions options) { private readonly NameResolver nameResolver = new NameResolver(); private readonly Dictionary<string, (GenericInstanceType, TypeDefinition)> interceptorTypeCache = new Dictionary<string, (GenericInstanceType, TypeDefinition)>(); private readonly Dictionary<string, MethodReference> interceptorMethodRefCache = new Dictionary<string, MethodReference>(); public WeaverResult Weave(MethodDefinition method) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown MethodBodyRocks.SimplifyMacros(method.Body); ILContext val = new ILContext(method); try { ILCursor val2 = new ILCursor(val); WeaverResult weaverResult = new WeaverResult(); string scope = ((MemberReference)method.DeclaringType).Name + "." + ((MemberReference)method).Name; MethodReference targetMethodRef = null; while (val2.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { (Instruction instr) => ILPatternMatchingExt.MatchCallOrCallvirt(instr, ref targetMethodRef) })) { if (targetMethodRef == null || !((MemberReference)targetMethodRef).DeclaringType.IsSupportedCollectionType()) { continue; } GenericInstanceType genericInstanceType = ((MemberReference)targetMethodRef).DeclaringType.GetGenericInstanceType(); string name; if (genericInstanceType == null) { weaverResult.AddSkipped(scope, ((MemberReference)targetMethodRef).FullName, "Non-generic collection type"); } else if (!nameResolver.TryResolveName(val2.Clone(), ((IEnumerable<TypeReference>)genericInstanceType.GenericArguments).ToArray(), out name)) { weaverResult.AddSkipped(scope, ((MemberReference)targetMethodRef).FullName, "Unresolvable name"); } else { if (!options.IsFieldIncluded(name)) { continue; } TypeDefinition interceptorTypeDef = GetInterceptorTypeDef(val2.Module, genericInstanceType); if (interceptorTypeDef == null) { weaverResult.AddSkipped(scope, name, "No interceptor found"); continue; } MethodReference interceptorMethodRef = GetInterceptorMethodRef(val2.Module, interceptorTypeDef, targetMethodRef, genericInstanceType); if (interceptorMethodRef == null) { weaverResult.AddSkipped(scope, name, "No matching interceptor method found"); continue; } PatchCollectionCall(val2, interceptorMethodRef, name); weaverResult.AddPatched(scope, name, (MethodReference)(object)method); } } MethodBodyRocks.OptimizeMacros(method.Body); return weaverResult; } finally { ((IDisposable)val)?.Dispose(); } } private void PatchCollectionCall(ILCursor cursor, MethodReference interceptorMethodRef, string declaredName) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) List<Instruction> list = ((IEnumerable<Instruction>)cursor.Method.Body.Instructions).Where((Instruction instr) => instr.Operand == cursor.Next).ToList(); ILLabel val = cursor.MarkLabel(); cursor.Emit(OpCodes.Ldstr, declaredName).Remove().Emit(OpCodes.Call, interceptorMethodRef); foreach (Instruction item in list) { item.Operand = val.Target; } } private TypeDefinition? GetInterceptorTypeDef(ModuleDefinition module, GenericInstanceType collectionType) { if (!interceptorTypeCache.TryGetValue(((MemberReference)collectionType).FullName, out (GenericInstanceType, TypeDefinition) value)) { Type interceptorRuntimeType = GetInterceptorRuntimeType(collectionType); if ((object)interceptorRuntimeType == null) { return null; } GenericInstanceType obj = TypeReferenceRocks.MakeGenericInstanceType(module.ImportReference(interceptorRuntimeType), ((IEnumerable<TypeReference>)collectionType.GenericArguments).ToArray()); TypeDefinition item = ((TypeReference)obj).Resolve(); value = (obj, item); interceptorTypeCache[((MemberReference)collectionType).FullName] = value; } return value.Item2; } private MethodReference? GetInterceptorMethodRef(ModuleDefinition module, TypeDefinition? interceptorTypeDef, MethodReference targetMethod, GenericInstanceType collectionType) { MethodDefinition val = ((interceptorTypeDef != null) ? ((IEnumerable<MethodDefinition>)interceptorTypeDef.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition m) => ((MemberReference)m).Name.Equals("Invoke" + ((MemberReference)targetMethod).Name, StringComparison.OrdinalIgnoreCase) && ((MethodReference)m).Parameters.Count - 2 == targetMethod.Parameters.Count && ((IEnumerable<ParameterDefinition>)((MethodReference)m).Parameters).Skip(1).Take(((MethodReference)m).Parameters.Count - 2).Zip((IEnumerable<ParameterDefinition>)targetMethod.Parameters, (ParameterDefinition interceptorParam, ParameterDefinition methodParam) => ((ParameterReference)interceptorParam).ParameterType.IsEquivalentTo(((ParameterReference)methodParam).ParameterType, collectionType)) .All((bool match) => match))) : null); if (val == null) { return null; } string text = string.Join("|", ((IEnumerable<ParameterDefinition>)targetMethod.Parameters).Select((ParameterDefinition p) => ((MemberReference)((ParameterReference)p).ParameterType).FullName)); string key = ((MemberReference)collectionType).FullName + "::" + ((MemberReference)targetMethod).Name + "::" + text; if (!interceptorMethodRefCache.TryGetValue(key, out MethodReference value)) { value = module.ImportReference((MethodReference)(object)val); ((MemberReference)value).DeclaringType = (TypeReference)(object)interceptorTypeCache[((MemberReference)collectionType).FullName].Item1; interceptorMethodRefCache[key] = value; } return value; } private Type? GetInterceptorRuntimeType(GenericInstanceType? genericInstanceType) { string text = ((genericInstanceType != null) ? ((MemberReference)((TypeReference)genericInstanceType).GetElementType()).FullName : null); if (text == "System.Collections.Generic.List`1" || text == "System.Collections.Generic.IList`1") { return typeof(ListInterceptor<>); } return null; } } internal class NameResolver { internal bool TryResolveName(ILCursor cursor, TypeReference[] targetGenericArguments, out string name) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_019f: 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_0173: Expected O, but got Unknown string name2 = ((MemberReference)cursor.Method).Name; Instruction next = cursor.Next; name = $"{name2}_unk_{((next != null) ? next.Offset : 0)}"; if (cursor.Next == null) { return false; } Instruction next2 = cursor.Next; while (cursor.TryGotoPrev((MoveType)2, new Func<Instruction, bool>[1] { (Instruction instr) => instr.MatchCollectionLoad(cursor.Method, targetGenericArguments) })) { if (cursor.Next == null) { return false; } int stackCount = 1; if (!TryTraceToTarget(cursor.Next, next2, ref stackCount) || stackCount != 0) { continue; } if (cursor.Previous.OpCode.IsFieldLoad()) { FieldReference val = (FieldReference)cursor.Previous.Operand; name = ((MemberReference)((MemberReference)val).DeclaringType).Name + "." + ((MemberReference)val).Name; return true; } if (cursor.Previous.OpCode.IsLdarg()) { name = $"{((MemberReference)cursor.Method).Name}_arg{cursor.Method.GetParameterIndex(cursor.Previous)}"; return true; } while (cursor.Previous.OpCode.IsLdloc() && cursor.TryGotoPrev((MoveType)0, new Func<Instruction, bool>[1] { (Instruction instr) => instr.IsComplimentaryStOf(cursor.Previous) })) { if (cursor.SkipNeutralBackward().Previous.OpCode.IsFieldLoad()) { FieldReference val2 = (FieldReference)cursor.Previous.Operand; name = ((MemberReference)((MemberReference)val2).DeclaringType).Name + "." + ((MemberReference)val2).Name; return true; } if (cursor.Previous.OpCode.IsLdarg()) { name = $"{((MemberReference)cursor.Method).Name}_arg{cursor.Method.GetParameterIndex(cursor.Previous)}"; return true; } } } return false; } private bool TryTraceToTarget(Instruction current, Instruction target, ref int stackCount) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (current == null || target == null) { return false; } Instruction obj; for (; current != null; current = obj) { if (current == target) { stackCount -= current.GetStackPopCount(); return true; } stackCount -= current.GetStackPopCount(); stackCount += current.GetStackPushCount(); if (current.OpCode.IsUnconditionalBranch()) { object operand = current.Operand; Instruction val = (Instruction)((operand is Instruction) ? operand : null); if (val != null) { obj = val; continue; } } obj = current.Next; } return false; } } public class WeaverOptions { private readonly HashSet<string> includedFieldNames = new HashSet<string>(); public IReadOnlyCollection<string> IncludedFieldNames => includedFieldNames; public WeaverOptions IncludeField(string fieldName) { includedFieldNames.Add(fieldName); return this; } internal bool IsFieldIncluded(string fieldName) { return includedFieldNames.Contains(fieldName); } } public class WeaverResult { private class Entry { public ResultKind Kind { get; set; } public string Scope { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public string Details { get; set; } = string.Empty; } private enum ResultKind { Patched, Skipped } private readonly List<Entry> entries = new List<Entry>(); public int PatchedCount => entries.Count((Entry e) => e.Kind == ResultKind.Patched); public int SkippedCount => entries.Count((Entry e) => e.Kind == ResultKind.Skipped); public void AddPatched(string scope, string name, MethodReference methodReference) { entries.Add(new Entry { Kind = ResultKind.Patched, Scope = scope, Name = name, Details = ((MemberReference)methodReference).FullName }); } public void AddSkipped(string scope, string name, string reason) { entries.Add(new Entry { Kind = ResultKind.Skipped, Scope = scope, Name = name, Details = reason }); } public void Merge(WeaverResult other) { if (other != null) { entries.AddRange(other.entries); } } public string CompileLog() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("=== Weaver Results ==="); foreach (Entry item in entries.Where((Entry e) => e.Kind == ResultKind.Patched)) { stringBuilder.AppendLine(" ✔ [" + item.Scope + "] " + item.Name + " -> " + item.Details); } List<Entry> list = entries.Where((Entry e) => e.Kind == ResultKind.Skipped).ToList(); if (list.Count > 0) { stringBuilder.AppendLine("--- Skipped ---"); foreach (Entry item2 in list) { stringBuilder.AppendLine(" ✘ [" + item2.Scope + "] " + item2.Name + " -> " + item2.Details); } } return stringBuilder.ToString(); } } } namespace CollectionWeaver.Extensions { internal static class ArrayTypeExtensions { internal static bool IsEquivalentTo(this ArrayType source, ArrayType target, GenericInstanceType? genericContext) { if (((TypeSpecification)source).ElementType.IsEquivalentTo(((TypeSpecification)target).ElementType, genericContext)) { return source.Rank == target.Rank; } return false; } } internal static class CursorExtensions { internal static ILCursor SkipNeutralForward(this ILCursor cursor) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) while (cursor.Next != null && cursor.Next.OpCode.IsNeutral()) { cursor.GotoNext(Array.Empty<Func<Instruction, bool>>()); } return cursor; } internal static ILCursor SkipNeutralBackward(this ILCursor cursor) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) while (cursor.Previous != null && cursor.Previous.OpCode.IsNeutral()) { cursor.GotoPrev(Array.Empty<Func<Instruction, bool>>()); } return cursor; } } internal static class GenericInstanceTypeExtensions { internal static bool IsEquivalentTo(this GenericInstanceType source, GenericInstanceType target, GenericInstanceType? genericContext) { if (!((TypeSpecification)source).ElementType.IsEquivalentTo(((TypeSpecification)target).ElementType, genericContext)) { return false; } Collection<TypeReference> genericArguments = source.GenericArguments; Collection<TypeReference> genericArguments2 = target.GenericArguments; if (genericArguments.Count != genericArguments2.Count) { return false; } for (int i = 0; i < genericArguments.Count; i++) { if (!genericArguments[i].IsEquivalentTo(genericArguments2[i], genericContext)) { return false; } } return true; } } internal static class GenericParameterExtensions { internal static bool TryResolveAndMatch(this GenericParameter genericParam, TypeReference target, GenericInstanceType? genericContext) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) GenericParameter val = (GenericParameter)(object)((target is GenericParameter) ? target : null); if (val != null) { if (genericParam.Position == val.Position) { return genericParam.Type == val.Type; } return false; } if (genericContext != null && genericParam.Position < genericContext.GenericArguments.Count) { return ((MemberReference)genericContext.GenericArguments[genericParam.Position]).FullName == ((MemberReference)target).FullName; } return false; } } internal static class InstructionExtensions { internal static bool MatchCollectionLoad(this Instruction instruction, MethodDefinition method, TypeReference[] targetGenericArguments) { //IL_0001: 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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected I4, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Invalid comparison between Unknown and I4 //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Invalid comparison between Unknown and I4 //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Invalid comparison between Unknown and I4 if (!instruction.OpCode.IsLoadCode()) { return false; } OpCode opCode = instruction.OpCode; Code code = ((OpCode)(ref opCode)).Code; if ((int)code <= 120) { switch (code - 2) { case 4: goto IL_0099; case 5: goto IL_00ab; case 6: goto IL_00bd; case 7: goto IL_00cf; case 15: goto IL_00e1; case 0: goto IL_00fe; case 1: goto IL_011b; case 2: goto IL_0136; case 3: goto IL_0151; case 13: goto IL_016c; case 8: case 9: case 10: case 11: case 12: case 14: goto IL_01a0; } if ((int)code == 120) { goto IL_0186; } } else { if ((int)code == 123) { goto IL_0186; } if ((int)code == 199) { goto IL_016c; } if ((int)code == 202) { goto IL_00e1; } } goto IL_01a0; IL_00bd: TypeReference val = method.Body.GetVariableType(2); goto IL_01a2; IL_0099: val = method.Body.GetVariableType(0); goto IL_01a2; IL_0186: object operand = instruction.Operand; object obj = ((operand is FieldReference) ? operand : null); val = ((obj != null) ? ((FieldReference)obj).FieldType : null); goto IL_01a2; IL_0151: val = (((MethodReference)method).HasThis ? method.GetParameterType(2) : method.GetParameterType(3)); goto IL_01a2; IL_00ab: val = method.Body.GetVariableType(1); goto IL_01a2; IL_00fe: val = (TypeReference)(((MethodReference)method).HasThis ? ((object)method.DeclaringType) : ((object)method.GetParameterType(0))); goto IL_01a2; IL_00e1: object operand2 = instruction.Operand; object obj2 = ((operand2 is VariableReference) ? operand2 : null); val = ((obj2 != null) ? ((VariableReference)obj2).VariableType : null); goto IL_01a2; IL_0136: val = (((MethodReference)method).HasThis ? method.GetParameterType(1) : method.GetParameterType(2)); goto IL_01a2; IL_01a2: TypeReference val2 = val; if (val2 == null || !val2.IsSupportedCollectionType()) { return false; } GenericInstanceType genericInstanceType = val2.GetGenericInstanceType(); if (genericInstanceType != null) { return targetGenericArguments.Select((TypeReference x) => ((MemberReference)x).FullName).SequenceEqual(((IEnumerable<TypeReference>)genericInstanceType.GenericArguments).Select((TypeReference x) => ((MemberReference)x).FullName)); } return false; IL_011b: val = (((MethodReference)method).HasThis ? method.GetParameterType(0) : method.GetParameterType(1)); goto IL_01a2; IL_01a0: val = null; goto IL_01a2; IL_016c: object operand3 = instruction.Operand; object obj3 = ((operand3 is ParameterReference) ? operand3 : null); val = ((obj3 != null) ? ((ParameterReference)obj3).ParameterType : null); goto IL_01a2; IL_00cf: val = method.Body.GetVariableType(3); goto IL_01a2; } internal 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 false; } int? localCodeIndex = stInstruction.GetLocalCodeIndex(); int? localCodeIndex2 = ldInstruction.GetLocalCodeIndex(); if (localCodeIndex.HasValue) { return localCodeIndex == localCodeIndex2; } return false; } internal 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; VariableReference val = (VariableReference)((operand is VariableReference) ? operand : null); return (val != null) ? new int?(val.Index) : ((int?)null); } case 8: case 9: case 10: case 12: break; } return null; } internal static int GetStackPopCount(this Instruction inst) { //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_0085: Expected I4, but got Unknown OpCode opCode = inst.OpCode; StackBehaviour stackBehaviourPop = ((OpCode)(ref opCode)).StackBehaviourPop; return (int)stackBehaviourPop switch { 0 => 0, 1 => 1, 2 => 2, 3 => 1, 4 => 2, 5 => 2, 6 => 2, 7 => 3, 8 => 2, 9 => 2, 10 => 1, 11 => 2, 12 => 2, 13 => 3, 14 => 3, 15 => 3, 16 => 3, 17 => 3, 27 => inst.GetVarPop(), _ => 0, }; } internal static int GetStackPushCount(this Instruction inst) { //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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected I4, but got Unknown OpCode opCode = inst.OpCode; StackBehaviour stackBehaviourPush = ((OpCode)(ref opCode)).StackBehaviourPush; return (stackBehaviourPush - 19) switch { 0 => 0, 1 => 1, 2 => 2, 3 => 1, 4 => 1, 5 => 1, 6 => 1, 7 => 1, 9 => inst.GetVarPush(), _ => 0, }; } internal static int GetVarPop(this Instruction inst) { //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_000f: Invalid comparison between Unknown and I4 //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 OpCode opCode = inst.OpCode; if ((int)((OpCode)(ref opCode)).FlowControl == 2) { object operand = inst.Operand; MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null); if (val != null) { int num; if (val.HasThis) { opCode = inst.OpCode; num = (((int)((OpCode)(ref opCode)).Code != 114) ? 1 : 0); } else { num = 0; } bool flag = (byte)num != 0; return val.Parameters.Count + (flag ? 1 : 0); } } opCode = inst.OpCode; return ((int)((OpCode)(ref opCode)).Code == 68) ? 1 : 0; } internal static int GetVarPush(this Instruction inst) { //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_000f: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 OpCode opCode = inst.OpCode; if ((int)((OpCode)(ref opCode)).FlowControl == 2) { object operand = inst.Operand; MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null); if (val != null) { return ((int)val.ReturnType.MetadataType != 1) ? 1 : 0; } } return 0; } } internal static class MethodBodyExtensions { internal static TypeReference? GetVariableType(this MethodBody body, int index) { if (index < 0 || index >= body.Variables.Count) { return null; } return ((VariableReference)body.Variables[index]).VariableType; } } internal static class MethodDefinitionExtensions { internal static TypeReference? GetParameterType(this MethodDefinition method, int index) { if (index < 0 || index >= ((MethodReference)method).Parameters.Count) { return null; } return ((ParameterReference)((MethodReference)method).Parameters[index]).ParameterType; } internal static int? GetParameterIndex(this MethodDefinition method, 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_0027: Expected I4, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 OpCode opCode = instr.OpCode; Code code = ((OpCode)(ref opCode)).Code; switch (code - 2) { default: if ((int)code == 14 || (int)code == 199) { object operand = instr.Operand; ParameterReference val = (ParameterReference)((operand is ParameterReference) ? operand : null); return (val != null) ? new int?(val.Index) : ((int?)null); } return null; case 0: return ((MethodReference)method).HasThis ? ((int?)null) : new int?(0); case 1: return (!((MethodReference)method).HasThis) ? 1 : 0; case 2: return ((MethodReference)method).HasThis ? 1 : 2; case 3: return ((MethodReference)method).HasThis ? 2 : 3; } } } internal static class OpCodeExtensions { internal 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; } internal 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; } internal 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; } internal 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; } internal 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; } internal 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; } internal 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; } internal 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; } internal 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; } internal static bool IsNeutral(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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 Code code = ((OpCode)(ref opCode)).Code; if ((int)code <= 209) { if ((int)code == 0 || code - 207 <= 2) { goto IL_002f; } } else if ((int)code == 211 || (int)code == 218) { goto IL_002f; } return false; IL_002f: return true; } internal static bool IsUnconditionalBranch(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 //IL_0012: 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_001a: Invalid comparison between Unknown and I4 Code code = ((OpCode)(ref opCode)).Code; if ((int)code == 42 || (int)code == 55 || code - 187 <= 1) { return true; } return false; } internal static bool IsConditionalBranch(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 - 43 <= 1 || code - 56 <= 1) { return true; } return false; } internal static bool IsCompareBranch(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 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 Code code = ((OpCode)(ref opCode)).Code; if (code - 45 <= 9 || code - 58 <= 9) { return true; } return false; } internal static bool IsSwitchBranch(this OpCode opCode) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 return (int)((OpCode)(ref opCode)).Code == 68; } } internal static class TypeDefinitionExtensions { internal static bool IsClassType(this TypeDefinition typeDef) { if (typeDef.IsClass && !typeDef.IsInterface) { return !((TypeReference)typeDef).IsValueType; } return false; } } internal static class TypeReferenceExtensions { private static readonly Dictionary<string, bool> collectionTypeCache = new Dictionary<string, bool>(); private static readonly Dictionary<string, GenericInstanceType?> genericInstanceCache = new Dictionary<string, GenericInstanceType>(); internal static bool IsSupportedCollectionType(this TypeReference typeRef) { return typeRef.IsListType(); } internal static bool IsListType(this TypeReference typeRef) { if (!collectionTypeCache.TryGetValue(((MemberReference)typeRef).FullName, out var value)) { bool flag = typeRef.Namespace == "System.Collections.Generic"; if (flag) { string name = ((MemberReference)typeRef).Name; bool flag2 = ((name == "List`1" || name == "IList`1") ? true : false); flag = flag2; } if (flag && typeRef is GenericInstanceType) { value = true; } else { TypeDefinition obj = typeRef.Resolve(); value = ((obj == null) ? ((bool?)null) : obj.BaseType?.IsListType()) == true; } collectionTypeCache[((MemberReference)typeRef).FullName] = value; } return value; } internal static GenericInstanceType? GetGenericInstanceType(this TypeReference typeRef) { if (!genericInstanceCache.TryGetValue(((MemberReference)typeRef).FullName, out GenericInstanceType value)) { try { GenericInstanceType val = (GenericInstanceType)(object)((typeRef is GenericInstanceType) ? typeRef : null); value = (GenericInstanceType)((val == null) ? ((object)typeRef.Resolve().BaseType?.GetGenericInstanceType()) : ((object)val)); genericInstanceCache[((MemberReference)typeRef).FullName] = value; } catch (Exception ex) { Log.Debug("Failed to resolve generic instance type for " + ((MemberReference)typeRef).FullName + ": " + ex.Message); genericInstanceCache[((MemberReference)typeRef).FullName] = null; } } return value; } internal static bool IsEquivalentTo(this TypeReference source, TypeReference target, GenericInstanceType? genericContext = null) { if (source == null || target == null) { return false; } if (((MemberReference)source).FullName == ((MemberReference)target).FullName) { return true; } GenericParameter val = (GenericParameter)(object)((source is GenericParameter) ? source : null); if (val != null) { return val.TryResolveAndMatch(target, genericContext); } GenericParameter val2 = (GenericParameter)(object)((target is GenericParameter) ? target : null); if (val2 != null) { return val2.TryResolveAndMatch(source, genericContext); } GenericInstanceType val3 = (GenericInstanceType)(object)((source is GenericInstanceType) ? source : null); if (val3 != null) { GenericInstanceType val4 = (GenericInstanceType)(object)((target is GenericInstanceType) ? target : null); if (val4 != null) { return val3.IsEquivalentTo(val4, genericContext); } } ArrayType val5 = (ArrayType)(object)((source is ArrayType) ? source : null); if (val5 != null) { ArrayType val6 = (ArrayType)(object)((target is ArrayType) ? target : null); if (val6 != null) { return val5.IsEquivalentTo(val6, genericContext); } } return false; } } } namespace CollectionWeaver.Core { public class ConsoleLogger : ILogger { private readonly object logLock = new object(); public void Log(LogLevel logLevel, string message) { lock (logLock) { ConsoleColor foregroundColor = Console.ForegroundColor; try { Console.ForegroundColor = GetLevelColor(logLevel); Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] [{logLevel}] {message}"); } finally { Console.ForegroundColor = foregroundColor; } } } private ConsoleColor GetLevelColor(LogLevel level) { return level switch { LogLevel.Debug => ConsoleColor.DarkGray, LogLevel.Info => ConsoleColor.White, LogLevel.Warning => ConsoleColor.Yellow, LogLevel.Error => ConsoleColor.Red, _ => ConsoleColor.Gray, }; } } public interface ILogger { void Log(LogLevel logLevel, string message); } [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public sealed class InterceptorHandler : Attribute { } public static class InterceptorRegistry { public static void RegisterFromAssembly(Assembly assembly) { if ((object)assembly == null) { throw new ArgumentNullException("assembly"); } foreach (Type item in assembly.GetTypes().Where(IsInterceptorType)) { TryRegisterHandler(item); } } public static void RegisterFromAllAssemblies() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { RegisterFromAssembly(assembly); } catch (Exception ex) { Log.Debug("Skipping assembly " + assembly.GetName().Name + ": " + ex.Message); } } } private static bool IsInterceptorType(Type type) { if (type.IsClass && !type.IsAbstract) { return type.GetCustomAttribute<InterceptorHandler>() != null; } return false; } private static void TryRegisterHandler(Type handlerType) { Type type = FindInterceptorBase(handlerType); if ((object)type == null) { Log.Warning(handlerType.Name + " has [Interceptor] but does not inherit from a valid InterceptorHandler<T>"); return; } Type type2 = ResolveInterceptorType(type); if ((object)type2 == null) { Log.Warning("No runtime interceptor found for " + type.Name); return; } MethodInfo method = type2.GetMethod("RegisterHandler", BindingFlags.Static | BindingFlags.Public); if ((object)method == null) { Log.Error("Cannot access RegisterHandler method on " + type2.Name); } else { RegisterHandler(method, handlerType, type.GenericTypeArguments); } } private static Type? FindInterceptorBase(Type type) { Type baseType = type.BaseType; while ((object)baseType != null) { if (baseType.IsGenericType && baseType.Name.EndsWith("InterceptorHandler`1")) { return baseType; } baseType = baseType.BaseType; } return null; } private static Type? ResolveInterceptorType(Type interceptorBase) { return ((!(interceptorBase.Name == "ListInterceptorHandler`1")) ? null : typeof(ListInterceptor<>))?.MakeGenericType(interceptorBase.GenericTypeArguments); } private static void RegisterHandler(MethodInfo registerMethod, Type handlerType, Type[] genericArgs) { try { object obj = Activator.CreateInstance(handlerType); if (obj == null) { Log.Error("Activator.CreateInstance returned null for " + handlerType.Name); return; } registerMethod.Invoke(null, new object[1] { obj }); Log.Info("Registered " + handlerType.Name + " for " + string.Join(", ", genericArgs.Select((Type a) => a.Name))); } catch (Exception ex) { Log.Error("Failed to register " + handlerType.Name + ": " + ex.Message); } } } public abstract class ListInterceptorHandler<T> { public abstract bool ShouldHandleCall(string fieldName); public virtual T GetItem(List<T> list, int index, string fieldName) { return list[index]; } public virtual void SetItem(List<T> list, int index, T value, string fieldName) { list[index] = value; } public virtual int Count(List<T> list, string fieldName) { return list.Count; } public virtual List<T>.Enumerator GetEnumerator(List<T> list, string fieldName) { return list.GetEnumerator(); } public virtual void Add(List<T> list, T item, string fieldName) { list.Add(item); } public virtual void Insert(List<T> list, int index, T value, string fieldName) { list.Insert(index, value); } public virtual void AddRange(List<T> list, IEnumerable<T> values, string fieldName) { list.AddRange(values); } public virtual bool Remove(List<T> list, T value, string fieldName) { return list.Remove(value); } public virtual void RemoveRange(List<T> list, int index, int count, string fieldName) { list.RemoveRange(index, count); } public virtual void Clear(List<T> list, string fieldName) { list.Clear(); } public virtual bool Contains(List<T> list, T value, string fieldName) { return list.Contains(value); } public virtual int IndexOf(List<T> list, T value, string fieldName) { return list.IndexOf(value); } public virtual void Sort(List<T> list, string fieldName) { list.Sort(); } public virtual void Sort(List<T> list, Comparison<T> comparison, string fieldName) { list.Sort(comparison); } public virtual void Sort(List<T> list, IComparer<T> comparer, string fieldName) { list.Sort(comparer); } public virtual void Reverse(List<T> list, string fieldName) { list.Reverse(); } public virtual void Reverse(List<T> list, int index, int count, string fieldName) { list.Reverse(index, count); } public virtual void CopyTo(List<T> list, T[] array, int arrayIndex, string fieldName) { list.CopyTo(array, arrayIndex); } public virtual void RemoveAt(List<T> list, int index, string fieldName) { list.RemoveAt(index); } public virtual void InsertRange(List<T> list, int index, IEnumerable<T> values, string fieldName) { list.InsertRange(index, values); } public virtual int LastIndexOf(List<T> list, T value, string fieldName) { return list.LastIndexOf(value); } public virtual bool Exists(List<T> list, Predicate<T> predicate, string fieldName) { return list.Exists(predicate); } public virtual T Find(List<T> list, Predicate<T> predicate, string fieldName) { return list.Find(predicate); } public virtual int FindIndex(List<T> list, Predicate<T> predicate, string fieldName) { return list.FindIndex(predicate); } public virtual int FindIndex(List<T> list, int index, Predicate<T> predicate, string fieldName) { return list.FindIndex(index, predicate); } public virtual int FindIndex(List<T> list, int index, int count, Predicate<T> predicate, string fieldName) { return list.FindIndex(index, count, predicate); } public virtual T FindLast(List<T> list, Predicate<T> predicate, string fieldName) { return list.FindLast(predicate); } public virtual int FindLastIndex(List<T> list, Predicate<T> predicate, string fieldName) { return list.FindLastIndex(predicate); } public virtual int FindLastIndex(List<T> list, int index, Predicate<T> predicate, string fieldName) { return list.FindLastIndex(index, predicate); } public virtual int FindLastIndex(List<T> list, int index, int count, Predicate<T> predicate, string fieldName) { return list.FindLastIndex(index, count, predicate); } public virtual bool TrueForAll(List<T> list, Predicate<T> predicate, string fieldName) { return list.TrueForAll(predicate); } public virtual T[] ToArray(List<T> list, string fieldName) { return list.ToArray(); } } public static class Log { public static ILogger Logger { get; set; } = new ConsoleLogger(); public static LogLevel LogLevel { get; set; } = LogLevel.Debug; internal static void Debug(string message) { InternalLog(LogLevel.Debug, message); } internal static void Info(string message) { InternalLog(LogLevel.Info, message); } internal static void Warning(string message) { InternalLog(LogLevel.Warning, message); } internal static void Error(string message) { InternalLog(LogLevel.Error, message); } private static void InternalLog(LogLevel logLevel, string message) { if (logLevel >= LogLevel) { Logger.Log(logLevel, message); } } } public enum LogLevel { Debug, Info, Warning, Error, None } }
BepInEx/patchers/EnhancedPrefabLoader/EnhancedPrefabLoaderPrepatch.dll
Decompiled 3 weeks agousing 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.Prepatch.Models; using EnhancedPrefabLoader.Shared.Extensions; using EnhancedPrefabLoader.Shared.Helpers; 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.2.3.0")] [assembly: AssemblyInformationalVersion("6.2.3+35f34656f829a028d941f0dc922be3d2b18bf963")] [assembly: AssemblyProduct("Enhanced Prefab Loader Prepatch")] [assembly: AssemblyTitle("EnhancedPrefabLoaderPrepatch")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("6.2.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [CompilerGenerated] internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T> { object IEnumerator.Current => _item; T IEnumerator<T>.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<T>.Count => 1; T IReadOnlyList<T>.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } } int ICollection<T>.Count => 1; bool ICollection<T>.IsReadOnly => true; T IList<T>.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<T>.Default.Equals(_item, (T)value); } int IList.IndexOf(object value) { if (!EqualityComparer<T>.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<T> IEnumerable<T>.GetEnumerator() { return new Enumerator(_item); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return EqualityComparer<T>.Default.Equals(_item, item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { array[arrayIndex] = _item; } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { if (!EqualityComparer<T>.Default.Equals(_item, item)) { return -1; } return 0; } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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.Models { public class BundleDescriptor { private List<string> assemblies = new List<string>(); private List<CustomShopInfo> customShops = new List<CustomShopInfo>(); private List<ItemInfo> items = new List<ItemInfo>(); private List<PrefabInfo> prefabs = new List<PrefabInfo>(); private List<CardExpansionInfo> cardExpansions = new List<CardExpansionInfo>(); public string BundleId { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public bool ItemPricesSuppliedByApi { get; set; } public List<string> Assemblies { get { return assemblies; } set { assemblies = value ?? new List<string>(); } } public List<CustomShopInfo> CustomShops { get { return customShops; } set { customShops = value ?? new List<CustomShopInfo>(); } } public List<ItemInfo> Items { get { return items; } set { items = value ?? new List<ItemInfo>(); } } public List<PrefabInfo> Prefabs { get { return prefabs; } set { prefabs = value ?? new List<PrefabInfo>(); } } public List<CardExpansionInfo> CardExpansions { get { return cardExpansions; } set { cardExpansions = value ?? new List<CardExpansionInfo>(); } } public List<PrefabInfo> Furniture => Prefabs.Where((PrefabInfo p) => p.AddItemToFurnitureShop).ToList(); public List<PrefabInfo> Deco => Prefabs.Where((PrefabInfo p) => p.IsDecoObject || p.IsDecoFloorTexture || p.IsDecoCeilingTexture || p.IsDecoWallTexture).ToList(); public HashSet<string> MeshNames { get { HashSet<string> hashSet = new HashSet<string>(); foreach (string item in from i in Items where !string.IsNullOrWhiteSpace(i.Mesh) select i.Mesh) { 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<string> Rarities { get; set; } = new List<string>(); public List<CardInfo> Cards { get; set; } = new List<CardInfo>(); public string CardPriceStrategy { get; set; } = string.Empty; public bool CardPriceStrategySuppliedByApi { get; set; } 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<string> PlayCardMaterials { get; set; } = new List<string>(); 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; } 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<string> MaterialList { get; set; } = new List<string>(); [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; } [JsonProperty("HasBigBox")] private bool HasBigBoxAlias { set { HasBigBox = value; } } [JsonProperty("BigBoxHideTillUnlocked")] private bool BigBoxHideTillUnlockedAlias { set { BigBoxHideTillUnlocked = value; } } [JsonProperty("BigBoxLicensePrice")] private float BigBoxLicensePriceAlias { set { BigBoxLicensePrice = value; } } [JsonProperty("BigBoxLicenseLevelRequirement")] private int BigBoxLicenseLevelRequirementAlias { set { BigBoxLicenseLevelRequirement = value; } } [JsonProperty("BigBoxIgnoreDoubleImage")] private bool BigBoxIgnoreDoubleImageAlias { set { BigBoxIgnoreDoubleImage = value; } } public float MinMarketPricePercent { get; set; } public float MaxMarketPricePercent { get; set; } public string FollowItemPrice { get; set; } = string.Empty; public bool AutoSetBoxPrice { get; set; } public bool MarketPricePercentSuppliedByApi { get; set; } public bool FollowItemPriceSuppliedByApi { get; set; } public bool AutoBoxPriceSuppliedByApi { get; set; } public bool LicensePriceSuppliedByApi { get; set; } public bool LicenseLevelSuppliedByApi { 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<string> PriceAffectedBy { get; set; } = new List<string>(); public bool IsSprayCan { get; set; } public bool IsCardPack { get; set; } public bool ApiManaged { 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<string, float> NormalWeights { get; set; } = new Dictionary<string, float>(); public Dictionary<string, float> GodWeights { get; set; } = new Dictionary<string, float>(); public Dictionary<string, Dictionary<string, float>> SlotWeights { get; set; } = new Dictionary<string, Dictionary<string, float>>(); public bool NormalWeightsSuppliedByApi { get; set; } public bool GodWeightsSuppliedByApi { get; set; } public bool SlotWeightsSuppliedByApi { get; set; } public bool CanHaveGodPacksSuppliedByApi { get; set; } public bool GodPackPercentageSuppliedByApi { get; set; } [Obsolete("Use NormalWeights, GodWeights, and SlotWeights instead. This field exists for backwards compatibility with older descriptors.")] public List<RarityWeightInfo> GenerationWeights { get; set; } = new List<RarityWeightInfo>(); 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<string> Errors { get; set; } = new List<string>(); public int ItemCount { get; set; } public int FurnitureCount { get; set; } public int CustomShopCount { get; set; } public int DecoCount { get; set; } public List<CardExpansionMetadata> CardExpansions { get; set; } = new List<CardExpansionMetadata>(); } 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 LevelRequirementSuppliedByApi { get; set; } public bool AddItemToFurnitureShop { get; set; } public string Description { get; set; } = string.Empty; public string ObjectType { get; set; } public List<VideoClipInfo> VideoClips { get; set; } = new List<VideoClipInfo>(); 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; } } 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 const string BundleDirectoryPattern = "*_prefabloader"; public static List<string> GetAllBundleDescriptorsIn(string basePath) { return Directory.EnumerateDirectories(basePath, "*_prefabloader", 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) { string directoryName = Path.GetDirectoryName(directory); DirectoryInfo directoryInfo = new DirectoryInfo(string.IsNullOrEmpty(directoryName) ? directory : directoryName); 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<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key) { if (!dict.TryGetValue(key, out TValue value)) { return default(TValue); } return value; } public static TValue GetOrAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, Func<TKey, TValue> factory) { if (!dict.TryGetValue(key, out TValue value)) { value = (dict[key] = factory(key)); } return value; } public static void MergeAdd<TKey>(this Dictionary<TKey, int> 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<TKey, TValue>(this Dictionary<TKey, TValue> dict, IEnumerable<KeyValuePair<TKey, TValue>> items) { foreach (KeyValuePair<TKey, TValue> item in items) { dict[item.Key] = item.Value; } } } public static class ListExtensions { public static List<T> Shuffle<T>(this List<T> 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<T> SwapAndRemove<T>(this List<T> 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<string, HashSet<string>> userData, Dictionary<string, Dictionary<string, int>> 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 num = startingValue; TypeDefinition val = ((IEnumerable<TypeDefinition>)assembly.MainModule.Types).FirstOrDefault((Func<TypeDefinition, bool>)((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<FieldDefinition>)val.Fields).FirstOrDefault((Func<FieldDefinition, bool>)((FieldDefinition f) => f.HasConstant && f.IsStatic && f.IsLiteral)); if (val2 == null) { Patcher.Log.LogWarning((object)("No valid enum fields found in " + enumName + ".")); continue; } HashSet<string> hashSet = new HashSet<string>(from f in (IEnumerable<FieldDefinition>)val.Fields where f.HasConstant && f.IsStatic && f.IsLiteral select ((MemberReference)f).Name); HashSet<int> hashSet2 = new HashSet<int>(from f in (IEnumerable<FieldDefinition>)val.Fields where f.HasConstant && f.IsStatic && f.IsLiteral select Convert.ToInt32(f.Constant)); SortedDictionary<int, FieldDefinition> sortedDictionary = new SortedDictionary<int, FieldDefinition>(); HashSet<string> hashSet3 = (from f in userData[enumName] select f.Sanitize() into f where !string.IsNullOrWhiteSpace(f) select f).ToHashSet(); if (savedData.TryGetValue(enumName, out Dictionary<string, int> value)) { List<string> list = new List<string>(); foreach (KeyValuePair<string, int> 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(num) || sortedDictionary.ContainsKey(num); num++) { } sortedDictionary[num] = new FieldDefinition(fieldName, val2.Attributes, (TypeReference)(object)val) { Constant = num }; savedData.GetOrAdd(enumName, (string _) => new Dictionary<string, int>())[fieldName] = num; hashSet.Add(fieldName); hashSet2.Add(num); } foreach (KeyValuePair<int, FieldDefinition> 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 bool initialized; private readonly Dictionary<string, string> keyMapping = new Dictionary<string, string> { { "FurnitureObjectTypes", "EObjectType" }, { "ItemTypes", "EItemType" }, { "FurnitureTypes", "EObjectType" }, { "DecoTypes", "EDecoObject" }, { "DecoObject", "EDecoObject" }, { "PackType", "ECollectionPackType" }, { "Rarity", "ERarity" }, { "CardExpansions", "ECardExpansionType" } }; public Dictionary<string, Dictionary<string, int>> SavedData { get; private set; } = new Dictionary<string, Dictionary<string, int>>(); public Dictionary<string, HashSet<string>> UserData { get; private set; } = new Dictionary<string, HashSet<string>>(); 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() { string text = Path.Combine(SaveDirectory, "enum_values.json"); foreach (string item in new List<string>(3) { Paths.PatcherPluginPath + "/EnhancedPrefabLoader/savedTypes", Paths.PatcherPluginPath + "/EnhancedPrefabLoader/enum_values.json", text }) { if (!File.Exists(item)) { continue; } try { foreach (KeyValuePair<string, Dictionary<string, int>> item2 in JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, int>>>(File.ReadAllText(item)) ?? new Dictionary<string, Dictionary<string, int>>()) { SavedData[MapLegacyKey(item2.Key)] = item2.Value; } 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 + ".")); } } } private void LoadNewEnumEntries() { List<string> allBundleDescriptorsIn = FileHelper.GetAllBundleDescriptorsIn(Paths.PluginPath); UserData["EObjectType"] = new HashSet<string>(); UserData["EDecoObject"] = new HashSet<string>(); UserData["EItemType"] = new HashSet<string>(); UserData["ECardExpansionType"] = new HashSet<string>(); UserData["ERarity"] = new HashSet<string>(); UserData["ECollectionPackType"] = new HashSet<string>(); foreach (string item in allBundleDescriptorsIn) { try { PrepatchBundleDescriptor prepatchBundleDescriptor = JsonConvert.DeserializeObject<PrepatchBundleDescriptor>(File.ReadAllText(item)); if (prepatchBundleDescriptor != null) { UserData["EObjectType"].UnionWith((from p in prepatchBundleDescriptor.Prefabs where p.AddItemToFurnitureShop select p.ObjectType).Where(HasValue)); UserData["EDecoObject"].UnionWith((from p in prepatchBundleDescriptor.Prefabs where p.IsDecoObject || p.IsDecoFloorTexture || p.IsDecoCeilingTexture || p.IsDecoWallTexture select p.DecoObject).Where(HasValue)); UserData["EItemType"].UnionWith(prepatchBundleDescriptor.Items.Select((PrepatchBundleDescriptor.PrepatchItemInfo i) => i.ItemType).Where(HasValue)); UserData["ECardExpansionType"].UnionWith(prepatchBundleDescriptor.CardExpansions.Select((PrepatchBundleDescriptor.PrepatchCardExpansionInfo c) => c.CardExpansion).Where(HasValue)); UserData["ERarity"].UnionWith(prepatchBundleDescriptor.CardExpansions.SelectMany((PrepatchBundleDescriptor.PrepatchCardExpansionInfo c) => c.Rarities).Where(HasValue)); UserData["ECollectionPackType"].UnionWith((from i in prepatchBundleDescriptor.Items where i.IsCardPack select (!HasValue(i.PackType)) ? i.ItemType : i.PackType).Where(HasValue)); } } catch (Exception ex) { Patcher.Log.LogError((object)("Failed to load bundle descriptor from " + item + ": " + ex.Message)); } } } private static bool HasValue(string value) { return !string.IsNullOrWhiteSpace(value); } } 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<string> TargetDLLs { get; } = new <>z__ReadOnlySingleElementList<string>("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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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("MonsterData_ScriptableObject.m_CardBackImageList") .IncludeField("MonsterData_ScriptableObject.m_CardFoilMaskImageList") .IncludeField("MonsterData_ScriptableObject.m_CardUISettingList"); 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) : ((int?)null))}, Skipped: {((val2 != null) ? new int?(val2.SkippedCount) : ((int?)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.2.3"; } } namespace EnhancedPrefabLoader.Prepatch.Models { internal class PrepatchBundleDescriptor { internal class PrepatchItemInfo { public string ItemType { get; set; } = string.Empty; public bool IsCardPack { get; set; } public string PackType { get; set; } = string.Empty; } internal class PrepatchPrefabInfo { public bool AddItemToFurnitureShop { get; set; } public string ObjectType { get; set; } = string.Empty; 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; } internal class PrepatchCardExpansionInfo { private List<string> rarities = new List<string>(); public string CardExpansion { get; set; } = string.Empty; public List<string> Rarities { get { return rarities; } set { rarities = value ?? new List<string>(); } } } private List<PrepatchItemInfo> items = new List<PrepatchItemInfo>(); private List<PrepatchPrefabInfo> prefabs = new List<PrepatchPrefabInfo>(); private List<PrepatchCardExpansionInfo> cardExpansions = new List<PrepatchCardExpansionInfo>(); public List<PrepatchItemInfo> Items { get { return items; } set { items = value ?? new List<PrepatchItemInfo>(); } } public List<PrepatchPrefabInfo> Prefabs { get { return prefabs; } set { prefabs = value ?? new List<PrepatchPrefabInfo>(); } } public List<PrepatchCardExpansionInfo> CardExpansions { get { return cardExpansions; } set { cardExpansions = value ?? new List<PrepatchCardExpansionInfo>(); } } } } 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) : ((int?)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_0012: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Invalid comparison between Unknown and I4 //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Invalid comparison between Unknown and I4 //IL_005b: 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_00a4: Expected I4, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Invalid comparison between Unknown and I4 //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Invalid comparison between Unknown and I4 //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Invalid comparison between Unknown and I4 elementType = null; if (!((instr != null) ? new OpCode?(instr.OpCode) : ((OpCode?)null)).HasValue || ((methodBody != null) ? methodBody.Method : null) == null || !instr.OpCode.IsLoadCode()) { return false; } try { OpCode opCode = instr.OpCode; Code code = ((OpCode)(ref opCode)).Code; if ((int)code <= 120) { switch (code - 2) { case 4: goto IL_00d5; case 5: goto IL_00ed; case 6: goto IL_0105; case 7: goto IL_011d; case 15: goto IL_0135; case 0: goto IL_0153; case 1: goto IL_0191; case 2: goto IL_01bb; case 3: goto IL_01e5; case 12: goto IL_020f; case 8: case 9: case 10: case 11: case 13: case 14: goto IL_0245; } if ((int)code == 120) { goto IL_022a; } } else { if ((int)code == 123) { goto IL_022a; } if ((int)code == 199) { goto IL_020f; } if ((int)code == 202) { goto IL_0135; } } goto IL_0245; IL_00d5: TypeReference val = ((VariableReference)methodBody.Variables[0]).VariableType; goto IL_0248; IL_0135: object operand = instr.Operand; object obj = ((operand is VariableReference) ? operand : null); val = ((obj != null) ? ((VariableReference)obj).VariableType : null); goto IL_0248; IL_01e5: val = ((ParameterReference)((MethodReference)methodBody.Method).Parameters[((MethodReference)methodBody.Method).HasThis ? 2 : 3]).ParameterType; goto IL_0248; IL_00ed: val = ((VariableReference)methodBody.Variables[1]).VariableType; goto IL_0248; IL_0153: object obj3; if (!((MethodReference)methodBody.Method).HasThis) { ParameterDefinition obj2 = ((MethodReference)methodBody.Method).Parameters[0]; obj3 = ((obj2 != null) ? ((ParameterReference)obj2).ParameterType : null); } else { obj3 = methodBody.Method.DeclaringType; } val = (TypeReference)obj3; goto IL_0248; IL_0245: val = null; goto IL_0248; IL_020f: object operand2 = instr.Operand; object obj4 = ((operand2 is ParameterReference) ? operand2 : null); val = ((obj4 != null) ? ((ParameterReference)obj4).ParameterType : null); goto IL_0248; IL_022a: object operand3 = instr.Operand; object obj5 = ((operand3 is FieldReference) ? operand3 : null); val = ((obj5 != null) ? ((FieldReference)obj5).FieldType : null); goto IL_0248; IL_0248: 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_011d: val = ((VariableReference)methodBody.Variables[3]).VariableType; goto IL_0248; IL_0191: val = ((ParameterReference)((MethodReference)methodBody.Method).Parameters[(!((MethodReference)methodBody.Method).HasThis) ? 1 : 0]).ParameterType; goto IL_0248; IL_01bb: val = ((ParameterReference)((MethodReference)methodBody.Method).Parameters[((MethodReference)methodBody.Method).HasThis ? 1 : 2]).ParameterType; goto IL_0248; IL_0105: val = ((VariableReference)methodBody.Variables[2]).VariableType; goto IL_0248; } catch (Exception ex) when (((ex is ArgumentOutOfRangeException || ex is NullReferenceException) ? 1 : 0) != 0) { elementType = null; 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; } } }
BepInEx/plugins/EnhancedPrefabLoader/EnhancedPrefabLoader.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using CollectionWeaver.Core; using EnhancedPrefabLoader.API; using EnhancedPrefabLoader.API.Assets; using EnhancedPrefabLoader.API.Behaviors; using EnhancedPrefabLoader.API.Events; using EnhancedPrefabLoader.API.Extensions; using EnhancedPrefabLoader.API.InternalBridges; using EnhancedPrefabLoader.API.Models; using EnhancedPrefabLoader.API.Registry; using EnhancedPrefabLoader.API.Services; using EnhancedPrefabLoader.API.UI; using EnhancedPrefabLoader.Core; using EnhancedPrefabLoader.Core.Assets; using EnhancedPrefabLoader.Core.Cards; using EnhancedPrefabLoader.Core.Cards.ExpGenerators; using EnhancedPrefabLoader.Core.Cards.PriceGenerators; using EnhancedPrefabLoader.Core.Components; using EnhancedPrefabLoader.Core.Events; using EnhancedPrefabLoader.Core.Extensions; using EnhancedPrefabLoader.Core.ExternalBridges; using EnhancedPrefabLoader.Core.LoadingPipeline; using EnhancedPrefabLoader.Core.LoadingPipeline.Processors; using EnhancedPrefabLoader.Core.LoadingPipeline.Validators; using EnhancedPrefabLoader.Core.Models.Runtime; using EnhancedPrefabLoader.Core.Models.SaveData; using EnhancedPrefabLoader.Core.Packs.PackGenerators; using EnhancedPrefabLoader.Core.Patches; using EnhancedPrefabLoader.Core.Properties; using EnhancedPrefabLoader.Core.Registry; using EnhancedPrefabLoader.Core.Saves; using EnhancedPrefabLoader.Core.Services; using EnhancedPrefabLoader.Core.Services.Internal; using EnhancedPrefabLoader.Core.Settings; using EnhancedPrefabLoader.Core.Shops; using EnhancedPrefabLoader.Core.Trading; using EnhancedPrefabLoader.Core.Uninstall; using EnhancedPrefabLoader.Core.Utils; using EnhancedPrefabLoader.Shared.Enums; using EnhancedPrefabLoader.Shared.Extensions; using EnhancedPrefabLoader.Shared.Helpers; using EnhancedPrefabLoader.Shared.Models; using HarmonyLib; using I2.Loc; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Experimental.Rendering; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.SceneManagement; using UnityEngine.UI; using UnityEngine.Video; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("EnhancedPrefabLoader")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("6.2.3.0")] [assembly: AssemblyInformationalVersion("6.2.3+35f34656f829a028d941f0dc922be3d2b18bf963")] [assembly: AssemblyProduct("Enhanced Prefab Loader")] [assembly: AssemblyTitle("EnhancedPrefabLoader")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("6.2.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [CompilerGenerated] internal sealed class <>z__ReadOnlyArray<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { int ICollection.Count => _items.Length; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection<T>.Count => _items.Length; T IReadOnlyList<T>.this[int index] => _items[index]; int ICollection<T>.Count => _items.Length; bool ICollection<T>.IsReadOnly => true; T IList<T>.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } public <>z__ReadOnlyArray(T[] items) { _items = items; } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.CopyTo(Array array, int index) { ((ICollection)_items).CopyTo(array, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return ((IList)_items).Contains(value); } int IList.IndexOf(object value) { return ((IList)_items).IndexOf(value); } 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<T> IEnumerable<T>.GetEnumerator() { return ((IEnumerable<T>)_items).GetEnumerator(); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return ((ICollection<T>)_items).Contains(item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { ((ICollection<T>)_items).CopyTo(array, arrayIndex); } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { return ((IList<T>)_items).IndexOf(item); } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } } [CompilerGenerated] internal sealed class <>z__ReadOnlyList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { int ICollection.Count => _items.Count; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection<T>.Count => _items.Count; T IReadOnlyList<T>.this[int index] => _items[index]; int ICollection<T>.Count => _items.Count; bool ICollection<T>.IsReadOnly => true; T IList<T>.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } public <>z__ReadOnlyList(List<T> items) { _items = items; } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.CopyTo(Array array, int index) { ((ICollection)_items).CopyTo(array, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return ((IList)_items).Contains(value); } int IList.IndexOf(object value) { return ((IList)_items).IndexOf(value); } 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<T> IEnumerable<T>.GetEnumerator() { return ((IEnumerable<T>)_items).GetEnumerator(); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return _items.Contains(item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { _items.CopyTo(array, arrayIndex); } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { return _items.IndexOf(item); } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } } [CompilerGenerated] internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T> { object IEnumerator.Current => _item; T IEnumerator<T>.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<T>.Count => 1; T IReadOnlyList<T>.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } } int ICollection<T>.Count => 1; bool ICollection<T>.IsReadOnly => true; T IList<T>.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<T>.Default.Equals(_item, (T)value); } int IList.IndexOf(object value) { if (!EqualityComparer<T>.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<T> IEnumerable<T>.GetEnumerator() { return new Enumerator(_item); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return EqualityComparer<T>.Default.Equals(_item, item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { array[arrayIndex] = _item; } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { if (!EqualityComparer<T>.Default.Equals(_item, item)) { return -1; } return 0; } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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; } } } public sealed class ConfigurationManagerAttributes { public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput); public bool? ShowRangeAsPercent; public Action<ConfigEntryBase> CustomDrawer; public CustomHotkeyDrawerFunc CustomHotkeyDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; public Func<object, string> ObjToStr; public Func<string, object> StrToObj; } namespace EnhancedPrefabLoader { [BepInDependency("EnhancedPrefabLoader.API", "6.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("EnhancedPrefabLoader", "Enhanced Prefab Loader", "6.2.3")] public class Plugin : BaseUnityPlugin { private readonly Harmony harmony = new Harmony("EnhancedPrefabLoader"); private bool legacyPlayTablesChecked; internal static Plugin Instance { get; private set; } public Plugin() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown Instance = this; } private void Awake() { EplRuntimeData.Config.Initialize(((BaseUnityPlugin)this).Config); ModLogger.Initialize(((BaseUnityPlugin)this).Logger); ValidateApiAssembly(); Epl.RegisterApi((IEplApi)(object)new EplApi()); InterceptorRegistry.RegisterFromAssembly(Assembly.GetExecutingAssembly()); StreamingAssetsBridge.AssetLoadBridge = (IAssetLoadBridge)(object)EplRuntimeData.Services.StreamingAssetService; StreamingAssetsBridge.AssetRefTracker = (IAssetRefTracker)(object)EplRuntimeData.Services.StreamingAssetService; EplRuntimeData.Events.OnInventoryBaseAwake += delegate { EplRuntimeData.Services.ShopInventoryManager.PopulateAllShopInventories(); }; SceneManager.sceneLoaded += OnSceneLoad; harmony.PatchAll(); ModLogger.Info("Plugin Enhanced Prefab Loader v:6.2.3 by GhostNarwhal is loaded!", "Awake", "C:\\GitLab-Runner\\builds\\-F4_x1RGt\\0\\tcg-mods\\prefabloader\\EnhancedPrefabLoader.Core\\Plugin.cs"); } private void OnDestroy() { harmony.UnpatchSelf(); ModLogger.Info("Plugin Enhanced Prefab Loader is unloaded!", "OnDestroy", "C:\\GitLab-Runner\\builds\\-F4_x1RGt\\0\\tcg-mods\\prefabloader\\EnhancedPrefabLoader.Core\\Plugin.cs"); } private static void ValidateApiAssembly() { Assembly assembly = typeof(Epl).Assembly; AssemblyName loadedName = assembly.GetName(); AssemblyName assemblyName = typeof(Plugin).Assembly.GetReferencedAssemblies().FirstOrDefault((AssemblyName a) => a.Name == loadedName.Name); if (assemblyName != null && loadedName.Version < assemblyName.Version) { ModLogger.Error($"Loaded {loadedName.Name} {loadedName.Version} is older than the {assemblyName.Version} this EnhancedPrefabLoader build was compiled against — another mod is likely shipping an outdated copy at '{assembly.Location}'. Remove duplicate EnhancedPrefabLoader.API.dll files; only the standalone API mod should provide it.", "ValidateApiAssembly", "C:\\GitLab-Runner\\builds\\-F4_x1RGt\\0\\tcg-mods\\prefabloader\\EnhancedPrefabLoader.Core\\Plugin.cs"); } } private void NeutralizeLegacyEnhancedPlayTables() { if (!Chainloader.PluginInfos.ContainsKey("EnhancedPlayTables")) { return; } ModLogger.Error("EnhancedPlayTables is installed alongside EnhancedPrefabLoader, which now includes its play-table card features — uninstall EnhancedPlayTables. Its patches have been disabled for this session.", "NeutralizeLegacyEnhancedPlayTables", "C:\\GitLab-Runner\\builds\\-F4_x1RGt\\0\\tcg-mods\\prefabloader\\EnhancedPrefabLoader.Core\\Plugin.cs"); foreach (MethodBase item in Harmony.GetAllPatchedMethods().ToList()) { harmony.Unpatch(item, (HarmonyPatchType)0, "EnhancedPlayTables"); } } private void OnSceneLoad(Scene scene, LoadSceneMode _) { if (!legacyPlayTablesChecked) { legacyPlayTablesChecked = true; NeutralizeLegacyEnhancedPlayTables(); } if (((Scene)(ref scene)).name == "Title") { EplRuntimeData.Services.SaveDataManager.ResetAllSaveData(); EplRuntimeData.Services.ShopService.ResetUIState(); EplRuntimeData.Services.PlayTableService.Reset(); EplRuntimeData.Services.CardExpansionSelectService.IsLoaded = false; EplRuntimeData.Services.CardRaritySelectService.IsLoaded = false; EplRuntimeData.Services.CollectionBinderService.IsLoaded = false; EplRuntimeData.Services.SettingsScreenService.IsLoaded = false; EplRuntimeData.Services.ScriptHookService.Reset(); } else { EplRuntimeData.Services.ShopService.CreateAndRegisterCustomShops(); EplRuntimeData.Services.StreamingAssetService.StartCleanupCoroutine(); EplRuntimeData.Services.ScriptHookService.SubscribeGameEvents(); } } } } namespace EnhancedPrefabLoader.Shared.Models { public class BundleDescriptor { private List<string> assemblies = new List<string>(); private List<CustomShopInfo> customShops = new List<CustomShopInfo>(); private List<ItemInfo> items = new List<ItemInfo>(); private List<PrefabInfo> prefabs = new List<PrefabInfo>(); private List<CardExpansionInfo> cardExpansions = new List<CardExpansionInfo>(); public string BundleId { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public bool ItemPricesSuppliedByApi { get; set; } public List<string> Assemblies { get { return assemblies; } set { assemblies = value ?? new List<string>(); } } public List<CustomShopInfo> CustomShops { get { return customShops; } set { customShops = value ?? new List<CustomShopInfo>(); } } public List<ItemInfo> Items { get { return items; } set { items = value ?? new List<ItemInfo>(); } } public List<PrefabInfo> Prefabs { get { return prefabs; } set { prefabs = value ?? new List<PrefabInfo>(); } } public List<CardExpansionInfo> CardExpansions { get { return cardExpansions; } set { cardExpansions = value ?? new List<CardExpansionInfo>(); } } public List<PrefabInfo> Furniture => Prefabs.Where((PrefabInfo p) => p.AddItemToFurnitureShop).ToList(); public List<PrefabInfo> Deco => Prefabs.Where((PrefabInfo p) => p.IsDecoObject || p.IsDecoFloorTexture || p.IsDecoCeilingTexture || p.IsDecoWallTexture).ToList(); public HashSet<string> MeshNames { get { HashSet<string> hashSet = new HashSet<string>(); foreach (string item in from i in Items where !string.IsNullOrWhiteSpace(i.Mesh) select i.Mesh) { 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<string> Rarities { get; set; } = new List<string>(); public List<CardInfo> Cards { get; set; } = new List<CardInfo>(); public string CardPriceStrategy { get; set; } = string.Empty; public bool CardPriceStrategySuppliedByApi { get; set; } 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<string> PlayCardMaterials { get; set; } = new List<string>(); 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; } 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<string> MaterialList { get; set; } = new List<string>(); [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; } [JsonProperty("HasBigBox")] private bool HasBigBoxAlias { set { HasBigBox = value; } } [JsonProperty("BigBoxHideTillUnlocked")] private bool BigBoxHideTillUnlockedAlias { set { BigBoxHideTillUnlocked = value; } } [JsonProperty("BigBoxLicensePrice")] private float BigBoxLicensePriceAlias { set { BigBoxLicensePrice = value; } } [JsonProperty("BigBoxLicenseLevelRequirement")] private int BigBoxLicenseLevelRequirementAlias { set { BigBoxLicenseLevelRequirement = value; } } [JsonProperty("BigBoxIgnoreDoubleImage")] private bool BigBoxIgnoreDoubleImageAlias { set { BigBoxIgnoreDoubleImage = value; } } public float MinMarketPricePercent { get; set; } public float MaxMarketPricePercent { get; set; } public string FollowItemPrice { get; set; } = string.Empty; public bool AutoSetBoxPrice { get; set; } public bool MarketPricePercentSuppliedByApi { get; set; } public bool FollowItemPriceSuppliedByApi { get; set; } public bool AutoBoxPriceSuppliedByApi { get; set; } public bool LicensePriceSuppliedByApi { get; set; } public bool LicenseLevelSuppliedByApi { 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<string> PriceAffectedBy { get; set; } = new List<string>(); public bool IsSprayCan { get; set; } public bool IsCardPack { get; set; } public bool ApiManaged { 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<string, float> NormalWeights { get; set; } = new Dictionary<string, float>(); public Dictionary<string, float> GodWeights { get; set; } = new Dictionary<string, float>(); public Dictionary<string, Dictionary<string, float>> SlotWeights { get; set; } = new Dictionary<string, Dictionary<string, float>>(); public bool NormalWeightsSuppliedByApi { get; set; } public bool GodWeightsSuppliedByApi { get; set; } public bool SlotWeightsSuppliedByApi { get; set; } public bool CanHaveGodPacksSuppliedByApi { get; set; } public bool GodPackPercentageSuppliedByApi { get; set; } [Obsolete("Use NormalWeights, GodWeights, and SlotWeights instead. This field exists for backwards compatibility with older descriptors.")] public List<RarityWeightInfo> GenerationWeights { get; set; } = new List<RarityWeightInfo>(); 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<string> Errors { get; set; } = new List<string>(); public int ItemCount { get; set; } public int FurnitureCount { get; set; } public int CustomShopCount { get; set; } public int DecoCount { get; set; } public List<CardExpansionMetadata> CardExpansions { get; set; } = new List<CardExpansionMetadata>(); } 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 LevelRequirementSuppliedByApi { get; set; } public bool AddItemToFurnitureShop { get; set; } public string Description { get; set; } = string.Empty; public string ObjectType { get; set; } public List<VideoClipInfo> VideoClips { get; set; } = new List<VideoClipInfo>(); 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; } } 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 const string BundleDirectoryPattern = "*_prefabloader"; public static List<string> GetAllBundleDescriptorsIn(string basePath) { return Directory.EnumerateDirectories(basePath, "*_prefabloader", 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) { string directoryName = Path.GetDirectoryName(directory); DirectoryInfo directoryInfo = new DirectoryInfo(string.IsNullOrEmpty(directoryName) ? directory : directoryName); 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<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key) { if (!dict.TryGetValue(key, out TValue value)) { return default(TValue); } return value; } public static TValue GetOrAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, Func<TKey, TValue> factory) { if (!dict.TryGetValue(key, out TValue value)) { value = (dict[key] = factory(key)); } return value; } public static void MergeAdd<TKey>(this Dictionary<TKey, int> 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<TKey, TValue>(this Dictionary<TKey, TValue> dict, IEnumerable<KeyValuePair<TKey, TValue>> items) { foreach (KeyValuePair<TKey, TValue> item in items) { dict[item.Key] = item.Value; } } } public static class ListExtensions { public static List<T> Shuffle<T>(this List<T> 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<T> SwapAndRemove<T>(this List<T> 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.Core { internal class BundleManager { internal class BundleHandle { private AssetBundle? assetBundle; private AssetBundleCreateRequest? loadRequest; private bool isLoading; public bool HasError { get; private set; } public bool IsLoaded { get; private set; } public static BundleHandle Create(string bundlePath) { string bundleName = Path.GetFileNameWithoutExtension(bundlePath); AssetBundle val = AssetBundle.GetAllLoadedAssetBundles().FirstOrDefault((Func<AssetBundle, bool>)((AssetBundle b) => ((Object)b).name == bundleName)); if (val != null) { ModLogger.Debug("Bundle '" + bundleName + "' already loaded externally, reusing.", "Create", "C:\\GitLab-Runner\\builds\\-F4_x1RGt\\0\\tcg-mods\\prefabloader\\EnhancedPrefabLoader.Core\\BundleManager.cs"); return new BundleHandle { assetBundle = val, IsLoaded = true }; } return new BundleHandle { loadRequest = AssetBundle.LoadFromFileAsync(bundlePath) }; } internal IEnumerator WaitForLoadAsync() { if (IsLoaded) { yield break; } if (!isLoading) { isLoading = true; if (loadRequest != null) { yield return loadRequest; assetBundle = loadRequest.assetBundle; loadRequest = null; IsLoaded = assetBundle != null; HasError = assetBundle == null; } isLoading = false; } while (isLoading) { ModLogger.Debug("Waiting for another coroutine to finish loading bundle.", "WaitForLoadAsync", "C:\\GitLab-Runner\\builds\\-F4_x1RGt\\0\\tcg-mods\\prefabloader\\EnhancedPrefabLoader.Core\\BundleManager.cs"); yield return null; } } internal AssetBundleRequest? LoadAssetAsync<T>(string assetName) where T : Object { if (!string.IsNullOrEmpty(assetName)) { AssetBundle? obj = assetBundle; if (obj == null) { return null; } return obj.LoadAssetAsync<T>(assetName); } return null; } internal AssetBundleRequest? LoadAssetAsync(string assetName, Type type) { if (!string.IsNullOrEmpty(assetName)) { AssetBundle? obj = assetBundle; if (obj == null) { return null; } return obj.LoadAssetAsync(assetName, type); } return null; } internal AssetBundleRequest? LoadAllAsync<T>() where T : Object { AssetBundle? obj = assetBundle; if (obj == null) { return null; } return obj.LoadAllAssetsAsync<T>(); } } private readonly Dictionary<string, BundleHandle> bundleHandles = new Dictionary<string, BundleHandle>(); internal BundleHandle GetOrOpen(string bundlePath) { if (bundleHandles.TryGetValue(bundlePath, out BundleHandle value)) { if (!value.HasError) { return value; } bundleHandles.Remove(bundlePath); } value = BundleHandle.Create(bundlePath); bundleHandles[bundlePath] = value; return value; } } internal class EplApi : IEplApi { public bool IsBundleLoadingComplete => EplRuntimeData.IsBundleLoadingComplete; public IBundleRegistry BundleRegistry => (IBundleRegistry)(object)EplRuntimeData.Assets.BundleRegistry; public IEplAssets Assets => (IEplAssets)(object)EplRuntimeData.Assets; public IEplServices Services => (IEplServices)(object)EplRuntimeData.Services; public IEplEvents Events => (IEplEvents)(object)EplRuntimeData.Events; } internal class EplCaches { internal Dictionary<string, Material> CardBackMaterials { get; } = new Dictionary<string, Material>(); internal Material? OriginalCardBackMaterial { get; set; } internal List<(Material Material, Color OriginalColor)> LightingAwareMaterials { get; } = new List<(Material, Color)>(); } internal class EplConfig { internal bool ExcludeBaseGameCardsFromTrade { get; private set; } internal bool SparkleFoilEnabled { get; private set; } internal bool UseCustomExpForBase { get; private set; } internal bool DisableBaseGamePlayCards { get; private set; } internal int PreferEplTableItemsChance { get; private set; } internal bool FlipTableCards { get; private set; } internal int FacedownCardChance { get; private set; } internal int TappedCardChance { get; private set; } internal float TappedCardAngle { get; private set; } internal bool OptimizeShelfVisibilityUpdates { get; private set; } internal bool OptimizeMonsterDataLookups { get; private set; } internal bool OptimizeCardSaveIndexLookups { get; private set; } internal bool ReduceStreamedTextureMemory { get; private set; } internal bool OptimizeRestockDataLookups { get; private set; } internal bool OptimizeClockUpdates { get; private set; } internal bool OptimizeCardBorderTypeLookups { get; private set; } internal ConfigEntry<LogLevel> MinimumLogLevelEntry { get; private set; } internal ConfigEntry<float> CollectionBinderSpacingXEntry { get; private set; } internal ConfigEntry<float> CollectionBinderSpacingYEntry { get; private set; } internal ConfigEntry<Vector2> CollectionBinderButtonSizeEntry { get; private set; } internal ConfigEntry<float> CardExpansionSelectSpacingXEntry { get; private set; } internal ConfigEntry<float> CardExpansionSelectSpacingYEntry { get; private set; } internal ConfigEntry<Vector2> CardExpansionSelectButtonSizeEntry { get; private set; } internal ConfigEntry<float> RaritySelectSpacingXEntry { get; private set; } internal ConfigEntry<float> RaritySelectSpacingYEntry { get; private set; } internal ConfigEntry<Vector2> RaritySelectButtonSizeEntry { get; private set; } internal void Initialize(ConfigFile config) { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_044b: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Expected O, but got Unknown //IL_04e6: Unknown result type (might be due to invalid IL or missing references) //IL_04f0: Expected O, but got Unknown //IL_053d: Unknown result type (might be due to invalid IL or missing references) //IL_0547: Expected O, but got Unknown //IL_059e: Unknown result type (might be due to invalid IL or missing references) //IL_05a8: Expected O, but got Unknown ConfigEntry<bool> excludeBaseGame = config.Bind<bool>("Trading", "ExcludeBaseGameCardsFromTrade", false, "When enabled, base-game expansions (Tetramon, Destiny, Ghost) will not appear in customer card trade/sell selection."); ExcludeBaseGameCardsFromTrade = excludeBaseGame.Value; excludeBaseGame.SettingChanged += delegate { ExcludeBaseGameCardsFromTrade = excludeBaseGame.Value; }; ConfigEntry<bool> sparkleFoil = config.Bind<bool>("CardUI", "Sparkle Foil Enabled", true, "When enabled, foil cards display the sparkle glitter effect."); SparkleFoilEnabled = sparkleFoil.Value; sparkleFoil.SettingChanged += delegate { SparkleFoilEnabled = sparkleFoil.Value; }; CollectionBinderSpacingXEntry = config.Bind<float>("CollectionBinderUI", "ExpansionSpacingX", 30f, (ConfigDescription)null); CollectionBinderSpacingYEntry = config.Bind<float>("CollectionBinderUI", "ExpansionSpacingY", -45f, (ConfigDescription)null); CollectionBinderButtonSizeEntry = config.Bind<Vector2>("CollectionBinderUI", "ExpansionButtonSize", new Vector2(325f, 184.5f), (ConfigDescription)null); CardExpansionSelectSpacingXEntry = config.Bind<float>("UI", "ExpansionSpacingX", 30f, (ConfigDescription)null); CardExpansionSelectSpacingYEntry = config.Bind<float>("UI", "ExpansionSpacingY", -45f, (ConfigDescription)null); CardExpansionSelectButtonSizeEntry = config.Bind<Vector2>("UI", "ExpansionButtonSize", new Vector2(325f, 184.5f), (ConfigDescription)null); RaritySelectSpacingXEntry = config.Bind<float>("UI", "RaritySpacingX", 30f, (ConfigDescription)null); RaritySelectSpacingYEntry = config.Bind<float>("UI", "RaritySpacingY", -45f, (ConfigDescription)null); RaritySelectButtonSizeEntry = config.Bind<Vector2>("UI", "RarityButtonSize", new Vector2(325f, 184.5f), (ConfigDescription)null); ConfigEntry<bool> useCustomExp = config.Bind<bool>("GamePlay", "UseCustomExpForBase", false, "When enabled, base-game card expansions will use the EPL experience formula instead of the vanilla formula."); UseCustomExpForBase = useCustomExp.Value; useCustomExp.SettingChanged += delegate { UseCustomExpForBase = useCustomExp.Value; }; MinimumLogLevelEntry = config.Bind<LogLevel>("Logging", "Minimum log level to log", LogLevel.Warning, (ConfigDescription)null); ConfigEntry<bool> optimizeShelfVisibility = config.Bind<bool>("Performance", "OptimizeShelfVisibilityUpdates", false, "When enabled, replaces the base game's per-frame shelf item visibility pass with change detection — item meshes are only toggled when a shelf crosses the distance/angle threshold, plus a periodic 0.5s refresh. Greatly reduces per-frame overhead in large stocked shops. Disable if another mod patches ShelfManager.Update."); OptimizeShelfVisibilityUpdates = optimizeShelfVisibility.Value; optimizeShelfVisibility.SettingChanged += delegate { OptimizeShelfVisibilityUpdates = optimizeShelfVisibility.Value; }; ConfigEntry<bool> optimizeMonsterData = config.Bind<bool>("Performance", "OptimizeMonsterDataLookups", false, "When enabled, base-game monster data lookups use a cached dictionary instead of scanning the data lists on every call (card prices, pack opening, card rendering). Lookups that miss the cache fall back to the vanilla scan. Disable if another mod patches InventoryBase.GetMonsterData."); OptimizeMonsterDataLookups = optimizeMonsterData.Value; optimizeMonsterData.SettingChanged += delegate { OptimizeMonsterDataLookups = optimizeMonsterData.Value; }; ConfigEntry<bool> optimizeCardSaveIndex = config.Bind<bool>("Performance", "OptimizeCardSaveIndexLookups", false, "When enabled, base-game card save index lookups use a cached index dictionary instead of rescanning the shown monster list on every call (the hottest card path: add/remove card, prices, binder, bulk donation). EPL expansions are unaffected — they already use their own cached path. Disable if another mod patches CPlayerData.GetCardSaveIndex."); OptimizeCardSaveIndexLookups = optimizeCardSaveIndex.Value; optimizeCardSaveIndex.SettingChanged += delegate { OptimizeCardSaveIndexLookups = optimizeCardSaveIndex.Value; }; ConfigEntry<bool> reduceStreamedTextures = config.Bind<bool>("Performance", "ReduceStreamedTextureMemory", false, "When enabled, the base game's web-streamed textures (downloaded card art) release their CPU-side pixel copies after loading, halving their memory for the session. Disable if another mod reads pixels from these cached textures."); ReduceStreamedTextureMemory = reduceStreamedTextures.Value; reduceStreamedTextures.SettingChanged += delegate { ReduceStreamedTextureMemory = reduceStreamedTextures.Value; }; ConfigEntry<bool> optimizeRestockData = config.Bind<bool>("Performance", "OptimizeRestockDataLookups", false, "When enabled, restock data lookups (check price screens, barcode scanner, customer purchasing, trades) use a cached index dictionary over the combined base+EPL entry list instead of rescanning it per call. Disable if another mod patches InventoryBase.GetRestockData* methods."); OptimizeRestockDataLookups = optimizeRestockData.Value; optimizeRestockData.SettingChanged += delegate { OptimizeRestockDataLookups = optimizeRestockData.Value; }; ConfigEntry<bool> optimizeClock = config.Bind<bool>("Performance", "OptimizeClockUpdates", false, "When enabled, the in-game clock string is only rebuilt when the displayed time actually changes instead of every frame, removing constant string allocation garbage. Disable if another mod patches LightManager.EvaluateTimeClock."); OptimizeClockUpdates = optimizeClock.Value; optimizeClock.SettingChanged += delegate { OptimizeClockUpdates = optimizeClock.Value; }; ConfigEntry<bool> optimizeCardBorders = config.Bind<bool>("Performance", "OptimizeCardBorderTypeLookups", false, "When enabled, base-game card border type lookups use fixed tables instead of building a new list on every call (several call sites run per card in loops). EPL expansions are unaffected. Disable if another mod patches CPlayerData.GetCardBorderType."); OptimizeCardBorderTypeLookups = optimizeCardBorders.Value; optimizeCardBorders.SettingChanged += delegate { OptimizeCardBorderTypeLookups = optimizeCardBorders.Value; }; ConfigEntry<bool> disableBaseCards = config.Bind<bool>("PlayTable", "DisableBaseGamePlayCards", false, "When enabled, base game card textures will not appear on play tables. If no mod expansion textures are available, this setting is ignored."); DisableBaseGamePlayCards = disableBaseCards.Value; disableBaseCards.SettingChanged += delegate { DisableBaseGamePlayCards = disableBaseCards.Value; }; ConfigEntry<int> preferEplTableItems = config.Bind<int>("PlayTable", "PreferEplTableItemsChance", 50, new ConfigDescription("Chance (%) that a play table's decorations (playmat, deck box, comic book) are picked from EPL-added items when any are unlocked. At 0 every unlocked item has equal odds, so large base-game pools drown out EPL items; at 100 EPL items are always picked when available.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); PreferEplTableItemsChance = preferEplTableItems.Value; preferEplTableItems.SettingChanged += delegate { PreferEplTableItemsChance = preferEplTableItems.Value; }; ConfigEntry<bool> flipTableCards = config.Bind<bool>("PlayTable", "FlipTableCards", true, "When enabled, the cards laid out on play tables become individual face-up cards instead of the vanilla facedown rows, with configurable facedown/tapped rolls per card. Card faces always come from the expansion the table picked."); FlipTableCards = flipTableCards.Value; flipTableCards.SettingChanged += delegate { FlipTableCards = flipTableCards.Value; }; ConfigEntry<int> facedownChance = config.Bind<int>("PlayTable", "FacedownCardChance", 10, new ConfigDescription("Chance (%) for each flipped table card to be placed facedown. Only used when FlipTableCards is enabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); FacedownCardChance = facedownChance.Value; facedownChance.SettingChanged += delegate { FacedownCardChance = facedownChance.Value; }; ConfigEntry<int> tappedChance = config.Bind<int>("PlayTable", "TappedCardChance", 10, new ConfigDescription("Chance (%) for each flipped table card to be \"tapped\" (rotated sideways). Only used when FlipTableCards is enabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); TappedCardChance = tappedChance.Value; tappedChance.SettingChanged += delegate { TappedCardChance = tappedChance.Value; }; ConfigEntry<float> tappedAngle = config.Bind<float>("PlayTable", "TappedCardAngle", 75f, new ConfigDescription("Angle in degrees a \"tapped\" table card is rotated. Only used when FlipTableCards is enabled.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 90f), Array.Empty<object>())); TappedCardAngle = tappedAngle.Value; tappedAngle.SettingChanged += delegate { TappedCardAngle = tappedAngle.Value; }; } } internal static class EplRuntimeData { internal static bool IsBundleLoadingComplete { get; set; } internal static BundleAssetTracker BundleAssetTracker { get; set; } = new BundleAssetTracker(); internal static List<Assembly> Assemblies { get; private set; } = new List<Assembly>(); internal static EplCaches Caches { get; private set; } = new EplCaches(); internal static EplConfig Config { get; private set; } = new EplConfig(); internal static EplEvents Events { get; private set; } = new EplEvents(); internal static EplAssets Assets { get; private set; } = new EplAssets(new BundleRegistry(BundleAssetTracker)); internal static EplServices Services { get; private set; } = new EplServices(new SaveDataService(BundleAssetTracker)); } public enum LogLevel { Debug, Info, Warning, Error, None } public static class ModLogger { private static ManualLogSource logger; private static LogLevel logLevel; public static void Initialize(ManualLogSource logger) { ModLogger.logger = logger; logLevel = EplRuntimeData.Config.MinimumLogLevelEntry.Value; EplRuntimeData.Config.MinimumLogLevelEntry.SettingChanged += delegate { logLevel = EplRuntimeData.Config.MinimumLogLevelEntry.Value; }; } public static void Debug(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "") { if (logLevel <= LogLevel.Debug) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath); logger.LogDebug((object)("[" + fileNameWithoutExtension + "." + memberName + "]: " + message)); } } public static void Info(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "") { if (logLevel <= LogLevel.Info) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath); logger.LogInfo((object)("[" + fileNameWithoutExtension + "." + memberName + "]: " + message)); } } public static void Warning(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "") { if (logLevel <= LogLevel.Warning) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath); logger.LogWarning((object)("[" + fileNameWithoutExtension + "." + memberName + "]: " + message)); } } public static void Error(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "") { if (logLevel <= LogLevel.Error) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath); logger.LogError((object)("[" + fileNameWithoutExtension + "." + memberName + "]: " + message)); } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "EnhancedPrefabLoader"; public const string PLUGIN_NAME = "Enhanced Prefab Loader"; public const string PLUGIN_VERSION = "6.2.3"; } } namespace EnhancedPrefabLoader.Core.Utils { internal static class CardExpansionTypeResolver { private static ECardExpansionType[]? sortedModKeys; internal static ECardExpansionType Resolve(int index) { if (index >= 8 && index < 200000) { ECardExpansionType[] array = GetSortedModKeys(); int num = index - 8; if (num < array.Length) { return array[num]; } return (ECardExpansionType)0; } return (ECardExpansionType)index; } internal static void InvalidateCache() { sortedModKeys = null; } private static ECardExpansionType[] GetSortedModKeys() { return sortedModKeys ?? (sortedModKeys = EplRuntimeData.Assets.CardExpansionLibrary.CardExpansionData.Keys.OrderBy((ECardExpansionType k) => (int)k).ToArray()); } } internal static class DecoObjectResolver { private static EDecoObject[]? sortedModKeys; internal static EDecoObject Resolve(int index) { if (index >= 184 && index < 200000) { EDecoObject[] array = GetSortedModKeys(); int num = index - 184; if (num < array.Length) { return array[num]; } return (EDecoObject)0; } return (EDecoObject)index; } internal static void InvalidateCache() { sortedModKeys = null; } private static EDecoObject[] GetSortedModKeys() { return sortedModKeys ?? (sortedModKeys = EplRuntimeData.Assets.DecoLibrary.DecoObjectData.Keys.OrderBy((EDecoObject k) => (int)k).ToArray()); } } internal static class GameBuild { internal static Type? PriceTagAtlasMapType { get; } = AccessTools.TypeByName("PriceTagAtlasMap"); internal static Type? StoredBoxRecordType { get; } = AccessTools.TypeByName("StoredBoxRecord"); internal static bool HasPriceTagAtlas { get; } = (object)PriceTagAtlasMapType != null && (object)AccessTools.Field(typeof(UI_PriceTag), "m_AtlasMap") != null && (object)AccessTools.Field(typeof(UI_PriceTag), "m_InstancedRenderer") != null; internal static bool HasLegacyPriceTagIcon { get; } = (object)AccessTools.Field(typeof(UI_PriceTag), "m_Icon") != null; internal static bool HasItemMaterialPropertyBlocks { get; } = (object)AccessTools.Property(typeof(Item), "m_MaterialPropertyBlock") != null; internal static bool HasItemSharedMaterialSlots { get; } = (object)AccessTools.Method(typeof(Item), "SetSharedMaterialForFirstSlot", (Type[])null, (Type[])null) != null; internal static bool HasStoredBoxRecords { get; } = (object)StoredBoxRecordType != null && (object)AccessTools.Method(typeof(RestockManager), "GetWarehouseCompartmentList", (Type[])null, (Type[])null) != null && (object)AccessTools.Method(typeof(ShelfCompartment), "TryPopLastStoredBoxRecord", (Type[])null, (Type[])null) != null; } internal static class ItemTypeResolver { private static EItemType[]? sortedModKeys; internal static EItemType Resolve(int index) { if (index >= 130 && index < 200000) { EItemType[] array = GetSortedModKeys(); int num = index - 130; if (num < array.Length) { return array[num]; } return (EItemType)0; } return (EItemType)index; } internal static void InvalidateCache() { sortedModKeys = null; } private static EItemType[] GetSortedModKeys() { return sortedModKeys ?? (sortedModKeys = EplRuntimeData.Assets.ItemLibrary.ItemData.Keys.OrderBy((EItemType k) => (int)k).ToArray()); } } } namespace EnhancedPrefabLoader.Core.Uninstall { internal class CardRemovalStrategy(HashSet<ECardExpansionType> cardExpansions) : IAssetRemovalStrategy { private Dictionary<CardData, int> removedCards = new Dictionary<CardData, int>(); public RemovalResult RemoveAssets() { removedCards = new Dictionary<CardData, int>(); RemoveFromCardShelves(); RemoveFromBinder(); RemoveFromBulkDonationBoxes(); RemoveFromCardStorageShelves(); RemoveFromCardPackageBoxes(); RemoveFromCardGrading(); RemoveFromDecks(); RemoveFromAutoPackOpeners(); RemoveFromHeldCards(); return RemovalResult.Success(removedCards.Values.Sum(), removedCards.Sum<KeyValuePair<CardData, int>>((KeyValuePair<CardData, int> kvp) => CPlayerData.GetCardMarketPrice(kvp.Key) * (float)kvp.Value)); } private void RemoveFromCardShelves() { RemoveFromShelfCardCompartments(CSingleton<ShelfManager>.Instance.m_CardShelfList); RemoveFromShelfCardCompartments((IEnumerable<CardShelf>)CSingleton<ShelfManager>.Instance.m_CardItemCombiShelfList); } private void RemoveFromShelfCardCompartments(IEnumerable<CardShelf> cardShelves) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) foreach (InteractableCardCompartment item in cardShelves.SelectMany((CardShelf cs) => cs.m_CardCompartmentList)) { if (item.m_StoredCardList.Count == 0) { continue; } CardData cardData = item.m_StoredCardList[0].m_Card3dUI.m_CardUI.m_CardData; if (!cardExpansions.Contains(cardData.expansionType)) { continue; } foreach (InteractableCardPriceTag interactablePriceTag in item.m_InteractablePriceTagList) { interactablePriceTag.SetPriceChecked(false); } item.m_StoredCardList[0].SetIsDisplayedOnShelf(false); item.m_StoredCardList[0].SetTargetRotation(Quaternion.identity); item.m_StoredCardList.RemoveAt(0); item.SetPriceTagCardData((CardData)null); item.SetPriceTagVisibility(false); if (item.m_CardShelf?.m_ElectronicCardListener != null) { item.m_CardShelf.m_ElectronicCardListener.UpdateCardUI((CardData)null); } removedCards[cardData] = removedCards.GetValueOrDefault(cardData) + 1; } } private void RemoveFromBinder() { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) foreach (CardData item in CPlayerData.m_GradedCardInventoryList.Where((CompactCardDataAmount c) => cardExpansions.Contains(c.expansionType)).Select((Func<CompactCardDataAmount, CardData>)CPlayerData.GetGradedCardData).ToList()) { CPlayerData.RemoveGradedCard(item, false); removedCards[item] = removedCards.GetValueOrDefault(item) + 1; } CardExpansionLibrary cardExpansionLibrary = EplRuntimeData.Assets.CardExpansionLibrary; foreach (ECardExpansionType item2 in cardExpansions) { if (!cardExpansionLibrary.CardExpansionData.TryGetValue(item2, out ModCardExpansionData value)) { continue; } foreach (KeyValuePair<EMonsterType, ModCardData> card in value.Cards) { card.Deconstruct(out var _, out var value2); CardData val = value2.ToCardData(); int cardAmount = CPlayerData.GetCardAmount(val); if (cardAmount > 0) { CPlayerData.ReduceCard(val, cardAmount); removedCards[val] = removedCards.GetValueOrDefault(val) + cardAmount; } } } } private void RemoveFromBulkDonationBoxes() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) foreach (List<CompactCardDataAmount> item in CSingleton<ShelfManager>.Instance.m_BulkDonationBoxList.Select((InteractableBulkDonationBox b) => b.m_CompactCardDataAmountList)) { foreach (CompactCardDataAmount item2 in item.Where((CompactCardDataAmount c) => cardExpansions.Contains(c.expansionType))) { CardData cardData = CPlayerData.GetCardData(item2.cardSaveIndex, item2.expansionType, item2.isDestiny); removedCards[cardData] = removedCards.GetValueOrDefault(cardData) + item2.amount; } item.RemoveAll((CompactCardDataAmount c) => cardExpansions.Contains(c.expansionType)); } } private void RemoveFromCardStorageShelves() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) foreach (List<CompactCardDataAmount> item in CSingleton<ShelfManager>.Instance.m_CardStorageShelfList.Select((InteractableCardStorageShelf b) => b.m_CompactCardDataAmountList)) { foreach (CompactCardDataAmount item2 in item.Where((CompactCardDataAmount c) => cardExpansions.Contains(c.expansionType))) { CardData cardData = CPlayerData.GetCardData(item2.cardSaveIndex, item2.expansionType, item2.isDestiny); removedCards[cardData] = removedCards.GetValueOrDefault(cardData) + item2.amount; } item.RemoveAll((CompactCardDataAmount c) => cardExpansions.Contains(c.expansionType)); } } private void RemoveFromCardPackageBoxes() { foreach (InteractablePackagingBox_Card packageBox in RestockManager.GetCardPackagingBoxList().ToList()) { packageBox.m_StoredCardList.RemoveAll(delegate(InteractableCard3d i) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) CardData cardData = i.m_Card3dUI.m_CardUI.m_CardData; if (cardExpansions.Contains(cardData.expansionType)) { removedCards[cardData] = removedCards.GetValueOrDefault(cardData) + 1; packageBox.m_StoredCardDataList.Remove(cardData); ((InteractableObject)i).OnDestroyed(); return true; } return false; }); if (packageBox.m_StoredCardList.Count == 0) { CSingleton<ShelfManager>.Instance.m_SpawnedPackageBoxCardList.Remove(packageBox); ((InteractableObject)packageBox).OnDestroyed(); } } } private void RemoveFromCardGrading() { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown foreach (GradeCardSubmitSet item in CPlayerData.m_GradeCardInProgressList.ToList()) { item.m_CardDataList.RemoveAll(delegate(CardData cardData) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (!cardExpansions.Contains(cardData.expansionType)) { return false; } removedCards[cardData] = removedCards.GetValueOrDefault(cardData) + 1; return true; }); if (item.m_CardDataList.Count == 0) { CPlayerData.m_GradeCardInProgressList.Remove(item); } } GradeCardSubmitSet currentGradeCardSubmitSet = CPlayerData.m_CurrentGradeCardSubmitSet; if (currentGradeCardSubmitSet?.m_CardDataList == null) { return; } for (int num = 0; num < currentGradeCardSubmitSet.m_CardDataList.Count; num++) { if (cardExpansions.Contains(currentGradeCardSubmitSet.m_CardDataList[num].expansionType)) { currentGradeCardSubmitSet.m_CardDataList[num] = new CardData(); } } } private void RemoveFromDecks() { foreach (DeckCompactCardDataList deckCompactCardData in CPlayerData.m_DeckCompactCardDataList) { deckCompactCardData.compactCardDataAmountList.RemoveAll((CompactCardDataAmount c) => cardExpansions.Contains(c.expansionType)); } } private void RemoveFromAutoPackOpeners() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) foreach (List<CompactCardDataAmount> item in CSingleton<ShelfManager>.Instance.m_AutoPackOpenerList.Select((InteractableAutoPackOpener p) => p.m_CompactCardDataAmountList)) { foreach (CompactCardDataAmount item2 in item.Where((CompactCardDataAmount c) => cardExpansions.Contains(c.expansionType))) { CardData cardData = CPlayerData.GetCardData(item2.cardSaveIndex, item2.expansionType, item2.isDestiny); removedCards[cardData] = removedCards.GetValueOrDefault(cardData) + item2.amount; } item.RemoveAll((CompactCardDataAmount c) => cardExpansions.Contains(c.expansionType)); } } private void RemoveFromHeldCards() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) InteractionPlayerController instance = CSingleton<InteractionPlayerController>.Instance; if (!Object.op_Implicit((Object)(object)instance)) { return; } List<InteractableCard3d> currentHoldingCard3dList = instance.m_CurrentHoldingCard3dList; bool flag = false; for (int num = Math.Min(currentHoldingCard3dList.Count, CPlayerData.m_HoldCardDataList.Count) - 1; num >= 0; num--) { CardData val = CPlayerData.m_HoldCardDataList[num]; if (cardExpansions.Contains(val.expansionType)) { removedCards[val] = removedCards.GetValueOrDefault(val) + 1; ((InteractableObject)currentHoldingCard3dList[num]).OnDestroyed(); currentHoldingCard3dList.RemoveAt(num); CPlayerData.m_HoldCardDataList.RemoveAt(num); flag = true; } } if (!flag) { return; } if (currentHoldingCard3dList.Count == 0) { instance.ExitHoldCardMode(); return; } for (int i = 0; i < currentHoldingCard3dList.Count; i++) { ((InteractableObject)currentHoldingCard3dList[i]).LerpToTransform(instance.m_HoldCardPosList[i], instance.m_HoldCardPosList[i], 3f); } } } internal class CustomerRemovalStrategy(HashSet<ECardExpansionType> cardExpansions, HashSet<EItemType> items) : IAssetRemovalStrategy { public RemovalResult RemoveAssets() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) int num = 0; float num2 = 0f; foreach (Customer customer in CSingleton<CustomerManager>.Instance.m_CustomerList) { if (!customer.IsActive() || !IsCarryingBundleContent(customer)) { continue; } foreach (Item item in from i in customer.m_ItemInBagList.Concat(customer.m_ItemInHandList) where items.Contains(i.m_ItemType) select i) { num++; num2 += RestockManager.GetItemMarketPrice(item.m_ItemType); } foreach (CardData item2 in from c in customer.m_CardInBagList select c.m_Card3dUI.m_CardUI.m_CardData into c where cardExpansions.Contains(c.expansionType) select c) { num++; num2 += CPlayerData.GetCardMarketPrice(item2); } customer.DeactivateCustomer(); } return RemovalResult.Success(num, num2); } private bool IsCarryingBundleContent(Customer customer) { if (!customer.m_ItemInBagList.Concat(customer.m_ItemInHandList).Any((Item i) => items.Contains(i.m_ItemType)) && !customer.m_CardInBagList.Any((InteractableCard3d c) => cardExpansions.Contains(c.m_Card3dUI.m_CardUI.m_CardData.expansionType))) { return HasBundleTournamentPrize(customer); } return true; } private bool HasBundleTournamentPrize(Customer customer) { CustomerTournamentData customerTournamentData = customer.GetCustomerTournamentData(); if (customerTournamentData == null) { return false; } if (customerTournamentData.m_TargetPrizeData == null || !customerTournamentData.m_TargetPrizeData.IsBundleContent(cardExpansions, items)) { return customerTournamentData.m_PrizeDataList.Any((TournamentPrizeData p) => p.IsBundleContent(cardExpansions, items)); } return true; } } internal class DecoRemovalStrategy(HashSet<EDecoObject> decoTypes, string bundleId) : IAssetRemovalStrategy { public RemovalResult RemoveAssets() { //IL_0018: 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) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) float totalValue = 0f; int totalDecoCount = 0; foreach (EDecoObject item in decoTypes) { if (EplRuntimeData.Services.SaveDataManager.TryGetSaveData<EDecoObject, DecoSaveData>(item, out DecoSaveData data)) { totalDecoCount += data.ItemCount; totalValue += InventoryBase.GetItemDecoPurchaseData(item).price * (float)data.ItemCount; data.Reset(); } } ResetTextureSaveData((DecoFlags)3, EplRuntimeData.Assets.DecoLibrary.firstInsertedCeilingTexture, CSingleton<InventoryBase>.Instance.m_ObjectData_SO.m_CeilingDecoDataList, ref totalDecoCount, ref totalValue); ResetTextureSaveData((DecoFlags)1, EplRuntimeData.Assets.DecoLibrary.firstInsertedFloorTexture, CSingleton<InventoryBase>.Instance.m_ObjectData_SO.m_FloorDecoDataList, ref totalDecoCount, ref totalValue); ResetTextureSaveData((DecoFlags)2, EplRuntimeData.Assets.DecoLibrary.firstInsertedWallTexture, CSingleton<InventoryBase>.Instance.m_ObjectData_SO.m_WallDecoDataList, ref totalDecoCount, ref totalValue); return RemovalResult.Success(totalDecoCount, totalValue); } private unsafe void ResetTextureSaveData(DecoFlags category, int? firstInsertedIndex, List<ShopDecoData> decoDataList, ref int totalDecoCount, ref float totalValue) { if (!firstInsertedIndex.HasValue) { return; } string category2 = ((object)(*(DecoFlags*)(&category))/*cast due to .constrained prefix*/).ToString(); BundleAssetTracker bundleAssetTracker = EplRuntimeData.BundleAssetTracker; SaveDataService saveDataManager = EplRuntimeData.Services.SaveDataManager; for (int i = firstInsertedIndex.Value; i < decoDataList.Count; i++) { string name = decoDataList[i].name; if (!(bundleAssetTracker.GetBundleIdFor(category2, name) != bundleId) && saveDataManager.TryGetSaveData<DecoSaveData>(category2, name, out DecoSaveData data)) { totalDecoCount += data.ItemCount; totalValue += decoDataList[i].price * (float)data.ItemCount; data.Reset(); } } } } internal interface IAssetRemovalStrategy { RemovalResult RemoveAssets(); } internal class InteractableObjectRemovalStrategy(HashSet<EObjectType> furnitures, HashSet<EDecoObject> decos) : IAssetRemovalStrategy { private readonly Dictionary<EItemType, int> itemsToRestock = new Dictionary<EItemType, int>(); public RemovalResult RemoveAssets() { //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: 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_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) itemsToRestock.Clear(); int num = 0; float num2 = 0f; List<InteractableObject> list = (from Transform t in (IEnumerable)CSingleton<ShelfManager>.Instance.m_ShelfParentGrp select ((Component)t).GetComponent<InteractableObject>() into i where i != null && (furnitures.Contains(i.m_ObjectType) || decos.Contains(i.m_DecoObjectType)) select i).ToList(); FurnitureLibrary furnitureLibrary = EplRuntimeData.Assets.FurnitureLibrary; foreach (InteractableObject item in list) { InteractableDecoration val = (InteractableDecoration)(object)((item is InteractableDecoration) ? item : null); if (val == null) { InteractableBulkDonationBox val2 = (InteractableBulkDonationBox)(object)((item is InteractableBulkDonationBox) ? item : null); if (val2 == null) { InteractableCardStorageShelf val3 = (InteractableCardStorageShelf)(object)((item is InteractableCardStorageShelf) ? item : null); if (val3 == null) { CardItemCombiShelf val4 = (CardItemCombiShelf)(object)((item is CardItemCombiShelf) ? item : null); if (val4 == null) { CardShelf val5 = (CardShelf)(object)((item is CardShelf) ? item : null); if (val5 == null) { InteractableWorkbench val6 = (InteractableWorkbench)(object)((item is InteractableWorkbench) ? item : null); if (val6 == null) { Shelf val7 = (Shelf)(object)((item is Shelf) ? item : null); if (val7 == null) { WarehouseShelf val8 = (WarehouseShelf)(object)((item is WarehouseShelf) ? item : null); ModFurniturePurchaseData value; if (val8 != null) { EmptyWarehouseShelf(val8); num2 += furnitureLibrary.FurnitureData[((InteractableObject)val8).m_ObjectType].BaseFurniturePurchaseData.price; } else if (furnitureLibrary.FurnitureData.TryGetValue(item.m_ObjectType, out value)) { num2 += value.BaseFurniturePurchaseData.price; } else if (decos.Contains(item.m_DecoObjectType)) { num2 += InventoryBase.GetItemDecoPurchaseData(item.m_DecoObjectType).price; } } else { EmptyShelf(val7); num2 += furnitureLibrary.FurnitureData[((InteractableObject)val7).m_ObjectType].BaseFurniturePurchaseData.price; } } else { EmptyWorkbench(val6); num2 += furnitureLibrary.FurnitureData[((InteractableObject)val6).m_ObjectType].BaseFurniturePurchaseData.price; } } else { EmptyCardShelf(val5); num2 += furnitureLibrary.FurnitureData[((InteractableObject)val5).m_ObjectType].BaseFurniturePurchaseData.price; } } else { EmptyCombiShelf(val4); num2 += furnitureLibrary.FurnitureData[((InteractableObject)val4).m_ObjectType].BaseFurniturePurchaseData.price; } } else { EmptyCardStorageShelf(val3); num2 += furnitureLibrary.FurnitureData[((InteractableObject)val3).m_ObjectType].BaseFurniturePurchaseData.price; } } else { EmptyBulkDonationBox(val2); num2 += furnitureLibrary.FurnitureData[((InteractableObject)val2).m_ObjectType].BaseFurniturePurchaseData.price; } } else { num2 += InventoryBase.GetItemDecoPurchaseData(((InteractableObject)val).m_DecoObjectType).price; } if (item.m_IsBoxedUp) { ((InteractableObject)item.m_InteractablePackagingBox_Shelf).OnDestroyed(); } else { item.OnDestroyed(); } num++; } RestockItems(); return RemovalResult.Success(num, num2); } private void EmptyWarehouseShelf(WarehouseShelf warehouseShelf) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) foreach (ShelfCompartment item in from p in warehouseShelf.m_StorageCompartmentList.SelectMany((InteractableStorageCompartment s) => s.m_ShelfCompartment.m_InteractablePackagingBoxList) select p.m_ItemCompartment) { itemsToRestock[item.m_ItemType] = itemsToRestock.GetValueOrDefault(item.m_ItemType) + item.m_StoredItemList.Count; } if (!StoredBoxRecordAccess.IsAvailable) { return; } foreach (ShelfCompartment item2 in warehouseShelf.m_StorageCompartmentList.Select((InteractableStorageCompartment s) => s.m_ShelfCompartment)) { int num = StoredBoxRecordAccess.RecordCount(item2); for (int num2 = 0; num2 < num; num2++) { object record = StoredBoxRecordAccess.Peek(item2, num2); EItemType key = StoredBoxRecordAccess.ItemTypeOf(record); itemsToRestock[key] = itemsToRestock.GetValueOrDefault(key) + StoredBoxRecordAccess.AmountOf(record); } } } private void EmptyCombiShelf(CardItemCombiShelf combiShelf) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) EmptyCardShelf((CardShelf)(object)combiShelf); foreach (ShelfCompartment shelfItemCompartment in combiShelf.GetShelfItemCompartmentList()) { itemsToRestock[shelfItemCompartment.m_ItemType] = itemsToRestock.GetValueOrDefault(shelfItemCompartment.m_ItemType) + shelfItemCompartment.m_StoredItemList.Count; } } private void EmptyShelf(Shelf shelf) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) foreach (ShelfCompartment itemCompartment in ((InteractableObject)shelf).m_ItemCompartmentList) { itemsToRestock[itemCompartment.m_ItemType] = itemsToRestock.GetValueOrDefault(itemCompartment.m_ItemType) + itemCompartment.m_StoredItemList.Count; } } private void EmptyWorkbench(InteractableWorkbench interactableWorkbench) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) foreach (Item storedItem in interactableWorkbench.m_StoredItemList) { itemsToRestock[storedItem.m_ItemType] = itemsToRestock.GetValueOrDefault(storedItem.m_ItemType) + 1; } } private static void EmptyCardShelf(CardShelf cardShelf) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) foreach (InteractableCardCompartment item in cardShelf.m_CardCompartmentList.Where((InteractableCardCompartment c) => c.m_StoredCardList.Count > 0)) { foreach (InteractableCardPriceTag interactablePriceTag in item.m_InteractablePriceTagList) { interactablePriceTag.SetPriceChecked(false); } CardData cardData = item.m_StoredCardList[0].m_Card3dUI.m_CardUI.m_CardData; item.m_StoredCardList[0].SetIsDisplayedOnShelf(false); item.m_StoredCardList[0].SetTargetRotation(Quaternion.identity); item.m_StoredCardList.RemoveAt(0); item.SetPriceTagCardData((CardData)null); item.SetPriceTagVisibility(false); if (item.m_CardShelf?.m_ElectronicCardListener != null) { item.m_CardShelf.m_ElectronicCardListener.UpdateCardUI((CardData)null); } CPlayerData.AddCard(cardData, 1); } } private static void EmptyCardStorageShelf(InteractableCardStorageShelf interactableCardStorageShelf) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) foreach (CompactCardDataAmount compactCardDataAmount in interactableCardStorageShelf.m_CompactCardDataAmountList) { CPlayerData.AddCard(CPlayerData.GetCardData(compactCardDataAmount.cardSaveIndex, compactCardDataAmount.expansionType, compactCardDataAmount.isDestiny), compactCardDataAmount.amount); } interactableCardStorageShelf.m_CompactCardDataAmountList.Clear(); } private static void EmptyBulkDonationBox(InteractableBulkDonationBox interactableBulkDonationBox) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) foreach (CompactCardDataAmount compactCardDataAmount in interactableBulkDonationBox.m_CompactCardDataAmountList) { CPlayerData.AddCard(CPlayerData.GetCardData(compactCardDataAmount.cardSaveIndex, compactCardDataAmount.expansionType, compactCardDataAmount.isDestiny), compactCardDataAmount.amount); } interactableBulkDonationBox.m_CompactCardDataAmountList.Clear(); } private void RestockItems() { //IL_0021: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<EItemType, int> item in itemsToRestock) { item.Deconstruct(out var key, out var value); EItemType val = key; int num2; int num = (num2 = value); int maxItemCountInBox = RestockManager.GetMaxItemCountInBox(val, true); int num3 = Mathf.CeilToInt((float)num / (float)maxItemCountInBox); for (int i = 0; i < num3; i++) { int num4 = ((num2 >= maxItemCountInBox) ? maxItemCountInBox : num2); RestockManager.SpawnPackageBoxItem(val, num4, true); num2 -= num4; } } } } internal class ItemRemovalStrategy(HashSet<EItemType> items) : IAssetRemovalStrategy { private List<Item> removedItems = new List<Item>(); public RemovalResult RemoveAssets() { removedItems = new List<Item>(); RemoveFromShelves(); RemoveFromPackagingBoxes(); RemoveFromWorkbenches(); RemoveFromAutoPackOpeners(); RemoveFromPlayTables(); RemoveFromHeldItems(); float num = RemoveFromRestockQueue(); (int Count, float Value) tuple = RemoveFromStoredBoxRecords(); int item = tuple.Count; float item2 = tuple.Value; float totalValue = removedItems.Select((Item i) => RestockManager.GetItemMarketPrice(i.m_ItemType)).Sum() + num + item2; foreach (Item removedItem in removedItems) { ItemSpawnManager.DisableItem(removedItem); } return RemovalResult.Success(removedItems.Count + item, totalValue); } private (int Count, float Value) RemoveFromStoredBoxRecords() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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) if (!StoredBoxRecordAccess.IsAvailable) { return (Count: 0, Value: 0f); } int num = 0; float num2 = 0f; foreach (ShelfCompartment warehouseCompartment in StoredBoxRecordAccess.GetWarehouseCompartments()) { if (!Object.op_Implicit((Object)(object)warehouseCompartment) || !HasMatchingRecord(warehouseCompartment)) { continue; } List<object> list = new List<object>(); object record; while (StoredBoxRecordAccess.TryPop(warehouseCompartment, out record)) { EItemType val = StoredBoxRecordAccess.ItemTypeOf(record); if (!items.Contains(val)) { list.Add(record); continue; } num++; num2 += RestockManager.GetItemMarketPrice(val) * (float)StoredBoxRecordAccess.AmountOf(record); } for (int num3 = list.Count - 1; num3 >= 0; num3--) { StoredBoxRecordAccess.Add(warehouseCompartment, list[num3]); } if (warehouseCompartment.m_ItemAmount == 0) { warehouseCompartment.RemoveLabel(false); } } return (Count: num, Value: num2); } private bool HasMatchingRecord(ShelfCompartment compartment) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) int num = StoredBoxRecordAccess.RecordCount(compartment); for (int i = 0; i < num; i++) { if (items.Contains(StoredBoxRecordAccess.ItemTypeOf(StoredBoxRecordAccess.Peek(compartment, i)))) { return true; } } return false; } private void RemoveFromPackagingBoxes() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) foreach (InteractablePackagingBox_Item item in RestockManager.GetItemPackagingBoxList().ToList()) { if (!items.Contains(item.m_ItemType) && !items.Contains(item.m_ItemCompartment.m_ItemType)) { continue; } if (item.m_IsStored) { item.m_BoxStoredCompartment.RemoveBox(item); if (item.m_BoxStoredCompartment.m_ItemAmount == 0) { item.m_BoxStoredCompartment.RemoveLabel(false); } } removedItems.AddRange(item.m_ItemCompartment.m_StoredItemList); EmptyItemCompartment(item.m_ItemCompartment); ((InteractableObject)item).OnDestroyed(); } } private void RemoveFromShelves() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) ShelfManager instance = CSingleton<ShelfManager>.Instance; foreach (ShelfCompartment item in instance.m_ShelfList.SelectMany((Shelf s) => ((InteractableObject)s).m_ItemCompartmentList).Concat(instance.m_CardItemCombiShelfList.SelectMany((CardItemCombiShelf s) => s.GetShelfItemCompartmentList()))) { if (items.Contains(item.m_ItemType) && item.m_ItemAmount != 0) { removedItems.AddRange(item.m_StoredItemList); EmptyItemCompartment(item); } } } private void RemoveFromWorkbenches() { foreach (InteractableWorkbench workbench in CSingleton<ShelfManager>.Instance.m_WorkbenchList) { foreach (Item item in workbench.m_StoredItemList.Where((Item i) => items.Contains(i.m_ItemType)).ToList()) { removedItems.Add(item); workbench.RemoveItem(item); } } } private void RemoveFromAutoPackOpeners() { foreach (InteractableAutoPackOpener autoPackOpener in CSingleton<ShelfManager>.Instance.m_AutoPackOpenerList) { List<Item> list = autoPackOpener.m_StoredItemList.Where((Item i) => items.Contains(i.m_ItemType)).ToList(); if (list.Count == 0) { continue; } foreach (Item item in list) { removedItems.Add(item); autoPackOpener.RemoveItem(item); } if (Object.op_Implicit((Object)(object)autoPackOpener.m_AutoCardOpenerUI)) { autoPackOpener.m_AutoCardOpenerUI.UpdatePackCountText(autoPackOpener.m_StoredItemList.Count, autoPackOpener.m_MaxPackCount); } } } private void RemoveFromPlayTables() { //IL_0035: 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_005b: Unknown result type (might be due to invalid IL or missing references) foreach (InteractablePlayTable playTable in CSingleton<ShelfManager>.Instance.m_PlayTableList) { for (int i = 0; i < playTable.m_TableGameItemSetDataList.Count; i++) { TableGameItemSetData val = playTable.m_TableGameItemSetDataList[i]; if (val != null && (items.Contains(val.playMatType) || items.Contains(val.deckBoxType) || items.Contains(val.comicBookType))) { playTable.m_TableGameItemSetDataList[i] = null; } } } } private void RemoveFromHeldItems() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) InteractionPlayerController instance = CSingleton<InteractionPlayerController>.Instance; if (!Object.op_Implicit((Object)(object)instance)) { return; } List<Item> holdItemList = instance.m_HoldItemList; bool flag = false; for (int num = holdItemList.Count - 1; num >= 0; num--) { if (items.Contains(holdItemList[num].m_ItemType)) { removedItems.Add(holdItemList[num]); holdItemList.RemoveAt(num); flag = true; } } if (!flag) { return; } CPlayerData.m_HoldItemTypeList.RemoveAll((EItemType t) => items.Contains(t)); if (holdItemList.Count == 0) { instance.SetCurrentGameState((EGameState)0); instance.m_IsHoldItemMode = false; return; } for (int num2 = 0; num2 < holdItemList.Count; num2++) { holdItemList[num2].SmoothLerpToTransform(instance.m_HoldCardPackPosList[num2], instance.m_HoldCardPackPosList[num2], true); } } private float RemoveFromRestockQueue() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) RestockManager instance = CSingleton<RestockManager>.Instance; float num = 0f; for (int num2 = CPlayerData.m_SpawnBoxRestockIndexWaitingList.Count - 1; num2 >= 0; num2--) { RestockData restockData = InventoryBase.GetRestockData(CPlayerData.m_SpawnBoxRestockIndexWaitingList[num2]); if (restockData != null && items.Contains(restockData.itemType)) { int maxItemCountInBox = RestockManager.GetMaxItemCountInBox(restockData.itemType, restockData.isBigBox); num += RestockManager.GetItemMarketPrice(restockData.itemType) * (float)maxItemCountInBox * (float)CPlayerData.m_SpawnBoxItemCountWaitingList[num2]; CPlayerData.m_SpawnBoxRestockIndexWaitingList.RemoveAt(num2); CPlayerData.m_SpawnBoxItemCountWaitingList.RemoveAt(num2); if (num2 < instance.m_SpawnBoxItemWaitingList.Count) { instance.m_SpawnBoxItemWaitingList.RemoveAt(num2); } } } return num; } private static void EmptyItemCompartment(ShelfCompartment itemCompartment) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) itemCompartment.m_StoredItemList.Clear(); itemCompartment.m_ItemAmount = 0; itemCompartment.m_ItemType = (EItemType)(-1); itemCompartment.RemoveLabel(false); } } internal class RemovalResult { internal bool IsSuccess { get; private set; } internal int AssetsRemoved { get; private set; } internal float TotalValue { get; private set; } internal string ErrorMessage { get; private set; } = string.Empty; private RemovalResult() { } internal static RemovalResult Success(int assetsRemoved, float totalValue) { return new RemovalResult { IsSuccess = true, AssetsRemoved = assetsRemoved, TotalValue = totalValue }; } internal static RemovalResult Failure(string msg) { return new RemovalResult { IsSuccess = false, ErrorMessage = msg }; } internal static RemovalResult Empty() { return new RemovalResult { IsSuccess = true }; } internal void Merge(RemovalResult other) { IsSuccess = IsSuccess && other.IsSuccess; AssetsRemoved += other.AssetsRemoved; TotalValue += other.TotalValue; if (!string.IsNullOrWhiteSpace(other.ErrorMessage)) { ErrorMessage = (string.IsNullOrWhiteSpace(ErrorMessage) ? other.ErrorMessage : (ErrorMessage + "\n" + other.ErrorMessage)); } } } internal static class StoredBoxRecordAccess { private static readonly MethodInfo? getWarehouseCompartmentList = AccessTools.Method(typeof(RestockManager), "GetWarehouseCompartmentList", (Type[])null, (Type[])null); private static readonly MethodInfo? getRecordCount = AccessTools.Method(typeof(ShelfCompartment), "GetStoredBoxRecordCount", (Type[])null, (Type[])null); private static readonly MethodInfo? peekRecord = AccessTools.Method(typeof(ShelfCompartment), "PeekStoredBoxRecord", (Type[])null, (Type[])null); private static readonly MethodInfo? tryPopRecord = AccessTools.Method(typeof(ShelfCompartment), "TryPopLastStoredBoxRecord", (Type[])null, (Type[])null); private static readonly MethodInfo? addRecord = AccessTools.Method(typeof(ShelfCompartment), "AddStoredBoxRecord", (Type[])null, (Type[])null); private static readonly FieldInfo? itemTypeField = AccessTools.Field(GameBuild.StoredBoxRecordType, "itemType"); private static readonly FieldInfo? amountField = AccessTools.Field(GameBuild.StoredBoxRecordType, "amount"); internal static bool IsAvailable { get { if (GameBuild.HasStoredBoxRecords && (object)getWarehouseCompartmentList != null && (object)getRecordCount != null && (object)peekRecord != null && (object)tryPopRecord != null && (object)addRecord != null && (object)itemTypeField != null) { return (object)amountField != null; } return false; } } internal static List<ShelfCompartment> GetWarehouseCompartments() { return (getWarehouseCompartmentList.Invoke(null, null) as List<ShelfCompartment>) ?? new List<ShelfCompartment>(); } internal static int RecordCount(ShelfCompartment compartment) { return (int)getRecordCount.Invoke(compartment, null); } internal static object Peek(ShelfCompartment compartment, int index) { return peekRecord.Invoke(compartment, new object[1] { index }); } internal static bool TryPop(ShelfCompartment compartment, out object? record) { object[] array = new object[1]; bool flag = (bool)tryPopRecord.Invoke(compartment, array); record = (flag ? array[0] : null); return flag; } internal static void Add(ShelfCompartment compartment, object record) { addRecord.Invoke(compartment, new object[1] { record }); } internal static EItemType ItemTypeOf(object record) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return (EItemType)itemTypeField.GetValue(record); } internal static int AmountOf(object record) { return (int)amountField.GetValue(record); } } internal static class TournamentPrizeDataExtensions { internal static bool IsBundleContent(this TournamentPrizeData prize, HashSet<ECardExpansionType> cardExpansions, HashSet<EItemType> items) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!prize.IsCard() || !cardExpansions.Contains(prize.m_CardData.expansionType)) { if (prize.IsItem()) { return items.Contains(prize.m_ItemType); } return false; } return true; } } internal class TournamentRemovalStrategy(HashSet<ECardExpansionType> cardExpansions, HashSet<EItemType> items) : IAssetRemovalStrategy { public RemovalResult RemoveAssets() { int num = 0; float num2 = 0f; TournamentData tournamentData = CPlayerData.m_TournamentData; if (tournamentData != null) { foreach (TournamentPrizeDataList prizeData in tournamentData.m_PrizeDataList) { foreach (TournamentPrizeData item in prizeData.m_PrizeDataList.Where((TournamentPrizeData p) => p.IsBundleContent(cardExpansions, items))) { num += item.m_Count; num2 += GetPrizeValue(item); } prizeData.m_PrizeDataList.RemoveAll((TournamentPrizeData p) => p.IsBundleContent(cardExpansions, items)); } } foreach (CustomerTournamentData item2 in from d in CSingleton<ShelfManager>.Instance.m_PlayTableList.SelectMany((InteractablePlayTable t) => t.m_CustomerTournamentDataList).Append(CPlayerData.m_PlayerTournamentData) where d != null select d) { item2.m_PrizeDataList.RemoveAll((TournamentPrizeData p) => p.IsBundleContent(cardExpansions, items)); if (item2.m_TargetPrizeData != null && item2.m_TargetPrizeData.IsBundleContent(cardExpansions, items)) { item2.m_TargetPrizeData = null; } } return RemovalResult.Success(num, num2); } private static float GetPrizeValue(TournamentPrizeData prize) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (!prize.IsCard()) { return RestockManager.GetItemMarketPrice(prize.m_ItemType) * (float)prize.m_Count; } return CPlayerData.GetCardMarketPrice(prize.m_CardData) * (float)prize.m_Count; } } } namespace EnhancedPrefabLoader.Core.Trading { internal class CardTradeManager { private readonly CardSelectionService cardSelectionService = new CardSelectionService(); private readonly CardTradePricingService cardTradePricingService = new CardTradePricingService(); private readonly CardTradeUIManager cardTradeUIManager = new CardTradeUIManager(); public void SetCustomer(CustomerTradeCardScreen screen, Customer customer, CustomerTradeData customerTradeData) { CSingleton<CustomerManager>.Instance.m_IsPlayerTrading = true; screen.m_CurrentCustomer = customer; screen.m_HasAccepted = false; screen.m_IsTrading = customerTradeData?.m_IsTrading ?? (Random.Range(0, 100) < Math.Min(40, CPlayerData.m_ShopLevel)); screen.m_CardData_L = (CardData)((customerTradeData != null) ? ((object)customerTradeData.m_CardData_L) : ((object)cardSelectionService.SelectRandomCard())); if (screen.m_IsTrading) { SetupTradeMode(screen, customerTradeData); } else { SetupSellMode(screen, customerTradeData); } cardTradeUIManager.UpdateUI(screen); } private void SetupTradeMode(CustomerTradeCardScreen screen, CustomerTradeData customerTradeData) { screen.m_CardData_R = (CardData)((customerTradeData != null) ? ((object)customerTradeData.m_CardData_R) : ((object)cardSelectionService.SelectPlayerCard(screen.m_CardData_L, customerTradeData))); if (screen.m_CardData_R == null) { screen.m_IsTrading = false; SetupSellMode(screen, customerTradeData); } } private void SetupSellMode(CustomerTradeCardScreen screen, CustomerTradeData customerTradeData) { cardTradePricingService.CalculateAskingPrice(screen, screen.m_CardData_L, customerTradeData); if (customerTradeData != null) { screen.m_PriceSet = customerTradeData.m_PriceSet; screen.m_LastPriceSet = customerTradeData.m_LastPriceSet; } else { screen.OnInputTextUpdated("0"); } } } internal class CardTradePricingService { private static readonly (float threshold, float minBonus, float maxBonus)[] PriceTiers = new(float, float, float)[9] { (10f, 0f, 0.03f), (20f, 0f, 0.04f), (100f, 0.01f, 0.05f), (300f, 0.01f, 0.06f), (500f, 0.01f, 0.08f), (1000f, 0.01f, 0.1f), (2000f, 0.02f, 0.11f), (5000f, 0.03f, 0.12f), (8000f, 0.03f, 0.12f) }; public void CalculateAskingPrice(CustomerTradeCardScreen screen, CardData customerCard, CustomerTradeData customerTradeData) { screen.m_SellCardMarketPrice = CPlayerData.GetCardMarketPrice(customerCard); if (customerTradeData != null) { screen.m_SellCardAskPrice = customerTradeData.m_SellCardAskPrice; screen.m_MaxDeclineCount = customerTradeData.m_MaxDeclineCount; screen.m_DeclineCount = customerTradeData.m_DeclineCount; } else { screen.m_SellCardAskPrice = CalculateInitialAskingPrice(screen.m_SellCardMarketPrice); screen.m_MaxDeclineCount = Random.Range(0, 5); screen.m_DeclineCount = 0; } } private float CalculateInitialAskingPrice(float marketPrice) { float num = Random.Range(0.7f, 1.2f); (float, float, float)[] priceTiers = PriceTiers; for (int i = 0; i < priceTiers.Length; i++) { (float, float, float) tuple = priceTiers[i]; if (marketPrice > tuple.Item1) { num += Random.Range(tuple.Item2, tuple.Item3); } } return num * marketPrice; } } internal class CardTradeUIManager { public void UpdateUI(CustomerTradeCardScreen screen) { SetTradingScreenText(screen); UpdateScreenGrpVisibility(screen); SetPriceTexts(screen); UpdateCardDisplays(screen); UpdateButtonVisibility(screen); } private void SetTradingScreenText(CustomerTradeCardScreen screen) { List<string> list = (screen.m_IsTrading ? screen.m_CustomerTradeCardTextList : screen.m_CustomerSellCardTextList); ((TMP_Text)screen.m_CustomerTopText).text = LocalizationManager.GetTranslation("CustomerTrade/" + list[Random.Range(0, list.Count)], true, 0, true, false, (GameObject)null, (string)null, true); screen.m_CustomerTopTextAnim.Rewind(); screen.m_CustomerTopTextAnim.Play(); } private void UpdateScreenGrpVisibility(CustomerTradeCardScreen screen) { screen.m_CustomerTradingText.SetActive(screen.m_IsTrading); screen.m_CustomerSellingText.SetActive(!screen.m_IsTrading); screen.m_TradeGrp_R.SetActive(screen.m_IsTrading); screen.m_SellGrp_R.SetActive(!screen.m_IsTrading); } private void SetPriceTexts(CustomerTradeCardScreen screen) { string translation = LocalizationManager.GetTranslation("Market Price", true, 0, true, false, (GameObject)null, (string)null, true); string priceString = GameInstance.GetPriceString(CPlayerData.GetCardMarketPrice(screen.m_CardData_L), false, true, false, "F2"); string translation2 = LocalizationManager.GetTranslation("Ask Price", true, 0, true, false, (GameObject)null, (string)null, true); string priceString2 = GameInstance.GetPriceString(screen.m_SellCardAskPrice, false, true, false, "F2"); if (screen.m_IsTrading) { ((TMP_Text)screen.m_MarketPrice_L).text = translation + " : " + priceString; return; } ((TMP_Text)screen.m_MarketPrice_L).text = translation2 + " : " + priceString2 + "\n" + translation + " : " + priceString; screen.m_CardUI_Buying.SetCardUI(screen.m_CardData_L); } private void UpdateButtonVisibility(CustomerTradeCardScreen screen) { screen.m_AcceptBtn.SetActive(true); screen.m_CancelBtn.SetActive(true); screen.m_LetMeThinkBtn.SetActive(true); screen.m_DoneBtn.SetActive(false); } private void UpdateCardDisplays(CustomerTradeCardScreen screen) { screen.m_IsNewUI.SetActive(CPlayerData.GetCardAmount(screen.m_CardData_L) == 0); screen.m_CardUI_L.SetCardUI(screen.m_CardData_L); screen.m_CardUI_Album_L.SetCardUI(screen.m_CardData_L); ((TMP_Text)screen.m_AlbumCardCount_L).text = GetCardCountText(screen.m_CardData_L); if (screen.m_IsTrading && screen.m_CardData_R != null) { screen.m_CardUI_R.SetCardUI(screen.m_CardData_R); screen.m_CardUI_Album.SetCardUI(screen.m_CardData_R); ((TMP_Text)screen.m_AlbumCardCount).text = GetCardCountText(screen.m_CardData_R); float cardMarketPrice = CPlayerData.GetCardMarketPrice(screen.m_CardData_R); string translation = LocalizationManager.GetTranslation("Market Price", true, 0, true, false, (GameObject)null, (string)null, true); ((TMP_Text)screen.m_MarketPrice_R).text = translation + " : " + GameInstance.GetPriceString(cardMarketPrice, false, true, false, "F2"); } } private string GetCardCountText(CardData card) { if (card.cardGrade <= 0) { return "X" + CPlayerData.GetCardAmount(card); } if (!CPlayerData.HasGradedCardInAlbum(card)) { return "X0"; } return "X1"; } } } namespace EnhancedPrefabLoader.Core.Shops { internal class CustomShopScreen : RestockItemScreen, ICustomShopScreen { private TextMeshProUGUI? pageUrl; private Image? pageLogo; private Image? pageHeader; private Image? pageBackground; private Color originalHeaderColor; private Color originalBackgroundColor; private string displayName = string.Empty; private readonly List<string> pageUrls = new List<string>(4) { "cards", "accessories", "figurines", "all" }; private List<List<RestockData>> pageItems = new List<List<RestockData>>(); private int currentPageIndex; internal bool IsOpen => ((UIScreenBase)this).m_ScreenGroup.activeSelf; public override void Awake() { //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Expected O, but got Unknown //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Expected O, but got Unknown
BepInEx/plugins/EnhancedPrefabLoader/Scripts.dll
Decompiled 3 weeks agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Video; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("Scripts")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("6.0.0.0")] [assembly: AssemblyInformationalVersion("6.0.0+35f34656f829a028d941f0dc922be3d2b18bf963")] [assembly: AssemblyProduct("Scripts")] [assembly: AssemblyTitle("Scripts")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("6.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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; } } } public class CeilingHangingInteractableObject : InteractableObject { private static readonly Collider[] overlapBuffer = (Collider[])(object)new Collider[1]; private static readonly int blockedMask = LayerMask.GetMask(new string[2] { "MoveStateBlockedArea", "Customer" }); private static readonly int shopValidMask = LayerMask.GetMask(new string[1] { "MoveStateValidArea" }); private static readonly int warehouseValidMask = LayerMask.GetMask(new string[1] { "MoveStateValidWarehouseArea" }); private static readonly int shopModelMask = LayerMask.GetMask(new string[1] { "ShopModel" }); public override void Update() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (!base.m_IsMovingObject) { return; } ((Component)this).transform.position = Vector3.Lerp(((Component)this).transform.position, base.m_TargetMoveObjectPosition, Time.deltaTime * 7.5f); bool flag = GetCollisionCount(blockedMask) == 0; if (flag) { if (base.m_PlaceObjectInShopOnly) { flag = GetCollisionCount(shopValidMask) > 0; } else if (base.m_PlaceObjectInWarehouseOnly) { flag = GetCollisionCount(warehouseValidMask) > 0; } } base.m_IsMovingObjectValidState = flag; ShelfManager.SetMoveObjectPreviewModelValidState(flag); } public override void OnPlacedMovedObject() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) CSingleton<InteractionPlayerController>.Instance.OnExitMoveObjectMode(); base.m_IsMovingObject = false; ((Component)this).gameObject.layer = base.m_OriginalLayer; ((Collider)base.m_BoxCollider).enabled = true; for (int i = 0; i < base.m_BoxColliderList.Count; i++) { ((Collider)base.m_BoxColliderList[i]).enabled = true; } Vector3 position = ((Component)base.m_PickupObjectMesh).transform.position; position.y += 0.2f; RaycastHit val = default(RaycastHit); if (Physics.Raycast(position, Vector3.up, ref val, 50f, shopModelMask)) { ((Component)this).transform.position = ((RaycastHit)(ref val)).point; } ((Component)base.m_MoveStateValidArea).gameObject.SetActive(true); ShelfManager.DisableMoveObjectPreviewMode(); if (Object.op_Implicit((Object)(object)base.m_BoxCollider)) { ((Component)CSingleton<ShelfManager>.Instance.m_MoveObjectCustomerBlocker).gameObject.SetActive(false); } if (!base.m_IsBoxedUp && Object.op_Implicit((Object)(object)base.m_InteractablePackagingBox_Shelf)) { if (Object.op_Implicit((Object)(object)base.m_Shelf_WorldUIGrp)) { ((Component)base.m_Shelf_WorldUIGrp).transform.position = ((Component)this).transform.position; } base.m_InteractablePackagingBox_Shelf.EmptyBoxShelf(); ((InteractableObject)base.m_InteractablePackagingBox_Shelf).OnDestroyed(); } if (Object.op_Implicit((Object)(object)base.m_Shelf_WorldUIGrp) && !base.m_IsBoxedUp) { ((Component)base.m_Shelf_WorldUIGrp).transform.position = ((Component)this).transform.position; ((Component)base.m_Shelf_WorldUIGrp).transform.rotation = ((Component)this).transform.rotation; } if (Object.op_Implicit((Object)(object)base.m_NavMeshCut)) { base.m_NavMeshCut.SetActive(false); base.m_NavMeshCut.SetActive(true); } } private int GetCollisionCount(int layerMask) { //IL_0006: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) return Physics.OverlapBoxNonAlloc(base.m_MoveStateValidArea.position, base.m_MoveStateValidArea.lossyScale / 2f, overlapBuffer, base.m_MoveStateValidArea.rotation, layerMask); } } namespace Scripts { public class CustomInteractableDeco : InteractableDecoration { public bool m_CanBePlacedOnFurniture; public bool m_IsDecorationCeiling; private static readonly Collider[] overlapBuffer = (Collider[])(object)new Collider[1]; private static readonly int blockedMask = LayerMask.GetMask(new string[2] { "MoveStateBlockedArea", "Customer" }); private static readonly int shopValidMask = LayerMask.GetMask(new string[1] { "MoveStateValidArea" }); private static readonly int warehouseValidMask = LayerMask.GetMask(new string[1] { "MoveStateValidWarehouseArea" }); private static readonly int anyValidMask = LayerMask.GetMask(new string[2] { "MoveStateValidArea", "MoveStateValidWarehouseArea" }); private static readonly int decorationBlockerMask = LayerMask.GetMask(new string[1] { "DecorationBlocker" }); private static readonly int decorationBlockedMask = LayerMask.GetMask(new string[1] { "DecorationMoveStateBlockedArea" }); public override void Update() { if (((InteractableObject)this).m_IsMovingObject) { UpdatePosition(); bool isMovingObjectValidState = (((InteractableObject)this).m_IsDecorationVertical ? IsValidWallPlacement() : (m_IsDecorationCeiling ? IsValidCeilingPlacement() : IsValidFloorOrFurniturePlacement())); ((InteractableObject)this).m_IsMovingObjectValidState = isMovingObjectValidState; ShelfManager.SetMoveObjectPreviewModelValidState(((InteractableObject)this).m_IsMovingObjectValidState); } } public override void OnPlacedMovedObject() { //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_010a: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) CSingleton<InteractionPlayerController>.Instance.OnExitMoveObjectMode(); ((Component)((InteractableObject)this).m_MoveStateValidArea).gameObject.SetActive(true); ((Component)this).gameObject.layer = ((InteractableObject)this).m_OriginalLayer; ((InteractableObject)this).m_IsMovingObject = false; if (((InteractableObject)this).m_BoxCollider != null) { ((Component)CSingleton<ShelfManager>.Instance.m_MoveObjectCustomerBlocker).gameObject.SetActive(false); ((Collider)((InteractableObject)this).m_BoxCollider).enabled = true; } foreach (BoxCollider boxCollider in ((InteractableObject)this).m_BoxColliderList) { ((Collider)boxCollider).enabled = true; } if (!m_CanBePlacedOnFurniture && !m_IsDecorationCeiling && !((InteractableObject)this).m_IsDecorationVertical) { Vector3 position = ((Component)this).transform.position; position.y = 0f; ((Component)this).transform.position = position; } else if (m_IsDecorationCeiling) { Vector3 position2 = ((Component)this).transform.position; Bounds bounds = ((Collider)((InteractableObject)this).m_BoxCollider).bounds; position2.y = 3f - (((Bounds)(ref bounds)).max.y - ((Component)this).transform.position.y); ((Component)this).transform.position = position2; } else if (((InteractableObject)this).m_IsDecorationVertical && ((InteractableObject)this).m_LastHitTransform != null) { ((InteractableObject)this).m_DecoPlaccedLockedRoomBlocker = null; DecoBlocker component = ((Component)((InteractableObject)this).m_LastHitTransform).GetComponent<DecoBlocker>(); if (component != null) { ((InteractableObject)this).m_DecoPlaccedLockedRoomBlocker = component.m_LockedRoomBlocker; ((InteractableObject)this).m_DecoPlaccedLockedRoomBlocker.AddToVerticalDecoObjectList((InteractableObject)(object)this); if (((InteractableObject)this).m_DecoPlaccedLockedRoomBlocker.m_MainRoomIndex != -1) { ((InteractableObject)this).m_IsVerticalSnapToWarehouseWall = false; ((InteractableObject)this).m_VerticalSnapWallIndex = ((InteractableObject)this).m_DecoPlaccedLockedRoomBlocker.m_MainRoomIndex; } else if (((InteractableObject)this).m_DecoPlaccedLockedRoomBlocker.m_StoreRoomIndex != -1) { ((InteractableObject)this).m_IsVerticalSnapToWarehouseWall = true; ((InteractableObject)this).m_VerticalSnapWallIndex = ((InteractableObject)this).m_DecoPlaccedLockedRoomBlocker.m_StoreRoomIndex; } } } ShelfManager.DisableMoveObjectPreviewMode(); if (!((InteractableObject)this).m_IsBoxedUp && ((InteractableObject)this).m_InteractablePackagingBox_Shelf != null) { if (((InteractableObject)this).m_Shelf_WorldUIGrp != null) { ((Component)((InteractableObject)this).m_Shelf_WorldUIGrp).transform.position = ((Component)this).transform.position; } ((InteractableObject)this).m_InteractablePackagingBox_Shelf.EmptyBoxShelf(); ((InteractableObject)((InteractableObject)this).m_InteractablePackagingBox_Shelf).OnDestroyed(); } if (((InteractableObject)this).m_Shelf_WorldUIGrp != null && !((InteractableObject)this).m_IsBoxedUp) { ((Component)((InteractableObject)this).m_Shelf_WorldUIGrp).transform.position = ((Component)this).transform.position; ((Component)((InteractableObject)this).m_Shelf_WorldUIGrp).transform.rotation = ((Component)this).transform.rotation; } if (((InteractableObject)this).m_NavMeshCut != null) { ((InteractableObject)this).m_NavMeshCut.SetActive(false); ((InteractableObject)this).m_NavMeshCut.SetActive(true); } } private void UpdatePosition() { //IL_000c: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) ((Component)this).transform.position = Vector3.Lerp(((Component)this).transform.position, ((InteractableObject)this).m_TargetMoveObjectPosition, Time.deltaTime * 7.5f); if (m_IsDecorationCeiling) { float y = ((Component)this).transform.position.y; Bounds bounds = ((Collider)((InteractableObject)this).m_BoxCollider).bounds; if (y + (((Bounds)(ref bounds)).max.y - ((Component)this).transform.position.y) > 3f) { Vector3 position = ((Component)this).transform.position; bounds = ((Collider)((InteractableObject)this).m_BoxCollider).bounds; position.y = 3f - (((Bounds)(ref bounds)).max.y - ((Component)this).transform.position.y); ((Component)this).transform.position = position; } } else if (((InteractableObject)this).m_IsDecorationVertical && ((InteractableObject)this).m_LastHitTransform != null) { Quaternion rotation = Quaternion.FromToRotation(Vector3.forward, ((InteractableObject)this).m_HitNormal); Vector3 eulerAngles = ((Quaternion)(ref rotation)).eulerAngles; eulerAngles.x = 0f; Quaternion rotation2 = ((Component)this).transform.rotation; eulerAngles.z = ((Quaternion)(ref rotation2)).eulerAngles.z; if (((InteractableObject)this).m_IsFlipped) { eulerAngles.y += 180f; } ((Quaternion)(ref rotation)).eulerAngles = eulerAngles; ((Component)this).transform.rotation = rotation; } } private bool IsValidFloorOrFurniturePlacement() { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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) //IL_0066: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) if (GetCollisionCount(blockedMask) != 0) { return false; } if (((InteractableObject)this).m_PlaceObjectInShopOnly && GetCollisionCount(shopValidMask) == 0) { return false; } if (((InteractableObject)this).m_PlaceObjectInWarehouseOnly && GetCollisionCount(warehouseValidMask) == 0) { return false; } if (m_CanBePlacedOnFurniture) { Bounds bounds = ((Collider)((InteractableObject)this).m_BoxCollider).bounds; Vector3 center = ((Bounds)(ref bounds)).center; bounds = ((Collider)((InteractableObject)this).m_BoxCollider).bounds; center.y = ((Bounds)(ref bounds)).min.y; RaycastHit val = default(RaycastHit); if (Physics.Raycast(center, Vector3.down, ref val, 0.1f) && ((RaycastHit)(ref val)).normal.y > 0.9f) { return true; } } return ((Component)this).transform.position.y <= 0.1f; } private bool IsValidCeilingPlacement() { //IL_0006: 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: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = ((Collider)((InteractableObject)this).m_BoxCollider).bounds; float num = ((Bounds)(ref bounds)).max.y - ((Component)this).transform.position.y; float num2 = 3.1f - num; if (((Component)this).transform.position.y < num2 && ((Component)this).transform.position.y > num2 - 0.2f) { return GetCollisionCount(anyValidMask) > 0; } return false; } private bool IsValidWallPlacement() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((InteractableObject)this).m_TargetMoveObjectPosition - ((Component)this).transform.position; if (((Vector3)(ref val)).magnitude <= 0.02f && ((Component)this).transform.position.y >= 0.1f && GetCollisionCount(decorationBlockerMask) > 0) { Transform transform = ((Component)overlapBuffer[0]).transform; if (GetCollisionCount(decorationBlockedMask) == 0) { ((InteractableObject)this).m_LastHitTransform = transform; return true; } } ((InteractableObject)this).m_LastHitTransform = null; return false; } private int GetCollisionCount(int layerMask) { //IL_0006: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) return Physics.OverlapBoxNonAlloc(((InteractableObject)this).m_MoveStateValidArea.position, ((InteractableObject)this).m_MoveStateValidArea.lossyScale / 2f, overlapBuffer, ((InteractableObject)this).m_MoveStateValidArea.rotation, layerMask); } } public class CustomInteractableObject : InteractableObject { private static readonly Collider[] overlapBuffer = (Collider[])(object)new Collider[1]; private static readonly int blockedMask = LayerMask.GetMask(new string[2] { "MoveStateBlockedArea", "Customer" }); private static readonly int shopValidMask = LayerMask.GetMask(new string[1] { "MoveStateValidArea" }); private static readonly int warehouseValidMask = LayerMask.GetMask(new string[1] { "MoveStateValidWarehouseArea" }); private static readonly int shopModelMask = LayerMask.GetMask(new string[1] { "ShopModel" }); public override void Awake() { } public override void Update() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (!base.m_IsMovingObject) { return; } ((Component)this).transform.position = Vector3.Lerp(((Component)this).transform.position, base.m_TargetMoveObjectPosition, Time.deltaTime * 7.5f); bool flag = GetCollisionCount(blockedMask) == 0; if (flag) { if (base.m_PlaceObjectInShopOnly) { flag = GetCollisionCount(shopValidMask) > 0; } else if (base.m_PlaceObjectInWarehouseOnly) { flag = GetCollisionCount(warehouseValidMask) > 0; } } base.m_IsMovingObjectValidState = flag; ShelfManager.SetMoveObjectPreviewModelValidState(flag); } public override void OnPlacedMovedObject() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) CSingleton<InteractionPlayerController>.Instance.OnExitMoveObjectMode(); base.m_IsMovingObject = false; ((Component)this).gameObject.layer = base.m_OriginalLayer; ((Collider)base.m_BoxCollider).enabled = true; for (int i = 0; i < base.m_BoxColliderList.Count; i++) { ((Collider)base.m_BoxColliderList[i]).enabled = true; } Vector3 position = ((Component)base.m_PickupObjectMesh).transform.position; position.y += 0.2f; RaycastHit val = default(RaycastHit); if (Physics.Raycast(position, Vector3.down, ref val, 100f, shopModelMask)) { ((Component)this).transform.position = ((RaycastHit)(ref val)).point; } ((Component)base.m_MoveStateValidArea).gameObject.SetActive(true); ShelfManager.DisableMoveObjectPreviewMode(); if (Object.op_Implicit((Object)(object)base.m_BoxCollider)) { ((Component)CSingleton<ShelfManager>.Instance.m_MoveObjectCustomerBlocker).gameObject.SetActive(false); } if (!base.m_IsBoxedUp && Object.op_Implicit((Object)(object)base.m_InteractablePackagingBox_Shelf)) { if (Object.op_Implicit((Object)(object)base.m_Shelf_WorldUIGrp)) { ((Component)base.m_Shelf_WorldUIGrp).transform.position = ((Component)this).transform.position; } base.m_InteractablePackagingBox_Shelf.EmptyBoxShelf(); ((InteractableObject)base.m_InteractablePackagingBox_Shelf).OnDestroyed(); } if (Object.op_Implicit((Object)(object)base.m_Shelf_WorldUIGrp) && !base.m_IsBoxedUp) { ((Component)base.m_Shelf_WorldUIGrp).transform.position = ((Component)this).transform.position; ((Component)base.m_Shelf_WorldUIGrp).transform.rotation = ((Component)this).transform.rotation; } if (Object.op_Implicit((Object)(object)base.m_NavMeshCut)) { base.m_NavMeshCut.SetActive(false); base.m_NavMeshCut.SetActive(true); } } private int GetCollisionCount(int layerMask) { //IL_0006: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) return Physics.OverlapBoxNonAlloc(base.m_MoveStateValidArea.position, base.m_MoveStateValidArea.lossyScale / 2f, overlapBuffer, base.m_MoveStateValidArea.rotation, layerMask); } } public class VideoPlayerController : MonoBehaviour { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ErrorEventHandler <>9__9_1; internal void <Start>b__9_1(VideoPlayer source, string error) { Debug.Log((object)error); } } public bool m_StopOnPickupObject; public AudioSource m_AudioSource; public VideoPlayer m_VideoPlayer; public InteractableObject m_InteractableObject; private bool isPrepared; private InteractableObject InteractableObject { get { if (!Object.op_Implicit((Object)(object)m_InteractableObject)) { m_InteractableObject = ((Component)this).GetComponentInParent<InteractableObject>(); } return m_InteractableObject; } } private VideoPlayer VideoPlayer { get { if (!Object.op_Implicit((Object)(object)m_VideoPlayer)) { m_VideoPlayer = ((Component)this).gameObject.GetComponent<VideoPlayer>(); } return m_VideoPlayer; } } public void Start() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)m_AudioSource)) { VideoPlayer.audioOutputMode = (VideoAudioOutputMode)1; } VideoPlayer.prepareCompleted += (EventHandler)delegate(VideoPlayer player) { if (player.audioTrackCount > 0) { player.SetTargetAudioSource((ushort)0, m_AudioSource); } else { Debug.LogWarning((object)"Video has no audio tracks!"); } isPrepared = true; }; VideoPlayer videoPlayer = VideoPlayer; object obj = <>c.<>9__9_1; if (obj == null) { ErrorEventHandler val = delegate(VideoPlayer source, string error) { Debug.Log((object)error); }; <>c.<>9__9_1 = val; obj = (object)val; } videoPlayer.errorReceived += (ErrorEventHandler)obj; VideoPlayer.Prepare(); } public void Update() { if (isPrepared) { if (InteractableObject.GetIsBoxedUp() && VideoPlayer.isPlaying) { VideoPlayer.Stop(); } if (InteractableObject.GetIsMovingObject() && m_StopOnPickupObject && VideoPlayer.isPlaying) { VideoPlayer.Stop(); } if (!InteractableObject.GetIsMovingObject() && !InteractableObject.GetIsBoxedUp() && !VideoPlayer.isPlaying) { VideoPlayer.Play(); } } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "Scripts"; public const string PLUGIN_NAME = "Scripts"; public const string PLUGIN_VERSION = "6.0.0"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { internal IgnoresAccessChecksToAttribute(string assemblyName) { } } }