Compare commits

..

2 Commits

Author SHA1 Message Date
45c3f90da0 логи 2024-09-27 02:40:53 +05:00
d24dbea501 moved some files 2024-09-26 01:10:11 +05:00
17 changed files with 240 additions and 94 deletions

View File

@ -1,13 +0,0 @@
namespace Млаумчерб.Клиент;
public class LauncherLogger : FileLogger
{
public static readonly IOPath LogsDirectory = "launcher_logs";
public LauncherLogger() : base(LogsDirectory, "млаумчерб")
{
#if DEBUG
DebugLogEnabled = true;
#endif
}
}

View File

@ -13,6 +13,7 @@ global using Directory = DTLib.Filesystem.Directory;
global using Path = DTLib.Filesystem.Path;
using System.Globalization;
using Avalonia;
using Млаумчерб.Клиент.видимое;
namespace Млаумчерб.Клиент;

View File

@ -1,7 +1,8 @@
using CliWrap;
using DTLib.Extensions;
using Млаумчерб.Клиент.видимое;
using Млаумчерб.Клиент.классы;
using static Млаумчерб.Клиент.классы.Пролетариат;
using static Млаумчерб.Клиент.классы.Пути;
namespace Млаумчерб.Клиент;
@ -28,7 +29,7 @@ public class GameVersionDescriptor
string name = GetVersionDescriptorName(f);
propsList.Add(new GameVersionProps(name, null, f));
}
var remoteVersions = await Network.GetDownloadableVersions();
var remoteVersions = await Сеть.GetDownloadableVersions();
propsList.AddRange(remoteVersions);
return propsList;
}
@ -40,7 +41,7 @@ public class GameVersionDescriptor
if (props.RemoteDescriptorUrl is null)
throw new NullReferenceException("can't download game version descriptor '"
+ props.Name + "', because RemoteDescriptorUrl is null");
await Network.DownloadFileHTTP(props.RemoteDescriptorUrl, props.LocalDescriptorPath);
await Сеть.DownloadFileHTTP(props.RemoteDescriptorUrl, props.LocalDescriptorPath);
}
return new GameVersionDescriptor(props);
}
@ -64,10 +65,10 @@ public class GameVersionDescriptor
{
downloadCts = new CancellationTokenSource();
if(Приложение.Настройки.скачатьабу)
await Network.DownloadJava(descriptor.javaVersion, Приложение.Настройки.путь_к_жабе, force);
await Network.DownloadAssets(descriptor.assetIndex, downloadCts.Token, force);
await Network.DownloadVersionFile(descriptor.downloads.client.url, GetVersionJarFilePath(Name), force);
await Network.DownloadLibraries(descriptor.libraries, GetLibrariesDir(), force);
await Сеть.DownloadJava(descriptor.javaVersion, Приложение.Настройки.путь_к_жабе, force);
await Сеть.DownloadAssets(descriptor.assetIndex, downloadCts.Token, force);
await Сеть.DownloadVersionFile(descriptor.downloads.client.url, GetVersionJarFilePath(Name), force);
await Сеть.DownloadLibraries(descriptor.libraries, GetLibrariesDir(), force);
// await Network.DownloadModpack(modpack, WorkingDirectory, force);
_props.IsDownloaded = true;
}

View File

@ -0,0 +1,79 @@
namespace Млаумчерб.Клиент;
public class LauncherLogger : ILogger
{
private CompositeLogger _compositeLogger;
private FileLogger _fileLogger;
public static readonly IOPath LogsDirectory = "launcher_logs";
public IOPath LogfileName => _fileLogger.LogfileName;
public LauncherLogger()
{
_fileLogger = new FileLogger(LogsDirectory, "млаумчерб");
ILogger[] loggers =
[
_fileLogger,
#if DEBUG
new ConsoleLogger(),
#endif
];
_compositeLogger = new CompositeLogger(loggers);
#if DEBUG
DebugLogEnabled = true;
#endif
}
public delegate void LogHandler(string context, LogSeverity severity, object message, ILogFormat format);
public event LogHandler? OnLogMessage;
public void Log(string context, LogSeverity severity, object message, ILogFormat format)
{
_compositeLogger.Log(context, severity, message, format);
bool isEnabled = severity switch
{
LogSeverity.Debug => DebugLogEnabled,
LogSeverity.Info => InfoLogEnabled,
LogSeverity.Warn => WarnLogEnabled,
LogSeverity.Error => ErrorLogEnabled,
_ => throw new ArgumentOutOfRangeException(nameof(severity), severity, null)
};
if(isEnabled)
OnLogMessage?.Invoke(context, severity, message, format);
}
public void Dispose()
{
_compositeLogger.Dispose();
}
public ILogFormat Format
{
get => _compositeLogger.Format;
set => _compositeLogger.Format = value;
}
public bool DebugLogEnabled
{
get => _compositeLogger.DebugLogEnabled;
set => _compositeLogger.DebugLogEnabled = value;
}
public bool InfoLogEnabled
{
get => _compositeLogger.InfoLogEnabled;
set => _compositeLogger.InfoLogEnabled = value;
}
public bool WarnLogEnabled
{
get => _compositeLogger.WarnLogEnabled;
set => _compositeLogger.WarnLogEnabled = value;
}
public bool ErrorLogEnabled
{
get => _compositeLogger.ErrorLogEnabled;
set => _compositeLogger.ErrorLogEnabled = value;
}
}

