projekt sozdan

This commit is contained in:
Timerix 2024-08-31 23:55:57 +05:00
commit 5b9bd72308
16 changed files with 408 additions and 0 deletions

22
.gitignore vendored Normal file
View File

@ -0,0 +1,22 @@
# Build results
[Bb]in/
.bin/
[Dd]ebug/
[Rr]elease/
[Rr]eleases/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
[Pp]ublish/
# IDE files
.vs/
.vscode/
.vshistory/
.idea/
.editorconfig
*.user
#backups
.old*/

View File

@ -0,0 +1,50 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Млаумчерб.Клиент;
public class Config
{
public string username { get; set; } = "";
public int memory { get; set; } = 4096;
public bool fullscreen { get; set; }
[JsonIgnore] public static Config Instance { get; private set; } = new();
public const string FileName = "млаумчерб.конфиг";
public const string BackupFileName = "млаумчерб.конфиг.старый";
public static readonly Encoding UTF8WithoutBom = new UTF8Encoding(false);
public static void LoadFromFile()
{
//TODO: log
if(!File.Exists(FileName))
{
SaveToFile();
return;
}
string text = File.ReadAllText(FileName);
Config? c = JsonSerializer.Deserialize<Config>(text);
if (c is not null)
Instance = c;
else
{
File.Move(FileName, BackupFileName, true);
SaveToFile();
Errors.ShowMessageBox($"Не удалось прочитать конфиг.\n" +
$"Сломанный конфиг переименован в '{BackupFileName}'.\n" +
$"Создан новый файл '{FileName}'.");
}
}
public static void SaveToFile()
{
//TODO: log
var text = JsonSerializer.Serialize(Instance, new JsonSerializerOptions
{
WriteIndented = true
});
File.WriteAllText(FileName, text, UTF8WithoutBom);
}
}

View File

@ -0,0 +1,34 @@
using Avalonia.Controls;
using DTLib.Ben.Demystifier;
using MsBox.Avalonia;
using MsBox.Avalonia.Dto;
using MsBox.Avalonia.Models;
namespace Млаумчерб.Клиент;
public static class Errors
{
internal static void ShowMessageBox(Exception err)
=> ShowMessageBox(err.ToStringDemystified());
internal static async void ShowMessageBox(string err)
{
var box = MessageBoxManager.GetMessageBoxCustom(new MessageBoxCustomParams
{
ButtonDefinitions = new List<ButtonDefinition> { new() { Name = "пон" } },
ContentTitle = "ОШИБКА",
ContentMessage = err,
Icon = MsBox.Avalonia.Enums.Icon.Error,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
CanResize = true,
MaxWidth = 1000,
MaxHeight = 1000,
SizeToContent = SizeToContent.WidthAndHeight,
ShowInCenter = true,
Topmost = true
}
);
//TODO: write to log
await box.ShowAsync().ConfigureAwait(false);
}
}

View File

@ -0,0 +1,25 @@
global using System;
global using System.Collections.Generic;
global using System.IO;
global using System.Text;
using System.Globalization;
using Avalonia;
namespace Млаумчерб.Клиент;
class Главне
{
[STAThread]
public static void Main(string[] args)
{
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
}
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<Приложение>()
.UsePlatformDetect()
.LogToTrace();
}

View File

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>disable</ImplicitUsings>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>гойда.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<ApplicationIcon>капитал\icon.ico</ApplicationIcon>
<AssemblyName>млаумчерб</AssemblyName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.1.3" />
<PackageReference Include="Avalonia.Desktop" Version="11.1.3" />
<PackageReference Include="Avalonia.Themes.Simple" Version="11.1.3" />
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.1.3" />
<PackageReference Include="DTLib.Ben.Demystifier" Version="1.0.6" />
<PackageReference Include="MessageBox.Avalonia" Version="3.1.6" />
</ItemGroup>
<ItemGroup>
<AvaloniaResource Include="капитал\**"/>
</ItemGroup>
</Project>

View File

@ -0,0 +1,51 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Млаумчерб.Клиент.Окне"
Title="млаумчерб"
FontFamily="{StaticResource PlexMono}" FontSize="24"
Icon="avares://млаумчерб/капитал/icon.ico"
Width="600" Height="500"
Name="window">
<Grid>
<Grid.RowDefinitions>40 *</Grid.RowDefinitions>
<Image Grid.RowSpan="2" Stretch="UniformToFill"
Source="avares://млаумчерб/капитал/background.png"></Image>
<!-- <Border Grid.Row="0" Background="#7000b0"></Border> -->
<Grid Grid.Row="1" Margin="0 60">
<Grid.ColumnDefinitions>* 400 *</Grid.ColumnDefinitions>
<Border Grid.Column="1"
Height="400"
BorderThickness="1" BorderBrush="White"
Background="#b7303040">
<Grid>
<Grid.RowDefinitions>* 60</Grid.RowDefinitions>
<StackPanel Orientation="Vertical" Margin="10" Spacing="10">
<TextBlock>Username:</TextBlock>
<TextBox Text="{Binding #window.Username}"></TextBox>
<TextBlock>
<Run>Memory limit:</Run>
<TextBox Background="Transparent" Padding="0"
BorderThickness="1"
BorderBrush="#777777"
Text="{Binding #window.MemoryLimit}">
</TextBox>
<Run>Mb</Run>
</TextBlock>
<Slider Minimum="2048" Maximum="8192"
Foreground="Blue"
Value="{Binding #window.MemoryLimit}">
</Slider>
<CheckBox IsChecked="{Binding #window.Fullscreen}">Fullscreen</CheckBox>
<CheckBox IsChecked="{Binding #window.UpdateGameFiles}">Update game files</CheckBox>
</StackPanel>
<Button Grid.Row="1" Margin="10"
BorderThickness="1" BorderBrush="Gray"
Background="#BBFF4000"
Click="LaunchButtonHandler">
Launch
</Button>
</Grid>
</Border>
</Grid>
</Grid>
</Window>

