0
0
mirror of https://github.com/sp-tarkov/launcher.git synced 2025-02-12 16:50:43 -05:00

Merge branch '3.8.0'

This commit is contained in:
Refringe 2024-04-05 00:21:46 -04:00
commit 3f5c6b7028
Signed by: Refringe
GPG Key ID: 7715B85B4A6306ED
42 changed files with 831 additions and 440 deletions

View File

@ -0,0 +1,35 @@
name: Trigger Main Build Pipeline
on:
push:
tags:
- '*'
jobs:
trigger-main-build:
runs-on: ubuntu-latest
steps:
- name: Setup Git Config
run: |
git config --global user.email "noreply@sp-tarkov.com"
git config --global user.name "TriggerBot"
- name: Clone Build Repository
run: |
rm -rf ../Build
git clone https://${{ secrets.BUILD_USERNAME }}:${{ secrets.BUILD_ACCESS_TOKEN }}@dev.sp-tarkov.com/SPT-AKI/Build.git ../Build
- name: Trigger Branch
working-directory: ../Build
run: git checkout -b trigger || git checkout trigger
- name: Create Trigger File
working-directory: ../Build
run: |
echo "${GITHUB_REF_NAME}" > .gitea/trigger
git add .gitea/trigger
git commit -m "Launcher triggered build with tag '${GITHUB_REF_NAME}'"
- name: Force Push
working-directory: ../Build
run: git push --force origin trigger

View File

@ -19,9 +19,10 @@ git config --local user.email "USERNAME@SOMETHING.com"
## Requirements
- Escape From Tarkov 26535
- Escape From Tarkov 29197
- .NET 6 SDK
- Visual Studio Code
- [PowerShell v7](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows)
### For UI Development
@ -31,7 +32,7 @@ git config --local user.email "USERNAME@SOMETHING.com"
## Build
1. Run `dotnet tool restore` from command line inside project folder
2. Open Launcher.code-workspace in Visual Studio Code.
3. Run the build task: (top toolbar) Terminal -> Run Build Task...
3. Run the build task: (top toolbar) Terminal -> Run Build Task... (requires running twice on first run)
4. Copy-paste all files inside `Build` into `game root directory`, overwrite when prompted.
## Server Endpoints

View File

@ -1,12 +0,0 @@
{
"version": 1,
"isRoot": true,
"tools": {
"cake.tool": {
"version": "2.0.0",
"commands": [
"dotnet-cake"
]
}
}
}

View File

@ -1,22 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Aki.ByteBanger\Aki.ByteBanger.csproj" />
<ProjectReference Include="..\Aki.Launcher.Base\Aki.Launcher.Base.csproj" />
<ProjectReference Include="..\Aki.Launcher\Aki.Launcher.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(BuildingInsideVisualStudio)' == 'true'">
<Exec Command="dotnet cake &quot;../build.cake&quot; --config=&quot;$(ConfigurationName)&quot; --vsbuilt=true" />
</Target>
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(BuildingByReSharper)' == 'true'">
<Exec Command="dotnet cake &quot;../build.cake&quot; --config=&quot;$(ConfigurationName)&quot; --vsbuilt=true" />
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="dotnet publish ../Aki.Launcher/Aki.Launcher.csproj -c Release -f net8.0 -r win-x64 /p:IncludeNativeLibrariesForSelfExtract=true -p:PublishSingleFile=true --self-contained false"/>
<Exec Command="pwsh -NoProfile -ExecutionPolicy Bypass ../build.ps1" WorkingDirectory="$(ProjectDir)" />
</Target>
</Project>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@ -24,7 +24,7 @@ namespace Aki.ByteBanger
PatchedLength = patched.Length
};
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
using (SHA256 sha256 = SHA256.Create())
{
pi.OriginalChecksum = sha256.ComputeHash(original);
pi.PatchedChecksum = sha256.ComputeHash(patched);
@ -97,7 +97,7 @@ namespace Aki.ByteBanger
public static PatchResult Patch(byte[] input, PatchInfo pi)
{
byte[] inputHash;
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
using (SHA256 sha256 = SHA256.Create())
{
inputHash = sha256.ComputeHash(input);
}
@ -114,7 +114,7 @@ namespace Aki.ByteBanger
Array.Copy(itm.Data, 0, patchedData, itm.Offset, itm.Data.Length);
byte[] patchedHash;
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
using (SHA256 sha256 = SHA256.Create())
{
patchedHash = sha256.ComputeHash(patchedData);
}

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>Aki.Launch</RootNamespace>
</PropertyGroup>

View File

@ -8,11 +8,13 @@
*/
using System;
using Aki.Launcher.Helpers;
using Aki.Launcher.MiniCommon;
using Aki.Launcher.Models.Aki;
using Aki.Launcher.Models.Launcher;
using System.Threading.Tasks;
using Aki.Launcher.Controllers;
namespace Aki.Launcher
{
@ -135,6 +137,8 @@ namespace Aki.Launcher
{
return AccountStatus.NoConnection;
}
LogManager.Instance.Info($"Account Registered: {username}");
return Login(username, password);
}
@ -159,16 +163,20 @@ namespace Aki.Launcher
if(Json.Deserialize<bool>(json))
{
SelectedAccount = null;
LogManager.Instance.Info($"Account Removed: {data.username}");
return AccountStatus.OK;
}
else
{
LogManager.Instance.Error($"Failed to remove account: {data.username}");
return AccountStatus.UpdateFailed;
}
}
catch
{
LogManager.Instance.Error($"Failed to remove account: {data.username} - NO CONNECTION");
return AccountStatus.NoConnection;
}
}
@ -271,15 +279,18 @@ namespace Aki.Launcher
if (json != STATUS_OK)
{
LogManager.Instance.Error($"Failed to wipe account: {data.username}");
return AccountStatus.UpdateFailed;
}
}
catch
{
LogManager.Instance.Error($"Failed to wipe account: {data.username} - NO CONNECTION");
return AccountStatus.NoConnection;
}
SelectedAccount.edition = edition;
LogManager.Instance.Info($"Account Wiped: {data.username} -> {edition}");
return AccountStatus.OK;
}
}

View File

@ -57,23 +57,32 @@ namespace Aki.Launcher
public async Task<GameStarterResult> LaunchGame(ServerInfo server, AccountInfo account, string gamePath)
{
LogManager.Instance.Info(">>> Launching Game");
LogManager.Instance.Info($">>> Account: {account.username}");
LogManager.Instance.Info($">>> Server : {server.backendUrl}");
// setup directories
if (IsInstalledInLive())
{
LogManager.Instance.Warning("Failed installed in live check");
LogManager.Instance.Error("[LaunchGame] Installed in Live :: YES");
return GameStarterResult.FromError(-1);
}
LogManager.Instance.Info("[LaunchGame] Installed in Live :: NO");
LogManager.Instance.Info("[LaunchGame] Setup Game Files ...");
SetupGameFiles(gamePath);
if (!ValidationUtil.Validate())
{
LogManager.Instance.Warning("Failed validation check");
LogManager.Instance.Error("[LaunchGame] Game Validation :: FAILED");
return GameStarterResult.FromError(-2);
}
LogManager.Instance.Info("[LaunchGame] Game Validation :: OK");
if (account.wipe)
{
LogManager.Instance.Info("[LaunchGame] Wipe profile requested");
RemoveRegistryKeys();
CleanTempFiles();
}
@ -83,9 +92,12 @@ namespace Aki.Launcher
if (!File.Exists(clientExecutable))
{
LogManager.Instance.Warning($"Could not find {clientExecutable}");
LogManager.Instance.Error("[LaunchGame] Valid Game Path :: FAILED");
LogManager.Instance.Error($"Could not find {clientExecutable}");
return GameStarterResult.FromError(-6);
}
LogManager.Instance.Info("[LaunchGame] Valid Game Path :: OK");
// apply patches
ProgressReportingPatchRunner patchRunner = new ProgressReportingPatchRunner(gamePath);
@ -96,10 +108,12 @@ namespace Aki.Launcher
}
catch (TaskCanceledException)
{
LogManager.Instance.Warning("Failed to apply assembly patch");
LogManager.Instance.Error("[LaunchGame] Applying Patch :: FAILED");
return GameStarterResult.FromError(-4);
}
LogManager.Instance.Info("[LaunchGame] Applying Patch :: OK");
//start game
var args =
$"-force-gfx-jobs native -token={account.id} -config={Json.Serialize(new ClientConfig(server.backendUrl))}";
@ -107,6 +121,7 @@ namespace Aki.Launcher
if (_showOnly)
{
Console.WriteLine($"{clientExecutable} {args}");
LogManager.Instance.Info("[LaunchGame] NOOP :: show only");
}
else
{
@ -118,6 +133,7 @@ namespace Aki.Launcher
};
Process.Start(clientProcess);
LogManager.Instance.Info("[LaunchGame] Game process started");
}
return GameStarterResult.FromSuccess();
@ -160,6 +176,7 @@ namespace Aki.Launcher
if (File.Exists(file.FullName))
{
File.Delete(file.FullName);
LogManager.Instance.Warning($"File removed :: found in live dir: {file.FullName}");
isInstalledInLive = true;
}
}
@ -169,6 +186,7 @@ namespace Aki.Launcher
if (Directory.Exists(directory.FullName))
{
RemoveFilesRecurse(directory);
LogManager.Instance.Warning($"Directory removed :: found in live dir: {directory.FullName}");
isInstalledInLive = true;
}
}
@ -237,6 +255,7 @@ namespace Aki.Launcher
foreach (var value in key.GetValueNames())
{
key.DeleteValue(value);
LogManager.Instance.Debug($"Removing reg key: {key.Name}");
}
}
catch (Exception ex)
@ -266,6 +285,8 @@ namespace Aki.Launcher
bool RemoveFilesRecurse(DirectoryInfo basedir)
{
LogManager.Instance.Info($"Recursive Removal: {basedir}");
if (!basedir.Exists)
{
return true;
@ -286,6 +307,7 @@ namespace Aki.Launcher
{
file.IsReadOnly = false;
file.Delete();
LogManager.Instance.Debug($" -> del file: {file.FullName}");
}
// remove directory

View File

@ -17,35 +17,42 @@ namespace Aki.Launcher.Controllers
/// </summary>
public class LogManager
{
//TODO - update this to use reflection to get the calling method, class, etc
private static LogManager _instance;
public static LogManager Instance => _instance ?? (_instance = new LogManager());
private string filepath;
public static LogManager Instance => _instance ??= new LogManager();
private readonly string _filePath;
private readonly string _logFile;
public LogManager()
private LogManager()
{
filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "user", "logs");
_filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "user", "logs");
_logFile = Path.Combine(_filePath, "launcher.log");
if (File.Exists(_logFile))
{
File.Delete(_logFile);
}
Write($" ==== Launcher Started ====");
}
public void Write(string text)
private void Write(string text)
{
if (!Directory.Exists(filepath))
if (!Directory.Exists(_filePath))
{
Directory.CreateDirectory(filepath);
Directory.CreateDirectory(_filePath);
}
string filename = Path.Combine(filepath, "launcher.log");
File.AppendAllLines(filename, new[] { $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}]{text}" });
File.AppendAllLines(_logFile, new[] { $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}]{text}" });
}
public void Debug(string text) => Write($"[Debug]{text}");
public void Debug(string text) => Write($"[Debug] {text}");
public void Info(string text) => Write($"[Info]{text}");
public void Info(string text) => Write($"[Info] {text}");
public void Warning(string text) => Write($"[Warning]{text}");
public void Warning(string text) => Write($"[Warning] {text}");
public void Error(string text) => Write($"[Error]{text}");
public void Error(string text) => Write($"[Error] {text}");
public void Exception(Exception ex) => Write($"[Exception]{ex.Message}\nStacktrace:\n{ex.StackTrace}");
public void Exception(Exception ex) => Write($"[Exception] {ex.Message}\nStacktrace:\n{ex.StackTrace}");
}
}

View File

