public EnvironmentVariables(IMinecraftInstance instance, IDictionary <string, string> properties) { // Register defaults if (!properties.ContainsKey(ModsFolder)) { properties.Add(ModsFolder, Path.Combine(instance.Location.FullName, "mods")); } if (!properties.ContainsKey(ConfigFolder)) { properties.Add(ConfigFolder, Path.Combine(instance.Location.FullName, "config")); } if (!properties.ContainsKey(InstnaceFolder)) { properties.Add(InstnaceFolder, instance.Location.FullName); } if (!properties.ContainsKey(RootFolder)) { properties.Add(RootFolder, Path.Combine(instance.Location.FullName, "minecraft")); } // Order by longest value string (this is important when converting from paths) Properties = new ReadOnlyDictionary <string, string>( properties.OrderByDescending(prop => prop.Value.Length).ToDictionary(k => k.Key, v => v.Value) ); logger.Debug($"Environment variables of minecraft instance {instance} were set to: {Environment.NewLine + string.Join(Environment.NewLine, Properties.Select(pair => $"{pair.Key} <-> {pair.Value}"))}"); }
public void Save(IMinecraftInstance instance, object config) { PackslyInstanceFile cfg = instance.PackslyConfig; cfg.Adapters.SetConfigFor(this, config); cfg.Save(); }
public void Publish(IMinecraftInstance instance, IEnumerable <string> eventNames) { foreach (string eventName in eventNames) { Publish(instance, eventName); } }
public static void Publish(LifecycleOptions options) { Logo.Print(); ApplySettings(options); IMinecraftInstance instance = Packsly.Launcher.GetInstance(options.InstanceId); instance.Load(); logger.Debug($"Dispatching lifecycle events specified by command line arguments: {string.Join(", ", options.Events)}"); Packsly.Lifecycle.EventBus.Publish(instance, options.Events); instance.Save(); }
public ModLoaderManager(IMinecraftInstance mcInstnace) { mcInstance = mcInstnace; modLoaders = new List <ModLoaderInfo>(); ModLoaders = modLoaders.AsReadOnly(); compatibleSchemata = InstalationSchemas.Where(s => s.IsCompatible(mcInstnace)).ToArray(); foreach (IModLoaderHandler handler in compatibleSchemata) { handler.DetectModLoaders(mcInstnace, modLoaders); } Logger.Debug($"Detected mod loaders for instance {mcInstnace.GetType()} with name {mcInstance.Name}: {JsonConvert.SerializeObject(ModLoaders, Formatting.Indented)}"); }
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 FileManager(IMinecraftInstance instance) { this.instance = instance; // Remove missing or non-existent files foreach (GroupType group in Enum.GetValues(typeof(GroupType))) { FileInfo[] missingFiles = GetNotExistingFiles(group); if (missingFiles.Length == 0) { continue; } foreach (FileInfo file in missingFiles) { logger.Debug("Removing non-existing tracked file."); Remove(file, group); } } }
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 bool TryGetAdapterConfig(IAdapter adapter, IMinecraftInstance instance, out JObject config) { // Set default return value for the config config = null; // Try to get adapter config from the instance object adapterConfig = instance.PackslyConfig.Adapters.GetConfigFor(adapter); // This adapter has no configuration if (adapterConfig == null) { return(true); } // Try to parse adapter config try { config = JObject.FromObject(adapterConfig); return(true); } catch (Exception ex) { logger.Error(ex, $"Failed to parse configuration for adapter {adapter.Id}"); } return(false); }
public abstract bool IsCompatible(IMinecraftInstance instance);
private FileInfo GetForgeJarFile(IMinecraftInstance instance) { return(instance.Location .EnumerateFiles() .FirstOrDefault(file => forgeJarFilePattern.IsMatch(file.Name))); }
public void Uninstall(IMinecraftInstance instance, string modLoader) => Uninstall((T)instance, modLoader);
public bool IsCompatible(IMinecraftInstance instance) => instance.GetType() == typeof(T);
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."); }
public override bool IsCompatible(IMinecraftInstance instance) => true;
public void Install(IMinecraftInstance instance, string modLoader, string version) => Install((T)instance, modLoader, version);
public void Execute(JObject config, string lifecycleEvent, IMinecraftInstance instance) { Execute((TConfig)config?.ToObject(typeof(TConfig)), lifecycleEvent, instance); }
protected internal ChangedEventArgs(IMinecraftInstance instance, string eventName) { Instance = instance; EventName = eventName; }
public void Publish(IMinecraftInstance instance, string eventName) { logger.Debug($"Publishing lifecycle event '{eventName}' {(instance == null ? "..." : $" for minecraft instance '{instance.Id}'...")}");
public abstract void Execute(TConfig config, string lifecycleEvent, IMinecraftInstance instance);
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 override bool IsCompatible(IMinecraftInstance instance) { return(instance.GetType() == typeof(TInstance)); }
public void DetectModLoaders(IMinecraftInstance instance, List <ModLoaderInfo> modLoaders) => DetectModLoaders((T)instance, modLoaders);