InstalledGameVersionCatalog

This commit is contained in:
2024-12-31 17:55:30 +05:00
parent 2c780afea8
commit e5deb3f3d4
24 changed files with 477 additions and 341 deletions

View File

@@ -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">
<TextBlock Name="text" Background="Transparent"/>
</UserControl>

View File

@@ -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;
}
}

View File

@@ -25,6 +25,10 @@
<Setter Property="MinWidth" Value="50"/>
</Style>
<Style Selector="Button.button_dark">
<Setter Property="Background" Value="#65656070"/>
</Style>
<Style Selector="Border.menu_separator">
<Setter Property="Background" Value="#ff505050"/>
<Setter Property="Width" Value="1"/>

View File

@@ -1,13 +1,15 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Mlaumcherb.Client.Avalonia.классы;
namespace Mlaumcherb.Client.Avalonia.зримое;
public class LauncherApp : Application
{
public static LauncherLogger Logger = new();
public static Config Config = new();
public static Config Config = null!;
public static InstalledVersionCatalog InstalledVersionCatalog = null!;
public override void Initialize()
{
@@ -21,6 +23,8 @@ public class LauncherApp : Application
{
File.WriteAllText("launcher_profiles.json", "{}");
}
InstalledVersionCatalog = InstalledVersionCatalog.Load();
}
public override void OnFrameworkInitializationCompleted()

View File

@@ -34,20 +34,30 @@
<ScrollViewer Grid.Row="0"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<StackPanel Margin="10" Spacing="10">
<TextBlock>Версия:</TextBlock>
<ComboBox Name="InstalledVersionComboBox"/>
<StackPanel Margin="10" Spacing="6">
<TextBlock>Ник:</TextBlock>
<TextBox Background="Transparent"
Text="{Binding #window.PlayerName}"/>
<TextBlock>Версия игры:</TextBlock>
<ComboBox Name="InstalledVersionCatalogComboBox"/>
<Button Name="RescanInstalledVersionsButton"
Click="RescanInstalledVersionsButton_OnClick"
Classes="button_dark">
Обновить список
</Button>
<Button Name="DeleteVersionButton"
Click="DeleteVersionButton_OnClick">
Click="DeleteVersionButton_OnClick"
Classes="button_dark">
Удалить версию
</Button>
<Expander Header="Добавление версий"
BorderThickness="1" BorderBrush="Gray"
Padding="4">
<StackPanel>
<StackPanel Spacing="6">
<TextBlock>Источник:</TextBlock>
<ComboBox Name="VersionCatalogComboBox"/>
<ComboBox Name="RemoteVersionCatalogComboBox"/>
<WrapPanel>
<CheckBox Name="ReleaseVersionTypeCheckBox" IsChecked="True">релиз</CheckBox>
<CheckBox Name="SnapshotVersionTypeCheckBox">снапшот</CheckBox>
@@ -55,22 +65,20 @@
<CheckBox Name="OtherVersionTypeAlphaCheckBox">другое</CheckBox>
</WrapPanel>
<Button Name="SearchVersionsButton"
Click="SearchVersionsButton_OnClick">
Click="SearchVersionsButton_OnClick"
Classes="button_dark">
Поиск
</Button>
<TextBlock>Доступные версии:</TextBlock>
<ComboBox Name="VersionCatalogItemsComboBox"/>
<ComboBox Name="RemoteVersionCatalogItemsComboBox"/>
<Button Name="AddVersionButton" IsEnabled="False"
Click="AddVersionButton_OnClick">
Click="AddVersionButton_OnClick"
Classes="button_dark">
Добавить
</Button>
</StackPanel>
</Expander>
<TextBlock>Ник:</TextBlock>
<TextBox Background="Transparent"
Text="{Binding #window.PlayerName}"/>
<TextBlock>
<Run>Выделенная память:</Run>
<TextBox Background="Transparent" Padding="0"
@@ -84,8 +92,8 @@
Value="{Binding #window.MemoryLimit}">
</Slider>
<CheckBox IsChecked="{Binding #window.CheckGameFiles}">
Проверять файлы игры
<CheckBox IsChecked="{Binding #window.UpdateGameFiles}">
Проверить файлы игры
</CheckBox>
<CheckBox IsChecked="{Binding #window.EnableJavaDownload}">
Скачивать джаву

View File

@@ -32,13 +32,13 @@ public partial class MainWindow : Window
set => SetValue(MemoryLimitProperty, value);
}
public static readonly StyledProperty<bool> CheckGameFilesProperty =
AvaloniaProperty.Register<MainWindow, bool>(nameof(CheckGameFiles),
public static readonly StyledProperty<bool> UpdateGameFilesProperty =
AvaloniaProperty.Register<MainWindow, bool>(nameof(UpdateGameFiles),
defaultBindingMode: BindingMode.TwoWay, defaultValue: false);
public bool CheckGameFiles
public bool UpdateGameFiles
{
get => GetValue(CheckGameFilesProperty);
set => SetValue(CheckGameFilesProperty, value);
get => GetValue(UpdateGameFilesProperty);
set => SetValue(UpdateGameFilesProperty, value);
}
@@ -65,7 +65,7 @@ public partial class MainWindow : Window
InitializeComponent();
}
protected override async void OnLoaded(RoutedEventArgs e)
protected override void OnLoaded(RoutedEventArgs e)
{
try
{
@@ -75,28 +75,14 @@ public partial class MainWindow : Window
MemoryLimit = LauncherApp.Config.max_memory;
EnableJavaDownload = LauncherApp.Config.download_java;
RedirectGameOutput = LauncherApp.Config.redirect_game_output;
InstalledVersionComboBox.SelectedIndex = 0;
InstalledVersionComboBox.IsEnabled = false;
var versions = await GameVersion.GetAllVersionsAsync();
Dispatcher.UIThread.Invoke(() =>
foreach (var vc in LauncherApp.Config.version_catalogs)
{
foreach (var p in versions)
{
InstalledVersionComboBox.Items.Add(new VersionItemView(p));
// select last played version
if (LauncherApp.Config.last_launched_version != null &&
p.Name == LauncherApp.Config.last_launched_version)
InstalledVersionComboBox.SelectedIndex = InstalledVersionComboBox.Items.Count - 1;
}
InstalledVersionComboBox.IsEnabled = true;
foreach (var vc in LauncherApp.Config.version_catalogs)
{
VersionCatalogComboBox.Items.Add(vc);
}
VersionCatalogComboBox.SelectedIndex = 0;
});
RemoteVersionCatalogComboBox.Items.Add(vc);
}
RemoteVersionCatalogComboBox.SelectedIndex = 0;
UpdateInstalledVersionsCatalogView(LauncherApp.Config.last_launched_version);
}
catch (Exception ex)
{
@@ -104,6 +90,39 @@ public partial class MainWindow : Window
}
}
private void UpdateInstalledVersionsCatalogView(string? selectVersion)
{
LauncherApp.InstalledVersionCatalog.CheckInstalledVersions();
InstalledVersionCatalogComboBox.IsEnabled = false;
InstalledVersionCatalogComboBox.Items.Clear();
foreach (var p in LauncherApp.InstalledVersionCatalog.versions)
{
InstalledVersionCatalogComboBox.Items.Add(new InstalledGameVersionItemView(p.Value));
}
InstalledVersionCatalogComboBox.SelectedItem = null;
if(selectVersion is not null
&& LauncherApp.InstalledVersionCatalog.versions.TryGetValue(selectVersion, out var props))
{
foreach (InstalledGameVersionItemView? view in InstalledVersionCatalogComboBox.Items)
{
if (view?.Props.Id == props.Id)
{
InstalledVersionCatalogComboBox.SelectedItem = view;
break;
}
}
}
InstalledVersionCatalogComboBox.IsEnabled = true;
}
private void RescanInstalledVersionsButton_OnClick(object? sender, RoutedEventArgs e)
{
var selectedVersionView = InstalledVersionCatalogComboBox.SelectedItem as InstalledGameVersionItemView;
UpdateInstalledVersionsCatalogView(selectedVersionView?.Props.Id);
}
private void GuiLogMessage(LauncherLogger.LogMessage msg)
{
if (msg.severity == LogSeverity.Debug) return;
@@ -121,21 +140,19 @@ public partial class MainWindow : Window
{
try
{
Dispatcher.UIThread.Invoke(() => LaunchButton.IsEnabled = false);
if (InstalledVersionCatalogComboBox.SelectedItem is not InstalledGameVersionItemView selectedVersionView)
return;
var selectedVersionView = (VersionItemView?)InstalledVersionComboBox.SelectedItem;
var selectedVersion = selectedVersionView?.Props;
LauncherApp.Config.last_launched_version = selectedVersion?.Name;
Dispatcher.UIThread.Invoke(() => LaunchButton.IsEnabled = false);
LauncherApp.Config.last_launched_version = selectedVersionView.Props.Id;
LauncherApp.Config.player_name = PlayerName;
LauncherApp.Config.max_memory = MemoryLimit;
LauncherApp.Config.download_java = EnableJavaDownload;
LauncherApp.Config.redirect_game_output = RedirectGameOutput;
LauncherApp.Config.SaveToFile();
if (selectedVersion == null)
return;
var v = await GameVersion.CreateFromPropsAsync(selectedVersion, CheckGameFiles);
await v.UpdateFiles(CheckGameFiles, nt =>
var v = await selectedVersionView.Props.LoadDescriptor(UpdateGameFiles);
await v.Download(UpdateGameFiles, nt =>
{
Dispatcher.UIThread.Invoke(() =>
{
@@ -146,7 +163,7 @@ public partial class MainWindow : Window
);
Dispatcher.UIThread.Invoke(() =>
{
CheckGameFiles = false;
UpdateGameFiles = false;
});
await v.Launch();
}
@@ -156,10 +173,7 @@ public partial class MainWindow : Window
}
finally
{
Dispatcher.UIThread.Invoke(() =>
{
LaunchButton.IsEnabled = true;
});
Dispatcher.UIThread.Invoke(() => LaunchButton.IsEnabled = true);
}
}
@@ -217,72 +231,33 @@ public partial class MainWindow : Window
}
DownloadsPanel.Children.Clear();
}
private async void DeleteVersionButton_OnClick(object? sender, RoutedEventArgs e)
{
try
{
VersionItemView? sel = InstalledVersionComboBox.SelectedItem as VersionItemView;
if(sel is null)
return;
var box = MessageBoxManager.GetMessageBoxCustom(new MessageBoxCustomParams
{
ButtonDefinitions = new List<ButtonDefinition> { new() { Name = "Да" }, new() { Name = "Нет" } },
ContentTitle = $"Удаление версии {sel.Props.Name}",
ContentMessage = $"Вы уверены, что хотите удалить версию {sel.Props.Name}? Все файлы, включая сохранения, будут удалены!",
Icon = MsBox.Avalonia.Enums.Icon.Question,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
SizeToContent = SizeToContent.WidthAndHeight,
ShowInCenter = true,
Topmost = true
}
);
var result = await box.ShowAsync().ConfigureAwait(false);
if (result != "Да")
return;
sel.Props.DeleteFiles();
Dispatcher.UIThread.Invoke(() =>
{
InstalledVersionComboBox.Items.Remove(sel);
});
}
catch (Exception ex)
{
ErrorHelper.ShowMessageBox(nameof(MainWindow), ex);
}
}
private async void SearchVersionsButton_OnClick(object? sender, RoutedEventArgs e)
{
try
{
var catalogProps = VersionCatalogComboBox.SelectedItem as VersionCatalogProps;
if(catalogProps is null)
if(RemoteVersionCatalogComboBox.SelectedItem is not GameVersionCatalogProps catalogProps)
return;
var catalog = await catalogProps.GetVersionCatalogAsync();
var searchParams = new VersionSearchParams();
Dispatcher.UIThread.Invoke(() =>
var searchParams = new VersionSearchParams
{
searchParams.ReleaseTypeAllowed = ReleaseVersionTypeCheckBox.IsChecked ?? false;
searchParams.SnapshotTypeAllowed = SnapshotVersionTypeCheckBox.IsChecked ?? false;
searchParams.OldTypeAllowed = OldVersionTypeCheckBox.IsChecked ?? false;
searchParams.OtherTypeAllowed = OtherVersionTypeAlphaCheckBox.IsChecked ?? false;
});
ReleaseTypeAllowed = ReleaseVersionTypeCheckBox.IsChecked ?? false,
SnapshotTypeAllowed = SnapshotVersionTypeCheckBox.IsChecked ?? false,
OldTypeAllowed = OldVersionTypeCheckBox.IsChecked ?? false,
OtherTypeAllowed = OtherVersionTypeAlphaCheckBox.IsChecked ?? false
};
var versions = catalog.GetDownloadableVersions(searchParams);
Dispatcher.UIThread.Invoke(() =>
{
VersionCatalogItemsComboBox.IsEnabled = false;
VersionCatalogItemsComboBox.Items.Clear();
RemoteVersionCatalogItemsComboBox.IsEnabled = false;
RemoteVersionCatalogItemsComboBox.Items.Clear();
foreach (var p in versions)
{
VersionCatalogItemsComboBox.Items.Add(new VersionItemView(p));
RemoteVersionCatalogItemsComboBox.Items.Add(new RemoteGameVersionItemView(p));
}
VersionCatalogItemsComboBox.SelectedIndex = 0;
VersionCatalogItemsComboBox.IsEnabled = true;
RemoteVersionCatalogItemsComboBox.IsEnabled = true;
AddVersionButton.IsEnabled = versions.Count > 0;
});
}
@@ -296,12 +271,57 @@ public partial class MainWindow : Window
{
try
{
var selectedVersionView = VersionCatalogItemsComboBox.SelectedItem as VersionItemView;
if(selectedVersionView is null)
if(RemoteVersionCatalogComboBox.SelectedItem is not GameVersionCatalogProps catalogProps)
return;
InstalledVersionComboBox.Items.Insert(0, new VersionItemView(selectedVersionView.Props));
InstalledVersionComboBox.SelectedIndex = 0;
if(RemoteVersionCatalogItemsComboBox.SelectedItem is not RemoteGameVersionItemView sel)
return;
var installedProps = new InstalledGameVersionProps(sel.Props.id, catalogProps, sel.Props);
if (!LauncherApp.InstalledVersionCatalog.versions.TryAdd(sel.Props.id, installedProps))
throw new Exception("Версия уже была добавлена");
LauncherApp.InstalledVersionCatalog.Save();
var propsView = new InstalledGameVersionItemView(installedProps);
InstalledVersionCatalogComboBox.Items.Insert(0, propsView);
InstalledVersionCatalogComboBox.SelectedItem = propsView;
}
catch (Exception ex)
{
ErrorHelper.ShowMessageBox(nameof(MainWindow), ex);
}
}
private async void DeleteVersionButton_OnClick(object? sender, RoutedEventArgs e)
{
try
{
if(InstalledVersionCatalogComboBox.SelectedItem is not InstalledGameVersionItemView sel)
return;
var box = MessageBoxManager.GetMessageBoxCustom(new MessageBoxCustomParams
{
ButtonDefinitions = new List<ButtonDefinition> { new() { Name = "Да" }, new() { Name = "Нет" } },
ContentTitle = $"Удаление версии {sel.Props.Id}",
ContentMessage = $"Вы уверены, что хотите удалить версию {sel.Props.Id}? Все файлы, включая сохранения, будут удалены!",
Icon = MsBox.Avalonia.Enums.Icon.Question,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
SizeToContent = SizeToContent.WidthAndHeight,
ShowInCenter = true,
Topmost = true
}
);
var result = await box.ShowAsync().ConfigureAwait(false);
if (result != "Да")
return;
sel.Props.Delete();
Dispatcher.UIThread.Invoke(() =>
{
InstalledVersionCatalogComboBox.Items.Remove(sel);
LauncherApp.InstalledVersionCatalog.versions.Remove(sel.Props.Id);
LauncherApp.InstalledVersionCatalog.Save();
});
}
catch (Exception ex)
{

View File

@@ -1,34 +0,0 @@
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Threading;
using Mlaumcherb.Client.Avalonia.классы;
namespace Mlaumcherb.Client.Avalonia.зримое;
public partial class VersionItemView : ListBoxItem
{
public GameVersionProps Props { get; }
private SolidColorBrush _avaliableColor = new(Color.FromRgb(30, 130, 40));
private SolidColorBrush _unavaliableColor = new(Color.FromRgb(170, 70, 70));
public VersionItemView()
{
throw new Exception();
}
public VersionItemView(GameVersionProps props)
{
Props = props;
InitializeComponent();
text.Text = props.Name;
props.StatusChanged += UpdateBackground;
UpdateBackground(props.IsDownloaded);
}
private void UpdateBackground(bool isDownloaded)
{
Dispatcher.UIThread.Invoke(() =>
Background = isDownloaded ? _avaliableColor : _unavaliableColor
);
}
}