@ -14,6 +14,7 @@ using Newtonsoft.Json;
using System;
using System.ComponentModel;
using System.IO;
using Aki.Launcher.Controllers;
namespace Aki.Launcher.Helpers
{
@ -142,6 +143,8 @@ namespace Aki.Launcher.Helpers
{
if (!File.Exists(LauncherSettingsProvider.DefaultSettingsFileLocation))
{
LogManager.Instance.Warning("Launcher config not found");
LogManager.Instance.Info($"Creating launcher config: {LauncherSettingsProvider.DefaultSettingsFileLocation}");
LauncherStartGameAction = LauncherAction.MinimizeAction;
UseAutoLogin = true;
GamePath = Environment.CurrentDirectory;
@ -149,6 +152,8 @@ namespace Aki.Launcher.Helpers
Server = new ServerSetting { Name = "SPT-AKI", Url = "http://127.0.0.1:6969" };
SaveSettings();
}
LogManager.Instance.Info($"Using launcher config at: {LauncherSettingsProvider.DefaultSettingsFileLocation}");
}
public event PropertyChangedEventHandler PropertyChanged;

View File

@ -16,6 +16,7 @@ using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;
using Aki.Launcher.Controllers;
namespace Aki.Launcher.Helpers
{
@ -41,7 +42,8 @@ namespace Aki.Launcher.Helpers
public static void LoadLocaleFromFile(string localeRomanName)
{
LocaleData newLocale = Json.LoadClassWithoutSaving<LocaleData>(Path.Join(DefaultLocaleFolderPath, $"{localeRomanName}.json"));
var localePath = Path.Join(DefaultLocaleFolderPath, $"{localeRomanName}.json");
LocaleData newLocale = Json.LoadClassWithoutSaving<LocaleData>(localePath);
if (newLocale != null)
{
@ -54,9 +56,11 @@ namespace Aki.Launcher.Helpers
LauncherSettingsProvider.Instance.SaveSettings();
LocaleChanged(null, EventArgs.Empty);
return;
}
//could possibly raise an event here to say why the local wasn't changed.
LogManager.Instance.Error($"Could not load locale: {localePath}");
}
public static void TryAutoSetLocale()
@ -172,12 +176,17 @@ namespace Aki.Launcher.Helpers
englishLocale.i_understand = "I Understand";
englishLocale.game_version_mismatch_format_2 = "SPT is unable to run, this is because SPT expected to find EFT version '{1}',\nbut instead found version '{0}'\n\nEnsure you've downgraded your EFT as described in the install guide\non the page you downloaded SPT from";
englishLocale.description = "Description";
englishLocale.server_mods = "Server Mods";
englishLocale.profile_mods = "Profile Mods";
englishLocale.author = "Author";
englishLocale.wipe_on_start = "Wipe profile on game start";
englishLocale.copy_live_settings_question = "Would you like to copy your live game settings to spt";
englishLocale.mod_not_in_server_warning = "This mod was found in your profile, but is not loaded on the server";
englishLocale.active_server_mods = "Active Server Mods";
englishLocale.active_server_mods_info_text = "These mods are currently running on the server";
englishLocale.inactive_server_mods = "Inactive Server Mods";
englishLocale.inactive_server_mods_info_text =
"These mods have not been loaded by the server, but your profile has used them in the past";
englishLocale.open_link_question_format_1 = "Are you sure you want to open the following link: \n{0}";
englishLocale.open_link = "Open Link";
#endregion
Directory.CreateDirectory(LocalizationProvider.DefaultLocaleFolderPath);
@ -1576,38 +1585,6 @@ namespace Aki.Launcher.Helpers
}
#endregion
#region server_mods
private string _server_mods;
public string server_mods
{
get => _server_mods;
set
{
if (_server_mods != value)
{
_server_mods = value;
RaisePropertyChanged(nameof(server_mods));
}
}
}
#endregion
#region profile_mods
private string _profile_mods;
public string profile_mods
{
get => _profile_mods;
set
{
if (_profile_mods != value)
{
_profile_mods = value;
RaisePropertyChanged(nameof(profile_mods));
}
}
}
#endregion
#region author
private string _author;
public string author
@ -1672,6 +1649,111 @@ namespace Aki.Launcher.Helpers
}
}
#endregion
#region active_server_mods
private string _active_server_mods;
public string active_server_mods
{
get => _active_server_mods;
set
{
if (_active_server_mods != value)
{
_active_server_mods = value;
RaisePropertyChanged(nameof(active_server_mods));
}
}
}
#endregion
#region active_server_mods_info_text
private string _active_server_mods_info_text;
public string active_server_mods_info_text
{
get => _active_server_mods_info_text;
set
{
if (_active_server_mods_info_text != value)
{
_active_server_mods_info_text = value;
RaisePropertyChanged(nameof(active_server_mods_info_text));
}
}
}
#endregion
#region inactive_server_mods
private string _inactive_server_mods;
public string inactive_server_mods
{
get => _inactive_server_mods;
set
{
if (_inactive_server_mods != value)
{
_inactive_server_mods = value;
RaisePropertyChanged(nameof(inactive_server_mods));
}
}
}
#endregion
#region inactive_server_mods_info_text
private string _inactive_server_mods_info_text;
public string inactive_server_mods_info_text
{
get => _inactive_server_mods_info_text;
set
{
if (_inactive_server_mods_info_text != value)
{
_inactive_server_mods_info_text = value;
RaisePropertyChanged(nameof(inactive_server_mods_info_text));
}
}
}
#endregion
#region open_link_question_format_1
private string _open_link_question_format_1;
public string open_link_question_format_1
{
get => _open_link_question_format_1;
set
{
if (_open_link_question_format_1 != value)
{
_open_link_question_format_1 = value;
RaisePropertyChanged(nameof(open_link_question_format_1));
}
}
}
#endregion
#region open_link
private string _open_link;
public string open_link
{
get => _open_link;
set
{
if (_open_link != value)
{
_open_link = value;
RaisePropertyChanged(nameof(open_link));
}
}
}
#endregion
#endregion
public event PropertyChangedEventHandler PropertyChanged;

View File

@ -7,5 +7,6 @@
public string Author { get; set; }
public string Name { get; set; }
public string Version { get; set; }
public string Url { get; set; }
}
}

View File

@ -59,5 +59,10 @@ namespace Aki.Launcher.Models.Aki
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
public override string ToString()
{
return HasTag ? $"{Major}.{Minor}.{Build}-{Tag}" : $"{Major}.{Minor}.{Build}";
}
}
}

View File

@ -20,7 +20,7 @@ namespace Aki.Launcher.Models.Launcher
}
}
}
private int _profileModsCount;
public int ProfileModsCount
{
@ -35,20 +35,6 @@ namespace Aki.Launcher.Models.Launcher
}
}
private bool _hasProfileOnlyMods;
public bool HasProfileOnlyMods
{
get => _hasProfileOnlyMods;
set
{
if (_hasProfileOnlyMods != value)
{
_hasProfileOnlyMods = value;
RaisePropertyChanged(nameof(HasProfileOnlyMods));
}
}
}
private bool _hasMods;
public bool HasMods
{
@ -63,7 +49,8 @@ namespace Aki.Launcher.Models.Launcher
}
}
public ObservableCollection<AkiMod> Mods { get; private set; } = new ObservableCollection<AkiMod>();
public ObservableCollection<AkiMod> ActiveMods { get; private set; } = new ObservableCollection<AkiMod>();
public ObservableCollection<AkiMod> InactiveMods { get; private set; } = new ObservableCollection<AkiMod>();
public ModInfoCollection()
{
@ -73,15 +60,15 @@ namespace Aki.Launcher.Models.Launcher
ServerModsCount = serverMods?.Count() ?? 0;
ProfileModsCount = profileMods?.Count() ?? 0;
foreach (var serverMod in serverMods)
foreach (var activeMod in serverMods)
{
serverMod.InServer = true;
Mods.Add(serverMod);
activeMod.InServer = true;
ActiveMods.Add(activeMod);
}
foreach (var profileMod in profileMods)
foreach (var inactiveMod in profileMods)
{
var existingMod = Mods.Where(x => x.Name == profileMod.Name && x.Version == profileMod.Version && x.Author == profileMod.Author).FirstOrDefault();
var existingMod = ActiveMods.Where(x => x.Name == inactiveMod.Name && x.Version == inactiveMod.Version && x.Author == inactiveMod.Author).FirstOrDefault();
if (existingMod != null)
{
@ -89,12 +76,11 @@ namespace Aki.Launcher.Models.Launcher
continue;
}
profileMod.InProfile = true;
Mods.Add(profileMod);
inactiveMod.InProfile = true;
InactiveMods.Add(inactiveMod);
}
HasMods = Mods.Count() > 0;
HasProfileOnlyMods = Mods.Where(x => x.InProfile && !x.InServer).Count() > 0;
HasMods = ActiveMods.Count > 0 || InactiveMods.Count > 0;
}
public event PropertyChangedEventHandler PropertyChanged;

View File

@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
<Nullable>enable</Nullable>
<ApplicationIcon>Assets\icon.ico</ApplicationIcon>

View File

@ -81,13 +81,17 @@
"i_understand": "我了解",
"game_version_mismatch_format_2": "SPT无法运行这是由于SPT需要EFT版本 '{1}'\n但现有版本是 '{0}'\n\n确保你已经按照你下载SPT的页面上的\n安装指导的描述降级你的EFT",
"description": "描述",
"server_mods": "Server Mods",
"profile_mods": "Profile Mods",
"author": "Author",
"load_live_settings": "Load Live Settings",
"load_live_settings_succeeded": "Game settings copied from live",
"load_live_settings_failed": "Failed to copy live settings",
"wipe_on_start": "Wipe profile on game start",
"copy_live_settings_question": "Would you like to copy your live game settings to spt",
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server"
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server",
"active_server_mods": "Active Server Mods",
"active_server_mods_info_text": "These mods are currently running on the server",
"inactive_server_mods": "Inactive Server Mods",
"inactive_server_mods_info_text": "These mods have not been loaded by the server, but your profile has used them in the past",
"open_link_question_format_1": "Are you sure you want to open the following link: \n{0}",
"open_link": "Open Link"
}

View File

@ -81,13 +81,17 @@
"i_understand": "I Understand",
"game_version_mismatch_format_2": "SPT is unable to run, this is because SPT expected to find EFT version '{1}',\nbut instead found version '{0}'\n\nEnsure you've downgraded your EFT as described in the install guide\non the page you downloaded SPT from",
"description": "Description",
"server_mods": "Server Mods",
"profile_mods": "Profile Mods",
"author": "Author",
"load_live_settings": "Load Live Settings",
"load_live_settings_succeeded": "Game settings copied from live",
"load_live_settings_failed": "Failed to copy live settings",
"wipe_on_start": "Wipe profile on game start",
"copy_live_settings_question": "Would you like to copy your live game settings to spt",
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server"
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server",
"active_server_mods": "Active Server Mods",
"active_server_mods_info_text": "These mods are currently running on the server",
"inactive_server_mods": "Inactive Server Mods",
"inactive_server_mods_info_text": "These mods have not been loaded by the server, but your profile has used them in the past",
"open_link_question_format_1": "Are you sure you want to open the following link: \n{0}",
"open_link": "Open Link"
}

View File

@ -81,13 +81,17 @@
"i_understand": "I Understand",
"game_version_mismatch_format_2": "SPT is unable to run, this is because SPT expected to find EFT version '{1}',\nbut instead found version '{0}'\n\nEnsure you've downgraded your EFT as described in the install guide\non the page you downloaded SPT from",
"description": "Description",
"server_mods": "Server Mods",
"profile_mods": "Profile Mods",
"author": "Author",
"load_live_settings": "Load Live Settings",
"load_live_settings_succeeded": "Game settings copied from live",
"load_live_settings_failed": "Failed to copy live settings",
"wipe_on_start": "Wipe profile on game start",
"copy_live_settings_question": "Would you like to copy your live game settings to spt",
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server"
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server",
"active_server_mods": "Active Server Mods",
"active_server_mods_info_text": "These mods are currently running on the server",
"inactive_server_mods": "Inactive Server Mods",
"inactive_server_mods_info_text": "These mods have not been loaded by the server, but your profile has used them in the past",
"open_link_question_format_1": "Are you sure you want to open the following link: \n{0}",
"open_link": "Open Link"
}

View File

@ -81,13 +81,17 @@
"i_understand": "I Understand",
"game_version_mismatch_format_2": "SPT is unable to run, this is because SPT expected to find EFT version '{1}',\nbut instead found version '{0}'\n\nEnsure you've downgraded your EFT as described in the install guide\non the page you downloaded SPT from",
"description": "Description",
"server_mods": "Server Mods",
"profile_mods": "Profile Mods",
"author": "Author",
"load_live_settings": "Load Live Settings",
"load_live_settings_succeeded": "Game settings copied from live",
"load_live_settings_failed": "Failed to copy live settings",
"wipe_on_start": "Wipe profile on game start",
"copy_live_settings_question": "Would you like to copy your live game settings to spt",
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server"
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server",
"active_server_mods": "Active Server Mods",
"active_server_mods_info_text": "These mods are currently running on the server",
"inactive_server_mods": "Inactive Server Mods",
"inactive_server_mods_info_text": "These mods have not been loaded by the server, but your profile has used them in the past",
"open_link_question_format_1": "Are you sure you want to open the following link: \n{0}",
"open_link": "Open Link"
}