View File

@ -0,0 +1,82 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Interactivity;
namespace Млаумчерб.Клиент;
public partial class Окне : Window
{
public static readonly StyledProperty<string> UsernameProperty =
AvaloniaProperty.Register<Окне, string>(nameof(Username),
defaultBindingMode: BindingMode.TwoWay);
public string Username
{
get => GetValue(UsernameProperty);
set => SetValue(UsernameProperty, value);
}
public static readonly StyledProperty<int> MemoryLimitProperty =
AvaloniaProperty.Register<Окне, int>(nameof(MemoryLimit),
defaultBindingMode: BindingMode.TwoWay, defaultValue: 2048);
public int MemoryLimit
{
get => GetValue(MemoryLimitProperty);
set => SetValue(MemoryLimitProperty, value);
}
public static readonly StyledProperty<bool> FullscreenProperty =
AvaloniaProperty.Register<Окне, bool>(nameof(Fullscreen),
defaultBindingMode: BindingMode.TwoWay, defaultValue: false);
public bool Fullscreen
{
get => GetValue(FullscreenProperty);
set => SetValue(FullscreenProperty, value);
}
public static readonly StyledProperty<bool> UpdateGameFilesProperty =
AvaloniaProperty.Register<Окне, bool>(nameof(UpdateGameFiles),
defaultBindingMode: BindingMode.TwoWay, defaultValue: true);
public bool UpdateGameFiles
{
get => GetValue(UpdateGameFilesProperty);
set => SetValue(UpdateGameFilesProperty, value);
}
public Окне()
{
InitializeComponent();
}
protected override void OnLoaded(RoutedEventArgs e)
{
try
{
Config.LoadFromFile();
Username = Config.Instance.username;
MemoryLimit = Config.Instance.memory;
Fullscreen = Config.Instance.fullscreen;
}
catch (Exception ex)
{
Errors.ShowMessageBox(ex);
}
}
private void LaunchButtonHandler(object? sender, RoutedEventArgs e)
{
try
{
Config.Instance.username = Username;
Config.Instance.memory = MemoryLimit;
Config.Instance.fullscreen = Fullscreen;
Config.SaveToFile();
}
catch (Exception ex)
{
Errors.ShowMessageBox(ex);
}
}
}

View File

@ -0,0 +1,12 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Млаумчерб.Клиент.Приложение"
RequestedThemeVariant="Dark">
<Application.Styles>
<SimpleTheme />
</Application.Styles>
<Application.Resources>
<FontFamily x:Key="PlexMono">avares://млаумчерб/капитал/IBMPlexMono-Regular.ttf</FontFamily>
</Application.Resources>
</Application>

View File

@ -0,0 +1,23 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
namespace Млаумчерб.Клиент;
public partial class Приложение : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new Окне();
}
base.OnFrameworkInitializationCompleted();
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embedded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="млаумчерб.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,47 @@
#!/usr/bin/env bash
set -eo pipefail
mode="$1"
outdir="bin/publish"
args_selfcontained="
--self-contained
--use-current-runtime
-p:PublishSingleFile=true
-p:PublishTrimmed=true
-p:TrimMode=partial
-p:EnableCompressionInSingleFile=true
-p:OptimizationPreference=Size
-p:InvariantGlobalization=true
-p:DebugType=none
-p:IncludeNativeLibrariesForSelfExtract=true"
args_aot="
-p:PublishAot=true
-p:OptimizationPreference=Size
-p:DebugType=none"
case "$mode" in
aot | native | бинарное)
args="$args_aot"
;;
self-contained | selfcontained | небинарное)
args="$args_selfcontained"
;;
*)
echo "ПОЛЬЗОВАНИЕ: ./собрать.sh [способ]"
echo " СПОСОБЫ:"
echo " бинарное - компилирует промежуточный (управляемый) код в машинный вместе с рантаймом"
echo " небинарное - приделывает промежуточный (управляемый) код к рантайму"
echo " Оба способа собирают программу в один файл, который не является 80-мегабайтовым умственно отсталым кубом. Он 20-мегабайтовый >w<"
exit 1
;;
esac
rm -rf "$outdir"
command="dotnet publish -c Release -o $outdir $args"
echo "$command"
$command
find "$outdir" -name '*.pdb' -delete -printf "deleted '%p'\n"
ls -shk "$outdir" | sort -h

16
млаумчерб.sln Normal file
View File

@ -0,0 +1,16 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Млаумчерб.Клиент", "Млаумчерб.Клиент\Млаумчерб.Клиент.csproj", "{9B9D8B05-255F-49C3-89EC-3F43A66491D3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9B9D8B05-255F-49C3-89EC-3F43A66491D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9B9D8B05-255F-49C3-89EC-3F43A66491D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B9D8B05-255F-49C3-89EC-3F43A66491D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B9D8B05-255F-49C3-89EC-3F43A66491D3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal