示例#1
0
            private static ResolveEventHandler GenerateModAssemblyResolver(EverestModuleMetadata meta)
                => (sender, args) => {
                    AssemblyName asmName = args?.Name == null ? null : new AssemblyName(args.Name);
                    if (string.IsNullOrEmpty(asmName?.Name))
                        return null;

                    if (!string.IsNullOrEmpty(meta.PathArchive)) {
                        string asmPath = asmName.Name + ".dll";
                        using (ZipFile zip = new ZipFile(meta.PathArchive)) {
                            foreach (ZipEntry entry in zip.Entries) {
                                if (entry.FileName == asmPath)
                                    using (MemoryStream stream = entry.ExtractStream())
                                        return Relinker.GetRelinkedAssembly(meta, stream);
                            }
                        }
                    }

                    if (!string.IsNullOrEmpty(meta.PathDirectory)) {
                        string asmPath = Path.Combine(meta.PathDirectory, asmName.Name + ".dll");
                        if (File.Exists(asmPath))
                            using (FileStream stream = File.OpenRead(asmPath))
                                return Relinker.GetRelinkedAssembly(meta, stream);
                    }

                    return null;
                };
示例#2
0
        public static IMetadataTokenProvider Relink(this IMetadataTokenProvider mtp, Relinker relinker,
                                                    IGenericParameterProvider context)
        {
            switch (mtp)
            {
            case TypeReference reference:
                return(reference.Relink(relinker, context));

            case MethodReference reference:
                return(reference.Relink(relinker, context));

            case FieldReference reference:
                return(reference.Relink(relinker, context));

            case ParameterDefinition definition:
                return(definition.Relink(relinker, context));

            case CallSite site:
                return(site.Relink(relinker, context));

            default:
                throw new InvalidOperationException(
                          $"MonoMod can't handle metadata token providers of the type {mtp.GetType()}");
            }
        }
        /// <summary>
        /// Relink the given member reference (metadata token provider).
        /// </summary>
        /// <param name="mtp">The reference to relink.</param>
        /// <param name="relinker">The relinker to use during the relinking process.</param>
        /// <param name="context">The generic context provided to relink generic references.</param>
        /// <returns>A relinked reference.</returns>
        public static IMetadataTokenProvider Relink(this IMetadataTokenProvider mtp, Relinker relinker, IGenericParameterProvider context)
        {
            if (mtp is TypeReference)
            {
                return(((TypeReference)mtp).Relink(relinker, context));
            }
#if !CECIL0_10
            if (mtp is GenericParameterConstraint)
            {
                return(((GenericParameterConstraint)mtp).Relink(relinker, context));
            }
#endif
            if (mtp is MethodReference)
            {
                return(((MethodReference)mtp).Relink(relinker, context));
            }
            if (mtp is FieldReference)
            {
                return(((FieldReference)mtp).Relink(relinker, context));
            }
            if (mtp is ParameterDefinition)
            {
                return(((ParameterDefinition)mtp).Relink(relinker, context));
            }
            if (mtp is CallSite)
            {
                return(((CallSite)mtp).Relink(relinker, context));
            }
            throw new InvalidOperationException($"MonoMod can't handle metadata token providers of the type {mtp.GetType()}");
        }
示例#4
0
        public static CustomAttribute Relink(this CustomAttribute attrib, Relinker relinker,
                                             IGenericParameterProvider context)
        {
            var newAttrib = new CustomAttribute(attrib.Constructor.Relink(relinker, context));

            foreach (var attribArg in attrib.ConstructorArguments)
            {
                newAttrib.ConstructorArguments.Add(new CustomAttributeArgument(attribArg.Type.Relink(relinker, context),
                                                                               attribArg.Value));
            }
            foreach (var attribArg in attrib.Fields)
            {
                newAttrib.Fields.Add(new CustomAttributeNamedArgument(attribArg.Name,
                                                                      new CustomAttributeArgument(attribArg.Argument.Type.Relink(relinker, context),
                                                                                                  attribArg.Argument.Value))
                                     );
            }
            foreach (var attribArg in attrib.Properties)
            {
                newAttrib.Properties.Add(new CustomAttributeNamedArgument(attribArg.Name,
                                                                          new CustomAttributeArgument(attribArg.Argument.Type.Relink(relinker, context),
                                                                                                      attribArg.Argument.Value))
                                         );
            }
            return(newAttrib);
        }
示例#5
0
 public static CustomAttribute Relink(this CustomAttribute attrib, Relinker relinker, IGenericParameterProvider context)
 {
     attrib.Constructor = attrib.Constructor.Relink(relinker, context);
     // Don't foreach when modifying the collection
     for (int i = 0; i < attrib.ConstructorArguments.Count; i++)
     {
         CustomAttributeArgument attribArg = attrib.ConstructorArguments[i];
         attrib.ConstructorArguments[i] = new CustomAttributeArgument(attribArg.Type.Relink(relinker, context), attribArg.Value);
     }
     for (int i = 0; i < attrib.Fields.Count; i++)
     {
         CustomAttributeNamedArgument attribArg = attrib.Fields[i];
         attrib.Fields[i] = new CustomAttributeNamedArgument(attribArg.Name,
                                                             new CustomAttributeArgument(attribArg.Argument.Type.Relink(relinker, context), attribArg.Argument.Value)
                                                             );
     }
     for (int i = 0; i < attrib.Properties.Count; i++)
     {
         CustomAttributeNamedArgument attribArg = attrib.Properties[i];
         attrib.Properties[i] = new CustomAttributeNamedArgument(attribArg.Name,
                                                                 new CustomAttributeArgument(attribArg.Argument.Type.Relink(relinker, context), attribArg.Argument.Value)
                                                                 );
     }
     return(attrib);
 }