View File

@ -81,13 +81,17 @@
"i_understand": "I Understand",
"game_version_mismatch_format_2": "SPT is unable to run, this is because SPT expected to find EFT version '{1}',\nbut instead found version '{0}'\n\nEnsure you've downgraded your EFT as described in the install guide\non the page you downloaded SPT from",
"description": "Description",
"server_mods": "Server Mods",
"profile_mods": "Profile Mods",
"author": "Author",
"load_live_settings": "Load Live Settings",
"load_live_settings_succeeded": "Game settings copied from live",
"load_live_settings_failed": "Failed to copy live settings",
"wipe_on_start": "Wipe profile on game start",
"copy_live_settings_question": "Would you like to copy your live game settings to spt",
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server"
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server",
"active_server_mods": "Active Server Mods",
"active_server_mods_info_text": "These mods are currently running on the server",
"inactive_server_mods": "Inactive Server Mods",
"inactive_server_mods_info_text": "These mods have not been loaded by the server, but your profile has used them in the past",
"open_link_question_format_1": "Are you sure you want to open the following link: \n{0}",
"open_link": "Open Link"
}

View File

@ -81,13 +81,17 @@
"i_understand": "Accetto",
"game_version_mismatch_format_2": "SPT non riesce ad avviarsi, questo è perché SPT si aspettava la versione di EFT '{1}',\nmentre invece tu hai la versione '{0}'\n\nAssicurati di aver downgradato correttamente EFT come descritto nella guida all'installazione\nche hai trovato sulla pagina web da cui hai scaricato SPT",
"description": "Descrizione",
"server_mods": "Server Mods",
"profile_mods": "Profile Mods",
"author": "Author",
"load_live_settings": "Load Live Settings",
"load_live_settings_succeeded": "Game settings copied from live",
"load_live_settings_failed": "Failed to copy live settings",
"wipe_on_start": "Wipe profile on game start",
"copy_live_settings_question": "Would you like to copy your live game settings to spt",
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server"
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server",
"active_server_mods": "Active Server Mods",
"active_server_mods_info_text": "These mods are currently running on the server",
"inactive_server_mods": "Inactive Server Mods",
"inactive_server_mods_info_text": "These mods have not been loaded by the server, but your profile has used them in the past",
"open_link_question_format_1": "Are you sure you want to open the following link: \n{0}",
"open_link": "Open Link"
}

View File

@ -81,13 +81,17 @@
"i_understand": "了解",
"game_version_mismatch_format_2": "SPT を実行できません。これは、SPT が EFT バージョン '{1}' を検出することを期待していたためです\n代わりにバージョン '{0}' を検出しました\n\nインストール ガイドの説明に従って EFT をダウングレードしたことを確認してください\n SPT をダウンロードしたページ",
"description": "Description",
"server_mods": "Server Mods",
"profile_mods": "Profile Mods",
"author": "Author",
"load_live_settings": "Load Live Settings",
"load_live_settings_succeeded": "Game settings copied from live",
"load_live_settings_failed": "Failed to copy live settings",
"wipe_on_start": "Wipe profile on game start",
"copy_live_settings_question": "Would you like to copy your live game settings to spt",
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server"
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server",
"active_server_mods": "Active Server Mods",
"active_server_mods_info_text": "These mods are currently running on the server",
"inactive_server_mods": "Inactive Server Mods",
"inactive_server_mods_info_text": "These mods have not been loaded by the server, but your profile has used them in the past",
"open_link_question_format_1": "Are you sure you want to open the following link: \n{0}",
"open_link": "Open Link"
}

View File

@ -81,13 +81,17 @@
"i_understand": "이해하였습니다",
"game_version_mismatch_format_2": "당신의 게임 버전은 '{0}'이며 호환되는 버전은 '{1}' 입니다.\n\n게임 실행에 문제가 발생하거나 되지 않을 수 있습니다.",
"description": "설명",
"server_mods": "서버 모드",
"profile_mods": "프로필 모드",
"author": "개발자",
"load_live_settings": "공식(Live) 서버의 설정 불러오기",
"load_live_settings_succeeded": "공식(Live) 서버 설정을 불러왔습니다",
"load_live_settings_failed": "공식(Live) 서버 설정 불러오기에 실패하였습니다",
"wipe_on_start": "게임 시작 시 프로필 초기화",
"copy_live_settings_question": "공식(Live) 서버에서 사용하던 설정 파일을 SPT에 복사하시겠습니까?",
"mod_not_in_server_warning":"SPT 서버에 없는 모드가 플레이어 프로필에서 발견되었습니다"
"mod_not_in_server_warning":"SPT 서버에 없는 모드가 플레이어 프로필에서 발견되었습니다",
"active_server_mods": "Active Server Mods",
"active_server_mods_info_text": "These mods are currently running on the server",
"inactive_server_mods": "Inactive Server Mods",
"inactive_server_mods_info_text": "These mods have not been loaded by the server, but your profile has used them in the past",
"open_link_question_format_1": "Are you sure you want to open the following link: \n{0}",
"open_link": "Open Link"
}

View File

@ -81,13 +81,17 @@
"i_understand": "Rozumiem",
"game_version_mismatch_format_2": "SPT nie może zostać uruchomiony, ponieważ SPT oczekiwał wersji EFT '{1}',\nale zamiast tego znalazł wersję '{0}'\n\nUpewnij się, że zainstalowałeś starszą wersję EFT, zgodnie z instrukcją instalacji\nna stronie, z której pobrałeś SPT",
"description": "Opis",
"server_mods": "Mody serwera",
"profile_mods": "Mody profilu",
"author": "Autor",
"load_live_settings": "Wczytaj ustawienia EFT",
"load_live_settings_succeeded": "Ustawienia gry skopiowane z EFT",
"load_live_settings_failed": "Nie udało się skopiować ustawień EFT",
"wipe_on_start": "Wipe profile on game start",
"copy_live_settings_question": "Would you like to copy your live game settings to spt",
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server"
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server",
"active_server_mods": "Active Server Mods",
"active_server_mods_info_text": "These mods are currently running on the server",
"inactive_server_mods": "Inactive Server Mods",
"inactive_server_mods_info_text": "These mods have not been loaded by the server, but your profile has used them in the past",
"open_link_question_format_1": "Are you sure you want to open the following link: \n{0}",
"open_link": "Open Link"
}

View File

@ -81,13 +81,17 @@
"i_understand": "Я понимаю",
"game_version_mismatch_format_2": "Ваша версия игры: '{0}' и совместимая версия: '{1}'.\n\nИгра может работать некорректно или не работать вообще.",
"description": "Описание",
"server_mods": "Серверные моды",
"profile_mods": "Моды профиля",
"author": "Автор",
"load_live_settings": "Загрузить настройкий онлайн-версии",
"load_live_settings_succeeded": "Настройки игры скопированы из онлайн-версии",
"load_live_settings_failed": "Не удалось скопировать настройки онлайн-версии",
"wipe_on_start": "Wipe profile on game start",
"copy_live_settings_question": "Would you like to copy your live game settings to spt",
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server"
"wipe_on_start": "Очистить профиль при старте игры",
"copy_live_settings_question": "Хотите скопировать настройки онлайн-версии в spt?",
"mod_not_in_server_warning":"Этот мод был найден в вашем профиле, но не загружен на сервер",
"active_server_mods": "Активные серверные моды",
"active_server_mods_info_text": "На данный момент эти моды работают на сервере",
"inactive_server_mods": "Неактивные серверные моды",
"inactive_server_mods_info_text": "Эти моды не были загружены сервером, но ваш профиль использовал их раньше",
"open_link_question_format_1": "Вы уверены, что хотите открыть следующую ссылку? \n{0}",
"open_link": "Открыть ссылку"
}

View File

@ -81,13 +81,17 @@
"i_understand": "Lo entiendo",
"game_version_mismatch_format_2": "SPT no puede iniciar, esto es debido a que la versión de EFT esperada es '{1}',\npero la versión encontrada es '{0}'\n\nAsegurate de haber realizado el downgrade de tu versión de EFT, tal como se indica en la guía de instalación\nen la página en la que has descargado SPT",
"description": "Descripción",
"server_mods": "Server Mods",
"profile_mods": "Profile Mods",
"author": "Author",
"load_live_settings": "Load Live Settings",
"load_live_settings_succeeded": "Game settings copied from live",
"load_live_settings_failed": "Failed to copy live settings",
"wipe_on_start": "Wipe profile on game start",
"copy_live_settings_question": "Would you like to copy your live game settings to spt",
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server"
"mod_not_in_server_warning":"This mod was found in your profile, but is not loaded on the server",
"active_server_mods": "Active Server Mods",
"active_server_mods_info_text": "These mods are currently running on the server",
"inactive_server_mods": "Inactive Server Mods",
"inactive_server_mods_info_text": "These mods have not been loaded by the server, but your profile has used them in the past",
"open_link_question_format_1": "Are you sure you want to open the following link: \n{0}",
"open_link": "Open Link"
}

View File

@ -0,0 +1,97 @@
{
"ietf_tag": "tr",
"native_name": "Turkish",
"retry": "Yeniden Dene",
"server_connecting": "Bağlanıyor",
"server_unavailable_format_1": "Varsayılan sunucu '{0}' mevcut değil.",
"no_servers_available": "Sunucu bulunamadı. Ayarlardaki sunucu listesini kontrol edin.",
"settings_menu": "Ayarlar",
"back": "Geri dön",
"wipe_profile": "Profili Wipela",
"username": "Kullanıcı Adı",
"password": "Şifre",
"update": "Güncelleme",
"edit_account_update_error": "Profilinizi güncellerken bir sorun oluştu.",
"register": "Kayıt Ol",
"go_to_register": "Kayıt Ol'a git",
"login_or_register": "Giriş Yap / Kaydol",
"go_to_login": "Giriş Yap'a git",
"login_automatically": "Otomatik Oturum Açma",
"incorrect_login": "Kullanıcı adı veya şifre yanlış.",
"login_failed": "Oturum Açma Başarısız",
"edition": "Sürüm",
"id": "ID",
"logout": "Oturumu Kapat",
"account": "Profil",
"edit_account": "Profil Düzenle",
"start_game": "Oyunu Başlat",
"installed_in_live_game_warning": "Aki canlı oyun dizinine yüklenmemelidir. Lütfen Aki'yi bilgisayarınızın başka bir yerindeki oyun dizininin bir kopyasına yükleyin.",
"no_official_game_warning": "Escape From Tarkov oyunu bilgisayarınızda yüklü değil. Lütfen oyunun bir kopyasını satın alın ve geliştiricileri destekleyin!",
"eft_exe_not_found_warning": "EscapeFromTarkov.exe oyun yolunda bulunamadı. Lütfen dizinin doğru olup olmadığını kontrol edin.",
"account_exist": "Profil zaten mevcut",
"url": "URL",
"default_language": "Varsayılan Dil",
"game_path": "SPT Oyun Klasörü",
"clear_game_settings": "Oyun Ayarlarını Temizle",
"clear_game_settings_succeeded": "Oyun ayarları temizlendi.",
"clear_game_settings_failed": "Oyun ayarları temizlenirken bir sorun oluştu.",
"remove_registry_keys": "Kayıt Defteri Anahtarlarını Kaldır",
"remove_registry_keys_succeeded": "Kayıt defteri anahtarları kaldırıldı.",
"remove_registry_keys_failed": "Kayıt defteri anahtarları kaldırılırken bir sorun oluştu.",
"clean_temp_files": "Temp Dosyalarını Temizleme",
"clean_temp_files_succeeded": "Temp dosyaları temizlendi.",
"clean_temp_files_failed": "Temp dosyalar temizlenirken bir sorun oluştu.",
"select_folder": "Klasör Seçin",
"registration_failed": "Kayıt başarısız oldu.",
"minimize_action": "Küçült",
"do_nothing_action": "Hiçbir şey yapma",
"exit_action": "Başlatıcıyı Kapat",
"on_game_start": "Oyun Başlayınca başlatıcıya ne yapılsın",
"game": "Oyun",
"new_password": "Yeni Parola",
"cancel": "İptal",
"need_an_account": "Henüz bir profiliniz yok mu?",
"have_an_account": "Zaten bir profiliniz var mı?",
"reapply_patch": "Yamayı Yeniden Uygula",
"failed_to_receive_patches": "Yamalar alınamadı",
"failed_core_patch": "Core yaması başarısız",
"failed_mod_patch": "Mod yaması başarısız oldu",
"ok": "TAMAM.",
"account_page_denied": "Profil sayfası reddedildi. Ya giriş yapmadınız ya da oyun çalışıyor.",
"account_updated": "Profiliniz güncellendi",
"nickname": "Kullanıcı adı",
"side": "Taraf",
"level": "Level",
"patching": "Yama",
"file_mismatch_dialog_message": "Girdi dosyası hash'i beklenen hash ile eşleşmiyor. İstemci dosyalarınız için AKI'nin yanlış sürümünü kullanıyor olabilirsiniz.\n\nDevam etmek istiyor musunuz?",
"yes": "Evet",
"no": "Hayır",
"open_folder": "Klasörü Aç",
"select_edition": "Versiyon Seçin",
"profile_created": "Profil Oluşturuldu",
"registration_question_format_1": "Profil '{0}' mevcut değil.\n\nBunu oluşturmak ister misiniz?",
"next_level_in": "Bir sonraki seviye",
"wipe_warning": "Hesap sürümünüzü değiştirmek için profil silmeniz gerekir. Bu, oyun ilerlemenizi sıfırlayacaktır.",
"copied": "Kopyalandı",
"no_profile_data": "Profil verisi yok",
"profile_version_mismath": "Profiliniz farklı bir aki sürümü kullanılarak oluşturulmuştur ve sorunları olabilir",
"profile_removed": "Profil kaldırıldı",
"profile_removal_failed": "Profil kaldırılamadı",
"profile_remove_question_format_1": "'{0}' profilini kalıcı olarak kaldıralım mı?",
"i_understand": "Anlıyorum.",
"game_version_mismatch_format_2": "SPT çalıştırılamıyor, bunun nedeni SPT'nin '{1}' EFT sürümünü bulmayı beklemesi, ancak bunun yerine '{0}' sürümünü bulmasıdır\n\nEFT'nizi SPT'yi indirdiğiniz sayfada değil\nkurulum kılavuzunda açıklandığı şekilde düşürdüğünüzden emin olun",
"description": "Açıklama",
"author": "Yazar",
"load_live_settings": "Canlı Ayarları Yükle",
"load_live_settings_succeeded": "Oyun ayarları canlıdan kopyalandı",
"load_live_settings_failed": "Canlı ayarlar kopyalanamadı",
"wipe_on_start": "Oyun başladığında profili wipela",
"copy_live_settings_question": "Canlı oyun ayarlarınızı spt'ye kopyalamak ister misiniz",
"mod_not_in_server_warning":"Bu mod profilinizde bulundu, ancak sunucuda yüklü değil",
"active_server_mods": "Aktif Sunucu Modları",
"active_server_mods_info_text": "Bu modlar şu anda sunucuda çalışmaktadır",
"inactive_server_mods": "Aktif Olmayan Sunucu Modları",
"inactive_server_mods_info_text": "Bu modlar sunucu tarafından yüklenmedi, ancak profiliniz geçmişte bunları kullandı",
"open_link_question_format_1": "Aşağıdaki bağlantıyı açmak istediğinizden emin misiniz? \n{0}",
"open_link": "Bağlantıyı Aç"
}

