This commit is contained in:
Timerix 2025-01-06 01:01:34 +05:00
parent da58c11e59
commit cbfd5f8da8
7 changed files with 154 additions and 0 deletions

View File

@ -1,5 +1,6 @@
using Mlaumcherb.Client.Avalonia.зримое;
using Mlaumcherb.Client.Avalonia.классы;
using Mlaumcherb.Client.Avalonia.сеть.Update;
using Mlaumcherb.Client.Avalonia.холопы;
namespace Mlaumcherb.Client.Avalonia;
@ -25,6 +26,13 @@ public record Config
new() { name = "Тимериховое", url = "https://timerix.ddns.net/minecraft/catalog.json" },
new() { name = "Mojang", url = "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json" },
];
public UpdateHelper.GiteaConfig gitea { get; set; } = new UpdateHelper.GiteaConfig
{
serverUrl = "https://timerix.ddns.net:3322",
user = "Timerix",
repo = "mlaumcherb",
};
[JsonIgnore] private static IOPath _filePath = "млаумчерб.json";

View File

@ -1,5 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version>1.1.0</Version>
<OutputType Condition="'$(Configuration)' == 'Debug'">Exe</OutputType>
<OutputType Condition="'$(Configuration)' != 'Debug'">WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
@ -34,5 +35,9 @@
<AvaloniaResource Include="капитал\**"/>
<EmbeddedResource Include="встроенное\**" />
</ItemGroup>
<ItemGroup>
<Folder Include="Gitea\" />
</ItemGroup>
</Project>

View File

@ -2,6 +2,9 @@ using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Mlaumcherb.Client.Avalonia.классы;
using Mlaumcherb.Client.Avalonia.сеть;
using Mlaumcherb.Client.Avalonia.сеть.Update;
using Mlaumcherb.Client.Avalonia.холопы;
namespace Mlaumcherb.Client.Avalonia.зримое;
@ -17,6 +20,8 @@ public class LauncherApp : Application
Config = Config.LoadFromFile();
Logger.DebugLogEnabled = Config.debug;
AvaloniaXamlLoader.Load(this);
Update();
// some file required by forge installer
if (!File.Exists("launcher_profiles.json"))
@ -27,6 +32,27 @@ public class LauncherApp : Application
InstalledVersionCatalog = InstalledVersionCatalog.Load();
}
private async void Update()
{
try
{
Logger.LogInfo(nameof(LauncherApp), "checking for updates...");
var upd = new UpdateHelper(Config.gitea);
upd.DeleteBackupFiles();
if (await upd.IsUpdateAvailable())
{
Logger.LogInfo(nameof(LauncherApp), "downloading update...");
await upd.UpdateSelf();
Logger.LogInfo(nameof(LauncherApp), "restarting...");
upd.RestartSelf();
}
}
catch (Exception e)
{
ErrorHelper.ShowMessageBox(nameof(LauncherApp), e);
}
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)

View File

@ -178,6 +178,7 @@
<Button Classes="menu_button button_no_border" Click="ОткрытьФайлЛогов">лог-файл</Button>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock Name="LauncherVersionTextBox"/>
<Button Classes="menu_button button_no_border" Click="ОткрытьРепозиторий">исходный код</Button>
<gif:GifImage
Width="30" Height="30" Stretch="Uniform"

View File

@ -1,3 +1,4 @@
using System.Reflection;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Data;
@ -70,6 +71,7 @@ public partial class MainWindow : Window
try
{
LauncherApp.Logger.OnLogMessage += GuiLogMessage;
LauncherVersionTextBox.Text = $"v {Assembly.GetExecutingAssembly().GetName().Version}";
PlayerName = LauncherApp.Config.player_name;
MemoryLimit = LauncherApp.Config.max_memory;

View File

@ -0,0 +1,38 @@
using System.Linq;
namespace Mlaumcherb.Client.Avalonia.сеть.Update;
public class Release
{
[JsonRequired] public int id { get; set; }
[JsonRequired] public string tag_name { get; set; } = "";
[JsonRequired] public DateTime created_at { get; set; }
// ReSharper disable once CollectionNeverUpdated.Global
public List<Asset> assets { get; set; } = new();
public class Asset
{
[JsonRequired] public int id { get; set; }
[JsonRequired] public string name { get; set; } = "";
[JsonRequired] public int size { get; set; }
[JsonRequired] public DateTime created_at { get; set; }
[JsonRequired] public string browser_download_url { get; set; } = "";
public async Task Download(IOPath localPath)
{
await NetworkHelper.DownloadFile(browser_download_url, localPath);
}
}
public Asset? FindAssetByName(string name) =>
assets.FirstOrDefault(a => a.name == name);
}
public class GiteaClient(string ServerUrl)
{
public async Task<Release> GetLatestRelease(string user, string repo)
{
string url = $"{ServerUrl}//api/v1/repos/{user}/{repo}/releases/latest";
return await NetworkHelper.DownloadStringAndDeserialize<Release>(url);
}
}

View File

@ -0,0 +1,74 @@
using System.Diagnostics;
using System.Reflection;
namespace Mlaumcherb.Client.Avalonia.сеть.Update;
public class UpdateHelper
{
private readonly string _executableName = "млаумчерб.exe";
private readonly IOPath executablePathActual;
private readonly IOPath executablePathOld;
private readonly IOPath executablePathNew;
public class GiteaConfig
{
[JsonRequired] public required string serverUrl { get; set; }
[JsonRequired] public required string user { get; set; }
[JsonRequired] public required string repo { get; set; }
}
private GiteaConfig _giteaConfig;
public UpdateHelper(GiteaConfig giteaConfig)
{
_giteaConfig = giteaConfig;
executablePathActual = _executableName;
executablePathOld = _executableName + ".old";
executablePathNew = _executableName + ".new";
Gitea = new GiteaClient(giteaConfig.serverUrl);
}
public GiteaClient Gitea { get; }
public void DeleteBackupFiles()
{
if(File.Exists(executablePathOld))
File.Delete(executablePathOld);
}
public async Task<bool> IsUpdateAvailable()
{
var latest = await Gitea.GetLatestRelease(_giteaConfig.user, _giteaConfig.repo);
if (!Version.TryParse(latest.tag_name, out var latestVersion))
throw new Exception($"Can't parse version of latest release: {latest.tag_name}");
Version? currentVersion = Assembly.GetExecutingAssembly().GetName().Version;
if(currentVersion is null)
throw new Exception($"Can't get current version from {Assembly.GetExecutingAssembly().GetName()}");
return currentVersion < latestVersion;
}
public async Task UpdateSelf()
{
if(File.Exists(executablePathNew))
File.Delete(executablePathNew);
var latest = await Gitea.GetLatestRelease(_giteaConfig.user, _giteaConfig.repo);
var asset = latest.FindAssetByName(_executableName);
if(asset == null)
throw new Exception($"Can't find updated executable on gitea: {_executableName}");
await asset.Download(executablePathNew);
File.Move(executablePathActual, executablePathOld, true);
File.Move(executablePathNew, executablePathActual, true);
}
public void RestartSelf()
{
Process.Start(executablePathActual.ToString());
Thread.Sleep(500);
Environment.Exit(0);
}
}