示例#6
0
            /// <summary>
            /// Load a mod .dll given its metadata at runtime. Doesn't load the mod content.
            /// </summary>
            /// <param name="meta">Metadata of the mod to load.</param>
            public static void LoadMod(EverestModuleMetadata meta)
            {
                if (!Flags.SupportRuntimeMods)
                {
                    Logger.Log(LogLevel.Warn, "loader", "Loader disabled!");
                    return;
                }

                if (meta == null)
                {
                    return;
                }

                // Add an AssemblyResolve handler for all bundled libraries.
                AppDomain.CurrentDomain.AssemblyResolve += GenerateModAssemblyResolver(meta);

                // Load the actual assembly.
                Assembly asm = null;

                if (!string.IsNullOrEmpty(meta.PathArchive))
                {
                    using (ZipFile zip = new ZipFile(meta.PathArchive)) {
                        foreach (ZipEntry entry in zip.Entries)
                        {
                            string entryName = entry.FileName.Replace('\\', '/');
                            if (entryName == meta.DLL)
                            {
                                using (MemoryStream stream = entry.ExtractStream()) {
                                    if (meta.Prelinked)
                                    {
                                        asm = Assembly.Load(stream.GetBuffer());
                                    }
                                    else
                                    {
                                        asm = Relinker.GetRelinkedAssembly(meta, stream);
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (meta.Prelinked)
                    {
                        asm = Assembly.LoadFrom(meta.DLL);
                    }
                    else
                    {
                        using (FileStream stream = File.OpenRead(meta.DLL))
                            asm = Relinker.GetRelinkedAssembly(meta, stream);
                    }
                }

                if (asm != null)
                {
                    LoadModAssembly(meta, asm);
                }
            }
示例#7
0
            /// <summary>
            /// Load a mod .dll given its metadata at runtime. Doesn't load the mod content.
            /// </summary>
            /// <param name="meta">Metadata of the mod to load.</param>
            public static void LoadMod(EverestModuleMetadata meta) {
                if (Flags.IsDisabled || !Flags.SupportRuntimeMods) {
                    Logger.Log(LogLevel.Warn, "loader", "Loader disabled!");
                    return;
                }

                if (meta == null)
                    return;

                // Add an AssemblyResolve handler for all bundled libraries.
                AppDomain.CurrentDomain.AssemblyResolve += GenerateModAssemblyResolver(meta);

                ApplyRelinkerHackfixes(meta);

                // Load the actual assembly.
                Assembly asm = null;
                if (!string.IsNullOrEmpty(meta.PathArchive)) {
                    bool returnEarly = false;
                    using (ZipFile zip = new ZipFile(meta.PathArchive)) {
                        foreach (ZipEntry entry in zip.Entries) {
                            string entryName = entry.FileName.Replace('\\', '/');
                            if (entryName == meta.DLL) {
                                using (MemoryStream stream = entry.ExtractStream())
                                    asm = Relinker.GetRelinkedAssembly(meta, stream);
                            }

                            if (entryName == "main.lua") {
                                new LuaModule(meta).Register();
                                returnEarly = true;
                            }
                        }
                    }

                    if (returnEarly)
                        return;

                } else {
                    if (!string.IsNullOrEmpty(meta.DLL) && File.Exists(meta.DLL)) {
                            using (FileStream stream = File.OpenRead(meta.DLL))
                                asm = Relinker.GetRelinkedAssembly(meta, stream);
                    }

                    if (File.Exists(Path.Combine(meta.PathDirectory, "main.lua"))) {
                        new LuaModule(meta).Register();
                        return;
                    }
                }

                ApplyModHackfixes(meta, asm);

                if (asm == null) {
                    // Register a null module for content mods.
                    new NullModule(meta).Register();
                    return;
                }

                LoadModAssembly(meta, asm);
            }
示例#8
0
        public static IMetadataTokenProvider Relink(this FieldReference field, Relinker relinker,
                                                    IGenericParameterProvider context)
        {
            var declaringType = field.DeclaringType.Relink(relinker, context);

            return(relinker(
                       new FieldReference(field.Name, field.FieldType.Relink(relinker, declaringType), declaringType),
                       context));
        }
示例#9
0
 public static ParameterDefinition Relink(this ParameterDefinition param, Relinker relinker, IGenericParameterProvider context)
 {
     param = ((MethodReference)param.Method).Relink(relinker, context).Parameters[param.Index];
     param.ParameterType = param.ParameterType.Relink(relinker, context);
     // Don't foreach when modifying the collection
     for (int i = 0; i < param.CustomAttributes.Count; i++)
     {
         param.CustomAttributes[i] = param.CustomAttributes[i].Relink(relinker, context);
     }
     return(param);
 }
示例#10
0
            internal static void ReloadModAssembly(object source, FileSystemEventArgs e, bool retrying = false)
            {
                if (!File.Exists(e.FullPath))
                {
                    return;
                }

                Logger.Log(LogLevel.Info, "loader", $"Reloading mod assembly: {e.FullPath}");
                QueuedTaskHelper.Do("ReloadModAssembly:" + e.FullPath, () => {
                    EverestModule module = _Modules.FirstOrDefault(m => m.Metadata.DLL == e.FullPath);
                    if (module == null)
                    {
                        return;
                    }

                    AssetReloadHelper.Do($"{Dialog.Clean("ASSETRELOADHELPER_RELOADINGMODASSEMBLY")} {Path.GetFileName(e.FullPath)}", () => {
                        Assembly asm = null;
                        using (FileStream stream = File.OpenRead(e.FullPath))
                            asm = Relinker.GetRelinkedAssembly(module.Metadata, Path.GetFileNameWithoutExtension(e.FullPath), stream);

                        if (asm == null)
                        {
                            if (!retrying)
                            {
                                // Retry.
                                QueuedTaskHelper.Do("ReloadModAssembly:" + e.FullPath, () => {
                                    ReloadModAssembly(source, e, true);
                                });
                            }
                            return;
                        }

                        ((FileSystemWatcher)source).Dispose();

                        // be sure to save this module's save data and session before reloading it, so that they are not lost.
                        if (SaveData.Instance != null)
                        {
                            Logger.Log("core", $"Saving save data slot {SaveData.Instance.FileSlot} for {module.Metadata} before reloading");
                            module.SaveSaveData(SaveData.Instance.FileSlot);

                            if (SaveData.Instance.CurrentSession?.InArea ?? false)
                            {
                                Logger.Log("core", $"Saving session slot {SaveData.Instance.FileSlot} for {module.Metadata} before reloading");
                                module.SaveSession(SaveData.Instance.FileSlot);
                            }
                        }

                        Unregister(module);
                        LoadModAssembly(module.Metadata, asm);
                    });
                    AssetReloadHelper.ReloadLevel();
                });
            }
示例#11
0
        public static GenericParameter Relink(this GenericParameter param, Relinker relinker, IGenericParameterProvider context)
        {
            GenericParameter newParam = new GenericParameter(param.Name, param.Owner)
            {
                Attributes = param.Attributes
            }.Update(param);

            foreach (TypeReference constraint in param.Constraints)
            {
                newParam.Constraints.Add(constraint.Relink(relinker, context));
            }
            return(newParam);
        }
示例#12
0
        public static MethodReference Relink(this MethodReference method, Relinker relinker,
                                             IGenericParameterProvider context)
        {
            if (method.IsGenericInstance)
            {
                var methodg = (GenericInstanceMethod)method;
                var gim     = new GenericInstanceMethod(methodg.ElementMethod.Relink(relinker, context));
                foreach (var arg in methodg.GenericArguments)
                {
                    // Generic arguments for the generic instance are often given by the next higher provider.
                    gim.GenericArguments.Add(arg.Relink(relinker, context));
                }

                return((MethodReference)relinker(gim, context));
            }

            var relink = new MethodReference(method.Name, method.ReturnType,
                                             method.DeclaringType.Relink(relinker, context))
            {
                CallingConvention = method.CallingConvention,
                ExplicitThis      = method.ExplicitThis,
                HasThis           = method.HasThis
            };


            foreach (var param in method.GenericParameters)
            {
                var paramN = new GenericParameter(param.Name, param.Owner)
                {
                    Attributes = param.Attributes
                                 // MetadataToken = param.MetadataToken
                }.Update(param);

                relink.GenericParameters.Add(paramN);

                foreach (var constraint in param.Constraints)
                {
                    paramN.Constraints.Add(constraint.Relink(relinker, relink));
                }
            }

            relink.ReturnType = relink.ReturnType?.Relink(relinker, relink);

            foreach (var param in method.Parameters)
            {
                param.ParameterType = param.ParameterType.Relink(relinker, method);
                relink.Parameters.Add(param);
            }

            return((MethodReference)relinker(relink, context));
        }
示例#13
0
        /// <summary>
        /// Relink the given generic parameter reference.
        /// </summary>
        /// <param name="param">The reference to relink.</param>
        /// <param name="relinker">The relinker to use during the relinking process.</param>
        /// <param name="context">The generic context provided to relink generic references.</param>
        /// <returns>A relinked reference.</returns>
        public static GenericParameter Relink(this GenericParameter param, Relinker relinker, IGenericParameterProvider context)
        {
            GenericParameter newParam = new GenericParameter(param.Name, param.Owner)
            {
                Attributes = param.Attributes
            }.Update(param.Position, param.Type);

#pragma warning disable IDE0008 // TypeReference in cecil 0.10, GenericParameterConstraint in cecil 0.11
            foreach (var constraint in param.Constraints)
#pragma warning restore IDE0008
            {
                newParam.Constraints.Add(constraint.Relink(relinker, context));
            }
            return(newParam);
        }
示例#14
0
        /// <summary>
        /// Relink the given method reference.
        /// </summary>
        /// <param name="method">The reference to relink.</param>
        /// <param name="relinker">The relinker to use during the relinking process.</param>
        /// <param name="context">The generic context provided to relink generic references.</param>
        /// <returns>A relinked reference.</returns>
        public static IMetadataTokenProvider Relink(this MethodReference method, Relinker relinker, IGenericParameterProvider context)
        {
            if (method.IsGenericInstance)
            {
                GenericInstanceMethod methodg = (GenericInstanceMethod)method;
                GenericInstanceMethod gim     = new GenericInstanceMethod((MethodReference)methodg.ElementMethod.Relink(relinker, context));
                foreach (TypeReference arg in methodg.GenericArguments)
                {
                    // Generic arguments for the generic instance are often given by the next higher provider.
                    gim.GenericArguments.Add(arg.Relink(relinker, context));
                }

                return((MethodReference)relinker(gim, context));
            }

            MethodReference relink = new MethodReference(method.Name, method.ReturnType, method.DeclaringType.Relink(relinker, context));

            relink.CallingConvention = method.CallingConvention;
            relink.ExplicitThis      = method.ExplicitThis;
            relink.HasThis           = method.HasThis;

            foreach (GenericParameter param in method.GenericParameters)
            {
                GenericParameter paramN = new GenericParameter(param.Name, param.Owner)
                {
                    Attributes = param.Attributes
                }.Update(param.Position, param.Type);

                relink.GenericParameters.Add(paramN);

#pragma warning disable IDE0008 // TypeReference in cecil 0.10, GenericParameterConstraint in cecil 0.11
                foreach (var constraint in param.Constraints)
                {
#pragma warning restore IDE0008
                    paramN.Constraints.Add(constraint.Relink(relinker, relink));
                }
            }

            relink.ReturnType = relink.ReturnType?.Relink(relinker, relink);

            foreach (ParameterDefinition param in method.Parameters)
            {
                param.ParameterType = param.ParameterType.Relink(relinker, method);
                relink.Parameters.Add(param);
            }

            return((MethodReference)relinker(relink, context));
        }
示例#15
0
            private static ResolveEventHandler GenerateModAssemblyResolver(EverestModuleMetadata meta)
            => (sender, args) => {
                AssemblyName name = args?.Name == null ? null : new AssemblyName(args.Name);
                if (string.IsNullOrEmpty(name?.Name))
                {
                    return(null);
                }

                string path = name.Name + ".dll";
                if (!string.IsNullOrEmpty(meta.DLL))
                {
                    path = Path.Combine(Path.GetDirectoryName(meta.DLL), path);
                }

                if (!string.IsNullOrEmpty(meta.PathArchive))
                {
                    string zipPath = path.Replace('\\', '/');
                    using (ZipFile zip = new ZipFile(meta.PathArchive)) {
                        foreach (ZipEntry entry in zip.Entries)
                        {
                            if (entry.FileName == zipPath)
                            {
                                using (MemoryStream stream = entry.ExtractStream())
                                    return(Relinker.GetRelinkedAssembly(meta, Path.GetFileNameWithoutExtension(zipPath), stream));
                            }
                        }
                    }
                }

                if (!string.IsNullOrEmpty(meta.PathDirectory))
                {
                    string filePath = path;
                    if (!File.Exists(filePath))
                    {
                        path = Path.Combine(meta.PathDirectory, filePath);
                    }
                    if (File.Exists(filePath))
                    {
                        using (FileStream stream = File.OpenRead(filePath))
                            return(Relinker.GetRelinkedAssembly(meta, Path.GetFileNameWithoutExtension(filePath), stream));
                    }
                }

                return(null);
            };
示例#16
0
        /// <summary>
        /// Relink the given callsite.
        /// </summary>
        /// <param name="method">The reference to relink.</param>
        /// <param name="relinker">The relinker to use during the relinking process.</param>
        /// <param name="context">The generic context provided to relink generic references.</param>
        /// <returns>A relinked reference.</returns>
        public static CallSite Relink(this CallSite method, Relinker relinker, IGenericParameterProvider context)
        {
            CallSite relink = new CallSite(method.ReturnType);

            relink.CallingConvention = method.CallingConvention;
            relink.ExplicitThis      = method.ExplicitThis;
            relink.HasThis           = method.HasThis;

            relink.ReturnType = relink.ReturnType?.Relink(relinker, context);

            foreach (ParameterDefinition param in method.Parameters)
            {
                param.ParameterType = param.ParameterType.Relink(relinker, context);
                relink.Parameters.Add(param);
            }

            return((CallSite)relinker(relink, context));
        }
示例#17
0
        /// <summary>
        /// Relink the given parameter definition.
        /// </summary>
        /// <param name="param">The reference to relink.</param>
        /// <param name="relinker">The relinker to use during the relinking process.</param>
        /// <param name="context">The generic context provided to relink generic references.</param>
        /// <returns>A relinked reference.</returns>
        public static ParameterDefinition Relink(this ParameterDefinition param, Relinker relinker, IGenericParameterProvider context)
        {
            param = (param.Method as MethodReference)?.Parameters[param.Index] ?? param;
            ParameterDefinition newParam = new ParameterDefinition(param.Name, param.Attributes, param.ParameterType.Relink(relinker, context))
            {
                IsIn          = param.IsIn,
                IsLcid        = param.IsLcid,
                IsOptional    = param.IsOptional,
                IsOut         = param.IsOut,
                IsReturnValue = param.IsReturnValue,
                MarshalInfo   = param.MarshalInfo
            };

            if (param.HasConstant)
            {
                newParam.Constant = param.Constant;
            }
            return(newParam);
        }
示例#18
0
            internal static void ReloadModAssembly(object source, FileSystemEventArgs e, bool retrying = false)
            {
                if (!File.Exists(e.FullPath))
                {
                    return;
                }

                Logger.Log(LogLevel.Info, "loader", $"Reloading mod assembly: {e.FullPath}");
                QueuedTaskHelper.Do("ReloadModAssembly:" + e.FullPath, () => {
                    EverestModule module = _Modules.FirstOrDefault(m => m.Metadata.DLL == e.FullPath);
                    if (module == null)
                    {
                        return;
                    }

                    AssetReloadHelper.Do($"Reloading mod assembly: {Path.GetFileName(e.FullPath)}", () => {
                        Assembly asm = null;
                        using (FileStream stream = File.OpenRead(e.FullPath))
                            asm = Relinker.GetRelinkedAssembly(module.Metadata, stream);

                        if (asm == null)
                        {
                            if (!retrying)
                            {
                                // Retry.
                                QueuedTaskHelper.Do("ReloadModAssembly:" + e.FullPath, () => {
                                    ReloadModAssembly(source, e, true);
                                });
                            }
                            return;
                        }

                        ((FileSystemWatcher)source).Dispose();
                        Unregister(module);
                        LoadModAssembly(module.Metadata, asm);
                    });
                    AssetReloadHelper.ReloadLevel();
                });
            }
示例#19
0
            public static void LoadZip(string archive)
            {
                if (!File.Exists(archive)) // Relative path?
                {
                    archive = Path.Combine(PathMods, archive);
                }
                if (!File.Exists(archive)) // It just doesn't exist.
                {
                    return;
                }

                Logger.Log("loader", $"Loading mod .zip: {archive}");

                EverestModuleMetadata meta = null;
                Assembly asm = null;

                using (ZipFile zip = new ZipFile(archive)) {
                    // In case the icon appears before the metadata in the .zip, store it temporarily.
                    Texture2D icon = null;

                    // First read the metadata, ...
                    foreach (ZipEntry entry in zip.Entries)
                    {
                        if (entry.FileName == "metadata.yaml")
                        {
                            using (MemoryStream stream = entry.ExtractStream())
                                using (StreamReader reader = new StreamReader(stream))
                                    meta = EverestModuleMetadata.Parse(archive, "", reader);
                            continue;
                        }
                        if (entry.FileName == "icon.png")
                        {
                            using (Stream stream = entry.ExtractStream())
                                icon = Texture2D.FromStream(Celeste.Instance.GraphicsDevice, stream);
                            continue;
                        }
                    }

                    if (meta != null)
                    {
                        if (icon != null)
                        {
                            meta.Icon = icon;
                        }

                        // ... then check if the dependencies are loaded ...
                        // TODO: Enqueue the mod, reload it on Register of other mods, rechecking if deps loaded.
                        foreach (EverestModuleMetadata dep in meta.Dependencies)
                        {
                            if (!DependencyLoaded(dep))
                            {
                                Logger.Log("loader", $"Dependency {dep} of mod {meta} not loaded!");
                                return;
                            }
                        }

                        // ... then add an AssemblyResolve handler for all the .zip-ped libraries
                        AppDomain.CurrentDomain.AssemblyResolve += GenerateModAssemblyResolver(meta);
                    }

                    // ... then handle the assembly ...
                    foreach (ZipEntry entry in zip.Entries)
                    {
                        string entryName = entry.FileName.Replace('\\', '/');
                        if (meta != null && entryName == meta.DLL)
                        {
                            using (MemoryStream stream = entry.ExtractStream()) {
                                if (meta.Prelinked)
                                {
                                    asm = Assembly.Load(stream.GetBuffer());
                                }
                                else
                                {
                                    asm = Relinker.GetRelinkedAssembly(meta, stream);
                                }
                            }
                        }
                    }

                    // ... then tell the Content class to crawl through the zip.
                    // (This also registers the zip for recrawls further down the line.)
                    Content.Crawl(null, archive, zip);
                }

                if (meta != null && asm != null)
                {
                    LoadMod(meta, asm);
                }
            }
示例#20
0
            public static void LoadDir(string dir)
            {
                if (!Directory.Exists(dir)) // Relative path?
                {
                    dir = Path.Combine(PathMods, dir);
                }
                if (!Directory.Exists(dir)) // It just doesn't exist.
                {
                    return;
                }

                Logger.Log("loader", $"Loading mod directory: {dir}");

                EverestModuleMetadata meta = null;
                Assembly asm = null;

                // First read the metadata, ...
                string metaPath = Path.Combine(dir, "metadata.yaml");

                if (File.Exists(metaPath))
                {
                    using (StreamReader reader = new StreamReader(metaPath))
                        meta = EverestModuleMetadata.Parse("", dir, reader);
                }

                if (meta != null)
                {
                    // ... then check if the dependencies are loaded ...
                    foreach (EverestModuleMetadata dep in meta.Dependencies)
                    {
                        if (!DependencyLoaded(dep))
                        {
                            Logger.Log("loader", $"Dependency {dep} of mod {meta} not loaded!");
                            return;
                        }
                    }

                    // ... then add an AssemblyResolve handler for all the  .zip-ped libraries
                    AppDomain.CurrentDomain.AssemblyResolve += GenerateModAssemblyResolver(meta);
                }

                // ... then handle the assembly and all assets.
                Content.Crawl(null, dir);

                if (meta == null || !File.Exists(meta.DLL))
                {
                    return;
                }

                if (meta.Prelinked)
                {
                    asm = Assembly.LoadFrom(meta.DLL);
                }
                else
                {
                    using (FileStream stream = File.OpenRead(meta.DLL))
                        asm = Relinker.GetRelinkedAssembly(meta, stream);
                }

                if (asm != null)
                {
                    LoadMod(meta, asm);
                }
            }
示例#21
0
        public static MethodBody Clone(this MethodBody bo, MethodDefinition m, Relinker relinker = null)
        {
            if (bo == null)
            {
                return(null);
            }

            var bc = new MethodBody(m)
            {
                MaxStackSize = bo.MaxStackSize, InitLocals = bo.InitLocals, LocalVarToken = bo.LocalVarToken
            };

            bc.Instructions.AddRange(bo.Instructions.Select(o =>
            {
                var c    = Instruction.Create(OpCodes.Nop);
                c.OpCode = o.OpCode;
                switch (o.Operand)
                {
                case ParameterDefinition pdRef:
                    c.Operand = m.Parameters[pdRef.Index];
                    break;

                case IMetadataTokenProvider reference when relinker != null:
                    c.Operand = reference.Relink(relinker, m);
                    break;

                default:
                    c.Operand = o.Operand;
                    break;
                }

                c.Offset = o.Offset;
                return(c);
            }));

            foreach (var c in bc.Instructions)
            {
                switch (c.Operand)
                {
                case Instruction target:
                    c.Operand = bc.Instructions[bo.Instructions.IndexOf(target)];
                    break;

                case Instruction[] targets:
                    c.Operand = targets.Select(i => bc.Instructions[bo.Instructions.IndexOf(i)]).ToArray();
                    break;
                }
            }

            bc.ExceptionHandlers.AddRange(bo.ExceptionHandlers.Select(o =>
            {
                var c = new ExceptionHandler(o.HandlerType)
                {
                    TryStart    = o.TryStart == null ? null : bc.Instructions[bo.Instructions.IndexOf(o.TryStart)],
                    TryEnd      = o.TryEnd == null ? null : bc.Instructions[bo.Instructions.IndexOf(o.TryEnd)],
                    FilterStart =
                        o.FilterStart == null ? null : bc.Instructions[bo.Instructions.IndexOf(o.FilterStart)],
                    HandlerStart = o.HandlerStart == null
                        ? null
                        : bc.Instructions[bo.Instructions.IndexOf(o.HandlerStart)],
                    HandlerEnd = o.HandlerEnd == null ? null : bc.Instructions[bo.Instructions.IndexOf(o.HandlerEnd)],
                    CatchType  = relinker != null ? o.CatchType.Relink(relinker, m) : o.CatchType
                };
                return(c);
            }));

            bc.Variables.AddRange(bo.Variables.Select(o =>
            {
                var c = new VariableDefinition(relinker != null ? o.VariableType.Relink(relinker, m) : o.VariableType);
                return(c);
            }));

            m.CustomDebugInformations.AddRange(bo.Method
                                               .CustomDebugInformations); // Abstract. TODO: Implement deep CustomDebugInformations copy.
            m.DebugInformation.SequencePoints.AddRange(bo.Method.DebugInformation.SequencePoints.Select(o =>
            {
                var c = new SequencePoint(bc.Instructions.FirstOrDefault(i => i.Offset == o.Offset),
                                          o.Document)
                {
                    StartLine = o.StartLine, StartColumn = o.StartColumn, EndLine = o.EndLine, EndColumn = o.EndColumn
                };
                return(c);
            }));

            return(bc);
        }
示例#22
0
        /// <summary>
        /// Relink the given type reference.
        /// </summary>
        /// <param name="constraint">The reference to relink.</param>
        /// <param name="relinker">The relinker to use during the relinking process.</param>
        /// <param name="context">The generic context provided to relink generic references.</param>
        /// <returns>A relinked reference.</returns>
        public static GenericParameterConstraint Relink(this GenericParameterConstraint constraint, Relinker relinker, IGenericParameterProvider context)
        {
            if (constraint == null)
            {
                return(null);
            }

            GenericParameterConstraint relink = new GenericParameterConstraint(constraint.ConstraintType.Relink(relinker, context));

            foreach (CustomAttribute attrib in constraint.CustomAttributes)
            {
                relink.CustomAttributes.Add(attrib.Relink(relinker, context));
            }

            return(relink);
        }
示例#23
0
        public static string GenerateUDKFileForLevel(string udkPath, IMEPackage pcc)
        {
            #region AssetPackage

            string meshPackageName = $"{Path.GetFileNameWithoutExtension(pcc.FilePath)}Meshes";
            string meshFile        = Path.Combine(udkPath, @"UDKGame\Content\Shared\", $"{meshPackageName}.upk");
            MEPackageHandler.CreateAndSavePackage(meshFile, MEGame.UDK);
            using IMEPackage meshPackage = MEPackageHandler.OpenUDKPackage(meshFile);
            meshPackage.getEntryOrAddImport("Core.Package");

            IEntry defMat    = meshPackage.getEntryOrAddImport("EngineMaterials.DefaultMaterial", "Material", "Engine");
            var    allMats   = new HashSet <int>();
            var    relinkMap = new Dictionary <IEntry, IEntry>();
            #region StaticMeshes

            List <ExportEntry> staticMeshes = pcc.Exports.Where(exp => exp.ClassName == "StaticMesh").ToList();
            foreach (ExportEntry mesh in staticMeshes)
            {
                var        mats = new Queue <int>();
                StaticMesh stm  = ObjectBinary.From <StaticMesh>(mesh);
                foreach (StaticMeshRenderData lodModel in stm.LODModels)
                {
                    foreach (StaticMeshElement meshElement in lodModel.Elements)
                    {
                        mats.Enqueue(meshElement.Material);
                        allMats.Add(meshElement.Material);
                        meshElement.Material = 0;
                    }
                }
                if (pcc.GetEntry(stm.BodySetup) is ExportEntry rbBodySetup)
                {
                    rbBodySetup.RemoveProperty("PhysMaterial");
                }
                mesh.WriteBinary(stm);
                IEntry newParent = EntryImporter.GetOrAddCrossImportOrPackage(mesh.ParentFullPath, pcc, meshPackage);
                EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneTreeAsChild, mesh, meshPackage, newParent, false, out IEntry ent, relinkMap);
                ExportEntry portedMesh = (ExportEntry)ent;
                stm = ObjectBinary.From <StaticMesh>(portedMesh);
                foreach (StaticMeshRenderData lodModel in stm.LODModels)
                {
                    foreach (StaticMeshElement meshElement in lodModel.Elements)
                    {
                        meshElement.Material = mats.Dequeue();
                    }
                }
                portedMesh.WriteBinary(stm);
            }

            #endregion

            #region Materials
            using (IMEPackage udkResources = MEPackageHandler.OpenMEPackageFromStream(Utilities.GetCustomAppResourceStream(MEGame.UDK)))
            {
                ExportEntry normDiffMat = udkResources.Exports.First(exp => exp.ObjectName == "NormDiffMat");
                foreach (int matUIndex in allMats)
                {
                    if (pcc.GetEntry(matUIndex) is ExportEntry matExp)
                    {
                        List <IEntry> textures = new MaterialInstanceConstant(matExp).Textures;
                        ExportEntry   diff     = null;
                        ExportEntry   norm     = null;
                        foreach (IEntry texEntry in textures)
                        {
                            if (texEntry is ExportEntry texport)
                            {
                                if (texport.ObjectName.Name.ToLower().Contains("diff"))
                                {
                                    diff = texport;
                                }
                                else if (texport.ObjectName.Name.ToLower().Contains("norm"))
                                {
                                    norm = texport;
                                }
                            }
                        }
                        if (diff == null)
                        {
                            relinkMap[matExp] = defMat;
                            continue;
                        }
                        else
                        {
                            EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, diff, meshPackage, null, false, out IEntry ent);
                            diff = (ExportEntry)ent;
                            diff.RemoveProperty("TextureFileCacheName");
                            diff.RemoveProperty("TFCFileGuid");
                            diff.RemoveProperty("LODGroup");
                        }
                        if (norm != null)
                        {
                            EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, norm, meshPackage, null, false, out IEntry ent);
                            norm = (ExportEntry)ent;
                            norm.RemoveProperty("TextureFileCacheName");
                            norm.RemoveProperty("TFCFileGuid");
                            norm.RemoveProperty("LODGroup");
                        }
                        EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneTreeAsChild, normDiffMat, meshPackage, null, true, out IEntry matEnt);
                        ExportEntry newMat = (ExportEntry)matEnt;
                        newMat.ObjectName = matExp.ObjectName;
                        Material matBin = ObjectBinary.From <Material>(newMat);
                        matBin.SM3MaterialResource.UniformExpressionTextures = new UIndex[] { norm?.UIndex ?? 0, diff.UIndex };
                        newMat.WriteBinary(matBin);
                        relinkMap[matExp] = newMat;
                        if (newMat.GetProperty <ArrayProperty <ObjectProperty> >("Expressions") is {} expressionsProp&& expressionsProp.Count >= 2)
                        {
                            ExportEntry diffExpression = meshPackage.GetUExport(expressionsProp[0].Value);
                            ExportEntry normExpression = meshPackage.GetUExport(expressionsProp[1].Value);
                            diffExpression.WriteProperty(new ObjectProperty(diff.UIndex, "Texture"));
                            normExpression.WriteProperty(new ObjectProperty(norm?.UIndex ?? 0, "Texture"));
                        }
                    }
                    else if (pcc.GetEntry(matUIndex) is ImportEntry matImp)
                    {
                        relinkMap[matImp] = defMat;
                    }
                }

                var relinkMapping = new OrderedMultiValueDictionary <IEntry, IEntry>(relinkMap);
                foreach (ExportEntry stmExport in staticMeshes)
                {
                    if (relinkMap.TryGetValue(stmExport, out IEntry destEnt) && destEnt is ExportEntry destExp)
                    {
                        Relinker.Relink(stmExport, destExp, relinkMapping);
                    }
                }
            }
            #endregion


            meshPackage.Save();

            #endregion


            var    staticMeshActors = new List <ExportEntry>();
            var    lightActors      = new List <ExportEntry>();
            string tempPackagePath  = Path.Combine(App.ExecFolder, $"{Path.GetFileNameWithoutExtension(pcc.FilePath)}.udk");
            File.Copy(Path.Combine(App.ExecFolder, "empty.udk"), tempPackagePath, true);
            using IMEPackage udkPackage = MEPackageHandler.OpenUDKPackage(tempPackagePath);
            {
                var topLevelMeshPackages = new List <IEntry>();
                foreach (ExportEntry exportEntry in staticMeshes)
                {
                    IEntry imp = udkPackage.getEntryOrAddImport($"{exportEntry.FullPath}", "StaticMesh", "Engine", exportEntry.ObjectName.Number);
                    while (imp.Parent != null)
                    {
                        imp = imp.Parent;
                    }
                    if (!topLevelMeshPackages.Contains(imp))
                    {
                        topLevelMeshPackages.Add(imp);
                    }
                }

                ExportEntry levelExport          = udkPackage.Exports.First(exp => exp.ClassName == "Level");
                List <int>  actorsInLevel        = ObjectBinary.From <Level>(pcc.Exports.First(exp => exp.ClassName == "Level")).Actors.Select(u => u.value).ToList();
                var         componentToMatrixMap = new Dictionary <int, Matrix>();
                foreach (int uIndex in actorsInLevel)
                {
                    if (pcc.GetEntry(uIndex) is ExportEntry stcExp)
                    {
                        if (stcExp.ClassName == "StaticMeshCollectionActor")
                        {
                            StaticMeshCollectionActor stmc = ObjectBinary.From <StaticMeshCollectionActor>(stcExp);
                            var components = stcExp.GetProperty <ArrayProperty <ObjectProperty> >("StaticMeshComponents");
                            for (int i = 0; i < components.Count; i++)
                            {
                                componentToMatrixMap[components[i].Value] = stmc.LocalToWorldTransforms[i];
                            }
                        }
                        else if (stcExp.ClassName == "StaticLightCollectionActor")
                        {
                            StaticLightCollectionActor stlc = ObjectBinary.From <StaticLightCollectionActor>(stcExp);
                            var components = stcExp.GetProperty <ArrayProperty <ObjectProperty> >("LightComponents");
                            for (int i = 0; i < components.Count; i++)
                            {
                                componentToMatrixMap[components[i].Value] = stlc.LocalToWorldTransforms[i];
                            }
                        }
                    }
                }

                #region StaticMeshActors
                {
                    var    emptySMCBin          = new StaticMeshComponent();
                    IEntry staticMeshActorClass = udkPackage.getEntryOrAddImport("Engine.StaticMeshActor");
                    udkPackage.getEntryOrAddImport("Engine.Default__StaticMeshActor", "StaticMeshActor", "Engine");
                    IEntry staticMeshComponentArchetype = udkPackage.getEntryOrAddImport("Engine.Default__StaticMeshActor.StaticMeshComponent0",
                                                                                         "StaticMeshComponent", "Engine");
                    int smaIndex = 2;
                    int smcIndex = 2;
                    foreach (ExportEntry smc in pcc.Exports.Where(exp => exp.ClassName == "StaticMeshComponent"))
                    {
                        if (smc.Parent is ExportEntry parent && actorsInLevel.Contains(parent.UIndex) && parent.IsA("StaticMeshActorBase"))
                        {
                            StructProperty locationProp;
                            StructProperty rotationProp;
                            StructProperty scaleProp = null;
                            smc.CondenseArchetypes();
                            if (!(smc.GetProperty <ObjectProperty>("StaticMesh") is { } meshProp) || !pcc.IsUExport(meshProp.Value))
                            {
                                continue;
                            }

                            smc.WriteBinary(emptySMCBin);
                            smc.RemoveProperty("bBioIsReceivingDecals");
                            smc.RemoveProperty("bBioForcePrecomputedShadows");
                            //smc.RemoveProperty("bUsePreComputedShadows");
                            smc.RemoveProperty("bAcceptsLights");
                            smc.RemoveProperty("IrrelevantLights");
                            smc.RemoveProperty("Materials"); //should make use of this?
                            smc.ObjectName = new NameReference("StaticMeshComponent", smcIndex++);
                            if (parent.ClassName == "StaticMeshCollectionActor")
                            {
                                if (!componentToMatrixMap.TryGetValue(smc.UIndex, out Matrix m))
                                {
                                    continue;
                                }
                                (Vector3 posVec, Vector3 scaleVec, Rotator rotator) = m.UnrealDecompose();
                                locationProp = CommonStructs.Vector3Prop(posVec, "Location");
                                rotationProp = CommonStructs.RotatorProp(rotator, "Rotation");
                                scaleProp    = CommonStructs.Vector3Prop(scaleVec, "DrawScale3D");
                                //smc.WriteProperty(CommonStructs.Matrix(m, "CachedParentToWorld"));
                            }
                            else
                            {
                                locationProp = parent.GetProperty <StructProperty>("Location");
                                rotationProp = parent.GetProperty <StructProperty>("Rotation");
                                scaleProp    = parent.GetProperty <StructProperty>("DrawScale3D");
                                if (parent.GetProperty <FloatProperty>("DrawScale")?.Value is float scale)
                                {
                                    Vector3 scaleVec = Vector3.One;
                                    if (scaleProp != null)
                                    {
                                        scaleVec = CommonStructs.GetVector3(scaleProp);
                                    }
                                    scaleProp = CommonStructs.Vector3Prop(scaleVec * scale, "DrawScale3D");
                                }
                            }

                            ExportEntry sma = new ExportEntry(udkPackage, EntryImporter.CreateStack(MEGame.UDK, staticMeshActorClass.UIndex))
                            {
                                ObjectName = new NameReference("StaticMeshActor", smaIndex++),
                                Class      = staticMeshActorClass,
                                Parent     = levelExport
                            };
                            sma.ObjectFlags |= UnrealFlags.EObjectFlags.HasStack;
                            udkPackage.AddExport(sma);

                            EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, smc, udkPackage,
                                                                 sma, true, out IEntry result);
                            var props = new PropertyCollection
                            {
                                new ObjectProperty(result.UIndex, "StaticMeshComponent"),
                                new NameProperty(new NameReference(Path.GetFileNameWithoutExtension(smc.FileRef.FilePath), smc.UIndex),
                                                 "Tag"),
                                new ObjectProperty(result.UIndex, "CollisionComponent")
                            };
                            if (locationProp != null)
                            {
                                props.Add(locationProp);
                            }
                            if (rotationProp != null)
                            {
                                props.Add(rotationProp);
                            }

                            if (scaleProp != null)
                            {
                                props.Add(scaleProp);
                            }
                            sma.WriteProperties(props);
                            staticMeshActors.Add(sma);
                        }
                    }
                    IEntry topMeshPackageImport = udkPackage.getEntryOrAddImport(meshPackageName, "Package");
                    foreach (IEntry mp in topLevelMeshPackages)
                    {
                        mp.Parent = topMeshPackageImport;
                    }
                }
                #endregion

                #region LightActors
                {
                    IEntry pointLightClass       = udkPackage.getEntryOrAddImport("Engine.PointLight");
                    IEntry spotLightClass        = udkPackage.getEntryOrAddImport("Engine.SpotLight");
                    IEntry directionalLightClass = udkPackage.getEntryOrAddImport("Engine.DirectionalLight");

                    int plaIndex = 1;
                    int plcIndex = 1;
                    int slaIndex = 1;
                    int slcIndex = 1;
                    int dlaIndex = 1;
                    int dlcIndex = 1;
                    foreach (ExportEntry lightComponent in pcc.Exports)
                    {
                        if (!(lightComponent.Parent is ExportEntry parent && actorsInLevel.Contains(parent.UIndex)))
                        {
                            continue;
                        }
                        StructProperty locationProp;
                        StructProperty rotationProp;
                        StructProperty scaleProp;
                        switch (lightComponent.ClassName)
                        {
                        case "PointLightComponent":
                            lightComponent.CondenseArchetypes();
                            lightComponent.ObjectName = new NameReference("PointLightComponent", plcIndex++);
                            if (parent.ClassName == "StaticLightCollectionActor")
                            {
                                if (!componentToMatrixMap.TryGetValue(lightComponent.UIndex, out Matrix m))
                                {
                                    continue;
                                }
                                (Vector3 posVec, Vector3 scaleVec, Rotator rotator) = m.UnrealDecompose();
                                locationProp = CommonStructs.Vector3Prop(posVec, "Location");
                                rotationProp = CommonStructs.RotatorProp(rotator, "Rotation");
                                scaleProp    = CommonStructs.Vector3Prop(scaleVec, "DrawScale3D");
                            }
                            else
                            {
                                locationProp = parent.GetProperty <StructProperty>("Location");
                                rotationProp = parent.GetProperty <StructProperty>("Rotation");
                                scaleProp    = parent.GetProperty <StructProperty>("DrawScale3D");
                                if (parent.GetProperty <FloatProperty>("DrawScale")?.Value is float scale)
                                {
                                    Vector3 scaleVec = Vector3.One;
                                    if (scaleProp != null)
                                    {
                                        scaleVec = CommonStructs.GetVector3(scaleProp);
                                    }
                                    scaleProp = CommonStructs.Vector3Prop(scaleVec * scale, "DrawScale3D");
                                }
                            }

                            ExportEntry pla = new ExportEntry(udkPackage, EntryImporter.CreateStack(MEGame.UDK, pointLightClass.UIndex))
                            {
                                ObjectName = new NameReference("PointLight", plaIndex++),
                                Class      = pointLightClass,
                                Parent     = levelExport
                            };
                            pla.ObjectFlags |= UnrealFlags.EObjectFlags.HasStack;
                            udkPackage.AddExport(pla);

                            EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, lightComponent, udkPackage, pla, true,
                                                                 out IEntry portedPLC);
                            var plsProps = new PropertyCollection
                            {
                                new ObjectProperty(portedPLC.UIndex, "LightComponent"),
                                new NameProperty("PointLight", "Tag"),
                            };
                            if (locationProp != null)
                            {
                                plsProps.Add(locationProp);
                            }
                            if (rotationProp != null)
                            {
                                plsProps.Add(rotationProp);
                            }
                            if (scaleProp != null)
                            {
                                plsProps.Add(scaleProp);
                            }
                            pla.WriteProperties(plsProps);
                            lightActors.Add(pla);
                            break;

                        case "SpotLightComponent":
                            lightComponent.CondenseArchetypes();
                            lightComponent.ObjectName = new NameReference("SpotLightComponent", slcIndex++);
                            if (parent.ClassName == "StaticLightCollectionActor")
                            {
                                if (!componentToMatrixMap.TryGetValue(lightComponent.UIndex, out Matrix m))
                                {
                                    continue;
                                }
                                (Vector3 posVec, Vector3 scaleVec, Rotator rotator) = m.UnrealDecompose();
                                locationProp = CommonStructs.Vector3Prop(posVec, "Location");
                                rotationProp = CommonStructs.RotatorProp(rotator, "Rotation");
                                scaleProp    = CommonStructs.Vector3Prop(scaleVec, "DrawScale3D");
                            }
                            else
                            {
                                locationProp = parent.GetProperty <StructProperty>("Location");
                                rotationProp = parent.GetProperty <StructProperty>("Rotation");
                                scaleProp    = parent.GetProperty <StructProperty>("DrawScale3D");
                                if (parent.GetProperty <FloatProperty>("DrawScale")?.Value is float scale)
                                {
                                    Vector3 scaleVec = Vector3.One;
                                    if (scaleProp != null)
                                    {
                                        scaleVec = CommonStructs.GetVector3(scaleProp);
                                    }
                                    scaleProp = CommonStructs.Vector3Prop(scaleVec * scale, "DrawScale3D");
                                }
                            }

                            ExportEntry sla = new ExportEntry(udkPackage, EntryImporter.CreateStack(MEGame.UDK, spotLightClass.UIndex))
                            {
                                ObjectName = new NameReference("SpotLight", slaIndex++),
                                Class      = spotLightClass,
                                Parent     = levelExport
                            };
                            sla.ObjectFlags |= UnrealFlags.EObjectFlags.HasStack;
                            udkPackage.AddExport(sla);

                            EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, lightComponent, udkPackage, sla, true,
                                                                 out IEntry portedSLC);
                            var slaProps = new PropertyCollection
                            {
                                new ObjectProperty(portedSLC.UIndex, "LightComponent"),
                                new NameProperty("SpotLight", "Tag"),
                            };
                            if (locationProp != null)
                            {
                                slaProps.Add(locationProp);
                            }
                            if (rotationProp != null)
                            {
                                slaProps.Add(rotationProp);
                            }
                            if (scaleProp != null)
                            {
                                slaProps.Add(scaleProp);
                            }
                            sla.WriteProperties(slaProps);
                            lightActors.Add(sla);
                            break;

                        case "DirectionalLightComponent":
                            lightComponent.CondenseArchetypes();
                            lightComponent.ObjectName = new NameReference("DirectionalLightComponent", dlcIndex++);
                            if (parent.ClassName == "StaticLightCollectionActor")
                            {
                                if (!componentToMatrixMap.TryGetValue(lightComponent.UIndex, out Matrix m))
                                {
                                    continue;
                                }
                                (Vector3 posVec, Vector3 scaleVec, Rotator rotator) = m.UnrealDecompose();
                                locationProp = CommonStructs.Vector3Prop(posVec, "Location");
                                rotationProp = CommonStructs.RotatorProp(rotator, "Rotation");
                                scaleProp    = CommonStructs.Vector3Prop(scaleVec, "DrawScale3D");
                            }
                            else
                            {
                                locationProp = parent.GetProperty <StructProperty>("Location");
                                rotationProp = parent.GetProperty <StructProperty>("Rotation");
                                scaleProp    = parent.GetProperty <StructProperty>("DrawScale3D");
                                if (parent.GetProperty <FloatProperty>("DrawScale")?.Value is float scale)
                                {
                                    Vector3 scaleVec = Vector3.One;
                                    if (scaleProp != null)
                                    {
                                        scaleVec = CommonStructs.GetVector3(scaleProp);
                                    }
                                    scaleProp = CommonStructs.Vector3Prop(scaleVec * scale, "DrawScale3D");
                                }
                            }

                            ExportEntry dla = new ExportEntry(udkPackage, EntryImporter.CreateStack(MEGame.UDK, directionalLightClass.UIndex))
                            {
                                ObjectName = new NameReference("DirectionalLight", dlaIndex++),
                                Class      = directionalLightClass,
                                Parent     = levelExport
                            };
                            dla.ObjectFlags |= UnrealFlags.EObjectFlags.HasStack;
                            udkPackage.AddExport(dla);

                            EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, lightComponent, udkPackage, dla, true,
                                                                 out IEntry portedDLC);
                            var dlaProps = new PropertyCollection
                            {
                                new ObjectProperty(portedDLC.UIndex, "LightComponent"),
                                new NameProperty("DirectionalLight", "Tag"),
                            };
                            if (locationProp != null)
                            {
                                dlaProps.Add(locationProp);
                            }
                            if (rotationProp != null)
                            {
                                dlaProps.Add(rotationProp);
                            }
                            if (scaleProp != null)
                            {
                                dlaProps.Add(scaleProp);
                            }
                            dla.WriteProperties(dlaProps);
                            lightActors.Add(dla);
                            break;
                        }
                    }
                }
                UDKifyLights(udkPackage);
                #endregion

                Level level = ObjectBinary.From <Level>(levelExport);
                level.Actors = levelExport.GetChildren().Where(ent => ent.IsA("Actor")).Select(ent => new UIndex(ent.UIndex)).ToList();
                levelExport.WriteBinary(level);

                udkPackage.Save();
            }

            string resultFilePath = Path.Combine(udkPath, @"UDKGame\Content\Maps\", $"{Path.GetFileNameWithoutExtension(pcc.FilePath)}.udk");
            using (IMEPackage udkPackage2 = MEPackageHandler.OpenUDKPackage(Path.Combine(App.ExecFolder, "empty.udk")))
            {
                ExportEntry levelExport = udkPackage2.Exports.First(exp => exp.ClassName == "Level");
                Level       levelBin    = ObjectBinary.From <Level>(levelExport);
                foreach (ExportEntry actor in staticMeshActors)
                {
                    EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneTreeAsChild, actor, udkPackage2, levelExport, true, out IEntry result);
                    levelBin.Actors.Add(result.UIndex);
                }
                foreach (ExportEntry actor in lightActors)
                {
                    EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneTreeAsChild, actor, udkPackage2, levelExport, true, out IEntry result);
                    levelBin.Actors.Add(result.UIndex);
                }
                levelExport.WriteBinary(levelBin);
                udkPackage2.Save(resultFilePath);
            }
            File.Delete(tempPackagePath);
            return(resultFilePath);
        }