View File

@ -31,34 +31,37 @@
<PathGeometry x:Key="FolderWithPlus" Figures="M20 6h-8l-2-2H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-1 8h-3v3h-2v-3h-3v-2h3V9h2v3h3v2z" FillRule="NonZero"
/>
<PathGeometry x:Key="OpenFolder" Figures="M 2.2731724 14.474999 C 2.5381753 14.186249 3.2824783 12.195001 3.9271792 10.05 5.6676413 4.2592679 4.7621113 4.8000009 12.719033 4.8000009 c 5.6684 0 6.78597
0.072438 7.12511 0.4618343 0.332844 0.3821726 0.17704 1.1971998 -0.903259 4.7250006 -0.763041 2.4917722 -1.52781 4.4189802 -1.840552 4.6381652 C 16.708149 14.899859 14.592619 15 9.1783054
15 2.1694393 15 1.8160107 14.973129 2.2731724 14.474999 Z M 0.36305228 14.025959 C 0.11166709 13.786409 0 11.721164 0 7.3114288 0 1.9218189 0.0760474 0.8703905 0.49472143 0.47142828 0.8806724
0.10364926 1.7051307 0 4.2446088 0 7.4749739 0 7.5058294 0.00685701 8.2944922 0.89999983 L 9.0892098 1.8 h 3.6407872 c 3.221023 0 3.71338 0.069177 4.270431 0.5999996 0.346306 0.3300009 0.629646
0.802501 0.629646 1.0500009 0 0.3838238 -0.858607 0.4500002 -5.83853 0.4500002 -5.6986082 0 -5.856156 0.016794 -6.5739181 0.7007613 C 4.8131633 4.9861817 4.2426547 6.0999322 3.9498292 7.0757619
2.3566037 12.385128 1.8127023 13.81777 1.2887903 14.084957 c -0.37832867 0.192941 -0.68163535 0.173611 -0.92573802 -0.059 z" FillRule="NonZero"
/>
<PathGeometry x:Key="OpenFolder" Figures="M 2.2731724 14.474999 C 2.5381753 14.186249 3.2824783 12.195001 3.9271792 10.05 5.6676413 4.2592679 4.7621113 4.8000009 12.719033 4.8000009 c 5.6684 0 6.78597 0.072438 7.12511 0.4618343 0.332844 0.3821726 0.17704 1.1971998 -0.903259 4.7250006 -0.763041 2.4917722 -1.52781 4.4189802 -1.840552 4.6381652 C 16.708149 14.899859 14.592619 15 9.1783054 15 2.1694393 15 1.8160107 14.973129 2.2731724 14.474999 Z M 0.36305228 14.025959 C 0.11166709 13.786409 0 11.721164 0 7.3114288 0 1.9218189 0.0760474 0.8703905 0.49472143 0.47142828 0.8806724 0.10364926 1.7051307 0 4.2446088 0 7.4749739 0 7.5058294 0.00685701 8.2944922 0.89999983 L 9.0892098 1.8 h 3.6407872 c 3.221023 0 3.71338 0.069177 4.270431 0.5999996 0.346306 0.3300009 0.629646 0.802501 0.629646 1.0500009 0 0.3838238 -0.858607 0.4500002 -5.83853 0.4500002 -5.6986082 0 -5.856156 0.016794 -6.5739181 0.7007613 C 4.8131633 4.9861817 4.2426547 6.0999322 3.9498292 7.0757619 2.3566037 12.385128 1.8127023 13.81777 1.2887903 14.084957 c -0.37832867 0.192941 -0.68163535 0.173611 -0.92573802 -0.059 z"
FillRule="NonZero"
/>
<PathGeometry x:Key="Alert" Figures="M 1.1531774 13.277025 C 1.7874263 12.329396 3.9770847 8.9543883 6.0190869 5.7770253 8.0610888 2.599662 9.8524992 0 10 0 c 0.147501 0 1.938911 2.599662 3.980913 5.7770253 2.042002 3.177363 4.23166 6.5523707 4.86591 7.4999997 L 20 15 H 10 0 Z M 10.904431 11.75675 c 0 -0.540527 -0.301477 -0.810801 -0.904431 -0.810801 -0.6029544 0 -0.9044312 0.270274 -0.9044312 0.810801 0 0.540545 0.3014768 0.810818 0.9044312 0.810818 0.602954 0 0.904431 -0.270273 0.904431 -0.810818 z m 0 -4.4594502 C 10.904431 5.540539 10.783833 5.270267 10 5.270267 c -0.78384 0 -0.9044312 0.270272 -0.9044312 2.0270328 0 1.7567452 0.1205987 2.0270177 0.9044312 2.0270177 0.78384 0 0.904431 -0.2702725 0.904431 -2.0270177 z" FillRule="NonZero"
/>
<PathGeometry x:Key="Delete" Figures="M 1.371429 14.489266 C 1.0250013 14.152485 0.85714332 12.248674 0.85714332 8.6563122 V 3.3233314 H 6 11.142857 v 5.3329808 c 0 3.5923618 -0.167858 5.4961728 -0.514286 5.8329538 -0.7004895 0.680979 -8.5566525 0.680979 -9.257142 0 z M 0 1.6567735 C 0 0.96445539 0.28571444 0.82349613 1.6889935 0.82349613 c 0.9289457 0 1.8081847 -0.18748843 1.9538644 -0.41664027 0.3448694 -0.54247448 4.3694148 -0.54247448 4.7142842 0 0.1456846 0.22915184 1.0249187 0.41664027 1.9538639 0.41664027 1.40328 0 1.688994 0.14096714 1.688994 0.83327737 0 0.7935997 -0.285714 0.8332789 -6 0.8332789 -5.71428556 0 -6 -0.039683 -6 -0.8332789 z" FillRule="NonZero"
/>
<PathGeometry x:Key="Gear" Figures="m 4.4615102 11.271429 c 0 -0.992273 -0.845292 -1.7685001 -1.6612536 -1.5255145 C 1.5450127 10.119702 1.3309542 10.039187 0.67223375 8.9455133 L 0.00700434 7.8410343 0.69579591 7.1261827 C 1.5704786 6.2184053 1.5693913 5.4953105 0.69230711 4.7875001 L 0 4.228826 0.66874495 3.0894129 C 1.3304739 1.9619619 1.5415251 1.879247 2.8002845 2.2540889 3.6162462 2.4970745 4.4615381 1.7208472 4.4615381 0.7285713 4.4615381 0.05428908 4.5761682 0 6 0 c 1.4238306 0 1.5384619 0.05431176 1.5384619 0.7285713 0 0.9922759 0.8452919 1.7685032 1.6612536 1.5255176 1.2587595 -0.3748419 1.4698105 -0.292127 2.1315395 0.835324 L 12 4.228826 11.307692 4.7875001 c -0.877111 0.7078104 -0.878199 1.4309052 -0.0035 2.3386826 l 0.688796 0.7148516 -0.665233 1.104479 C 10.669034 10.039187 10.454975 10.119702 9.1997324 9.7459145 8.3837708 9.5029289 7.5384788 10.279156 7.5384788 11.271429 7.5384788 11.945711 7.4238487 12 6.0000169 12 4.5761863 12 4.461555 11.945688 4.461555 11.271429 Z M 7.4416793 7.4477106 C 8.3356062 6.628907 8.3527385 5.4951178 7.4848013 4.5943362 6.6450019 3.7227628 5.4821482 3.7060611 4.5582677 4.5522701 3.6643409 5.3710738 3.6472085 6.504863 4.5151457 7.4056445 5.3549451 8.2772179 6.5177988 8.2939196 7.4416793 7.4477106 Z" FillRule="NonZero"
<PathGeometry x:Key="Alert" Figures="M 1.1531774 13.277025 C 1.7874263 12.329396 3.9770847 8.9543883 6.0190869 5.7770253 8.0610888 2.599662 9.8524992 0 10 0 c 0.147501 0 1.938911 2.599662 3.980913 5.7770253 2.042002 3.177363 4.23166 6.5523707 4.86591 7.4999997 L 20 15 H 10 0 Z M 10.904431 11.75675 c 0 -0.540527 -0.301477 -0.810801 -0.904431 -0.810801 -0.6029544 0 -0.9044312 0.270274 -0.9044312 0.810801 0 0.540545 0.3014768 0.810818 0.9044312 0.810818 0.602954 0 0.904431 -0.270273 0.904431 -0.810818 z m 0 -4.4594502 C 10.904431 5.540539 10.783833 5.270267 10 5.270267 c -0.78384 0 -0.9044312 0.270272 -0.9044312 2.0270328 0 1.7567452 0.1205987 2.0270177 0.9044312 2.0270177 0.78384 0 0.904431 -0.2702725 0.904431 -2.0270177 z"
FillRule="NonZero"
/>
<PathGeometry x:Key="Server" Figures="M 1.6494282 17.929812 C 0.92664202 17.718549 0.3836749 17.162385 0.17114 16.415592 0.09187098 16.137063 0.0863444 15.971619 0.0863444 13.877198 c 0 -2.111449 0.004995 -2.258008 0.08674468 -2.545427 0.21592147 -0.75914 0.82682106 -1.3631677 1.54512992 -1.52775 0.3218444 -0.07374 14.284014 -0.074326 14.609533 -5.317e-4 0.842712 0.1908397 1.507625 0.9632907 1.630128 1.8937857 0.05616 0.426587 0.05616 3.933413 0 4.360001 -0.122896 0.933497 -0.784698 1.702333 -1.630128 1.893786 -0.161986 0.03667 -2.304745 0.05092 -7.3392714 0.04872 -6.0119248 -0.0025 -7.1458037 -0.01334 -7.3390524 -0.06989 z m 2.5421672 -2.991734 c 0.4100526 -0.159172 0.6868605 -0.586709 0.6868605 -1.06088 0 -0.952833 -1.0222858 -1.471242 -1.6855312 -0.854751 -0.2565468 0.238465 -0.3619533 0.48738 -0.3619533 0.854751 0 0.366373 0.1076352 0.621854 0.3582541 0.85034 0.2889152 0.2634 0.6634988 0.342079 1.0023699 0.21054 z m 10.5739626 -0.39758 c 0.447008 -0.25795 0.498036 -0.92881 0.09599 -1.26185 l -0.154666 -0.128119 -3.910457 -0.01398 c -2.6646075 -0.0095 -3.9607586 0.0019 -4.0683469 0.03574 -0.4386452 0.13812 -0.6081135 0.789478 -0.3066319 1.178555 0.2209522 0.28515 0.025427 0.272622 4.2859348 0.27462 3.722244 0.0018 3.914897 -0.0023 4.058185 -0.08497 z M 1.467854 8.1629798 C 0.95417626 7.9826349 0.60805366 7.7025173 0.33776606 7.2483968 0.00402544 6.6876657 0 6.6507887 0 4.1541464 0 1.7200918 0.00839022 1.6245238 0.26479626 1.1378639 0.43887006 0.80747199 0.7595484 0.47034506 1.0714819 0.28980176 1.6031353 -0.01791494 1.1093443 2.0102425e-4 8.965172 2.0102425e-4 c 5.041311 0 7.200906 0.0152029958 7.36258 0.0518070457 0.865249 0.19594118 1.513849 0.96757553 1.63473 1.94483093 0.02999 0.2424025 0.04105 1.1050261 0.03067 2.3909693 -0.01524 1.8913722 -0.02165 2.029278 -0.10668 2.3046735 -0.22977 0.7441927 -0.818438 1.3420951 -1.485878 1.509186 -0.123856 0.031004 -2.700479 0.04695 -7.4423765 0.04605 C 2.1266812 8.2464458 1.6915 8.2414898 1.4678485 8.1629786 Z M 4.3859875 5.0844445 C 4.7811078 4.8191684 4.9780404 4.2439044 4.8349315 3.7730215 4.7668555 3.5490256 4.5236513 3.2565013 4.2985765 3.1278962 4.0565272 2.9895915 3.6283308 2.9891697 3.3890159 3.1270101 2.7753048 3.4804635 2.6278188 4.3017289 3.0782612 4.8574294 3.3235181 5.1599969 3.5311532 5.2576628 3.8906484 5.2395503 4.1184172 5.2280683 4.2189566 5.1965975 4.3859875 5.0844569 Z M 14.837282 4.7559538 c 0.14415 -0.1141452 0.316152 -0.4583749 0.316152 -0.63272 0 -0.220612 -0.182401 -0.5222009 -0.386823 -0.6395916 l -0.187995 -0.1079544 -3.867912 0.00107 c -3.6787004 8.85e-4 -3.8765704 0.00529 -4.0448738 0.088298 -0.2617344 0.129081 -0.3842788 0.3424391 -0.3842788 0.6690602 0 0.2988716 0.080394 0.456782 0.3243274 0.6370544 l 0.1437 0.1061964 3.9829142 -0.01245 c 3.943322 -0.0123 3.984126 -0.01341 4.104791 -0.1089408 z" FillRule="NonZero"
<PathGeometry x:Key="Delete" Figures="M 1.371429 14.489266 C 1.0250013 14.152485 0.85714332 12.248674 0.85714332 8.6563122 V 3.3233314 H 6 11.142857 v 5.3329808 c 0 3.5923618 -0.167858 5.4961728 -0.514286 5.8329538 -0.7004895 0.680979 -8.5566525 0.680979 -9.257142 0 z M 0 1.6567735 C 0 0.96445539 0.28571444 0.82349613 1.6889935 0.82349613 c 0.9289457 0 1.8081847 -0.18748843 1.9538644 -0.41664027 0.3448694 -0.54247448 4.3694148 -0.54247448 4.7142842 0 0.1456846 0.22915184 1.0249187 0.41664027 1.9538639 0.41664027 1.40328 0 1.688994 0.14096714 1.688994 0.83327737 0 0.7935997 -0.285714 0.8332789 -6 0.8332789 -5.71428556 0 -6 -0.039683 -6 -0.8332789 z"
FillRule="NonZero"
/>
<PathGeometry x:Key="Profile" Figures="M 0.3329837 17.929 C 0.00508737 17.786405 -0.05110024 17.571418 0.03778307 16.799492 0.21646558 15.247684 0.95166383 13.834441 2.1658392 12.708809 c 1.3245634 -1.227967 2.9780762 -1.948137 4.8821724 -2.126377 0.5043111 -0.04721 3.4014294 -0.04717 3.9052184 3.6e-5 1.864914 0.174797 3.523972 0.885292 4.81329 2.061304 0.61887 0.564483 1.01831 1.064696 1.421974 1.780722 0.414766 0.735716 0.679701 1.547648 0.774964 2.374986 0.0877 0.761611 0.02794 0.991461 -0.293283 1.128074 L 17.499859 18 8.9979909 17.999972 C 0.55177854 17.999945 0.49505365 17.99944 0.3329837 17.929 Z M 8.3202612 9.4552574 C 7.1251577 9.3077085 6.0490147 8.8364362 5.1960615 8.0870837 4.3957904 7.384015 3.9359491 6.6300486 3.6909315 5.6192336 c -0.099356 -0.4098937 -0.099356 -1.3393063 0 -1.7491988 0.2454098 -1.0124321 0.7072521 -1.770154 1.503966 -2.4674819 2.1352618 -1.86890084 5.5016125 -1.87023371 7.6098625 -0.00302 0.803679 0.7117955 1.260458 1.4612436 1.505737 2.4704958 0.09932 0.4086858 0.09751 1.3356865 -0.0034 1.7536027 -0.243884 1.0097439 -0.698668 1.7557954 -1.502304 2.4644693 -1.011372 0.8918597 -2.211142 1.3476572 -3.6440554 1.3843916 -0.3191689 0.00819 -0.6973691 3.986e-4 -0.8404447 -0.017241 z" FillRule="NonZero"
<PathGeometry x:Key="Gear" Figures="m 4.4615102 11.271429 c 0 -0.992273 -0.845292 -1.7685001 -1.6612536 -1.5255145 C 1.5450127 10.119702 1.3309542 10.039187 0.67223375 8.9455133 L 0.00700434 7.8410343 0.69579591 7.1261827 C 1.5704786 6.2184053 1.5693913 5.4953105 0.69230711 4.7875001 L 0 4.228826 0.66874495 3.0894129 C 1.3304739 1.9619619 1.5415251 1.879247 2.8002845 2.2540889 3.6162462 2.4970745 4.4615381 1.7208472 4.4615381 0.7285713 4.4615381 0.05428908 4.5761682 0 6 0 c 1.4238306 0 1.5384619 0.05431176 1.5384619 0.7285713 0 0.9922759 0.8452919 1.7685032 1.6612536 1.5255176 1.2587595 -0.3748419 1.4698105 -0.292127 2.1315395 0.835324 L 12 4.228826 11.307692 4.7875001 c -0.877111 0.7078104 -0.878199 1.4309052 -0.0035 2.3386826 l 0.688796 0.7148516 -0.665233 1.104479 C 10.669034 10.039187 10.454975 10.119702 9.1997324 9.7459145 8.3837708 9.5029289 7.5384788 10.279156 7.5384788 11.271429 7.5384788 11.945711 7.4238487 12 6.0000169 12 4.5761863 12 4.461555 11.945688 4.461555 11.271429 Z M 7.4416793 7.4477106 C 8.3356062 6.628907 8.3527385 5.4951178 7.4848013 4.5943362 6.6450019 3.7227628 5.4821482 3.7060611 4.5582677 4.5522701 3.6643409 5.3710738 3.6472085 6.504863 4.5151457 7.4056445 5.3549451 8.2772179 6.5177988 8.2939196 7.4416793 7.4477106 Z"
FillRule="NonZero"
/>
<PathGeometry x:Key="Server" Figures="M 9 2 a 3 3 0 0 0 -3 3 v 14 a 3 3 0 0 0 3 3 h 6 a 3 3 0 0 0 3 -3 V 5 a 3 3 0 0 0 -3 -3 H 9 Z m -0.5 4.75 A 0.75 0.75 0 0 1 9.25 6 h 5.5 a 0.75 0.75 0 0 1 0 1.5 h -5.5 a 0.75 0.75 0 0 1 -0.75 -0.75 Z m 0 11 a 0.75 0.75 0 0 1 0.75 -0.75 h 5.5 a 0.75 0.75 0 0 1 0 1.5 h -5.5 a 0.75 0.75 0 0 1 -0.75 -0.75 Z m 0 -3 a 0.75 0.75 0 0 1 0.75 -0.75 h 5.5 a 0.75 0.75 0 0 1 0 1.5 h -5.5 a 0.75 0.75 0 0 1 -0.75 -0.75 Z"
FillRule="NonZero"
/>
<PathGeometry x:Key="Visible" Figures="M 8.1460091 11.992296 C 8.0833771 11.983726 7.8271527 11.94962 7.5766226 11.916501 5.4738087 11.63851 3.307191 10.538502 1.8055895 8.9865036 0.99350307 8.1471622 0.20885269 7.0014962 0.06261515 6.4415911 -0.09543836 5.836446 0.03094743 5.3924299 0.61168637 4.5126082 2.1934171 2.1162758 4.7047482 0.51722245 7.5576432 0.08986881 c 0.9965425 -0.14927859 2.4004313 -0.10960705 3.4270298 0.09684267 2.587437 0.52033387 4.890733 2.06079622 6.355054 4.25030892 0.880364 1.3163559 0.880364 1.8205157 0 3.1368717 -1.380858 2.0647171 -3.549401 3.5770229 -5.961514 4.1574569 -0.856848 0.206187 -1.237872 0.251481 -2.2262878 0.264644 -0.4906213 0.0066 -0.9432835 0.0049 -1.0059161 -0.0037 z M 10.00375 10.823681 c 1.580402 -0.184064 3.036374 -0.762072 4.334267 -1.7206639 0.806911 -0.5959633 1.727678 -1.6082743 2.255807 -2.4800822 0.223791 -0.3694213 0.244819 -0.4223443 0.244819 -0.6161567 0 -0.1907713 -0.02194 -0.2486339 -0.21891 -0.5772594 C 16.139008 4.6274618 15.319355 3.6858065 14.599055 3.1080687 13.549615 2.2663343 12.226695 1.6291427 10.931036 1.3413472 9.9257068 1.1180407 8.6514186 1.072587 7.6715205 1.2250823 6.4596265 1.413681 5.1758323 1.9009827 4.1603039 2.5578651 3.0858698 3.2528506 2.0336925 4.3396206 1.3810777 5.4284632 1.1844957 5.7564459 1.1628006 5.8137957 1.1628006 6.0054569 c 0 0.1916598 0.021695 0.2490095 0.2182771 0.5769922 0.4872889 0.8130086 1.2646309 1.703609 2.0200442 2.314365 1.3732099 1.1102489 3.0038256 1.7700389 4.839785 1.9583019 0.3582986 0.03674 1.3255717 0.0195 1.7628431 -0.03143 z M 8.424282 9.4462967 C 7.0826815 9.2020122 6.0360496 8.2699061 5.6341892 6.9615064 5.5409652 6.657984 5.5320793 6.5747813 5.5320793 6.0054569 c 0 -0.5693258 0.00889 -0.6525285 0.1021099 -0.956051 C 6.0036849 3.8463811 6.8861656 2.98618 8.1120346 2.6341171 c 0.2585334 -0.07425 0.383092 -0.085715 0.9070338 -0.083493 0.5461548 0.00231 0.6409868 0.012785 0.9412556 0.1039219 1.207183 0.3663972 2.073584 1.2475045 2.425556 2.4667264 0.07295 0.2527006 0.08614 0.3880692 0.08614 0.8841842 0 0.496115 -0.01319 0.6314836 -0.08614 0.8841829 C 12.02934 8.1246855 11.135575 9.0195412 9.9085538 9.3699912 9.5936312 9.4599382 8.7401624 9.5038134 8.424282 9.4462967 Z M 9.5076368 8.2923324 C 10.366726 8.1111151 11.114966 7.3661384 11.296977 6.5107909 11.468942 5.7026559 11.242767 4.9478995 10.65252 4.360227 10.185215 3.8949588 9.636363 3.6635631 9.0000888 3.6635631 c -1.0832373 0 -2.0747915 0.7928324 -2.2968886 1.8365583 -0.3563824 1.6747866 1.1223165 3.1470402 2.8044366 2.792211 z" FillRule="NonZero"
<PathGeometry x:Key="Profile" Figures="M 17.754 14 a 2.249 2.249 0 0 1 2.25 2.249 v 0.918 a 2.75 2.75 0 0 1 -0.513 1.599 C 17.945 20.929 15.42 22 12 22 c -3.422 0 -5.945 -1.072 -7.487 -3.237 a 2.75 2.75 0 0 1 -0.51 -1.595 v -0.92 a 2.249 2.249 0 0 1 2.249 -2.25 h 11.501 Z M 12 2.004 a 5 5 0 1 1 0 10 a 5 5 0 0 1 0 -10 Z"
FillRule="NonZero"
/>
<PathGeometry x:Key="Hide" Figures="M 2.5679207 11.950279 C 2.3351669 11.848352 2.2120578 11.621794 2.2615536 11.386472 2.2829097 11.284935 2.406899 11.16048 3.1342095 10.510528 3.600479 10.093851 3.975073 9.7476909 3.9666412 9.7412802 3.9582112 9.7348758 3.8563174 9.6765531 3.7402151 9.6116894 3.3432865 9.3899331 2.6146862 8.8843852 2.1745934 8.5253631 1.4755105 7.9550599 0.84697928 7.3017345 0.31975495 6.5973519 -0.1109968 6.0218597 -0.11001266 5.9715658 0.34380475 5.3683051 0.79713357 4.765693 1.2026605 4.3294038 1.821751 3.7782437 3.7996358 2.0173822 6.0828481 1.0932904 8.6657661 1.0082442 10.026095 0.96345226 11.294642 1.1629888 12.616829 1.6297255 l 0.362446 0.1279451 0.974489 -0.86206028 c 0.837883 -0.74121476 0.992984 -0.86511728 1.106424 -0.88386597 0.21226 -0.03508435 0.368054 0.0073974 0.518943 0.14147897 0.150551 0.13379088 0.198392 0.27172359 0.159952 0.46116733 C 15.717813 0.71921597 15.049325 1.3236974 9.4288293 6.3204432 5.9712731 9.3942863 3.0924188 11.930313 3.031374 11.956056 c -0.1436299 0.06056 -0.3168835 0.0584 -0.4634533 -0.0057 z M 5.5437673 8.3678503 6.2560185 7.7343309 6.1633995 7.6132055 C 6.0040135 7.4047614 5.8024019 6.9884285 5.7209365 6.6995065 5.6090617 6.3027367 5.6099817 5.6572624 5.7229565 5.2822485 5.8927146 4.7187469 6.1459432 4.320735 6.5899974 3.9194756 6.9337774 3.6088273 7.0919375 3.5033071 7.4695602 3.3326582 8.1983138 3.0033307 9.0070431 2.9203596 9.8076645 3.0927787 c 0.2832505 0.061 0.8108265 0.2649442 1.0409555 0.4023996 l 0.107086 0.063963 0.575769 -0.5123722 0.575769 -0.5123724 -0.137527 -0.051372 C 11.711023 2.3863919 11.032607 2.2156744 10.605468 2.1397237 9.4891497 1.9412282 8.2164836 1.9591805 7.1001438 2.1891692 5.8981601 2.4368028 4.5599509 3.0274763 3.5126657 3.7726496 2.8673014 4.2318435 2.0748395 4.9620744 1.5536836 5.5777938 1.1801385 6.0191182 1.1964931 5.9664432 1.3646818 6.1865377 1.9217887 6.9155785 2.8853398 7.7984046 3.7491949 8.3712784 4.0718054 8.585221 4.7673686 8.9959869 4.8136027 8.9998664 4.8234527 9.000666 5.1520285 8.7162858 5.5437673 8.3678503 Z M 10.086881 4.2605975 C 10.067181 4.2394984 9.9135181 4.1778344 9.7454186 4.1235664 7.988299 3.5563118 6.2448663 5.0974724 6.8849361 6.652174 6.9441441 6.7959868 7.0116945 6.9341123 7.0350489 6.9591191 7.0704519 6.9970277 7.3306566 6.7796712 8.6001105 5.6517746 9.7238916 4.6533037 10.113324 4.288912 10.086881 4.2605975 Z M 8.1813482 10.971535 C 7.5499084 10.917127 6.4080707 10.717759 6.2299494 10.630815 6.2017084 10.617031 6.3448223 10.469281 6.6395743 10.207928 L 7.0926051 9.8062269 7.4921782 9.87207 C 9.9454769 10.276376 12.393655 9.70425 14.463597 8.2428879 14.893119 7.9396484 15.588421 7.3422784 15.964397 6.9534718 16.196594 6.7133514 16.670924 6.1637582 16.753226 6.0394799 16.805706 5.960226 16.167191 5.2229443 15.551859 4.6522887 15.179021 4.3065193 14.60341 3.8468374 14.322107 3.670209 14.240277 3.6188319 14.172994 3.5624863 14.172581 3.544996 14.17165 3.503098 14.918434 2.842055 14.966762 2.842055 c 0.07393 0 0.745326 0.5199281 1.22835 0.9512387 0.575718 0.5140811 1.055156 1.0323984 1.474944 1.5945542 0.440243 0.589546 0.440174 0.6400726 -0.0017 1.2281406 -0.436413 0.5808359 -0.906604 1.0863801 -1.507523 1.6208737 -1.703071 1.5148164 -3.683425 2.4230968 -5.859106 2.6872508 -0.4787235 0.05813 -1.6834787 0.08506 -2.1204051 0.04742 z M 8.4428581 8.9563226 C 8.3009079 8.932297 8.1749454 8.9039084 8.1629407 8.893237 8.1509357 8.8825655 8.3635109 8.6762041 8.6353285 8.434648 L 9.1295436 7.9954549 9.4037532 7.9531385 C 9.7371384 7.9016912 10.176641 7.7204083 10.432705 7.5287264 10.822544 7.2369024 11.11352 6.7908395 11.198832 6.3542595 l 0.04662 -0.2385996 0.486402 -0.4330774 c 0.267519 -0.2381921 0.497363 -0.4330762 0.510763 -0.4330762 0.05888 0 0.115139 0.3897577 0.112833 0.7816379 -0.002 0.3483443 -0.01813 0.4743231 -0.09206 0.7210941 -0.388323 1.2961642 -1.647372 2.1872689 -3.1578417 2.2349937 -0.2590625 0.00822 -0.4974358 -0.003 -0.6626892 -0.0309 z" FillRule="NonZero"
/>
<PathGeometry x:Key="Open" Figures="M 6.25 4.75 a 1.5 1.5 0 0 0 -1.5 1.5 v 11.5 a 1.5 1.5 0 0 0 1.5 1.5 h 11.5 a 1.5 1.5 0 0 0 1.5 -1.5 v -4 a 1 1 0 1 1 2 0 v 4 a 3.5 3.5 0 0 1 -3.5 3.5 H 6.25 a 3.5 3.5 0 0 1 -3.5 -3.5 V 6.25 a 3.5 3.5 0 0 1 3.5 -3.5 h 4 a 1 1 0 1 1 0 2 h -4 Z m 6.5 -1 a 1 1 0 0 1 1 -1 h 6.5 a 1 1 0 0 1 1 1 v 6.5 a 1 1 0 1 1 -2 0 V 6.164 l -4.793 4.793 a 1 1 0 1 1 -1.414 -1.414 l 4.793 -4.793 H 13.75 a 1 1 0 0 1 -1 -1 Z"
FillRule="NonZero"
/>
<PathGeometry x:Key="Info" Figures="M 12 1.999 c 5.524 0 10.002 4.478 10.002 10.002 c 0 5.523 -4.478 10.001 -10.002 10.001 c -5.524 0 -10.002 -4.478 -10.002 -10.001 C 1.998 6.477 6.476 1.999 12 1.999 Z m -0.004 8.25 a 1 1 0 0 0 -0.992 0.885 l -0.007 0.116 l 0.003 5.502 l 0.007 0.117 a 1 1 0 0 0 1.987 -0.002 L 13 16.75 l -0.003 -5.501 l -0.007 -0.117 a 1 1 0 0 0 -0.994 -0.882 Z M 12 6.5 a 1.251 1.251 0 1 0 0 2.503 A 1.251 1.251 0 0 0 12 6.5 Z"
FillRule="NonZero"
/>
</Application.Resources>
</Application>

