Ejemplo n.º 1
0
        public override void Execute(RevisionUpdateSchemaConfig config, string lifecycleEvent, IMinecraftInstance instance)
        {
            if (!Uri.IsWellFormedUriString(config.UpdateUrl, UriKind.Absolute))
            {
                throw new FormatException($"Revision based updater '{GetType().FullName}' could not resolve update url '{config.UpdateUrl}' provided by configuration.");
            }

            logger.Info("Checking for modpack updates...");

            using (WebClient client = new WebClient()) {
                ModpackDefinition remoteModpack = JsonConvert.DeserializeObject <ModpackDefinition>(client.DownloadString(config.UpdateUrl));

                // Check if remote modpack has configuration for this adapter type
                // Without this we can't check for revision number changes and perform the update
                if (!remoteModpack.Adapters.ContainsKey(Id))
                {
                    throw new InvalidOperationException($"Revision based updater '{GetType().FullName}' failed to obtain revision number from update source because adapter configuration is missing.");
                }

                RevisionUpdateSchemaConfig remoteConfig = JObject.FromObject(remoteModpack.Adapters[Id]).ToObject <RevisionUpdateSchemaConfig>();

                // If there is an update available
                if (config.Revision != remoteConfig.Revision)
                {
                    Packsly.Lifecycle.EventBus.Publish(instance, Lifecycle.UpdateStarted);
                    logger.Info($"Updating modpack from revision {config.Revision} to {remoteConfig.Revision}!");

                    // Update instance config
                    // TODO: Add config option to the update adapter for this

                    /*
                     * foreach (KeyValuePair<string, object> environmentEntry in remoteModpack.Environments) {
                     *  if (environmentEntry.Key != Packsly.Launcher.Name) {
                     *      continue;
                     *  }
                     *
                     *  string settings = environmentEntry.Value.ToString();
                     *  Logger.Debug($"Updating configuration of minecraft instance {instance.Id} from modpack environment settings: {settings}");
                     *  instance.Configure(settings);
                     *  break;
                     * }
                     */

                    // Update modloaders and mods
                    UpdateModloaders(instance, remoteModpack);
                    UpdateMods(instance, remoteModpack);

                    // Update adapter settings saved in instnace.packsly file, because revision number has changed
                    Save(instance, remoteConfig);
                    Packsly.Lifecycle.EventBus.Publish(instance, Lifecycle.UpdateFinished);
                }
            }

            logger.Info("Modpack is up to date.");
        }
Ejemplo n.º 2
0
        private static Task SaveModpacksAsync()
        {
            var factory = new ExporterFactory();

            int id          = 0;
            var modMappings = new Dictionary <Mod, int>();

            foreach (var modManager in Manager.ModManagers)
            {
                foreach (var mod in modManager)
                {
                    // Assign an ID to every mod (note we do actually want reference equality here)
                    modMappings.Add(mod, id);

                    var modDef = new ModDefinition(id, mod.Name, ExportMode.SpecificVersion, mod.Version);
                    factory.ModDefinitions.Add(modDef);

                    id++;
                }
            }

            var modpackMappings = _modpacks.Swap(); // Safe here since both directions are unique

            foreach (var modpack in Modpacks)
            {
                var modIds     = new List <int>();
                var modpackIds = new List <int>();

                foreach (var child in modpack)
                {
                    if (child is Mod mod)
                    {
                        int modId = modMappings[mod];
                        modIds.Add(modId);
                    }
                    else if (child is Modpack subPack)
                    {
                        int packId = modpackMappings[subPack];
                        modpackIds.Add(packId);
                    }
                }

                var packDef = new ModpackDefinition(modpackMappings[modpack], modpack.DisplayName, modIds, modpackIds);
                factory.ModpackDefinitions.Add(packDef);
            }

            var    exporter = factory.CreateExporter();
            string path     = Path.Combine(ApplicationDataDirectory.FullName, "modpacks.json");

            return(exporter.ExportAsync(path));
        }