示例#24
0
        /// <summary>
        /// Check if the signatures of a given System.Reflection and Mono.Cecil member reference match.
        /// </summary>
        /// <param name="mref">The Mono.Cecil member reference.</param>
        /// <param name="minfo">The System.Reflection member reference.</param>
        /// <returns>True if both references share the same signature, false otherwise.</returns>
        public static bool Is(this MemberReference mref, MemberInfo minfo)
        {
            if (mref == null)
            {
                return(false);
            }

            TypeReference mrefDecl = mref.DeclaringType;

            if (mrefDecl?.FullName == "<Module>")
            {
                mrefDecl = null;
            }

            if (mref is GenericParameter genParamRef)
            {
                if (!(minfo is Type genParamInfo))
                {
                    return(false);
                }

                if (!genParamInfo.IsGenericParameter)
                {
                    if (genParamRef.Owner is IGenericInstance genParamRefOwner)
                    {
                        return(genParamRefOwner.GenericArguments[genParamRef.Position].Is(genParamInfo));
                    }
                    else
                    {
                        return(false);
                    }
                }

                // Don't check owner as it introduces a circular check.

                /*
                 * if (!(genParamRef.Owner as MemberReference).Is(genParamInfo.DeclaringMethod ?? (System.Reflection.MemberInfo) genParamInfo.DeclaringType))
                 *  return false;
                 */
                return(genParamRef.Position == genParamInfo.GenericParameterPosition);
            }

            if (minfo.DeclaringType != null)
            {
                if (mrefDecl == null)
                {
                    return(false);
                }

                Type declType = minfo.DeclaringType;

                if (minfo is Type)
                {
                    // Note: type.DeclaringType is supposed to == type.DeclaringType.GetGenericTypeDefinition()
                    // For whatever reason, old versions of mono (f.e. shipped with Unity 5.0.3) break this,
                    // requiring us to call .GetGenericTypeDefinition() manually instead.
                    if (declType.IsGenericType && !declType.IsGenericTypeDefinition)
                    {
                        declType = declType.GetGenericTypeDefinition();
                    }
                }

                if (!mrefDecl.Is(declType))
                {
                    return(false);
                }
            }
            else if (mrefDecl != null)
            {
                return(false);
            }

            // Note: This doesn't work for TypeSpecification, as the reflection-side type.Name changes with some modifiers (f.e. IsArray).
            if (!(mref is TypeSpecification) && mref.Name != minfo.Name)
            {
                return(false);
            }

            if (mref is TypeReference typeRef)
            {
                if (!(minfo is Type typeInfo))
                {
                    return(false);
                }

                if (typeInfo.IsGenericParameter)
                {
                    return(false);
                }

                if (mref is GenericInstanceType genTypeRef)
                {
                    if (!typeInfo.IsGenericType)
                    {
                        return(false);
                    }

                    Collection <TypeReference> gparamRefs = genTypeRef.GenericArguments;
                    Type[] gparamInfos = typeInfo.GetGenericArguments();
                    if (gparamRefs.Count != gparamInfos.Length)
                    {
                        return(false);
                    }

                    for (int i = 0; i < gparamRefs.Count; i++)
                    {
                        if (!gparamRefs[i].Is(gparamInfos[i]))
                        {
                            return(false);
                        }
                    }

                    return(genTypeRef.ElementType.Is(typeInfo.GetGenericTypeDefinition()));
                }
                else if (typeRef.HasGenericParameters)
                {
                    if (!typeInfo.IsGenericType)
                    {
                        return(false);
                    }

                    Collection <GenericParameter> gparamRefs = typeRef.GenericParameters;
                    Type[] gparamInfos = typeInfo.GetGenericArguments();
                    if (gparamRefs.Count != gparamInfos.Length)
                    {
                        return(false);
                    }

                    for (int i = 0; i < gparamRefs.Count; i++)
                    {
                        if (!gparamRefs[i].Is(gparamInfos[i]))
                        {
                            return(false);
                        }
                    }
                }
                else if (typeInfo.IsGenericType)
                {
                    return(false);
                }

                if (mref is ArrayType arrayTypeRef)
                {
                    if (!typeInfo.IsArray)
                    {
                        return(false);
                    }

                    return(arrayTypeRef.Dimensions.Count == typeInfo.GetArrayRank() && arrayTypeRef.ElementType.Is(typeInfo.GetElementType()));
                }

                if (mref is ByReferenceType byRefTypeRef)
                {
                    if (!typeInfo.IsByRef)
                    {
                        return(false);
                    }

                    return(byRefTypeRef.ElementType.Is(typeInfo.GetElementType()));
                }

                if (mref is PointerType ptrTypeRef)
                {
                    if (!typeInfo.IsPointer)
                    {
                        return(false);
                    }

                    return(ptrTypeRef.ElementType.Is(typeInfo.GetElementType()));
                }

                if (mref is TypeSpecification typeSpecRef)
                {
                    // Note: There are TypeSpecifications which map to non-ElementType-y reflection Types.
                    return(typeSpecRef.ElementType.Is(typeInfo.HasElementType ? typeInfo.GetElementType() : typeInfo));
                }

                // DeclaringType was already checked before.
                // Avoid converting nested type separators between + (.NET) and / (cecil)
                if (mrefDecl != null)
                {
                    return(mref.Name == typeInfo.Name);
                }
                return(mref.FullName == typeInfo.FullName.Replace("+", "/"));
            }
            else if (minfo is Type)
            {
                return(false);
            }

            if (mref is MethodReference methodRef)
            {
                if (!(minfo is MethodBase methodInfo))
                {
                    return(false);
                }

                Collection <ParameterDefinition> paramRefs = methodRef.Parameters;
                ParameterInfo[] paramInfos = methodInfo.GetParameters();
                if (paramRefs.Count != paramInfos.Length)
                {
                    return(false);
                }

                if (mref is GenericInstanceMethod genMethodRef)
                {
                    if (!methodInfo.IsGenericMethod)
                    {
                        return(false);
                    }

                    Collection <TypeReference> gparamRefs = genMethodRef.GenericArguments;
                    Type[] gparamInfos = methodInfo.GetGenericArguments();
                    if (gparamRefs.Count != gparamInfos.Length)
                    {
                        return(false);
                    }

                    for (int i = 0; i < gparamRefs.Count; i++)
                    {
                        if (!gparamRefs[i].Is(gparamInfos[i]))
                        {
                            return(false);
                        }
                    }

                    return(genMethodRef.ElementMethod.Is((methodInfo as System.Reflection.MethodInfo)?.GetGenericMethodDefinition() ?? methodInfo));
                }
                else if (methodRef.HasGenericParameters)
                {
                    if (!methodInfo.IsGenericMethod)
                    {
                        return(false);
                    }

                    Collection <GenericParameter> gparamRefs = methodRef.GenericParameters;
                    Type[] gparamInfos = methodInfo.GetGenericArguments();
                    if (gparamRefs.Count != gparamInfos.Length)
                    {
                        return(false);
                    }

                    for (int i = 0; i < gparamRefs.Count; i++)
                    {
                        if (!gparamRefs[i].Is(gparamInfos[i]))
                        {
                            return(false);
                        }
                    }
                }
                else if (methodInfo.IsGenericMethod)
                {
                    return(false);
                }

                Relinker resolver = null;
                resolver = (paramMemberRef, ctx) => paramMemberRef is TypeReference paramTypeRef?ResolveParameter(paramTypeRef) : paramMemberRef;

                TypeReference ResolveParameter(TypeReference paramTypeRef)
                {
                    if (paramTypeRef is GenericParameter paramGenParamTypeRef)
                    {
                        if (paramGenParamTypeRef.Owner is MethodReference && methodRef is GenericInstanceMethod paramGenMethodRef)
                        {
                            return(paramGenMethodRef.GenericArguments[paramGenParamTypeRef.Position]);
                        }

                        if (paramGenParamTypeRef.Owner is TypeReference paramGenParamTypeRefOwnerType && methodRef.DeclaringType is GenericInstanceType genTypeRefRef &&
                            paramGenParamTypeRefOwnerType.FullName == genTypeRefRef.ElementType.FullName) // This is to prevent List<Tuple<...>> checks from incorrectly checking Tuple's args in List.
                        {
                            return(genTypeRefRef.GenericArguments[paramGenParamTypeRef.Position]);
                        }

                        return(paramTypeRef);
                    }

                    if (paramTypeRef == methodRef.DeclaringType.GetElementType())
                    {
                        return(methodRef.DeclaringType);
                    }

                    return(paramTypeRef);
                }

                if (!methodRef.ReturnType.Relink(resolver, null).Is(((methodInfo as System.Reflection.MethodInfo)?.ReturnType ?? typeof(void))) &&
                    !methodRef.ReturnType.Is(((methodInfo as System.Reflection.MethodInfo)?.ReturnType ?? typeof(void))))
                {
                    return(false);
                }

                for (int i = 0; i < paramRefs.Count; i++)
                {
                    if (!paramRefs[i].ParameterType.Relink(resolver, null).Is(paramInfos[i].ParameterType) &&
                        !paramRefs[i].ParameterType.Is(paramInfos[i].ParameterType))
                    {
                        return(false);
                    }
                }

                return(true);
            }
            else if (minfo is MethodInfo)
            {
                return(false);
            }

            if (mref is FieldReference != minfo is FieldInfo)
            {
                return(false);
            }

            if (mref is PropertyReference != minfo is PropertyInfo)
            {
                return(false);
            }

            if (mref is EventReference != minfo is EventInfo)
            {
                return(false);
            }

            return(true);
        }
