diff --git a/Mlaumcherb.Client.Avalonia/Config.cs b/Mlaumcherb.Client.Avalonia/Config.cs index e0b11c3..470b88b 100644 --- a/Mlaumcherb.Client.Avalonia/Config.cs +++ b/Mlaumcherb.Client.Avalonia/Config.cs @@ -20,7 +20,7 @@ public record Config public bool redirect_game_output { get; set; } = false; public string? last_launched_version { get; set; } public int max_parallel_downloads { get; set; } = 16; - public VersionCatalogProps[] version_catalogs { get; set; } = + public GameVersionCatalogProps[] version_catalogs { get; set; } = [ new() { name = "Mojang", url = "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json" }, new() { name = "Тимериховое", url = "https://timerix.ddns.net/minecraft/catalog.json" } @@ -31,10 +31,10 @@ public record Config public static Config LoadFromFile() { - LauncherApp.Logger.LogInfo(nameof(Config), $"loading config from file '{_filePath}'"); + LauncherApp.Logger.LogDebug(nameof(Config), $"loading config from file '{_filePath}'"); if(!File.Exists(_filePath)) { - LauncherApp.Logger.LogInfo(nameof(Config), "file doesn't exist"); + LauncherApp.Logger.LogDebug(nameof(Config), "file doesn't exist"); return new Config(); } @@ -67,7 +67,7 @@ public record Config public void SaveToFile() { - LauncherApp.Logger.LogInfo(nameof(Config), $"saving config to file '{_filePath}'"); + LauncherApp.Logger.LogDebug(nameof(Config), $"saving config to file '{_filePath}'"); var text = JsonConvert.SerializeObject(this, Formatting.Indented); File.WriteAllText(_filePath, text); LauncherApp.Logger.LogDebug(nameof(Config), $"config has been saved: {text}"); diff --git a/Mlaumcherb.Client.Avalonia/GameVersion.cs b/Mlaumcherb.Client.Avalonia/GameVersion.cs index eded8b7..203bbce 100644 --- a/Mlaumcherb.Client.Avalonia/GameVersion.cs +++ b/Mlaumcherb.Client.Avalonia/GameVersion.cs @@ -7,15 +7,14 @@ using Mlaumcherb.Client.Avalonia.классы; using Mlaumcherb.Client.Avalonia.сеть; using Mlaumcherb.Client.Avalonia.сеть.TaskFactories; using Mlaumcherb.Client.Avalonia.холопы; -using Newtonsoft.Json.Linq; using static Mlaumcherb.Client.Avalonia.холопы.PathHelper; namespace Mlaumcherb.Client.Avalonia; public class GameVersion { - private readonly GameVersionProps _props; - public string Name => _props.Name; + private readonly InstalledGameVersionProps _props; + public string Id => _props.Id; public IOPath WorkingDirectory { get; } private IOPath JavaExecutableFilePath; @@ -27,69 +26,10 @@ public class GameVersion private CancellationTokenSource? _gameCts; private CommandTask? _commandTask; - public static Task> GetAllVersionsAsync() - { - var propsList = new List(); - - // local descriptors - Directory.Create(GetVersionsDir()); - foreach (IOPath subdir in Directory.GetDirectories(GetVersionsDir())) - { - string name = subdir.LastName().ToString(); - var d = new GameVersionProps(name); - if(!File.Exists(d.LocalDescriptorPath)) - throw new Exception("Can't find version descriptor file in directory '{subdir}'. Rename it as directory name."); - propsList.Add(d); - } - - // reverse sort - propsList.Sort((a, b) => b.CompareTo(a)); - return Task.FromResult(propsList); - } - - public static async Task CreateFromPropsAsync(GameVersionProps props, bool checkHash) - { - //TODO: refresh version descriptor from server - if (!File.Exists(props.LocalDescriptorPath)) - { - if (props.RemoteProps is null) - throw new NullReferenceException("can't download game version descriptor '" - + props.Name + "', because RemoteDescriptorUrl is null"); - await NetworkHelper.DownloadFile(props.RemoteProps.url, props.LocalDescriptorPath); - } - - return new GameVersion(props); - } - - private GameVersion(GameVersionProps props) + internal GameVersion(InstalledGameVersionProps props, GameVersionDescriptor descriptor) { _props = props; - - string descriptorText = File.ReadAllText(props.LocalDescriptorPath); - JObject descriptorRaw = JObject.Parse(descriptorText); - - // Descriptors can inherit from other descriptors. - // For example, 1.12.2-forge-14.23.5.2860 inherits from 1.12.2 - if (descriptorRaw.TryGetValue("inheritsFrom", out var v)) - { - string parentDescriptorId = v.Value() - ?? throw new Exception("inheritsFrom is null"); - LauncherApp.Logger.LogInfo(Name, $"merging descriptor '{parentDescriptorId}' with '{Name}'"); - IOPath parentDescriptorPath = GetVersionDescriptorPath(parentDescriptorId); - if (!File.Exists(parentDescriptorPath)) - throw new Exception($"Версия '{Name} требует установить версию '{parentDescriptorId}'"); - string parentDescriptorText = File.ReadAllText(parentDescriptorPath); - JObject parentDescriptorRaw = JObject.Parse(parentDescriptorText); - parentDescriptorRaw.Merge(descriptorRaw, - new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Concat }); - descriptorRaw = parentDescriptorRaw; - // removing dependency - descriptorRaw.Remove("inheritsFrom"); - File.WriteAllText(props.LocalDescriptorPath, descriptorRaw.ToString()); - } - - _descriptor = descriptorRaw.ToObject() - ?? throw new Exception($"can't parse descriptor file '{props.LocalDescriptorPath}'"); + _descriptor = descriptor; _javaArgs = new JavaArguments(_descriptor); _gameArgs = new GameArguments(_descriptor); _libraries = new Libraries(_descriptor); @@ -97,30 +37,28 @@ public class GameVersion JavaExecutableFilePath = GetJavaExecutablePath(_descriptor.javaVersion.component, LauncherApp.Config.debug); } - public async Task UpdateFiles(bool checkHashes, Action networkTaskCreatedCallback) + public async Task Download(bool update, Action networkTaskCreatedCallback) { - LauncherApp.Logger.LogInfo(Name, $"started updating version {Name}"); + + + LauncherApp.Logger.LogInfo(Id, $"started updating version {Id}"); List taskFactories = [ new AssetsDownloadTaskFactory(_descriptor), new LibrariesDownloadTaskFactory(_descriptor, _libraries), ]; - if (LauncherApp.Config.download_java) - { + if (LauncherApp.Config.download_java) taskFactories.Add(new JavaDownloadTaskFactory(_descriptor)); - } - if (_descriptor.modpack != null) - { + if (_descriptor.modpack != null) taskFactories.Add(new ModpackDownloadTaskFactory(_descriptor)); - } - // has to be downloaded last because it is used by GameVersionProps to check if version is installed + // has to be downloaded last because it is used to check if version is installed taskFactories.Add(new VersionJarDownloadTaskFactory(_descriptor)); var networkTasks = new List(); for (int i = 0; i < taskFactories.Count; i++) { - var nt = await taskFactories[i].CreateAsync(checkHashes); + var nt = await taskFactories[i].CreateAsync(update); if (nt != null) { networkTasks.Add(nt); @@ -142,8 +80,8 @@ public class GameVersion await res.CopyToAsync(file); } - _props.IsDownloaded = true; - LauncherApp.Logger.LogInfo(Name, $"finished updating version {Name}"); + _props.IsInstalled = true; + LauncherApp.Logger.LogInfo(Id, $"finished updating version {Id}"); } //minecraft player uuid explanation @@ -224,23 +162,23 @@ public class GameVersion .WithStandardOutputPipe(PipeTarget.ToDelegate(LogGameOut)) .WithStandardErrorPipe(PipeTarget.ToDelegate(LogGameError)); } - LauncherApp.Logger.LogInfo(Name, "launching the game"); - LauncherApp.Logger.LogDebug(Name, "java: " + command.TargetFilePath); - LauncherApp.Logger.LogDebug(Name, "working_dir: " + command.WorkingDirPath); - LauncherApp.Logger.LogDebug(Name, "arguments: \n\t" + argsList.MergeToString("\n\t")); + LauncherApp.Logger.LogInfo(Id, "launching the game"); + LauncherApp.Logger.LogDebug(Id, "java: " + command.TargetFilePath); + LauncherApp.Logger.LogDebug(Id, "working_dir: " + command.WorkingDirPath); + LauncherApp.Logger.LogDebug(Id, "arguments: \n\t" + argsList.MergeToString("\n\t")); _gameCts = new(); _commandTask = command.ExecuteAsync(_gameCts.Token); var result = await _commandTask; - LauncherApp.Logger.LogInfo(Name, $"game exited with code {result.ExitCode}"); + LauncherApp.Logger.LogInfo(Id, $"game exited with code {result.ExitCode}"); } private void LogGameOut(string line) { - LauncherApp.Logger.LogInfo(Name, line); + LauncherApp.Logger.LogInfo(Id, line); } private void LogGameError(string line) { - LauncherApp.Logger.LogWarn(Name, line); + LauncherApp.Logger.LogWarn(Id, line); } public void Close() @@ -249,5 +187,5 @@ public class GameVersion } - public override string ToString() => Name; + public override string ToString() => Id; } \ No newline at end of file diff --git a/Mlaumcherb.Client.Avalonia/LauncherLogger.cs b/Mlaumcherb.Client.Avalonia/LauncherLogger.cs index fcd8c83..ba8ca55 100644 --- a/Mlaumcherb.Client.Avalonia/LauncherLogger.cs +++ b/Mlaumcherb.Client.Avalonia/LauncherLogger.cs @@ -10,6 +10,7 @@ public class LauncherLogger : ILogger public LauncherLogger() { _fileLogger = new FileLogger(LogsDirectory, "млаумчерб"); + _fileLogger.DebugLogEnabled = true; ILogger[] loggers = [ _fileLogger, @@ -54,7 +55,11 @@ public class LauncherLogger : ILogger public bool DebugLogEnabled { get => _compositeLogger.DebugLogEnabled; - set => _compositeLogger.DebugLogEnabled = value; + set + { + _compositeLogger.DebugLogEnabled = value; + _fileLogger.DebugLogEnabled = true; + } } public bool InfoLogEnabled diff --git a/Mlaumcherb.Client.Avalonia/Mlaumcherb.Client.Avalonia.csproj b/Mlaumcherb.Client.Avalonia/Mlaumcherb.Client.Avalonia.csproj index 8db2004..ffdc793 100644 --- a/Mlaumcherb.Client.Avalonia/Mlaumcherb.Client.Avalonia.csproj +++ b/Mlaumcherb.Client.Avalonia/Mlaumcherb.Client.Avalonia.csproj @@ -13,6 +13,8 @@ млаумчерб Release;Debug x64 + + AVLN3001 diff --git a/Mlaumcherb.Client.Avalonia/зримое/VersionItemView.axaml b/Mlaumcherb.Client.Avalonia/зримое/GameVersionItemView.axaml similarity index 84% rename from Mlaumcherb.Client.Avalonia/зримое/VersionItemView.axaml rename to Mlaumcherb.Client.Avalonia/зримое/GameVersionItemView.axaml index be8ee04..a564ac2 100644 --- a/Mlaumcherb.Client.Avalonia/зримое/VersionItemView.axaml +++ b/Mlaumcherb.Client.Avalonia/зримое/GameVersionItemView.axaml @@ -4,7 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Mlaumcherb.Client.Avalonia" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" - x:Class="Mlaumcherb.Client.Avalonia.зримое.VersionItemView" + x:Class="Mlaumcherb.Client.Avalonia.зримое.GameVersionItemView" Padding="2"> diff --git a/Mlaumcherb.Client.Avalonia/зримое/GameVersionItemView.axaml.cs b/Mlaumcherb.Client.Avalonia/зримое/GameVersionItemView.axaml.cs new file mode 100644 index 0000000..b3aa5e3 --- /dev/null +++ b/Mlaumcherb.Client.Avalonia/зримое/GameVersionItemView.axaml.cs @@ -0,0 +1,48 @@ +using Avalonia.Controls; +using Avalonia.Media; +using Avalonia.Threading; +using Mlaumcherb.Client.Avalonia.классы; + +namespace Mlaumcherb.Client.Avalonia.зримое; + +public abstract partial class GameVersionItemView : ListBoxItem +{ + private static readonly SolidColorBrush _avaliableColor = new(Color.FromRgb(30, 130, 40)); + private static readonly SolidColorBrush _unavaliableColor = new(Color.FromRgb(170, 70, 70)); + + protected GameVersionItemView(string name, bool initialStatus) + { + InitializeComponent(); + text.Text = name; + UpdateBackground(initialStatus); + } + + protected void UpdateBackground(bool isInstalled) + { + Dispatcher.UIThread.Invoke(() => Background = isInstalled ? _avaliableColor : _unavaliableColor); + } +} + +// Background changes when props status changes +public class InstalledGameVersionItemView : GameVersionItemView +{ + public readonly InstalledGameVersionProps Props; + + public InstalledGameVersionItemView(InstalledGameVersionProps props) : base(props.Id, props.IsInstalled) + { + Props = props; + props.StatusChanged += UpdateBackground; + } +} + +// Background is set once by checking if the version is present in InstalledVersionsCatalog +public class RemoteGameVersionItemView : GameVersionItemView +{ + public readonly RemoteVersionDescriptorProps Props; + + public RemoteGameVersionItemView(RemoteVersionDescriptorProps props) + : base(props.id, LauncherApp.InstalledVersionCatalog.versions.ContainsKey(props.id)) + { + Props = props; + } +} \ No newline at end of file diff --git a/Mlaumcherb.Client.Avalonia/зримое/LauncherApp.axaml b/Mlaumcherb.Client.Avalonia/зримое/LauncherApp.axaml index 680e6c5..5b3640d 100644 --- a/Mlaumcherb.Client.Avalonia/зримое/LauncherApp.axaml +++ b/Mlaumcherb.Client.Avalonia/зримое/LauncherApp.axaml @@ -25,6 +25,10 @@ + +