Ejemplo n.º 3
0
        private static void UpdateMods(IMinecraftInstance instance, ModpackDefinition modpack)
        {
            // Remove local mods that are no longer in modpack
            foreach (FileInfo modFile in instance.Files.GetGroup(FileManager.GroupType.Mod))
            {
                if (modpack.Mods.Any(mod => mod.GetFilePath(instance.EnvironmentVariables) == modFile.FullName))
                {
                    continue;
                }

                logger.Info($"Removing mod {modFile.Name}...");
                instance.Files.Remove(modFile, FileManager.GroupType.Mod);
            }

            // Remove local resource files (configuration) that are no longer in modpack
            RemoteResource[] modpackResources = modpack.Mods.SelectMany(m => m.Resources).ToArray();
            foreach (FileInfo resourceFile in instance.Files.GetGroup(FileManager.GroupType.Resource))
            {
                if (modpackResources.Any(res => res.GetFilePath(instance.EnvironmentVariables) == resourceFile.FullName))
                {
                    continue;
                }

                logger.Info($"Removing resource {resourceFile.Name}...");
                instance.Files.Remove(resourceFile, FileManager.GroupType.Resource);
            }

            // Download mods that are defined in modpack but aren't available locally
            // NOTE: CanDownload property handles environment specific restrictions
            foreach (ModSource modpackMod in modpack.Mods.Where(mod => mod.CanDownload))
            {
                // Download new mods based on file name
                if (!instance.Files.GroupContains(FileManager.GroupType.Mod, modpackMod))
                {
                    logger.Info($"Downloading mod {modpackMod.FileName}...");
                    instance.Files.Download(modpackMod, FileManager.GroupType.Mod);
                }

                // Re-downland all resource files, no matter if they changed or not
                foreach (RemoteResource modpackResource in modpackMod.Resources.Where(resource => resource.CanDownload))
                {
                    logger.Info($"Downloading resource {modpackResource.FileName}...");
                    instance.Files.Download(modpackResource, FileManager.GroupType.Resource);
                }
            }
        }
Ejemplo n.º 4
0
        public IMinecraftInstance CreateInstance(DirectoryInfo workspace, string id, ModpackDefinition modpack)
        {
            DirectoryInfo instancesFolder = workspace.GetDirectories("instances").FirstOrDefault();

            if (instancesFolder == null)
            {
                instancesFolder = workspace.CreateSubdirectory("instances");
            }
            else
            {
                if (instancesFolder.GetDirectories().Any(dir => dir.Name == id))
                {
                    throw new DuplicateNameException($"Instance with id '{id}' already exists!");
                }
            }

            DirectoryInfo instanceFolder = new DirectoryInfo(Path.Combine(instancesFolder.FullName, id));

            return(new MmcMinecraftInstance(instanceFolder));
        }
Ejemplo n.º 5
0
        private static IMinecraftInstance CreateMinecraftInstnace(string instanceId, ModpackDefinition modpackDefinition)
        {
            IMinecraftInstance instance = Packsly.Launcher.CreateInstance(instanceId, modpackDefinition);

            // Set base minecraft instance properties
            instance.Name             = modpackDefinition.Name;
            instance.MinecraftVersion = modpackDefinition.MinecraftVersion;
            instance.Icon.Source      = modpackDefinition.Icon;
            logger.Debug($"Setting minecraft instance properties id={instance.Id} name={instance.Name} mc={instance.MinecraftVersion} icon={instance.Icon.Source}");

            // Load defaults
            instance.Load();

            // Save adapters defined in modpack along with configuration to packsly instance config file
            foreach (KeyValuePair <string, object> adapterDefinition in modpackDefinition.Adapters)
            {
                string adapterName     = adapterDefinition.Key;
                object adapterSettings = adapterDefinition.Value;

                logger.Debug($"Setting adapter config for {adapterName} for minecraft instance {instance.Id}");
                instance.PackslyConfig.Adapters.SetConfigFor(adapterName, adapterSettings);
            }

            // Configure instance using compatible environment settings
            foreach (KeyValuePair <string, object> environmentEntry in modpackDefinition.Environments)
            {
                string name = environmentEntry.Key;
                if (name != Packsly.Launcher.Name)
                {
                    continue;
                }

                string settings = environmentEntry.Value.ToString();
                logger.Debug($"Configuring minecraft instance {instance.Id} from modpack environment settings: {settings}");
                instance.Configure(settings);
                break;
            }

            return(instance);
        }