View File

@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<OutputType Condition="'$(Configuration)' == 'Debug'">Exe</OutputType>
<OutputType Condition="'$(Configuration)' != 'Debug'">WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
@ -21,7 +22,7 @@
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.*" />
<PackageReference Include="Avalonia.Labs.Gif" Version="11.2.999-cibuild-00051673"/>
<PackageReference Include="CliWrap" Version="3.6.*" />
<PackageReference Include="DTLib" Version="1.4.1" />
<PackageReference Include="DTLib" Version="1.4.2" />
<PackageReference Include="MessageBox.Avalonia" Version="3.1.*" />
<PackageReference Include="Newtonsoft.Json" Version="13.*" />
</ItemGroup>
@ -30,4 +31,19 @@
<AvaloniaResource Include="капитал\**"/>
</ItemGroup>
<ItemGroup>
<Compile Update="видимое\VersionItemView.axaml.cs">
<DependentUpon>VersionItemView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Update="видимое\Окне.axaml.cs">
<DependentUpon>Окне.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Update="видимое\Приложение.axaml.cs">
<DependentUpon>Приложение.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
</Project>

View File

@ -1,4 +1,6 @@
namespace Млаумчерб.Клиент;
using Млаумчерб.Клиент.видимое;
namespace Млаумчерб.Клиент;
public record Настройки
{

View File

@ -4,6 +4,7 @@ using MsBox.Avalonia;
using MsBox.Avalonia.Dto;
using MsBox.Avalonia.Enums;
using MsBox.Avalonia.Models;
using Млаумчерб.Клиент.видимое;
namespace Млаумчерб.Клиент;

View File

@ -1,11 +1,12 @@
using System.Buffers;
using System.Net.Http;
using Млаумчерб.Клиент.видимое;
using Млаумчерб.Клиент.классы;
using Timer = DTLib.Timer;
namespace Млаумчерб.Клиент;
public static class Network
public static class Сеть
{
private static HttpClient http = new();
private const string ASSET_SERVER_URL = "https://resources.download.minecraft.net/";
@ -54,7 +55,7 @@ public static class Network
public static async Task DownloadAssets(AssetIndexProperties assetIndexProperties, CancellationToken ct, bool force)
{
IOPath indexFilePath = Пролетариат.GetAssetIndexFilePath(assetIndexProperties.id);
IOPath indexFilePath = Пути.GetAssetIndexFilePath(assetIndexProperties.id);
if (File.Exists(indexFilePath) && !force)
return;
@ -149,7 +150,7 @@ public static class Network
}
catch (Exception ex)
{
Приложение.Логгер.LogWarn(nameof(Network), ex);
Приложение.Логгер.LogWarn(nameof(Сеть), ex);
}
}
return descriptors;

View File

@ -4,6 +4,6 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Млаумчерб.Клиент"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Млаумчерб.Клиент.VersionItemView">
x:Class="Млаумчерб.Клиент.видимое.VersionItemView">
<TextBlock Name="text" Background="Transparent"/>
</UserControl>

View File

@ -2,7 +2,7 @@
using Avalonia.Media;
using Млаумчерб.Клиент.классы;
namespace Млаумчерб.Клиент;
namespace Млаумчерб.Клиент.видимое;
public partial class VersionItemView : ListBoxItem
{

View File

@ -2,11 +2,11 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:gif="clr-namespace:Avalonia.Labs.Gif;assembly=Avalonia.Labs.Gif"
xmlns:local="clr-namespace:Млаумчерб"
x:Class="Млаумчерб.Клиент.Окне"
x:Class="Млаумчерб.Клиент.видимое.Окне"
Name="window"
Title="млаумчерб"
Icon="avares://млаумчерб/капитал/кубе.ico"
FontFamily="{StaticResource PlexMono}" FontSize="18"
FontFamily="{StaticResource MonospaceFont}" FontSize="18"
MinWidth="800" MinHeight="500"
Width="800" Height="500"
WindowStartupLocation="CenterScreen">
@ -25,9 +25,18 @@
<TextBlock FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center">
News
Лог
</TextBlock>
</Border>
<ScrollViewer Name="LogScrollViewer" Grid.Row="1"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Visible"
Background="Transparent">
<TextBox Name="LogTextBox"
FontSize="12"
IsReadOnly="True" TextWrapping="Wrap"
Background="Transparent" BorderThickness="0"/>
</ScrollViewer>
</Grid>
</Border>
<Border Grid.Column="1"
@ -36,40 +45,39 @@
<Grid>
<Grid.RowDefinitions>* 60</Grid.RowDefinitions>
<StackPanel Orientation="Vertical" Margin="10" Spacing="10">
<TextBlock>Version:</TextBlock>
<ComboBox Name="VersionComboBox">
</ComboBox>
<TextBlock>Версия:</TextBlock>
<ComboBox Name="VersionComboBox"/>
<TextBlock>Username:</TextBlock>
<TextBox Text="{Binding #window.Username}"></TextBox>
<TextBlock>Ник:</TextBlock>
<TextBox Background="Transparent"
Text="{Binding #window.Username}"/>
<TextBlock>
<Run>Memory limit:</Run>
<Run>Выделенная память:</Run>
<TextBox Background="Transparent" Padding="0"
BorderThickness="1"
BorderBrush="#777777"
Text="{Binding #window.MemoryLimit}">
</TextBox>
<Run>Mb</Run>
<Run>Мб</Run>
</TextBlock>
<Slider Minimum="2048" Maximum="8192"
Value="{Binding #window.MemoryLimit}">
</Slider>
<CheckBox IsChecked="{Binding #window.Fullscreen}">
Fullscreen
Запустить полноэкранное
</CheckBox>
<CheckBox IsChecked="{Binding #window.ForceUpdateGameFiles}">
Force update game files
<CheckBox IsChecked="{Binding #window.CheckGameFiles}">
Проверить файлы игры
</CheckBox>
</StackPanel>
<Button Grid.Row="1" Margin="10" Padding="0 0 0 4"
Classes="button_no_border"
Background="#BBFF5900"
Click="LaunchButtonHandler">
Launch
Background="#BBfd7300"
Click="Запуск">
Запуск
</Button>
</Grid>
</Border>
@ -81,21 +89,25 @@
<TextBlock FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center">
Downloads
Загрузки
</TextBlock>
</Border>
<ScrollViewer Name="DownloadsScrollViewer" Grid.Row="1"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Visible"
Background="Transparent"/>
</Grid>
</Border>
</Grid>
<Border Grid.Row="1" Background="#954808B0">
<Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Button Classes="menu_button button_no_border" Click="OpenLogsDirectory">logs directory</Button>
<Border Classes="menu_separator"></Border>
<Button Classes="menu_button button_no_border" Click="OpenLogFile">log file</Button>
<Button Classes="menu_button button_no_border" Click="ОткрытьПапкуЛаунчера">директория лаунчера</Button>
<Border Classes="menu_separator"/>
<Button Classes="menu_button button_no_border" Click="ОткрытьФайлЛогов">лог-файл</Button>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Classes="menu_button button_no_border" Click="OpenSourceRepository">source code</Button>
<Button Classes="menu_button button_no_border" Click="ОткрытьРепозиторий">исходный код</Button>
<gif:GifImage
Width="30" Height="30" Stretch="Uniform"
Source="avares://млаумчерб/капитал/лисик.gif"/>

View File

@ -1,12 +1,14 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Data;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
using Avalonia.VisualTree;
using Млаумчерб.Клиент.классы;
namespace Млаумчерб.Клиент;
namespace Млаумчерб.Клиент.видимое;
public partial class Окне : Window
{
@ -37,13 +39,13 @@ public partial class Окне : Window
set => SetValue(FullscreenProperty, value);
}
public static readonly StyledProperty<bool> ForceUpdateGameFilesProperty =
AvaloniaProperty.Register<Окне, bool>(nameof(ForceUpdateGameFiles),
public static readonly StyledProperty<bool> CheckGameFilesProperty =
AvaloniaProperty.Register<Окне, bool>(nameof(CheckGameFiles),
defaultBindingMode: BindingMode.TwoWay, defaultValue: false);
public bool ForceUpdateGameFiles
public bool CheckGameFiles
{
get => GetValue(ForceUpdateGameFilesProperty);
set => SetValue(ForceUpdateGameFilesProperty, value);
get => GetValue(CheckGameFilesProperty);
set => SetValue(CheckGameFilesProperty, value);
}
public Окне()
@ -55,12 +57,28 @@ public partial class Окне : Window
{
try
{
Приложение.Настройки = Настройки.ЗагрузитьИзФайла();
Приложение.Логгер.OnLogMessage += (context, severity, message, format) =>
{
StringBuilder b = new();
b.Append(DateTime.Now.ToString("[HH:mm:ss]["));
b.Append(severity);
b.Append("]: ");
b.Append(message);
b.Append('\n');
double offsetFromBottom = LogScrollViewer.Extent.Height
- LogScrollViewer.Offset.Y
- LogScrollViewer.Viewport.Height;
bool is_scrolled_to_end = offsetFromBottom < 20.0; // scrolled less then one line up
LogTextBox.Text += b.ToString();
if(is_scrolled_to_end)
LogScrollViewer.ScrollToEnd();
};
Username = Приложение.Настройки.имя_пользователя;
MemoryLimit = Приложение.Настройки.выделенная_память_мб;
Fullscreen = Приложение.Настройки.открыватьаесь_экран;
Directory.Create(Пролетариат.GetVersionDescriptorDir());
Directory.Create(Пути.GetVersionDescriptorDir());
VersionComboBox.SelectedIndex = 0;
VersionComboBox.IsEnabled = false;
var versions = await GameVersionDescriptor.GetAllVersionsAsync();
@ -82,11 +100,10 @@ public partial class Окне : Window
}
}
private async void LaunchButtonHandler(object? sender, RoutedEventArgs e)
private async void Запуск(object? sender, RoutedEventArgs e)
{
try
{
var selectedVersionView = (VersionItemView?)VersionComboBox.SelectedItem;
var selectedVersion = selectedVersionView?.Props;
Приложение.Настройки.последняяапущенная_версия = selectedVersion?.Name;
@ -98,8 +115,8 @@ public partial class Окне : Window
return;
var v = await GameVersionDescriptor.CreateFromPropsAsync(selectedVersion);
v.BeginUpdate(ForceUpdateGameFiles);
Dispatcher.UIThread.Invoke(() => ForceUpdateGameFiles = false);
v.BeginUpdate(CheckGameFiles);
Dispatcher.UIThread.Invoke(() => CheckGameFiles = false);
}
catch (Exception ex)
{
@ -107,11 +124,11 @@ public partial class Окне : Window
}
}
private void OpenLogsDirectory(object? s, RoutedEventArgs e)
private void ОткрытьПапкуЛаунчера(object? s, RoutedEventArgs e)
{
try
{
Launcher.LaunchDirectoryInfoAsync(new DirectoryInfo(LauncherLogger.LogsDirectory.ToString()))
Launcher.LaunchDirectoryInfoAsync(new DirectoryInfo(Directory.GetCurrent().ToString()))
.ConfigureAwait(false);
}
catch (Exception ex)
@ -120,7 +137,7 @@ public partial class Окне : Window
}
}
private void OpenLogFile(object? sender, RoutedEventArgs e)
private void ОткрытьФайлЛогов(object? sender, RoutedEventArgs e)
{
try
{
@ -133,7 +150,7 @@ public partial class Окне : Window
}
}
private void OpenSourceRepository(object? sender, RoutedEventArgs e)
private void ОткрытьРепозиторий(object? sender, RoutedEventArgs e)
{
try
{

View File

@ -1,6 +1,6 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Млаумчерб.Клиент.Приложение"
x:Class="Млаумчерб.Клиент.видимое.Приложение"
RequestedThemeVariant="Dark">
<Application.Styles>
<SimpleTheme />
@ -30,9 +30,30 @@
<Setter Property="Width" Value="1"/>
<Setter Property="Margin" Value="4"/>
</Style>
<Style Selector="ScrollBar /template/ Border">
<Setter Property="Width" Value="5"/>
<Setter Property="Margin" Value="4"/>
<Setter Property="ClipToBounds" Value="True"/>
<Setter Property="CornerRadius" Value="0"/>
</Style>
<Style Selector="ScrollBar /template/ Rectangle">
<Setter Property="Fill" Value="#d8ceb9"/>
</Style>
<Style Selector="ScrollBar /template/ Thumb">
<Setter Property="Background" Value="#fd7300"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="CornerRadius" Value="0"/>
</Style>
<Style Selector="ScrollBar /template/ Thumb /template/ Border">
<Setter Property="ClipToBounds" Value="True"/>
<Setter Property="CornerRadius" Value="0"/>
<Setter Property="Width" Value="5"/>
</Style>
</Application.Styles>
<Application.Resources>
<FontFamily x:Key="PlexMono">avares://млаумчерб/капитал/IBMPlexMono-Regular.ttf</FontFamily>
<FontFamily x:Key="MonospaceFont">avares://млаумчерб/капитал/IBMPlexMono-Regular.ttf</FontFamily>
</Application.Resources>
</Application>

View File

@ -2,15 +2,17 @@ using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
namespace Млаумчерб.Клиент;
namespace Млаумчерб.Клиент.видимое;
public class Приложение : Application
{
public static readonly LauncherLogger Логгер = new();
public static LauncherLogger Логгер = new();
public static Настройки Настройки = new();
public override void Initialize()
{
Логгер.LogInfo(nameof(Приложение), "приложение запущено");
Настройки = Настройки.ЗагрузитьИзФайла();
AvaloniaXamlLoader.Load(this);
}
@ -23,6 +25,4 @@ public class Приложение : Application
base.OnFrameworkInitializationCompleted();
}
public static Настройки Настройки = new();
}

View File

@ -22,11 +22,11 @@ public class GameVersionProps
Name = name;
LocalDescriptorPath = descriptorPath;
RemoteDescriptorUrl = url;
IsDownloaded = File.Exists(Пролетариат.GetVersionJarFilePath(name));
IsDownloaded = File.Exists(Пути.GetVersionJarFilePath(name));
}
public GameVersionProps(string name, string? url) :
this(name, url, Пролетариат.GetVersionDescriptorPath(name)) { }
this(name, url, Пути.GetVersionDescriptorPath(name)) { }
public override string ToString() => Name;
}

View File

@ -2,24 +2,5 @@
public static class Пролетариат
{
public static IOPath GetAssetIndexFilePath(string id) =>
Path.Concat(Приложение.Настройки.путь_к_кубачу, $"assets/indexes/{id}.json");
public static IOPath GetVersionDescriptorDir() =>
Path.Concat(Приложение.Настройки.путь_к_кубачу, "version_descriptors");
public static string GetVersionDescriptorName(IOPath path) =>
path.LastName().RemoveExtension().ToString();
public static IOPath GetVersionDescriptorPath(string name) =>
Path.Concat(GetVersionDescriptorDir(), Path.ReplaceRestrictedChars(name) + ".json");
public static IOPath GetVersionDir() =>
Path.Concat(Приложение.Настройки.путь_к_кубачу, "versions");
public static IOPath GetVersionJarFilePath(string name) =>
Path.Concat(GetVersionDir(), name + ".jar");
public static IOPath GetLibrariesDir() =>
Path.Concat(Приложение.Настройки.путь_к_кубачу, "libraries");
}
}

View File

@ -0,0 +1,27 @@
using Млаумчерб.Клиент.видимое;
namespace Млаумчерб.Клиент.классы;
public static class Пути
{
public static IOPath GetAssetIndexFilePath(string id) =>
Path.Concat(Приложение.Настройки.путь_к_кубачу, $"assets/indexes/{id}.json");
public static IOPath GetVersionDescriptorDir() =>
Path.Concat(Приложение.Настройки.путь_к_кубачу, "version_descriptors");
public static string GetVersionDescriptorName(IOPath path) =>
path.LastName().RemoveExtension().ToString();
public static IOPath GetVersionDescriptorPath(string name) =>
Path.Concat(GetVersionDescriptorDir(), Path.ReplaceRestrictedChars(name) + ".json");
public static IOPath GetVersionDir() =>
Path.Concat(Приложение.Настройки.путь_к_кубачу, "versions");
public static IOPath GetVersionJarFilePath(string name) =>
Path.Concat(GetVersionDir(), name + ".jar");
public static IOPath GetLibrariesDir() =>
Path.Concat(Приложение.Настройки.путь_к_кубачу, "libraries");
}