View File

@ -13,21 +13,26 @@
Background="{StaticResource AKI_Background_Dark}"
>
<!-- Icon stack -->
<StackPanel Grid.Row="1" Grid.ColumnSpan="3" Grid.Column="1"
VerticalAlignment="Center"
Orientation="Horizontal" Spacing="5"
>
VerticalAlignment="Center"
Orientation="Horizontal" Spacing="5"
>
<!-- Server Icon -->
<Path Data="{StaticResource Server}" Fill="{StaticResource AKI_Brush_DarkGrayBlue}"
IsVisible="{Binding IsInServer, RelativeSource={RelativeSource AncestorType=UserControl}}"
/>
IsVisible="{Binding IsInServer, RelativeSource={RelativeSource AncestorType=UserControl}}"
/>
<!-- Profile Icon -->
<Path Data="{StaticResource Profile}" Fill="{StaticResource AKI_Brush_DarkGrayBlue}"
IsVisible="{Binding IsInProfile, RelativeSource={RelativeSource AncestorType=UserControl}}"
/>
<!-- Info Icon -->
<Canvas>
<Rectangle ToolTip.Tip="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=mod_not_in_server_warning}" Fill="Transparent" Height="20" Width="20"/>
<Path Data="{StaticResource Alert}" Fill="{StaticResource AKI_Brush_Yellow}"
Margin="0 2 0 0" ToolTip.Tip="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=mod_not_in_server_warning}"
<Path Data="{StaticResource Info}" Fill="DodgerBlue"
ToolTip.Tip="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=mod_not_in_server_warning}"
>
<Path.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
@ -39,15 +44,38 @@
</Canvas>
</StackPanel>
<!-- Open mod url -->
<Button Grid.Row="1" Grid.Column="3" Classes="link"
IsVisible="{Binding ModUrl,
RelativeSource={RelativeSource AncestorType=UserControl},
Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
Command="{Binding OpenUrlCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
CommandParameter="{Binding ModUrl, RelativeSource={RelativeSource AncestorType=UserControl}}"
>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=open_link}"/>
<Path Data="{StaticResource Open}" Fill="{StaticResource AKI_Brush_Yellow}"
IsVisible="{Binding IsInProfile, RelativeSource={RelativeSource AncestorType=UserControl}}"
/>
</StackPanel>
</Button>
<!-- Mod Name -->
<Label Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2"
Content="{Binding ModName, RelativeSource={RelativeSource AncestorType=UserControl}}"
/>
<!-- Author Text -->
<Label Grid.Row="3" Grid.Column="1" FontSize="12" Foreground="DimGray"
Content="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=author}"
/>
<!-- Mod Author -->
<Label Grid.Row="3" Grid.Column="2" FontSize="12" HorizontalAlignment="Left"
Content="{Binding Author, RelativeSource={RelativeSource AncestorType=UserControl}}"
/>
<!-- Mod Version -->
<Label Grid.Row="3" Grid.Column="3" FontSize="12"
Content="{Binding Version, RelativeSource={RelativeSource AncestorType=UserControl}}"
/>