Ejemplo n.º 6
0
        private static void UpdateModloaders(IMinecraftInstance instance, ModpackDefinition modpack)
        {
            // Install or update mod-loaders
            foreach (KeyValuePair <string, string> modloaderEntry in modpack.ModLoaders)
            {
                string name    = modloaderEntry.Key;
                string version = modloaderEntry.Value;

                if (!instance.ModLoaderManager.ModLoaders.Any(ml => ml.Name == name && ml.Version != version))
                {
                    continue;
                }

                logger.Info($"Installing modloader '{name}' version '{version}'...");
                instance.ModLoaderManager.Install(name, version);
            }

            // Remove unused mod-loaders
            foreach (ModLoaderInfo modLoader in instance.ModLoaderManager.ModLoaders.Where(ml => !modpack.ModLoaders.ContainsKey(ml.Name)))
            {
                logger.Info($"Uninstalling modloader '{modLoader.Name}' version '{modLoader.Version}'");
                instance.ModLoaderManager.Uninstall(modLoader.Name);
            }
        }
Ejemplo n.º 7
0
        public static IMinecraftInstance CreateFromModpack(string modpackJson)
        {
            ModpackDefinition modpackDefinition = JsonConvert.DeserializeObject <ModpackDefinition>(modpackJson);

            char[] invalidChars = Path.GetInvalidFileNameChars();
            // TODO: Allow name overrides
            string instanceId = new string(modpackDefinition.Name.ToLowerInvariant().Where(m => !invalidChars.Contains(m)).ToArray());

            instanceId = instanceId.Replace(" ", "-");
            logger.Info($"Modpack name is '{modpackDefinition.Name}' using instance id '{instanceId}'.");

            IMinecraftInstance instance = CreateMinecraftInstnace(instanceId, modpackDefinition);

            Packsly.Lifecycle.EventBus.Publish(instance, Lifecycle.PreInstallation);

            try {
                // Install modloaders
                logger.Info("Setting up modloaders...");
                foreach (KeyValuePair <string, string> modloaderEntry in modpackDefinition.ModLoaders)
                {
                    string name    = modloaderEntry.Key;
                    string version = modloaderEntry.Value;

                    logger.Info($"Installing modloader '{name}' with version {version}.");
                    instance.ModLoaderManager.Install(name, version);
                }

                // Download mods
                logger.Info("Downloading required files...");
                foreach (ModSource mod in modpackDefinition.Mods)
                {
                    if (mod.CanDownload)
                    {
                        logger.Info($"Downloading mod {mod.FileName}...");
                        instance.Files.Download(mod, FileManager.GroupType.Mod);
                    }
                    else
                    {
                        logger.Info($"Skipping downloading mod {mod.FileName} since it is {(mod.EnvironmentOnly.IsBlacklist ? "blacklisted" : "whitelisted")} at '{string.Join(", ", mod.EnvironmentOnly.Entries)}'...");
                    }

                    // Download mod resources
                    foreach (RemoteResource resource in mod.Resources)
                    {
                        if (resource.CanDownload)
                        {
                            logger.Info($" - Downloading resource {resource.FileName}...");
                            instance.Files.Download(resource, FileManager.GroupType.Resource);
                        }
                        else
                        {
                            logger.Info($" - Skipping downloading resource {resource.FileName} since it is {(resource.EnvironmentOnly.IsBlacklist ? "blacklisted" : "whitelisted")} at '{string.Join(", ", resource.EnvironmentOnly.Entries)}'...");
                        }
                    }
                }

                instance.Save();
                logger.Info("Finishing installation.");
                Packsly.Lifecycle.EventBus.Publish(instance, Lifecycle.PostInstallation);
            } catch (Exception) {
                // Delete the instance if creation fails
                logger.Warn("Modpack installation failed, removing instance files.");
                instance.Delete();
                throw;
            }

            return(instance);
        }
Ejemplo n.º 8
0
 public IMinecraftInstance CreateInstance(DirectoryInfo workspace, string id, ModpackDefinition modpack)
 {
     return(new ServerMinecraftInstance(workspace));
 }