示例#25
0
        public static TypeReference Relink(this TypeReference type, Relinker relinker,
                                           IGenericParameterProvider context)
        {
            if (type == null)
            {
                return(null);
            }

            if (type is TypeSpecification ts)
            {
                var relinkedElem = ts.ElementType.Relink(relinker, context);

                if (type.IsSentinel)
                {
                    return(new SentinelType(relinkedElem));
                }

                if (type.IsByReference)
                {
                    return(new ByReferenceType(relinkedElem));
                }

                if (type.IsPointer)
                {
                    return(new PointerType(relinkedElem));
                }

                if (type.IsPinned)
                {
                    return(new PinnedType(relinkedElem));
                }

                if (type.IsArray)
                {
                    var at = new ArrayType(relinkedElem, ((ArrayType)type).Rank);
                    for (var i = 0; i < at.Rank; i++)
                    {
                        // It's a struct.
                        at.Dimensions[i] = ((ArrayType)type).Dimensions[i];
                    }
                    return(at);
                }

                if (type.IsRequiredModifier)
                {
                    return(new RequiredModifierType(
                               ((RequiredModifierType)type).ModifierType.Relink(relinker, context), relinkedElem));
                }

                if (type.IsOptionalModifier)
                {
                    return(new OptionalModifierType(
                               ((OptionalModifierType)type).ModifierType.Relink(relinker, context), relinkedElem));
                }

                if (type.IsGenericInstance)
                {
                    var git = new GenericInstanceType(relinkedElem);
                    foreach (var genArg in ((GenericInstanceType)type).GenericArguments)
                    {
                        git.GenericArguments.Add(genArg?.Relink(relinker, context));
                    }
                    return(git);
                }

                if (!type.IsFunctionPointer)
                {
                    throw new NotSupportedException(
                              $"MonoMod can't handle TypeSpecification: {type.FullName} ({type.GetType()})");
                }
                var fp = (FunctionPointerType)type;
                fp.ReturnType = fp.ReturnType.Relink(relinker, context);
                foreach (var t in fp.Parameters)
                {
                    t.ParameterType = t.ParameterType.Relink(relinker, context);
                }

                return(fp);
            }

            if (type.IsGenericParameter)
            {
                var genParam = context.GetGenericParameter((GenericParameter)type);
                if (genParam == null)
                {
                    throw new RelinkTargetNotFoundException(
                              $"{RelinkTargetNotFoundException.DefaultMessage} {type.FullName} (context: {context})", type,
                              context);
                }
                for (var i = 0; i < genParam.Constraints.Count; i++)
                {
                    if (!genParam.Constraints[i].IsGenericInstance
                        ) // That is somehow possible and causes a stack overflow.
                    {
                        genParam.Constraints[i] = genParam.Constraints[i].Relink(relinker, context);
                    }
                }
                return(genParam);
            }

            return((TypeReference)relinker(type, context));
        }
