diff --git a/Il2CppInterop.HarmonySupport/HarmonyBackendComponent.cs b/Il2CppInterop.HarmonySupport/HarmonyBackendComponent.cs index 1c1499e6..89661413 100644 --- a/Il2CppInterop.HarmonySupport/HarmonyBackendComponent.cs +++ b/Il2CppInterop.HarmonySupport/HarmonyBackendComponent.cs @@ -1,6 +1,7 @@ using HarmonyLib.Public.Patching; using Il2CppInterop.Common.Host; -using Il2CppInterop.Runtime.InteropTypes; +using Il2CppInterop.Runtime; +using Il2CppInterop.Runtime.Injection; namespace Il2CppInterop.HarmonySupport; @@ -21,7 +22,10 @@ internal class HarmonySupportComponent : IHostComponent private static void TryResolve(object sender, PatchManager.PatcherResolverEventArgs args) { - if (args.Original.DeclaringType?.IsSubclassOf(typeof(Il2CppObjectBase)) != true) + var declaringType = args.Original.DeclaringType; + if (declaringType == null) return; + if (Il2CppType.From(declaringType, false) == null || + ClassInjector.IsManagedTypeInjected(declaringType)) { return; } diff --git a/Il2CppInterop.Runtime/DelegateSupport.cs b/Il2CppInterop.Runtime/DelegateSupport.cs index 124f8d96..88a6528b 100644 --- a/Il2CppInterop.Runtime/DelegateSupport.cs +++ b/Il2CppInterop.Runtime/DelegateSupport.cs @@ -37,9 +37,11 @@ internal static Type GetOrCreateDelegateType(MethodSignature signature, MethodIn private static Type CreateDelegateType(MethodInfo managedMethodInner, MethodSignature signature) { - var newType = ModuleBuilder.DefineType( - "Il2CppToManagedDelegate_" + managedMethodInner.DeclaringType.FullName + "_" + signature.GetHashCode() + (signature.HasThis ? "HasThis" : "") + - (signature.ConstructedFromNative ? "FromNative" : ""), TypeAttributes.Sealed | TypeAttributes.Public, + var typeName = "Il2CppToManagedDelegate_" + managedMethodInner.DeclaringType + "_" + signature.GetHashCode() + + (signature.HasThis ? "HasThis" : "") + + (signature.ConstructedFromNative ? "FromNative" : ""); + + var newType = ModuleBuilder.DefineType(typeName, TypeAttributes.Sealed | TypeAttributes.Public, typeof(MulticastDelegate)); newType.SetCustomAttribute(new CustomAttributeBuilder( typeof(UnmanagedFunctionPointerAttribute).GetConstructor(new[] { typeof(CallingConvention) })!, diff --git a/Il2CppInterop.Runtime/Injection/ClassInjector.cs b/Il2CppInterop.Runtime/Injection/ClassInjector.cs index 82de25db..06de02f7 100644 --- a/Il2CppInterop.Runtime/Injection/ClassInjector.cs +++ b/Il2CppInterop.Runtime/Injection/ClassInjector.cs @@ -128,6 +128,13 @@ public static bool IsTypeRegisteredInIl2Cpp(Type type) var currentPointer = Il2CppClassPointerStore.GetNativeClassPointer(type); if (currentPointer != IntPtr.Zero) return true; + if (IsManagedTypeInjected(type)) return true; + + return false; + } + + internal static bool IsManagedTypeInjected(Type type) + { lock (InjectedTypes) { if (InjectedTypes.Contains(type.FullName)) @@ -305,7 +312,12 @@ public static void RegisterTypeInIl2Cpp(Type type, RegisterTypeOptions options) methodPointerArray[0] = ConvertStaticMethod(FinalizeDelegate, "Finalize", classPointer); var finalizeMethod = UnityVersionHandler.Wrap(methodPointerArray[0]); - if (!type.IsAbstract) methodPointerArray[1] = ConvertStaticMethod(CreateEmptyCtor(type, fieldsToInject), ".ctor", classPointer); + var fieldsToInitialize = type + .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + .Where(IsFieldEligible) + .ToArray(); + + if (!type.IsAbstract) methodPointerArray[1] = ConvertStaticMethod(CreateEmptyCtor(type, fieldsToInitialize), ".ctor", classPointer); var infos = new Dictionary<(string, int, bool), int>(eligibleMethods.Length); for (var i = 0; i < eligibleMethods.Length; i++) { @@ -372,6 +384,18 @@ static void FindAbstractMethods(List list, INativeClass } var abstractV = 0; + + INativeMethodInfoStruct HandleAbstractMethod(int position) + { + if (!extendsAbstract) throw new NullReferenceException("VTable method was null even though base type isn't abstract"); + + var nativeMethodInfoStruct = abstractBaseMethods[abstractV++]; + + vTablePointer[position].method = nativeMethodInfoStruct.MethodInfoPointer; + vTablePointer[position].methodPtr = nativeMethodInfoStruct.MethodPointer; + return nativeMethodInfoStruct; + } + for (var i = 0; i < baseClassPointer.VtableCount; i++) { vTablePointer[i] = baseVTablePointer[i]; @@ -380,18 +404,18 @@ static void FindAbstractMethods(List list, INativeClass if (baseVTablePointer[i].method == default) { - if (!extendsAbstract) throw new NullReferenceException("VTable method was null even though base type isn't abstract"); - - baseMethod = abstractBaseMethods[abstractV++]; - - vTablePointer[i].method = baseMethod.MethodInfoPointer; - vTablePointer[i].methodPtr = baseMethod.MethodPointer; + baseMethod = HandleAbstractMethod(i); } else { baseMethod = UnityVersionHandler.Wrap(vTablePointer[i].method); } + if (baseMethod.Name == IntPtr.Zero) + { + baseMethod = HandleAbstractMethod(i); + } + var methodName = Marshal.PtrToStringAnsi(baseMethod.Name); if (methodName == "Finalize") // slot number is not static diff --git a/Il2CppInterop.Runtime/InteropTypes/Fields/Il2CppReferenceField.cs b/Il2CppInterop.Runtime/InteropTypes/Fields/Il2CppReferenceField.cs index bc2b8af1..ee5c8024 100644 --- a/Il2CppInterop.Runtime/InteropTypes/Fields/Il2CppReferenceField.cs +++ b/Il2CppInterop.Runtime/InteropTypes/Fields/Il2CppReferenceField.cs @@ -28,7 +28,7 @@ public TRefObj Value public void Set(TRefObj value) { - *GetPointerToData() = value.Pointer; + *GetPointerToData() = value != null ? value.Pointer : IntPtr.Zero; } public static implicit operator TRefObj(Il2CppReferenceField _this)