View File

@ -1,3 +1,5 @@
using System.Diagnostics;
using System.Windows.Input;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
@ -55,5 +57,21 @@ namespace Aki.Launcher.CustomControls
}
public static readonly StyledProperty<bool> IsInProfileProperty =
AvaloniaProperty.Register<ModInfoCard, bool>(nameof(IsInProfile));
public string ModUrl
{
get => GetValue(ModUrlProperty);
set => SetValue(ModUrlProperty, value);
}
public static readonly StyledProperty<string> ModUrlProperty =
AvaloniaProperty.Register<ModInfoCard, string>(nameof(ModUrl));
public ICommand OpenUrlCommand
{
get => GetValue(OpenUrlCommandProperty);
set => SetValue(OpenUrlCommandProperty, value);
}
public static readonly StyledProperty<ICommand> OpenUrlCommandProperty =
AvaloniaProperty.Register<ModInfoCard, ICommand>(nameof(OpenUrlCommand));
}
}

View File

@ -5,6 +5,7 @@ using ReactiveUI;
using Splat;
using System.Reactive.Disposables;
using System.Threading.Tasks;
using Aki.Launcher.Controllers;
namespace Aki.Launcher.ViewModels
{
@ -51,6 +52,8 @@ namespace Aki.Launcher.ViewModels
AkiVersion version = Locator.Current.GetService<AkiVersion>("akiversion");
version.ParseVersionInfo(ServerManager.GetVersion());
LogManager.Instance.Info($"Connected to server: {ServerManager.SelectedServer.backendUrl} - Aki Version: {version}");
NavigateTo(new LoginViewModel(HostScreen, noAutoLogin));
}

