Project structure changes
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/package/out
|
72
Launcher-Core/Launcher.cs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
using System.Formats.Tar;
|
||||||
|
using System.Net;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security.AccessControl;
|
||||||
|
using CmlLib.Core;
|
||||||
|
using CmlLib.Core.Auth;
|
||||||
|
using CmlLib.Core.ProcessBuilder;
|
||||||
|
|
||||||
|
namespace Plombir;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Basically a class to manage everything launcher related.
|
||||||
|
TODO - minecraft downloading from webserver
|
||||||
|
*/
|
||||||
|
public class Launcher
|
||||||
|
{
|
||||||
|
private readonly string _version;
|
||||||
|
private readonly string _nickname;
|
||||||
|
static private MinecraftPath? _mcPath;
|
||||||
|
static private MinecraftLauncher? _mcLauncher;
|
||||||
|
|
||||||
|
public int DownloadProgress;
|
||||||
|
public string? DownloadStatus;
|
||||||
|
|
||||||
|
public Launcher(string userName, string version, string? location = null)
|
||||||
|
{
|
||||||
|
_version = version;
|
||||||
|
_nickname = userName;
|
||||||
|
_mcPath = new($"{location}/{version}/minecraft");
|
||||||
|
_mcLauncher = new(_mcPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
async public Task BuildLauncher(CancellationToken token)
|
||||||
|
{
|
||||||
|
if (_mcLauncher is null)
|
||||||
|
throw new NullReferenceException("Failed to build! Launcher is null!");
|
||||||
|
|
||||||
|
_mcLauncher.ByteProgressChanged += (_, args) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{(int)(args.ProgressedBytes * 0.000001)} MBytes / {(int)(args.TotalBytes * 0.000001)} MBytes");
|
||||||
|
DownloadProgress = (int)(args.ProgressedBytes * 100 / args.TotalBytes);
|
||||||
|
};
|
||||||
|
|
||||||
|
DownloadStatus = "Installing minecraft...";
|
||||||
|
Console.WriteLine(DownloadStatus);
|
||||||
|
await _mcLauncher.InstallAsync(_version);
|
||||||
|
DownloadStatus = "Finished!";
|
||||||
|
Console.WriteLine(DownloadStatus);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async public Task RunLauncher()
|
||||||
|
{
|
||||||
|
if (_mcLauncher is null)
|
||||||
|
throw new NullReferenceException("Failed to run launcher! Launcher is null!");
|
||||||
|
|
||||||
|
var process = await _mcLauncher.BuildProcessAsync(_version, new MLaunchOption
|
||||||
|
{
|
||||||
|
|
||||||
|
Session = MSession.CreateOfflineSession(_nickname),
|
||||||
|
MaximumRamMb = 4096,
|
||||||
|
|
||||||
|
}) ?? throw new Exception("Failed to start minecraft process!");
|
||||||
|
|
||||||
|
var processUtil = new ProcessWrapper(process);
|
||||||
|
processUtil.OutputReceived += (s, e) => Console.WriteLine(e);
|
||||||
|
processUtil.StartWithEvents();
|
||||||
|
|
||||||
|
await processUtil.WaitForExitTaskAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
9
Launcher-Core/Program.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace Plombir;
|
||||||
|
|
||||||
|
sealed class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
Console.WriteLine("init: launcher");
|
||||||
|
}
|
||||||
|
}
|
32
Launcher-Core/Utils.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using System.IO.Compression;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using SharpCompress.Archives;
|
||||||
|
using SharpCompress.Common;
|
||||||
|
using SharpCompress.Readers;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using CmlLib.Core;
|
||||||
|
|
||||||
|
namespace Plombir;
|
||||||
|
|
||||||
|
static public class Utils
|
||||||
|
{
|
||||||
|
|
||||||
|
public static async Task<List<string>> GetAllMcVersions()
|
||||||
|
{
|
||||||
|
return await Task.Run(async () =>
|
||||||
|
{
|
||||||
|
var ln = new MinecraftLauncher();
|
||||||
|
var result = new List<string>();
|
||||||
|
foreach (var x in await ln.GetAllVersionsAsync())
|
||||||
|
{
|
||||||
|
result.Add(x.Name);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
24
Launcher-UI/App.axaml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<Application
|
||||||
|
xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
x:Class="LauncherGUI.App"
|
||||||
|
xmlns:local="using:LauncherGUI"
|
||||||
|
RequestedThemeVariant="Default"
|
||||||
|
>
|
||||||
|
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
|
||||||
|
|
||||||
|
<Application.DataTemplates>
|
||||||
|
<local:ViewLocator />
|
||||||
|
</Application.DataTemplates>
|
||||||
|
|
||||||
|
<Application.Styles>
|
||||||
|
<FluentTheme />
|
||||||
|
</Application.Styles>
|
||||||
|
|
||||||
|
<Application.Resources>
|
||||||
|
<FontFamily
|
||||||
|
x:Key="QuicksandFont"
|
||||||
|
>avares://Launcher-UI/Assets/Fonts/Quicksand-SemiBold.ttf#Quicksand</FontFamily>
|
||||||
|
</Application.Resources>
|
||||||
|
|
||||||
|
</Application>
|
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 147 KiB |
Before Width: | Height: | Size: 892 B After Width: | Height: | Size: 892 B |
Before Width: | Height: | Size: 939 B After Width: | Height: | Size: 939 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 911 B After Width: | Height: | Size: 911 B |
@ -2,7 +2,7 @@ using System;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using Tommy;
|
using Tommy;
|
||||||
|
|
||||||
namespace PlombirLauncher;
|
namespace Plombir;
|
||||||
|
|
||||||
public class ConfigManager
|
public class ConfigManager
|
||||||
{
|
{
|
||||||
@ -27,7 +27,7 @@ public class ConfigManager
|
|||||||
["nickname"] = "slugcat"
|
["nickname"] = "slugcat"
|
||||||
};
|
};
|
||||||
|
|
||||||
using(StreamWriter writer = File.CreateText("tweaks.toml"))
|
using (StreamWriter writer = File.CreateText("tweaks.toml"))
|
||||||
{
|
{
|
||||||
toml.WriteTo(writer);
|
toml.WriteTo(writer);
|
||||||
// Remember to flush the data if needed!
|
// Remember to flush the data if needed!
|
||||||
@ -41,7 +41,7 @@ public class ConfigManager
|
|||||||
{
|
{
|
||||||
BuildDefault();
|
BuildDefault();
|
||||||
}
|
}
|
||||||
using(StreamReader reader = File.OpenText("tweaks.toml"))
|
using (StreamReader reader = File.OpenText("tweaks.toml"))
|
||||||
{
|
{
|
||||||
TomlTable table = TOML.Parse(reader);
|
TomlTable table = TOML.Parse(reader);
|
||||||
|
|
||||||
@ -58,18 +58,18 @@ public class ConfigManager
|
|||||||
|
|
||||||
TomlTable table;
|
TomlTable table;
|
||||||
|
|
||||||
using(StreamReader reader = File.OpenText("tweaks.toml"))
|
using (StreamReader reader = File.OpenText("tweaks.toml"))
|
||||||
{
|
{
|
||||||
table = TOML.Parse(reader);
|
table = TOML.Parse(reader);
|
||||||
|
|
||||||
table[key] = value;
|
table[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
using(StreamWriter writer = File.CreateText("tweaks.toml"))
|
using (StreamWriter writer = File.CreateText("tweaks.toml"))
|
||||||
{
|
{
|
||||||
table.WriteTo(writer);
|
table.WriteTo(writer);
|
||||||
// Remember to flush the data if needed!
|
// Remember to flush the data if needed!
|
||||||
writer.Flush();
|
writer.Flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -32,6 +32,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Launcher\cmllibLauncher.csproj" />
|
<ProjectReference Include="..\Launcher-Core\Launcher-Core.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
@ -1,14 +1,18 @@
|
|||||||
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using LauncherGUI.ViewModels;
|
using LauncherGUI.ViewModels;
|
||||||
using LauncherGUI.Views;
|
using LauncherGUI.Views;
|
||||||
|
|
||||||
namespace PlombirLauncher;
|
namespace Plombir;
|
||||||
|
|
||||||
public class LauncherUtils
|
public class LauncherUtils
|
||||||
{
|
{
|
||||||
public async static Task CreateMinecraftInstance(MainWindowViewModel vm, Window windowCaller)
|
public async static Task CreateMinecraftInstance(MainWindowViewModel vm, Window windowCaller)
|
||||||
{
|
{
|
||||||
|
if (vm.Usernick is null) throw new NullReferenceException("Failed to create minecraft instance! Nickname is null!");
|
||||||
|
if (vm.SelectedVersion is null) throw new NullReferenceException("Failed to create minecraft instance! Selected version is null!");
|
||||||
|
|
||||||
System.Console.WriteLine($"Creating minecraft instance for {vm.Usernick}, {vm.SelectedVersion} in {vm.RuntimeLocation}");
|
System.Console.WriteLine($"Creating minecraft instance for {vm.Usernick}, {vm.SelectedVersion} in {vm.RuntimeLocation}");
|
||||||
LoadingWindow loading = new(vm.Usernick, vm.SelectedVersion, vm.RuntimeLocation);
|
LoadingWindow loading = new(vm.Usernick, vm.SelectedVersion, vm.RuntimeLocation);
|
||||||
ConfigManager.WriteInConfig("last-version-launched", vm.SelectedVersion);
|
ConfigManager.WriteInConfig("last-version-launched", vm.SelectedVersion);
|
||||||
@ -20,4 +24,4 @@ public class LauncherUtils
|
|||||||
await loading.RunMinecraft();
|
await loading.RunMinecraft();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
BIN
Launcher-UI/PlombirLinux-v1-1-0.tar.gz
Normal file
BIN
Launcher-UI/PlombirWindows-v1-1-0.tar.gz
Normal file
@ -1,5 +1,5 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using PlombirLauncher;
|
using Plombir;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace LauncherGUI;
|
namespace LauncherGUI;
|
18
Launcher-UI/ViewModels/MainWindowViewModel.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Plombir;
|
||||||
|
|
||||||
|
namespace LauncherGUI.ViewModels;
|
||||||
|
|
||||||
|
public partial class MainWindowViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
public string Greeting { get; } = "Plombir launcher";
|
||||||
|
|
||||||
|
private string? _userNick = ConfigManager.ReadConfig("nickname");
|
||||||
|
public string? Usernick { get => _userNick; set { _userNick = value; OnPropertyChanged(nameof(Usernick)); } }
|
||||||
|
|
||||||
|
private string? _selectedVersion = ConfigManager.ReadConfig("last-version-launched");
|
||||||
|
public string? SelectedVersion { get => _selectedVersion; set { _selectedVersion = value; OnPropertyChanged(nameof(SelectedVersion)); } }
|
||||||
|
|
||||||
|
private string? _runtimeLocation = ConfigManager.ReadConfig("runtime-path");
|
||||||
|
public string? RuntimeLocation { get => _runtimeLocation; set { _runtimeLocation = value; OnPropertyChanged(nameof(RuntimeLocation)); } }
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using PlombirLauncher;
|
using Plombir;
|
||||||
using LauncherGUI.ViewModels;
|
using LauncherGUI.ViewModels;
|
||||||
|
|
||||||
namespace LauncherGUI.ViewModels;
|
namespace LauncherGUI.ViewModels;
|
||||||
@ -7,4 +7,4 @@ namespace LauncherGUI.ViewModels;
|
|||||||
public partial class VersionSelectorWindowViewModel : ViewModelBase
|
public partial class VersionSelectorWindowViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
// I save launcher data mostly in MainWindowViewModel.
|
// I save launcher data mostly in MainWindowViewModel.
|
||||||
}
|
}
|
@ -3,7 +3,7 @@ using System.Threading.Tasks;
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.VisualTree;
|
using Avalonia.VisualTree;
|
||||||
using PlombirLauncher;
|
using Plombir;
|
||||||
using LauncherGUI.ViewModels;
|
using LauncherGUI.ViewModels;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
@ -12,9 +12,9 @@ namespace LauncherGUI.Views;
|
|||||||
public partial class LoadingWindow : Window
|
public partial class LoadingWindow : Window
|
||||||
{
|
{
|
||||||
private Launcher ln;
|
private Launcher ln;
|
||||||
private Task _buildingTask;
|
private Task? _buildingTask;
|
||||||
|
|
||||||
// Tokens for controlling download task.
|
// Tokens for controlling download task.
|
||||||
CancellationTokenSource tokenSource = new CancellationTokenSource();
|
CancellationTokenSource tokenSource = new CancellationTokenSource();
|
||||||
public LoadingWindow(string nickname, string? version = null, string? location = null)
|
public LoadingWindow(string nickname, string? version = null, string? location = null)
|
||||||
{
|
{
|
||||||
@ -23,7 +23,7 @@ public partial class LoadingWindow : Window
|
|||||||
DataContext = new LoadingWindowViewModel();
|
DataContext = new LoadingWindowViewModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InitLoading()
|
public async Task InitLoading()
|
||||||
{
|
{
|
||||||
var viewModel = DataContext as LoadingWindowViewModel;
|
var viewModel = DataContext as LoadingWindowViewModel;
|
||||||
if (viewModel == null)
|
if (viewModel == null)
|
||||||
@ -31,10 +31,12 @@ public partial class LoadingWindow : Window
|
|||||||
throw new InvalidOperationException("No DataContext set");
|
throw new InvalidOperationException("No DataContext set");
|
||||||
}
|
}
|
||||||
|
|
||||||
Task updateGui = new Task(async () => {
|
Task updateGui = new Task(async () =>
|
||||||
while (ln.DownloadStatus != "Finished!"){
|
{
|
||||||
|
while (ln.DownloadStatus != "Finished!")
|
||||||
|
{
|
||||||
viewModel.Progress = ln.DownloadProgress;
|
viewModel.Progress = ln.DownloadProgress;
|
||||||
viewModel.LoadingStatus = ln.DownloadStatus;
|
viewModel.LoadingStatus = ln.DownloadStatus ?? "Looking at qubits...";
|
||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
}
|
}
|
||||||
viewModel.Progress = 100;
|
viewModel.Progress = 100;
|
||||||
@ -42,12 +44,12 @@ public partial class LoadingWindow : Window
|
|||||||
|
|
||||||
updateGui.Start();
|
updateGui.Start();
|
||||||
|
|
||||||
|
|
||||||
_buildingTask = ln.BuildLauncher(tokenSource.Token);
|
_buildingTask = ln.BuildLauncher(tokenSource.Token);
|
||||||
|
|
||||||
await _buildingTask;
|
await _buildingTask;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RunMinecraft()
|
public async Task RunMinecraft()
|
||||||
@ -62,4 +64,4 @@ public partial class LoadingWindow : Window
|
|||||||
System.Console.WriteLine("Loading disabled gracefully.");
|
System.Console.WriteLine("Loading disabled gracefully.");
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ using System.Linq;
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.VisualTree;
|
using Avalonia.VisualTree;
|
||||||
using PlombirLauncher;
|
using Plombir;
|
||||||
using CmlLib.Core.VersionMetadata;
|
using CmlLib.Core.VersionMetadata;
|
||||||
using LauncherGUI.ViewModels;
|
using LauncherGUI.ViewModels;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@ -29,11 +29,11 @@ public partial class MainWindow : Window
|
|||||||
|
|
||||||
var root = button.GetVisualRoot() as MainWindow;
|
var root = button.GetVisualRoot() as MainWindow;
|
||||||
if (root == null) return;
|
if (root == null) return;
|
||||||
|
|
||||||
var vm = DataContext as MainWindowViewModel;
|
var vm = DataContext as MainWindowViewModel;
|
||||||
await LauncherUtils.CreateMinecraftInstance(vm, root);
|
await LauncherUtils.CreateMinecraftInstance(vm, root);
|
||||||
button.Content = "Minecraft launched";
|
button.Content = "Minecraft launched";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnChooseVersionClick(object sender, RoutedEventArgs e)
|
private void OnChooseVersionClick(object sender, RoutedEventArgs e)
|
||||||
@ -86,4 +86,4 @@ public partial class MainWindow : Window
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -3,7 +3,7 @@ using Avalonia.Controls;
|
|||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.Platform.Storage;
|
using Avalonia.Platform.Storage;
|
||||||
using LauncherGUI.ViewModels;
|
using LauncherGUI.ViewModels;
|
||||||
using PlombirLauncher;
|
using Plombir;
|
||||||
|
|
||||||
namespace LauncherGUI.Views;
|
namespace LauncherGUI.Views;
|
||||||
|
|
||||||
@ -21,6 +21,7 @@ public partial class SettingsWindow : Window
|
|||||||
// Get top level from the current control. Alternatively, you can use Window reference instead.
|
// Get top level from the current control. Alternatively, you can use Window reference instead.
|
||||||
var topLevel = TopLevel.GetTopLevel(this);
|
var topLevel = TopLevel.GetTopLevel(this);
|
||||||
|
|
||||||
|
if (topLevel is null) throw new NullReferenceException("Failed to start file picker!");
|
||||||
// Start async operation to open the dialog.
|
// Start async operation to open the dialog.
|
||||||
var files = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
|
var files = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
|
||||||
{
|
{
|
||||||
@ -38,4 +39,3 @@ public partial class SettingsWindow : Window
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ using System.Threading.Tasks;
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using LauncherGUI.ViewModels;
|
using LauncherGUI.ViewModels;
|
||||||
using PlombirLauncher;
|
using Plombir;
|
||||||
|
|
||||||
namespace LauncherGUI.Views;
|
namespace LauncherGUI.Views;
|
||||||
|
|
||||||
@ -13,14 +13,14 @@ public partial class VersionSelectorWindow : Window
|
|||||||
private MainWindowViewModel _mainViewModel;
|
private MainWindowViewModel _mainViewModel;
|
||||||
public VersionSelectorWindow(MainWindowViewModel mainViewModel)
|
public VersionSelectorWindow(MainWindowViewModel mainViewModel)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_mainViewModel = mainViewModel;
|
_mainViewModel = mainViewModel;
|
||||||
|
|
||||||
//Load versions asynchronously
|
//Load versions asynchronously
|
||||||
var versionsList = Task.Run(() => PlombirLauncher.Utils.GetAllMcVersions().GetAwaiter().GetResult());
|
var versionsList = Task.Run(() => Plombir.Utils.GetAllMcVersions().GetAwaiter().GetResult());
|
||||||
|
|
||||||
versions.ItemsSource = versionsList.Result;
|
versions.ItemsSource = versionsList.Result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
|
private async void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
@ -30,10 +30,10 @@ public partial class VersionSelectorWindow : Window
|
|||||||
_mainViewModel.SelectedVersion = selectedVersion;
|
_mainViewModel.SelectedVersion = selectedVersion;
|
||||||
|
|
||||||
System.Console.WriteLine($"Selected version: {selectedVersion}");
|
System.Console.WriteLine($"Selected version: {selectedVersion}");
|
||||||
|
|
||||||
LauncherUtils.CreateMinecraftInstance(_mainViewModel, this);
|
LauncherUtils.CreateMinecraftInstance(_mainViewModel, this);
|
||||||
Close();
|
Close();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
6
Launcher-UI/tweaks.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
title = "Launcher tweaks file!"
|
||||||
|
# Path to folder that will hold all minecraft versions
|
||||||
|
runtime-path = "./runtime"
|
||||||
|
# Saving last launched version to use it after launch
|
||||||
|
last-version-launched = "1.20.1"
|
||||||
|
nickname = "slugcat"
|
11
package/build-targz-linux-ui.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
cd ../Launcher-UI
|
||||||
|
|
||||||
|
out_dir=../package/out/build
|
||||||
|
archieve_name=PlombirLinux-v1-1-0.tar.gz
|
||||||
|
|
||||||
|
rm -r $out_dir
|
||||||
|
|
||||||
|
dotnet publish -r linux-x64 -o $out_dir -p:PublishReadyToRun=true -p:PublishSingleFile=true --self-contained true -p:IncludeNativeLibrariesForSelfExtract=true
|
||||||
|
|
||||||
|
cd ../package/out
|
||||||
|
tar -czvf $archieve_name -C build/ .
|
11
package/build-targz-osx-ui.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
cd ../Launcher-UI
|
||||||
|
|
||||||
|
out_dir=../package/out/build
|
||||||
|
archieve_name=PlombirOSX-v1-1-0.tar.gz
|
||||||
|
|
||||||
|
rm -r $out_dir
|
||||||
|
|
||||||
|
dotnet publish -r osx-x64 -o $out_dir -p:PublishReadyToRun=true -p:PublishSingleFile=true --self-contained true -p:IncludeNativeLibrariesForSelfExtract=true
|
||||||
|
|
||||||
|
cd ../package/out
|
||||||
|
tar -czvf $archieve_name -C build/ .
|
11
package/build-targz-win-ui.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
cd ../Launcher-UI
|
||||||
|
|
||||||
|
out_dir=../package/out/build
|
||||||
|
archieve_name=PlombirWindows-v1-1-0.tar.gz
|
||||||
|
|
||||||
|
rm -r $out_dir
|
||||||
|
|
||||||
|
dotnet publish -r win-x64 -o $out_dir -p:PublishReadyToRun=true -p:PublishSingleFile=true --self-contained true -p:IncludeNativeLibrariesForSelfExtract=true
|
||||||
|
|
||||||
|
cd ../package/out
|
||||||
|
tar -czvf $archieve_name -C build/ .
|
@ -1,139 +0,0 @@
|
|||||||
using System.Formats.Tar;
|
|
||||||
using System.Net;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Security.AccessControl;
|
|
||||||
using CmlLib.Core;
|
|
||||||
using CmlLib.Core.Auth;
|
|
||||||
using CmlLib.Core.ProcessBuilder;
|
|
||||||
|
|
||||||
namespace PlombirLauncher
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Basically a class to manage everything launcher related.
|
|
||||||
TODO - minecraft downloading from webserver
|
|
||||||
*/
|
|
||||||
public class Launcher
|
|
||||||
{
|
|
||||||
private readonly string _version;
|
|
||||||
private readonly string _nickname;
|
|
||||||
static private MinecraftPath _mcPath;
|
|
||||||
static private MinecraftLauncher _mcLauncher;
|
|
||||||
|
|
||||||
public int DownloadProgress;
|
|
||||||
public string DownloadStatus;
|
|
||||||
|
|
||||||
public Launcher(string userName, string version, string? location = null)
|
|
||||||
{
|
|
||||||
_version = version;
|
|
||||||
_nickname = userName;
|
|
||||||
_mcPath = new($"{location}/{version}/minecraft");
|
|
||||||
_mcLauncher = new(_mcPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Using it for forge loading because i don't know event-based async.
|
|
||||||
//static TaskCompletionSource<bool> tcs = new();
|
|
||||||
|
|
||||||
|
|
||||||
// Not used. Because launcher supports only VANILLA.
|
|
||||||
// public async Task FetchMinecraft()
|
|
||||||
// {
|
|
||||||
|
|
||||||
// string archieve = "mc-archieve.tar.xz";
|
|
||||||
// string runtimePath = "runtime";
|
|
||||||
|
|
||||||
// System.Uri download_uri = new("https://dixxe.top/static/distro/cmllibcore-minecraft-forge-1201.tar.xz");
|
|
||||||
// WebClient client = new();
|
|
||||||
|
|
||||||
// if ((!File.Exists(archieve)) && (!Directory.Exists(runtimePath)))
|
|
||||||
// {
|
|
||||||
// DownloadStatus = "Fetching deploy-minecraft from host...";
|
|
||||||
// Console.WriteLine(DownloadStatus);
|
|
||||||
|
|
||||||
// // Implement async download
|
|
||||||
// client.DownloadFileAsync(download_uri, archieve);
|
|
||||||
// client.DownloadDataCompleted += (o, e) =>
|
|
||||||
// {
|
|
||||||
// DownloadStatus = "Download completed";
|
|
||||||
// Console.WriteLine(DownloadStatus);
|
|
||||||
// };
|
|
||||||
// client.DownloadProgressChanged += (o, e) =>
|
|
||||||
// {
|
|
||||||
// // Curentlly this scope doing nothing
|
|
||||||
// Console.WriteLine($"{e.ProgressPercentage}% downloaded");
|
|
||||||
// DownloadProgress = e.ProgressPercentage;
|
|
||||||
// DownloadStatus = "Fetching modpack...";
|
|
||||||
|
|
||||||
// if (DownloadProgress == 100)
|
|
||||||
// {
|
|
||||||
// tcs.SetResult(true);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// };
|
|
||||||
// // Waiting for archieve to download.
|
|
||||||
// await tcs.Task;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// DownloadStatus = "Unarchiving modpack...";
|
|
||||||
// unarchiveMinecraft(archieve, runtimePath);
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Not used. Because launcher supports only VANILLA.
|
|
||||||
// private void unarchiveMinecraft(string archieveName, string path)
|
|
||||||
// {
|
|
||||||
// if (Directory.Exists(path)) { return; }
|
|
||||||
// Console.WriteLine(DownloadStatus);
|
|
||||||
// Directory.CreateDirectory(path);
|
|
||||||
// Utils.UnzipTarGzFile(archieveName, path);
|
|
||||||
|
|
||||||
// if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
|
||||||
// {
|
|
||||||
// Utils.LinuxExec($"chmod -R +x {path}/");
|
|
||||||
// Console.WriteLine("Execute permissions added successfully.");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// File.Delete(archieveName);
|
|
||||||
// }
|
|
||||||
|
|
||||||
async public Task BuildLauncher(CancellationToken token)
|
|
||||||
{
|
|
||||||
_mcLauncher.ByteProgressChanged += (_, args) =>
|
|
||||||
{
|
|
||||||
Console.WriteLine($"{(int)(args.ProgressedBytes * 0.000001)} MBytes / {(int)(args.TotalBytes * 0.000001)} MBytes");
|
|
||||||
DownloadProgress = (int)(args.ProgressedBytes * 100 / args.TotalBytes);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Before installAsync I should fetch lightweight minecraft instance from webserver
|
|
||||||
// Then installAsync will download any runtime needed stuff.
|
|
||||||
// This method is FetchMinecraft()
|
|
||||||
// Currently this is only one viable option for forge installations.
|
|
||||||
// But it requires server, so forge (and all mod loaders) is disabled.
|
|
||||||
//await FetchMinecraft();
|
|
||||||
|
|
||||||
DownloadStatus = "Installing minecraft...";
|
|
||||||
Console.WriteLine(DownloadStatus);
|
|
||||||
await _mcLauncher.InstallAsync(_version);
|
|
||||||
DownloadStatus = "Finished!";
|
|
||||||
Console.WriteLine(DownloadStatus);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
async public Task RunLauncher()
|
|
||||||
{
|
|
||||||
var process = await _mcLauncher.BuildProcessAsync(_version, new MLaunchOption
|
|
||||||
{
|
|
||||||
|
|
||||||
Session = MSession.CreateOfflineSession(_nickname),
|
|
||||||
MaximumRamMb = 4096,
|
|
||||||
|
|
||||||
}) ?? throw new Exception("Failed to start minecraft process!");
|
|
||||||
|
|
||||||
var processUtil = new ProcessWrapper(process);
|
|
||||||
processUtil.OutputReceived += (s, e) => Console.WriteLine(e);
|
|
||||||
processUtil.StartWithEvents();
|
|
||||||
|
|
||||||
await processUtil.WaitForExitTaskAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
namespace PlombirLauncher
|
|
||||||
{
|
|
||||||
sealed class Program
|
|
||||||
{
|
|
||||||
public static void Main()
|
|
||||||
{
|
|
||||||
Console.WriteLine("init: launcher");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
using System.IO.Compression;
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using SharpCompress.Archives;
|
|
||||||
using SharpCompress.Common;
|
|
||||||
using SharpCompress.Readers;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using CmlLib.Core;
|
|
||||||
|
|
||||||
namespace PlombirLauncher
|
|
||||||
{
|
|
||||||
static public class Utils
|
|
||||||
{
|
|
||||||
public static void UnzipTarGzFile(string filePath, string destinationPath)
|
|
||||||
{
|
|
||||||
using (Stream stream = File.OpenRead(filePath))
|
|
||||||
{
|
|
||||||
using (var reader = ReaderFactory.Open(stream))
|
|
||||||
{
|
|
||||||
while (reader.MoveToNextEntry())
|
|
||||||
{
|
|
||||||
if (!reader.Entry.IsDirectory)
|
|
||||||
{
|
|
||||||
reader.WriteEntryToDirectory(destinationPath, new ExtractionOptions()
|
|
||||||
{
|
|
||||||
ExtractFullPath = true,
|
|
||||||
Overwrite = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LinuxExec(string cmd)
|
|
||||||
{
|
|
||||||
var escapedArgs = cmd.Replace("\"", "\\\"");
|
|
||||||
|
|
||||||
using var process = new Process
|
|
||||||
{
|
|
||||||
StartInfo = new ProcessStartInfo
|
|
||||||
{
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
UseShellExecute = false,
|
|
||||||
CreateNoWindow = true,
|
|
||||||
WindowStyle = ProcessWindowStyle.Hidden,
|
|
||||||
FileName = "/bin/bash",
|
|
||||||
Arguments = $"-c \"{escapedArgs}\""
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
process.Start();
|
|
||||||
process.WaitForExit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<List<string>> GetAllMcVersions()
|
|
||||||
{
|
|
||||||
return await Task.Run(async() => {
|
|
||||||
var ln = new MinecraftLauncher();
|
|
||||||
var result = new List<string>();
|
|
||||||
foreach (var x in await ln.GetAllVersionsAsync())
|
|
||||||
{
|
|
||||||
result.Add(x.Name);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
<Application xmlns="https://github.com/avaloniaui"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
x:Class="LauncherGUI.App"
|
|
||||||
xmlns:local="using:LauncherGUI"
|
|
||||||
RequestedThemeVariant="Default">
|
|
||||||
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
|
|
||||||
|
|
||||||
<Application.DataTemplates>
|
|
||||||
<local:ViewLocator/>
|
|
||||||
</Application.DataTemplates>
|
|
||||||
|
|
||||||
<Application.Styles>
|
|
||||||
<FluentTheme />
|
|
||||||
</Application.Styles>
|
|
||||||
|
|
||||||
<Application.Resources>
|
|
||||||
<FontFamily x:Key="QuicksandFont">avares://LauncherGUI/Assets/Fonts/Quicksand-SemiBold.ttf#Quicksand</FontFamily>
|
|
||||||
</Application.Resources>
|
|
||||||
|
|
||||||
</Application>
|
|
@ -1,18 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using PlombirLauncher;
|
|
||||||
|
|
||||||
namespace LauncherGUI.ViewModels;
|
|
||||||
|
|
||||||
public partial class MainWindowViewModel : ViewModelBase
|
|
||||||
{
|
|
||||||
public string Greeting { get; } = "Plombir launcher";
|
|
||||||
|
|
||||||
private string _userNick = ConfigManager.ReadConfig("nickname");
|
|
||||||
public string Usernick {get => _userNick; set {_userNick = value; OnPropertyChanged(nameof(Usernick)); }}
|
|
||||||
|
|
||||||
private string _selectedVersion = ConfigManager.ReadConfig("last-version-launched");
|
|
||||||
public string SelectedVersion {get => _selectedVersion; set {_selectedVersion = value; OnPropertyChanged(nameof(SelectedVersion)); }}
|
|
||||||
|
|
||||||
private string _runtimeLocation = ConfigManager.ReadConfig("runtime-path");
|
|
||||||
public string RuntimeLocation {get => _runtimeLocation; set {_runtimeLocation = value; OnPropertyChanged(nameof(RuntimeLocation)); }}
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
title = "Launcher tweaks file!"
|
|
||||||
runtime-path = "/home/nullmax17/test_folder"
|
|
||||||
last-version-launched = "1.15"
|
|
||||||
nickname = "nullmax17"
|
|
6
tweaks.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
title = "Launcher tweaks file!"
|
||||||
|
# Path to folder that will hold all minecraft versions
|
||||||
|
runtime-path = "./runtime"
|
||||||
|
# Saving last launched version to use it after launch
|
||||||
|
last-version-launched = "1.20.1"
|
||||||
|
nickname = "slugcat"
|