Ejemplo n.º 1
0
        public static void LoadModZIP(string archive)
        {
            if (!File.Exists(archive))
            {
                // Probably a mod in the mod directory
                archive = Path.Combine(ModsDirectory, archive);
            }
            if (!File.Exists(archive))
            {
                // It just doesn't exist.
                return;
            }

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

            GameModMetadata meta = null;
            Assembly        asm  = null;

            using (ZipFile zip = ZipFile.Read(archive)) {
                Texture2D icon = null;
                // First read the metadata, ...
                foreach (ZipEntry entry in zip.Entries)
                {
                    if (entry.FileName == "metadata.yaml")
                    {
                        using (MemoryStream ms = new MemoryStream()) {
                            entry.Extract(ms);
                            ms.Seek(0, SeekOrigin.Begin);
                            using (StreamReader reader = new StreamReader(ms))
                                meta = GameModMetadata.Parse(archive, "", reader);
                        }
                        continue;
                    }
                    if (entry.FileName == "icon.png")
                    {
                        icon      = new Texture2D(2, 2);
                        icon.name = "icon";
                        using (MemoryStream ms = new MemoryStream()) {
                            entry.Extract(ms);
                            ms.Seek(0, SeekOrigin.Begin);
                            icon.LoadImage(ms.GetBuffer());
                        }
                        icon.filterMode = FilterMode.Point;
                        continue;
                    }
                }

                if (meta != null)
                {
                    // In case the icon appears before the metadata in the .zip
                    if (icon != null)
                    {
                        meta.Icon = icon;
                    }

                    // ... then check if the mod runs on this profile ...
                    if (meta.ProfileID > ModAPI.Profile.Id)
                    {
                        ModLogger.Log("loader", "Mod meant for an in-dev YLMAPI version!");
                        return;
                    }

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

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

                // ... then the patch (if any) ...
                if (!string.IsNullOrEmpty(meta?.PatchDLL))
                {
                    foreach (ZipEntry entry in zip.Entries)
                    {
                        string entryName = entry.FileName.Replace("\\", "/");
                        if (entryName != meta.PatchDLL)
                        {
                            continue;
                        }

                        using (MemoryStream ms = new MemoryStream()) {
                            entry.Extract(ms);
                            ms.Seek(0, SeekOrigin.Begin);
                            ModRuntimePatcher.LoadPatch(ms);
                        }

                        break;
                    }
                }

                // ... then everything else
                foreach (ZipEntry entry in zip.Entries)
                {
                    string entryName = entry.FileName.Replace("\\", "/");
                    if (meta != null && entryName == meta.DLL)
                    {
                        using (MemoryStream ms = new MemoryStream()) {
                            entry.Extract(ms);
                            ms.Seek(0, SeekOrigin.Begin);
                            if (meta.Prelinked)
                            {
                                asm = Assembly.Load(ms.GetBuffer());
                            }
                            else
                            {
                                asm = meta.GetRelinkedAssembly(ms);
                            }
                        }
                    }

                    ModContent.AddMapping(entryName, new AssetMetadata(archive, entryName)
                    {
                        AssetType = entry.IsDirectory ? typeof(AssetTypeDirectory) : null
                    });
                }
            }

            if (meta != null && asm != null)
            {
                LoadMod(meta, asm);
            }
        }