View File

@ -0,0 +1,45 @@
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Aki.Launcher.Controllers;
using Aki.Launcher.Helpers;
using Aki.Launcher.Models.Launcher;
using Aki.Launcher.ViewModels.Dialogs;
using ReactiveUI;
namespace Aki.Launcher.ViewModels;
public class ModInfoViewModel : ViewModelBase
{
public ModInfoCollection ModsCollection { get; set; }
public ModInfoViewModel(IScreen Host, ModInfoCollection mods) : base(Host)
{
ModsCollection = mods;
}
public async Task OpenUrlCommand(string url)
{
if (!url.StartsWith("https://") && !url.StartsWith("https://"))
{
LogManager.Instance.Warning($"url does not start with http/s \n -URL-> '{url}'");
return;
}
var question = String.Format(LocalizationProvider.Instance.open_link_question_format_1, url);
var confirmText = LocalizationProvider.Instance.open_link;
var cancelText = LocalizationProvider.Instance.cancel;
var confirm = await ShowDialog(new ConfirmationDialogViewModel(HostScreen, question, confirmText, cancelText));
if (confirm is not (bool and true))
return;
Process.Start(new ProcessStartInfo
{
FileName = "cmd.exe",
UseShellExecute = true,
WindowStyle = ProcessWindowStyle.Hidden,
ArgumentList = { "/C", "start", url }
});
}
}

View File