示例#26
0
        protected override MethodInfo _Generate(DynamicMethodDefinition dmd, object context)
        {
            MethodDefinition def     = dmd.Definition;
            TypeDefinition   typeDef = context as TypeDefinition;

            bool             moduleIsTemporary   = false;
            ModuleDefinition module              = typeDef?.Module;
            HashSet <string> accessChecksIgnored = null;

            if (typeDef == null)
            {
                moduleIsTemporary   = true;
                accessChecksIgnored = new HashSet <string>();

                string name = dmd.GetDumpName("Cecil");
                module = ModuleDefinition.CreateModule(name, new ModuleParameters()
                {
                    Kind = ModuleKind.Dll,
#if !CECIL0_9
                    ReflectionImporterProvider = MMReflectionImporter.ProviderNoDefault
#endif
                });

                module.Assembly.CustomAttributes.Add(new CustomAttribute(module.ImportReference(DynamicMethodDefinition.c_UnverifiableCodeAttribute)));

                if (dmd.Debug)
                {
                    CustomAttribute caDebug = new CustomAttribute(module.ImportReference(DynamicMethodDefinition.c_DebuggableAttribute));
                    caDebug.ConstructorArguments.Add(new CustomAttributeArgument(
                                                         module.ImportReference(typeof(DebuggableAttribute.DebuggingModes)),
                                                         DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.Default
                                                         ));
                    module.Assembly.CustomAttributes.Add(caDebug);
                }

                typeDef = new TypeDefinition(
                    "",
                    $"DMD<{dmd.OriginalMethod?.Name?.Replace('.', '_')}>?{GetHashCode()}",
                    Mono.Cecil.TypeAttributes.Public | Mono.Cecil.TypeAttributes.Abstract | Mono.Cecil.TypeAttributes.Sealed | Mono.Cecil.TypeAttributes.Class
                    )
                {
                    BaseType = module.TypeSystem.Object
                };

                module.Types.Add(typeDef);
            }

            try {
#pragma warning disable IDE0039 // Use local function
                Relinker relinker = (mtp, ctx) => {
                    return(module.ImportReference(mtp));
                };
#pragma warning restore IDE0039 // Use local function

                MethodDefinition clone = new MethodDefinition("_" + def.Name.Replace('.', '_'), def.Attributes, module.TypeSystem.Void)
                {
                    MethodReturnType = def.MethodReturnType,
                    Attributes       = Mono.Cecil.MethodAttributes.Public | Mono.Cecil.MethodAttributes.HideBySig | Mono.Cecil.MethodAttributes.Public | Mono.Cecil.MethodAttributes.Static,
                    ImplAttributes   = Mono.Cecil.MethodImplAttributes.IL | Mono.Cecil.MethodImplAttributes.Managed,
                    DeclaringType    = typeDef,
                    NoInlining       = true
                };

                foreach (ParameterDefinition param in def.Parameters)
                {
                    clone.Parameters.Add(param.Clone().Relink(relinker, clone));
                }

                clone.ReturnType = def.ReturnType.Relink(relinker, clone);

                typeDef.Methods.Add(clone);

                clone.HasThis = def.HasThis;
                Mono.Cecil.Cil.MethodBody body = clone.Body = def.Body.Clone(clone);

                foreach (VariableDefinition var in clone.Body.Variables)
                {
                    var.VariableType = var.VariableType.Relink(relinker, clone);
                }

                foreach (ExceptionHandler handler in clone.Body.ExceptionHandlers)
                {
                    if (handler.CatchType != null)
                    {
                        handler.CatchType = handler.CatchType.Relink(relinker, clone);
                    }
                }

                for (int instri = 0; instri < body.Instructions.Count; instri++)
                {
                    Instruction instr   = body.Instructions[instri];
                    object      operand = instr.Operand;

                    // Import references.
                    if (operand is ParameterDefinition param)
                    {
                        operand = clone.Parameters[param.Index];
                    }
                    else if (operand is IMetadataTokenProvider mtp)
                    {
                        operand = mtp.Relink(relinker, clone);
                    }

                    if (operand is DynamicMethodReference dmref)
                    {
                        // TODO: Fix up DynamicMethod inline refs.
                    }

                    if (accessChecksIgnored != null && operand is MemberReference mref)
                    {
                        IMetadataScope asmRef = (mref as TypeReference)?.Scope ?? mref.DeclaringType.Scope;
                        if (!accessChecksIgnored.Contains(asmRef.Name))
                        {
                            CustomAttribute caAccess = new CustomAttribute(module.ImportReference(DynamicMethodDefinition.c_IgnoresAccessChecksToAttribute));
                            caAccess.ConstructorArguments.Add(new CustomAttributeArgument(
                                                                  module.ImportReference(typeof(DebuggableAttribute.DebuggingModes)),
                                                                  asmRef.Name
                                                                  ));
                            module.Assembly.CustomAttributes.Add(caAccess);
                            accessChecksIgnored.Add(asmRef.Name);
                        }
                    }

                    instr.Operand = operand;
                }

                clone.HasThis = false;

                if (def.HasThis)
                {
                    TypeReference type = def.DeclaringType;
                    if (type.IsValueType)
                    {
                        type = new ByReferenceType(type);
                    }
                    clone.Parameters.Insert(0, new ParameterDefinition("<>_this", Mono.Cecil.ParameterAttributes.None, type.Relink(relinker, clone)));
                }

                if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MONOMOD_DMD_DUMP")))
                {
                    string dir  = Path.GetFullPath(Environment.GetEnvironmentVariable("MONOMOD_DMD_DUMP"));
                    string name = module.Name + ".dll";
                    string path = Path.Combine(dir, name);
                    dir = Path.GetDirectoryName(path);
                    if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
                    {
                        Directory.CreateDirectory(dir);
                    }
                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                    using (Stream fileStream = File.OpenWrite(path))
                        module.Write(fileStream);
                }

                Assembly asm = ReflectionHelper.Load(module);

                return(asm.GetType(typeDef.FullName.Replace("+", "\\+"), false, false)
                       .GetMethod(clone.Name, BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static));
            } finally {
#if !CECIL0_9
                if (moduleIsTemporary)
                {
                    module.Dispose();
                }
#endif
            }
        }
        public MethodInfo GenerateViaCecil(TypeDefinition typeDef) {
            MethodDefinition def = Definition;

            bool moduleIsPrivate = false;
            ModuleDefinition module = typeDef?.Module;
            HashSet<string> accessChecksIgnored = null;
            if (typeDef == null) {
                moduleIsPrivate = true;
                accessChecksIgnored = new HashSet<string>();

                string name = $"DMDASM_{GetHashCode()}";
                module = ModuleDefinition.CreateModule(name + ".dll", new ModuleParameters() {
                    Kind = ModuleKind.Dll,
                    AssemblyResolver = new AssemblyCecilDefinitionResolver(_ModuleGen, new DefaultAssemblyResolver()),
                    ReflectionImporterProvider = new ReflectionCecilImporterProvider(null)
                });

#if !NETSTANDARD1_X
                module.Assembly.CustomAttributes.Add(new CustomAttribute(module.ImportReference(c_UnverifiableCodeAttribute)));
#endif

                if (Debug) {
                    CustomAttribute caDebug = new CustomAttribute(module.ImportReference(c_DebuggableAttribute));
                    caDebug.ConstructorArguments.Add(new CustomAttributeArgument(
                        module.ImportReference(typeof(DebuggableAttribute.DebuggingModes)),
                        DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.Default
                    ));
                    module.Assembly.CustomAttributes.Add(caDebug);
                }

                typeDef = new TypeDefinition(
                    "",
                    $"DMD<{Method?.GetFindableID(simple: true)?.Replace('.', '_')}>?{GetHashCode()}",
                    Mono.Cecil.TypeAttributes.Public | Mono.Cecil.TypeAttributes.Abstract | Mono.Cecil.TypeAttributes.Sealed | Mono.Cecil.TypeAttributes.Class
                ) {
                    BaseType = module.TypeSystem.Object
                };

                module.Types.Add(typeDef);
            }

            try {

#pragma warning disable IDE0039 // Use local function
                Relinker relinker = (mtp, ctx) => {
                    return module.ImportReference(mtp);
                };
#pragma warning restore IDE0039 // Use local function

                MethodDefinition clone = new MethodDefinition("_" + def.Name.Replace('.', '_'), def.Attributes, module.TypeSystem.Void) {
                    MethodReturnType = def.MethodReturnType,
                    Attributes = Mono.Cecil.MethodAttributes.Public | Mono.Cecil.MethodAttributes.HideBySig | Mono.Cecil.MethodAttributes.Public | Mono.Cecil.MethodAttributes.Static,
                    ImplAttributes = Mono.Cecil.MethodImplAttributes.IL | Mono.Cecil.MethodImplAttributes.Managed,
                    DeclaringType = typeDef,
                    NoInlining = true
                };

                foreach (ParameterDefinition param in def.Parameters)
                    clone.Parameters.Add(param.Clone().Relink(relinker, clone));

                clone.ReturnType = def.ReturnType.Relink(relinker, clone);

                typeDef.Methods.Add(clone);

                clone.HasThis = def.HasThis;
                Mono.Cecil.Cil.MethodBody body = clone.Body = def.Body.Clone(clone);

                foreach (VariableDefinition var in clone.Body.Variables)
                    var.VariableType = var.VariableType.Relink(relinker, clone);

                foreach (ExceptionHandler handler in clone.Body.ExceptionHandlers)
                    if (handler.CatchType != null)
                        handler.CatchType = handler.CatchType.Relink(relinker, clone);

                for (int instri = 0; instri < body.Instructions.Count; instri++) {
                    Instruction instr = body.Instructions[instri];
                    object operand = instr.Operand;

                    // Import references.
                    if (operand is ParameterDefinition param) {
                        operand = clone.Parameters[param.Index];

                    } else if (operand is IMetadataTokenProvider mtp) {
                        operand = mtp.Relink(relinker, clone);

                    }

                    if (operand is DynamicMethodReference dmref) {
                        // TODO: Fix up DynamicMethod inline refs.
                    }

                    if (accessChecksIgnored != null && operand is MemberReference mref) {
                        // TODO: Only do the following for inaccessible members.
                        IMetadataScope asmRef = (mref as TypeReference)?.Scope ?? mref.DeclaringType.Scope;
                        if (!accessChecksIgnored.Contains(asmRef.Name)) {
                            CustomAttribute caAccess = new CustomAttribute(module.ImportReference(c_IgnoresAccessChecksToAttribute));
                            caAccess.ConstructorArguments.Add(new CustomAttributeArgument(
                                module.ImportReference(typeof(DebuggableAttribute.DebuggingModes)),
                                asmRef.Name
                            ));
                            module.Assembly.CustomAttributes.Add(caAccess);
                            accessChecksIgnored.Add(asmRef.Name);
                        }
                    }

                    instr.Operand = operand;
                }

                clone.HasThis = false;

                if (def.HasThis) {
                    TypeReference type = def.DeclaringType;
                    if (type.IsValueType)
                        type = new ByReferenceType(type);
                    clone.Parameters.Insert(0, new ParameterDefinition("<>_this", Mono.Cecil.ParameterAttributes.None, type.Relink(relinker, clone)));
                }

                if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MONOMOD_DMD_DUMP"))) {
                    string dir = Path.GetFullPath(Environment.GetEnvironmentVariable("MONOMOD_DMD_DUMP"));
                    string name = module.Name + ".dll";
                    string path = Path.Combine(dir, name);
                    dir = Path.GetDirectoryName(path);
                    if (!Directory.Exists(dir))
                        Directory.CreateDirectory(dir);
                    if (File.Exists(path))
                        File.Delete(path);
                    using (Stream fileStream = File.OpenWrite(path))
                        module.Write(fileStream);
                }

                Assembly asm;
                using (MemoryStream asmStream = new MemoryStream()) {
                    module.Write(asmStream);
                    asmStream.Seek(0, SeekOrigin.Begin);
#if NETSTANDARD1_X
                    // System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromStream(asmStream);
                    asm = (Assembly) _AssemblyLoadContext_LoadFromStream.Invoke(_AssemblyLoadContext_Default, new object[] { asmStream });
#else
                    asm = Assembly.Load(asmStream.GetBuffer());
#endif
                }

                _DynModuleCache[module.Assembly.Name.FullName] = module.Assembly;
                _DynModuleReflCache[asm.GetModules()[0]] = module;
                _DynModuleIsPrivate = false;
                moduleIsPrivate = false;

#if !NETSTANDARD1_X
                AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
                    if (args.Name == asm.GetName().FullName || args.Name == asm.GetName().Name || args.Name == asm.FullName)
                        return asm;
                    return null;
                };
