using System.Linq; using CliWrap; using DTLib.Extensions; using Млаумчерб.Клиент.зримое; using Млаумчерб.Клиент.классы; using Млаумчерб.Клиент.сеть; using Млаумчерб.Клиент.сеть.NetworkTaskFactories; using static Млаумчерб.Клиент.классы.Пути; namespace Млаумчерб.Клиент; public class GameVersion { private readonly GameVersionProps _props; public string Name => _props.Name; public IOPath WorkingDirectory { get; } private IOPath JavaExecutableFilePath; private GameVersionDescriptor descriptor; private JavaArguments javaArgs; private GameArguments gameArgs; private Libraries libraries; private CancellationTokenSource? gameCts; private CommandTask? commandTask; public static async Task> GetAllVersionsAsync() { var propsSet = new HashSet(); // local descriptors foreach (IOPath f in Directory.GetFiles(GetVersionDescriptorsDir())) { string name = GetVersionDescriptorName(f); propsSet.Add(new GameVersionProps(name, null, f)); } // remote non-duplicating versions foreach (var removeVersion in await Сеть.GetDownloadableVersions()) { propsSet.Add(removeVersion); } // reverse sort var propsList = propsSet.ToList(); propsList.Sort((a, b) => b.CompareTo(a)); return propsList; } public static async Task CreateFromPropsAsync(GameVersionProps props) { if (!File.Exists(props.LocalDescriptorPath)) { if (props.RemoteDescriptorUrl is null) throw new NullReferenceException("can't download game version descriptor '" + props.Name + "', because RemoteDescriptorUrl is null"); await Сеть.DownloadFile(props.RemoteDescriptorUrl, props.LocalDescriptorPath); } return new GameVersion(props); } private GameVersion(GameVersionProps props) { _props = props; string descriptorText = File.ReadAllText(props.LocalDescriptorPath); descriptor = JsonConvert.DeserializeObject(descriptorText) ?? throw new Exception($"can't parse descriptor file '{props.LocalDescriptorPath}'"); javaArgs = new JavaArguments(descriptor); gameArgs = new GameArguments(descriptor); libraries = new Libraries(descriptor); WorkingDirectory = GetVersionDir(descriptor.id); JavaExecutableFilePath = GetJavaExecutablePath(descriptor.javaVersion.component); } public async Task UpdateFiles(bool checkHashes, Action networkTaskCreatedCallback) { Приложение.Логгер.LogInfo(nameof(GameVersion), $"started updating version {Name}"); List taskFactories = [ new AssetsDownloadTaskFactory(descriptor), new LibrariesDownloadTaskFactory(descriptor, libraries), new VersionFileDownloadTaskFactory(descriptor), ]; if(Приложение.Настройки.скачивать_жабу) { taskFactories.Add(new JavaDownloadTaskFactory(descriptor)); } //TODO: modpack /*if (modpack != null) { taskFactories.Add(new ModpackDownloadTaskFactory(modpack)); }*/ var networkTasks = new List(); for (int i = 0; i < taskFactories.Count; i++) { var nt = await taskFactories[i].CreateAsync(checkHashes); if (nt != null) { networkTasks.Add(nt); networkTaskCreatedCallback.Invoke(nt); } } foreach (var nt in networkTasks) { await nt.StartAsync(); } _props.IsDownloaded = true; Приложение.Логгер.LogInfo(nameof(GameVersion), $"finished updating version {Name}"); } public async Task Launch() { var javaArgsList = javaArgs.FillPlaceholders([]); var gameArgsList = gameArgs.FillPlaceholders([]); var command = Cli.Wrap(JavaExecutableFilePath.ToString()) .WithWorkingDirectory(WorkingDirectory.ToString()) .WithArguments(javaArgsList) .WithArguments(gameArgsList); Приложение.Логгер.LogInfo(nameof(GameVersion), $"launching the game" + "\njava: " + command.TargetFilePath + "\nworking_dir: " + command.WorkingDirPath + "\njava_arguments: \n\t" + javaArgsList.MergeToString("\n\t") + "\ngame_arguments: \n\t" + gameArgsList.MergeToString("\n\t")); gameCts = new(); commandTask = command.ExecuteAsync(gameCts.Token); var result = await commandTask; Приложение.Логгер.LogInfo(nameof(GameVersion), $"game exited with code {result.ExitCode}"); } public void Close() { gameCts?.Cancel(); } public override string ToString() => Name; }