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."); }
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)); }
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); } } }
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)); }
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); }
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); } }
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); }
public IMinecraftInstance CreateInstance(DirectoryInfo workspace, string id, ModpackDefinition modpack) { return(new ServerMinecraftInstance(workspace)); }