@ -26,13 +26,6 @@ namespace Aki.Launcher.ViewModels
set => this.RaiseAndSetIfChanged(ref _CurrentEdition, value);
}
private bool _ModsListIsVisible;
public bool ModsListIsVisible
{
get => _ModsListIsVisible;
set => this.RaiseAndSetIfChanged(ref _ModsListIsVisible, value);
}
private bool _WipeProfileOnStart;
public bool WipeProfileOnStart
{
@ -76,8 +69,6 @@ namespace Aki.Launcher.ViewModels
CurrentEdition = AccountManager.SelectedAccount.edition;
CurrentID = AccountManager.SelectedAccount.id;
ModsListIsVisible = false;
}
private async Task GameVersionCheck()
@ -104,7 +95,8 @@ namespace Aki.Launcher.ViewModels
}
}
public void ToggleModsListCommand() => ModsListIsVisible = !ModsListIsVisible;
public void OpenModsInfoCommand() =>
NavigateTo(new ModInfoViewModel(HostScreen, ModInfoCollection));
public void LogoutCommand()
{

View File

@ -0,0 +1,105 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:cc="using:Aki.Launcher.CustomControls"
xmlns:launcher="using:Aki.Launcher.Models.Aki"
xmlns:helpers="using:Aki.Launcher.Helpers"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Aki.Launcher.Views.ModInfoView">
<Grid RowDefinitions="10, Auto, 10, Auto, 10, *, 10" ColumnDefinitions="10, 2*, 10, 2*, 10">
<!-- back button -->
<Button Content="&#x279C;" FontSize="25"
HorizontalAlignment="Right"
Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3"
Command="{Binding NavigateBack}"
Classes="link"
/>
<!-- Active Mods List Header -->
<Border Grid.Row="3" Grid.Column="1"
CornerRadius="5"
Background="{StaticResource AKI_Background_Dark}">
<StackPanel Spacing="2" Margin="10">
<!-- Active mods count and text -->
<Label VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="16">
<Label.Content>
<MultiBinding StringFormat="{}{0}: {1}">
<Binding Source="{x:Static helpers:LocalizationProvider.Instance}" Path="active_server_mods"/>
<Binding Path="ModsCollection.ActiveMods.Count"/>
</MultiBinding>
</Label.Content>
</Label>
<!-- Active mods info text -->
<TextBlock Text="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=active_server_mods_info_text}"
VerticalAlignment="Center" HorizontalAlignment="Center"
FontSize="12"
TextWrapping="Wrap"
Foreground="{StaticResource AKI_Foreground_Light}"
/>
</StackPanel>
</Border>
<!-- Active Mods List -->
<ScrollViewer Grid.Row="5" Grid.Column="1">
<ItemsControl Items="{Binding ModsCollection.ActiveMods}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type launcher:AkiMod}">
<cc:ModInfoCard ModName="{Binding Name}"
Author="{Binding Author}"
Version="{Binding Version}"
IsInServer="{Binding InServer}"
IsInProfile="{Binding InProfile}"
ModUrl="{Binding Url}"
OpenUrlCommand="{Binding $parent[ItemsControl].DataContext.OpenUrlCommand}"
Margin="0 0 0 10" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<!-- Inactive Mods List Header -->
<Border Grid.Row="3" Grid.Column="3"
CornerRadius="5"
Background="{StaticResource AKI_Background_Dark}">
<StackPanel Spacing="2" Margin="10">
<!-- Inactive mods count and text -->
<Label VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="16">
<Label.Content>
<MultiBinding StringFormat="{}{0}: {1}">
<Binding Source="{x:Static helpers:LocalizationProvider.Instance}" Path="inactive_server_mods"/>
<Binding Path="ModsCollection.InactiveMods.Count"/>
</MultiBinding>
</Label.Content>
</Label>
<!-- Inactive mods info text -->
<TextBlock Text="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=inactive_server_mods_info_text}"
VerticalAlignment="Center" HorizontalAlignment="Center"
FontSize="12"
TextWrapping="Wrap"
Foreground="{StaticResource AKI_Foreground_Light}"
/>
</StackPanel>
</Border>
<!-- Inactive Mods List -->
<ScrollViewer Grid.Row="5" Grid.Column="3" >
<ItemsControl Items="{Binding ModsCollection.InactiveMods}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type launcher:AkiMod}">
<cc:ModInfoCard ModName="{Binding Name}"
Author="{Binding Author}"
Version="{Binding Version}"
IsInServer="{Binding InServer}"
IsInProfile="{Binding InProfile}"
ModUrl="{Binding Url}"
OpenUrlCommand="{Binding $parent[ItemsControl].DataContext.OpenUrlCommand}"
Margin="0 0 0 10" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>

View File

@ -0,0 +1,20 @@
using Aki.Launcher.ViewModels;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace Aki.Launcher.Views;
public partial class ModInfoView : ReactiveUserControl<ModInfoViewModel>
{
public ModInfoView()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}

View File

@ -4,183 +4,146 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:helpers="using:Aki.Launcher.Helpers"
xmlns:cvt="using:Aki.Launcher.Converters"
xmlns:cc="using:Aki.Launcher.CustomControls"
xmlns:launcher="using:Aki.Launcher.Models.Aki"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Aki.Launcher.Views.ProfileView">
<UserControl.Resources>
<cvt:ImageSourceConverter x:Key="imageSourceCvt"/>
</UserControl.Resources>
<Grid RowDefinitions="10,AUTO,10,AUTO,10,*,10,AUTO,10" ColumnDefinitions="10,AUTO,10,*,10">
<UserControl.Resources>
<cvt:ImageSourceConverter x:Key="imageSourceCvt" />
</UserControl.Resources>
<!-- profile info -->
<Border Grid.Row="1" Grid.Column="1" CornerRadius="5"
BorderBrush="{StaticResource AKI_Background_Dark}"
BorderThickness="5">
<Grid RowDefinitions="10,AUTO,AUTO,AUTO,AUTO,10" ColumnDefinitions="10,AUTO,*,10"
Background="{StaticResource AKI_Background_Dark}"
>
<StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="1">
<Label Content="{Binding CurrentUsername}" Margin="5 0"/>
<Grid RowDefinitions="10,AUTO,10,AUTO,10,*,10,AUTO,10" ColumnDefinitions="10,AUTO,10,*,10">
<!-- profile name and version -->
<Label x:Name="akiVersion"
Background="Transparent"
ToolTip.Tip="{Binding ProfileInfo.MismatchMessage}"
Classes.versionMismatch="{Binding ProfileInfo.VersionMismatch}"
>
<StackPanel Orientation="Horizontal" Background="Transparent">
<TextBlock Text="{Binding ProfileInfo.Aki.version}"/>
<Path Data="{StaticResource Alert}" Fill="{Binding ElementName=akiVersion, Path=Foreground}"
Margin="10 0"
IsVisible="{Binding ProfileInfo.VersionMismatch}"
/>
</StackPanel>
</Label>
</StackPanel>
<!-- profile info -->
<Border Grid.Row="1" Grid.Column="1" CornerRadius="5"
BorderBrush="{StaticResource AKI_Background_Dark}"
BorderThickness="5">
<Grid RowDefinitions="10,AUTO,AUTO,AUTO,AUTO,10" ColumnDefinitions="10,AUTO,*,10"
Background="{StaticResource AKI_Background_Dark}">
<StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="1">
<Label Content="{Binding CurrentUsername}" Margin="5 0" />
<!-- delete profile button -->
<Button HorizontalAlignment="Right" Grid.Row="1" Grid.Column="2"
Classes="icon"
Command="{Binding RemoveProfileCommand}"
IsEnabled="{Binding Source={x:Static helpers:LauncherSettingsProvider.Instance}, Path=!GameRunning}"
>
<Path Data="{StaticResource Delete}" Fill="IndianRed"/>
</Button>
<!-- profile name and version -->
<Label x:Name="akiVersion"
Background="Transparent"
ToolTip.Tip="{Binding ProfileInfo.MismatchMessage}"
Classes.versionMismatch="{Binding ProfileInfo.VersionMismatch}">
<StackPanel Orientation="Horizontal" Background="Transparent">
<TextBlock Text="{Binding ProfileInfo.Aki.version}" />
<Path Data="{StaticResource Info}"
Fill="{Binding ElementName=akiVersion, Path=Foreground}"
Margin="10 0"
IsVisible="{Binding ProfileInfo.VersionMismatch}" />
</StackPanel>
</Label>
</StackPanel>
<!-- profile id button -->
<Button Content="{Binding CurrentID}" Classes="link"
Grid.Row="2" Grid.Column="1"
Command="{Binding CopyCommand}"
CommandParameter="{Binding CurrentID}"
/>
<!-- delete profile button -->
<Button HorizontalAlignment="Right" Grid.Row="1" Grid.Column="2"
Classes="icon"
Command="{Binding RemoveProfileCommand}"
IsEnabled="{Binding Source={x:Static helpers:LauncherSettingsProvider.Instance}, Path=!GameRunning}">
<Path Data="{StaticResource Delete}" Fill="IndianRed" />
</Button>
<!-- profile edition button -->
<Button Content="{Binding CurrentEdition}" Classes="link"
Grid.Row="3" Grid.Column="1"
Command="{Binding ChangeEditionCommand}"
IsEnabled="{Binding Source={x:Static helpers:LauncherSettingsProvider.Instance}, Path=!GameRunning}"
/>
<!-- profile id button -->
<Button Content="{Binding CurrentID}" Classes="link"
Grid.Row="2" Grid.Column="1"
Command="{Binding CopyCommand}"
CommandParameter="{Binding CurrentID}" />
<!-- wipe profile checkbox -->
<CheckBox Content="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=wipe_on_start}"
Grid.Row="4" Grid.Column="1"
IsChecked="{Binding WipeProfileOnStart}"
IsEnabled="{Binding Source={x:Static helpers:LauncherSettingsProvider.Instance}, Path=!GameRunning}"
IsVisible="{Binding !ProfileWipePending}"
/>
</Grid>
</Border>
<!-- Total Mods Info -->
<Border Grid.Row="3" Grid.Column="1" CornerRadius="5"
BorderBrush="{StaticResource AKI_Background_Dark}"
BorderThickness="5" IsVisible="{Binding ModInfoCollection.HasMods}"
>
<Grid RowDefinitions="10,AUTO,AUTO,10" ColumnDefinitions="10,AUTO,*,AUTO,AUTO,AUTO,10"
Background="{StaticResource AKI_Background_Dark}">
<Label Grid.Row="1" Grid.Column="1" Content="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=server_mods}"
/>
<Label Grid.Row="2" Grid.Column="1" Content="{Binding ModInfoCollection.ServerModsCount}"
/>
<Label Grid.Row="1" Grid.Column="3" Content="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=profile_mods}"
/>
<Path Grid.Row="1" Grid.Column="4" Margin="10 4 0 0" IsVisible="{Binding ModInfoCollection.HasProfileOnlyMods}"
Data="{StaticResource Alert}" Fill="{StaticResource AKI_Brush_Yellow}"
/>
<Label Grid.Row="2" Grid.Column="3" Content="{Binding ModInfoCollection.ProfileModsCount}"
/>
<Button Grid.Row="0" Grid.RowSpan="4" Grid.Column="5" Grid.ColumnSpan="2"
VerticalAlignment="Stretch" FontSize="18" Margin="10 0 0 0"
Command="{Binding ToggleModsListCommand}"
Classes="icon"
>
<Button.Content>
<DockPanel LastChildFill="True">
<Path Data="{StaticResource Visible}" Fill="{StaticResource AKI_Foreground_Light}"
VerticalAlignment="Center"
IsVisible="{Binding !ModsListIsVisible}"
/>
<Path Data="{StaticResource Hide}" Fill="{StaticResource AKI_Foreground_Light}"
VerticalAlignment="Center"
IsVisible="{Binding ModsListIsVisible}"
/>
</DockPanel>
</Button.Content>
</Button>
</Grid>
</Border>
<!-- profile edition button -->
<Button Content="{Binding CurrentEdition}" Classes="link"
Grid.Row="3" Grid.Column="1"
Command="{Binding ChangeEditionCommand}"
IsEnabled="{Binding Source={x:Static helpers:LauncherSettingsProvider.Instance}, Path=!GameRunning}" />
<!-- Mods List -->
<ScrollViewer Grid.Row="1" Grid.RowSpan="5" Grid.Column="3" IsVisible="{Binding ModsListIsVisible}">
<ItemsControl Items="{Binding ModInfoCollection.Mods}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type launcher:AkiMod}">
<cc:ModInfoCard ModName="{Binding Name}"
Author="{Binding Author}"
Version="{Binding Version}"
IsInServer="{Binding InServer}"
IsInProfile="{Binding InProfile}"
Margin="0 0 0 10"
/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<!-- Bottom bar -->
<Border Grid.Row="7" Grid.Column="1" Grid.ColumnSpan="3" CornerRadius="5"
BorderBrush="{StaticResource AKI_Background_Dark}"
BorderThickness="5"
>
<DockPanel Background="{StaticResource AKI_Background_Dark}">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Stretch"
Spacing="10"
IsVisible="{Binding ProfileInfo.HasData}"
>
<Grid RowDefinitions="AUTO,AUTO" ColumnDefinitions="AUTO,AUTO">
<Image Source="{Binding SideImage.Path, Converter={StaticResource imageSourceCvt}}"
Grid.RowSpan="2" Height="40" Margin="10 0"/>
<Label Content="{Binding ProfileInfo.Nickname}" Grid.Row="0" Grid.Column="2"/>
<Label Content="{Binding ProfileInfo.Side}" Grid.Row="1" Grid.Column="2"/>
<!-- wipe profile checkbox -->
<CheckBox
Content="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=wipe_on_start}"
Grid.Row="4" Grid.Column="1"
IsChecked="{Binding WipeProfileOnStart}"
IsEnabled="{Binding Source={x:Static helpers:LauncherSettingsProvider.Instance}, Path=!GameRunning}"
IsVisible="{Binding !ProfileWipePending}" />
</Grid>
<Label Content="{Binding ProfileInfo.Level}" VerticalAlignment="Center"
FontSize="22"/>
<ProgressBar Value="{Binding ProfileInfo.XPLevelProgress}"/>
<StackPanel>
<Label Content="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=next_level_in}"
HorizontalAlignment="Center"
/>
<Label Content="{Binding ProfileInfo.RemainingExp, StringFormat={}{0} xp}"
HorizontalAlignment="Center"
/>
</StackPanel>
</StackPanel>
</Border>
<!-- Total Mods Info -->
<Border Grid.Row="3" Grid.Column="1" CornerRadius="5"
BorderBrush="{StaticResource AKI_Background_Dark}"
BorderThickness="5" IsVisible="{Binding ModInfoCollection.HasMods}">
<Grid RowDefinitions="10,AUTO,10" ColumnDefinitions="10,Auto,*,AUTO,10"
Background="{StaticResource AKI_Background_Dark}">
<!-- server mods count text -->
<Label Grid.Row="1" Grid.Column="1">
<Label.Content>
<MultiBinding StringFormat="{}{0}: {1}">
<Binding Source="{x:Static helpers:LocalizationProvider.Instance}" Path="active_server_mods"/>
<Binding Path="ModInfoCollection.ActiveMods.Count"/>
</MultiBinding>
</Label.Content>
</Label>
<!-- Show mods info view button -->
<Button Grid.Row="0" Grid.RowSpan="3" Grid.Column="3" Grid.ColumnSpan="2"
VerticalAlignment="Stretch" FontSize="18" Margin="10 0 0 0"
Command="{Binding OpenModsInfoCommand}"
Classes="icon">
<Button.Content>
<Path Data="{StaticResource Open}" Fill="{StaticResource AKI_Foreground_Light}"
VerticalAlignment="Center"
/>
</Button.Content>
</Button>
</Grid>
</Border>
<!-- Bottom bar -->
<Border Grid.Row="7" Grid.Column="1" Grid.ColumnSpan="3" CornerRadius="5"
BorderBrush="{StaticResource AKI_Background_Dark}"
BorderThickness="5">
<DockPanel Background="{StaticResource AKI_Background_Dark}">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Stretch"
Spacing="10"
IsVisible="{Binding ProfileInfo.HasData}">
<Grid RowDefinitions="AUTO,AUTO" ColumnDefinitions="AUTO,AUTO">
<Image Source="{Binding SideImage.Path, Converter={StaticResource imageSourceCvt}}"
Grid.RowSpan="2" Height="40" Margin="10 0" />
<Label Content="{Binding ProfileInfo.Nickname}" Grid.Row="0" Grid.Column="2" />
<Label Content="{Binding ProfileInfo.Side}" Grid.Row="1" Grid.Column="2" />
</Grid>
<Label Content="{Binding ProfileInfo.Level}" VerticalAlignment="Center"
FontSize="22" />
<ProgressBar Value="{Binding ProfileInfo.XPLevelProgress}" />
<StackPanel>
<Label
Content="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=next_level_in}"
HorizontalAlignment="Center" />
<Label Content="{Binding ProfileInfo.RemainingExp, StringFormat={}{0} xp}"
HorizontalAlignment="Center" />
</StackPanel>
</StackPanel>
<Button Content="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=start_game}"
HorizontalAlignment="Right"
VerticalContentAlignment="Center"
VerticalAlignment="Stretch"
DockPanel.Dock="Right"
Command="{Binding StartGameCommand}"
IsEnabled="{Binding Source={x:Static helpers:LauncherSettingsProvider.Instance}, Path=!GameRunning}"
Classes="yellow"
/>
<Button Content="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=logout}"
Command="{Binding LogoutCommand}"
Margin="10 0"
Classes="link"
DockPanel.Dock="Right"
HorizontalAlignment="Right"
/>
</DockPanel>
</Border>
</Grid>
</UserControl>
<Button Content="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=start_game}"
HorizontalAlignment="Right"
VerticalContentAlignment="Center"
VerticalAlignment="Stretch"
DockPanel.Dock="Right"
Command="{Binding StartGameCommand}"
IsEnabled="{Binding Source={x:Static helpers:LauncherSettingsProvider.Instance}, Path=!GameRunning}"
Classes="yellow" />
<Button Content="{Binding Source={x:Static helpers:LocalizationProvider.Instance}, Path=logout}"
Command="{Binding LogoutCommand}"
Margin="10 0"
Classes="link"
DockPanel.Dock="Right"
HorizontalAlignment="Right" />
</DockPanel>
</Border>
</Grid>
</UserControl>

View File

@ -18,7 +18,7 @@
{
"label": "build",
"type": "shell",
"command": "dotnet cake",
"command": "dotnet build --configuration Release",
"group": {
"kind": "build",
"isDefault": true

View File

@ -13,7 +13,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aki.Launcher", "Aki.Launche
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution

View File

@ -1,82 +0,0 @@
string target = Argument<string>("target", "ExecuteBuild");
string config = Argument<string>("config", "Release");
bool VSBuilt = Argument<bool>("vsbuilt", false);
// Cake API Reference: https://cakebuild.net/dsl/
// setup variables
var buildDir = "./Build";
var csprojPaths = GetFiles("./**/Aki.*(Launcher).csproj");
var delPaths = GetDirectories("./**/*(obj|bin)");
var akiData = "./Aki.Launcher/Aki_Data";
var licenseFile = "../LICENSE.md";
var publishRuntime = "win10-x64";
var launcherDebugFolder = "./Aki.Launcher/bin/Debug/net6.0/win10-x64";
// Clean build directory and remove obj / bin folder from projects
Task("Clean")
.WithCriteria(!VSBuilt) //building from VS will lock the files and fail to clean the project directories. Post-Build event on Aki.Build sets this switch to true to avoid this.
.Does(() =>
{
CleanDirectory(buildDir);
})
.DoesForEach(delPaths, (directoryPath) =>
{
DeleteDirectory(directoryPath, new DeleteDirectorySettings
{
Recursive = true,
Force = true
});
});
// Restore, build, and publish selected csproj files
Task("Publish")
.IsDependentOn("Clean")
.DoesForEach(csprojPaths, (csprojFile) =>
{
DotNetPublish(csprojFile.FullPath, new DotNetPublishSettings
{
NoLogo = true,
Configuration = config,
Runtime = publishRuntime,
PublishSingleFile = true,
SelfContained = false,
OutputDirectory = buildDir
});
});
// Copy Aki_Data folder and license to build directory
Task("CopyBuildData")
.IsDependentOn("Publish")
.Does(() =>
{
CopyDirectory(akiData, $"{buildDir}/Aki_Data");
CopyFile(licenseFile, $"{buildDir}/LICENSE-Launcher.txt");
});
// Copy Aki_Data to the launcher's debug directory so you can run the launcher with debugging from VS
Task("CopyDebugData")
.WithCriteria(config == "Debug")
.Does(() =>
{
EnsureDirectoryDoesNotExist($"{launcherDebugFolder}/Aki_Data");
CopyDirectory(akiData, $"{launcherDebugFolder}/Aki_Data");
});
// Remove pdb files from build if running in release configuration
Task("RemovePDBs")
.WithCriteria(config == "Release")
.IsDependentOn("CopyBuildData")
.Does(() =>
{
DeleteFiles($"{buildDir}/*.pdb");
});
// Runs all build tasks based on dependency and configuration
Task("ExecuteBuild")
.IsDependentOn("CopyBuildData")
.IsDependentOn("RemovePDBs")
.IsDependentOn("CopyDebugData");
// Runs target task
RunTarget(target);

22
project/build.ps1 Normal file
View File

@ -0,0 +1,22 @@
$buildFolder = "..\Build"
$akiDataFolder = "..\Build\Aki_Data"
$launcherExeFolder = "..\Aki.Launcher\bin\Release\net8.0\win-x64\publish"
$launcherAssetFolder = "..\Aki.Launcher\Aki_Data"
$licenseFile = "..\..\LICENSE.md"
# Delete build folder and contents to ensure it's clean
if (Test-Path "$buildFolder") { Remove-Item -Path "$buildFolder" -Recurse -Force }
# Create build folder and subfolders
$foldersToCreate = @("$buildFolder", "$akiDataFolder")
foreach ($folder in $foldersToCreate) {
if (-not (Test-Path "$folder")) { New-Item -Path "$folder" -ItemType Directory }
}
# Move built files to the build folder
Copy-Item -Path "$launcherExeFolder\Aki.Launcher.exe" -Destination "$buildFolder" -Force
Copy-Item -Path "$launcherAssetFolder" -Destination "$buildFolder" -Recurse -Force
# If any new DLLs need to be copied, add here
# Write the contents of the license file to a txt in the build folder
Get-Content "$licenseFile" | Out-File "$buildFolder\LICENSE-Launcher.txt" -Encoding UTF8