#endif

                return _Postbuild(asm.GetType(typeDef.FullName.Replace("+", "\\+"), false, false).GetMethod(clone.Name));

            } finally {
                if (moduleIsPrivate)
                    module.Dispose();
            }
        }
示例#28
0
        public static TypeReference Relink(this TypeReference type, Relinker relinker, IGenericParameterProvider context)
        {
            if (type == null)
            {
                return(null);
            }

            if (type is TypeSpecification)
            {
                TypeSpecification ts           = (TypeSpecification)type;
                TypeReference     relinkedElem = ts.ElementType.Relink(relinker, context);

                if (type.IsByReference)
                {
                    return(new ByReferenceType(relinkedElem));
                }

                if (type.IsPointer)
                {
                    return(new PointerType(relinkedElem));
                }

                if (type.IsPinned)
                {
                    return(new PinnedType(relinkedElem));
                }

                if (type.IsArray)
                {
                    return(new ArrayType(relinkedElem, ((ArrayType)type).Dimensions.Count));
                }

                if (type.IsRequiredModifier)
                {
                    return(new RequiredModifierType(((RequiredModifierType)type).ModifierType.Relink(relinker, context), relinkedElem));
                }

                if (type.IsOptionalModifier)
                {
                    return(new OptionalModifierType(((OptionalModifierType)type).ModifierType.Relink(relinker, context), relinkedElem));
                }

                if (type.IsGenericInstance)
                {
                    GenericInstanceType git = new GenericInstanceType(relinkedElem);
                    foreach (TypeReference genArg in ((GenericInstanceType)type).GenericArguments)
                    {
                        git.GenericArguments.Add(genArg?.Relink(relinker, context));
                    }
                    return(git);
                }

                if (type.IsFunctionPointer)
                {
                    FunctionPointerType fp = (FunctionPointerType)type;
                    fp.ReturnType = fp.ReturnType.Relink(relinker, context);
                    for (int i = 0; i < fp.Parameters.Count; i++)
                    {
                        fp.Parameters[i].ParameterType = fp.Parameters[i].ParameterType.Relink(relinker, context);
                    }
                    return(fp);
                }

                throw new InvalidOperationException($"MonoMod can't handle TypeSpecification: {type.FullName} ({type.GetType()})");
            }

            if (type.IsGenericParameter)
            {
                GenericParameter genParam = context.GetGenericParameter(((GenericParameter)type).Name);
                for (int i = 0; i < genParam.Constraints.Count; i++)
                {
                    if (!genParam.Constraints[i].IsGenericInstance) // That is somehow possible and causes a stack overflow.
                    {
                        genParam.Constraints[i] = genParam.Constraints[i].Relink(relinker, context);
                    }
                }
                return(genParam);
            }

            return((TypeReference)relinker(type, context));
        }
示例#29
0
        public static FieldReference Relink(this FieldReference field, Relinker relinker, IGenericParameterProvider context)
        {
            TypeReference declaringType = field.DeclaringType.Relink(relinker, context);

            return((FieldReference)relinker(new FieldReference(field.Name, field.FieldType.Relink(relinker, declaringType), declaringType), context));
        }