chore: refactor project, bug fixes
This commit is contained in:
parent
8dba3ab782
commit
10c2103762
|
|
@ -9,7 +9,78 @@ namespace Kiseki.Launcher.Windows
|
||||||
{
|
{
|
||||||
public readonly static string Version = Assembly.GetExecutingAssembly().GetName().Version!.ToString()[..^2];
|
public readonly static string Version = Assembly.GetExecutingAssembly().GetName().Version!.ToString()[..^2];
|
||||||
|
|
||||||
#region IBootstrapper implementation
|
private readonly string Payload;
|
||||||
|
private readonly Dictionary<string, string> Arguments = new();
|
||||||
|
|
||||||
|
public event EventHandler<string>? OnHeadingChange;
|
||||||
|
public event EventHandler<int>? OnProgressBarAdd;
|
||||||
|
public event EventHandler<Enums.ProgressBarState>? OnProgressBarStateChange;
|
||||||
|
public event EventHandler<string[]>? OnError;
|
||||||
|
|
||||||
|
public Bootstrapper(string payload)
|
||||||
|
{
|
||||||
|
Payload = payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Initialize()
|
||||||
|
{
|
||||||
|
if (!Helpers.Base64.IsBase64String(Payload))
|
||||||
|
{
|
||||||
|
Error($"Failed to launch {Constants.PROJECT_NAME}", $"Try launching {Constants.PROJECT_NAME} from the website again.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mode, version, ticket, joinscript
|
||||||
|
string[] pieces = Helpers.Base64.ConvertBase64ToString(Payload).Split("|");
|
||||||
|
if (pieces.Length != 4)
|
||||||
|
{
|
||||||
|
Error($"Failed to launch {Constants.PROJECT_NAME}", $"Try launching {Constants.PROJECT_NAME} from the website again.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Arguments["Mode"] = pieces[0];
|
||||||
|
Arguments["Version"] = pieces[1];
|
||||||
|
Arguments["Ticket"] = pieces[2];
|
||||||
|
Arguments["JoinScript"] = pieces[3];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Abort()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
#region MainWindow
|
||||||
|
|
||||||
|
protected virtual void HeadingChange(string heading)
|
||||||
|
{
|
||||||
|
OnHeadingChange!.Invoke(this, heading);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void ProgressBarAdd(int value)
|
||||||
|
{
|
||||||
|
OnProgressBarAdd!.Invoke(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void ProgressBarStateChange(Enums.ProgressBarState state)
|
||||||
|
{
|
||||||
|
OnProgressBarStateChange!.Invoke(this, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Error(string heading, string text)
|
||||||
|
{
|
||||||
|
// ugly hack for now (I don't want to derive EventHandler just for this)
|
||||||
|
OnError!.Invoke(this, new string[] { heading, text });
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
#region Installation
|
||||||
|
|
||||||
public static void Install()
|
public static void Install()
|
||||||
{
|
{
|
||||||
|
|
@ -97,6 +168,9 @@ namespace Kiseki.Launcher.Windows
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
#region Registration
|
||||||
|
|
||||||
public static void Register()
|
public static void Register()
|
||||||
{
|
{
|
||||||
using RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{Constants.PROJECT_NAME}");
|
using RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{Constants.PROJECT_NAME}");
|
||||||
|
|
@ -136,7 +210,7 @@ namespace Kiseki.Launcher.Windows
|
||||||
#endregion
|
#endregion
|
||||||
#region Licensing
|
#region Licensing
|
||||||
|
|
||||||
public static void TryLoadLicense()
|
public static void License()
|
||||||
{
|
{
|
||||||
if (!File.Exists(Directories.License))
|
if (!File.Exists(Directories.License))
|
||||||
{
|
{
|
||||||
|
|
@ -157,6 +231,14 @@ namespace Kiseki.Launcher.Windows
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Unlicense()
|
||||||
|
{
|
||||||
|
if (File.Exists(Directories.License))
|
||||||
|
{
|
||||||
|
File.Delete(Directories.License);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static bool AskForLicense(string licensePath, bool showDialog = true)
|
private static bool AskForLicense(string licensePath, bool showDialog = true)
|
||||||
{
|
{
|
||||||
DialogResult answer = showDialog ? MessageBox.Show($"{Constants.PROJECT_NAME} is currently under maintenance and requires a license in order to access games. Would you like to look for the license file now?", Constants.PROJECT_NAME, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) : DialogResult.Yes;
|
DialogResult answer = showDialog ? MessageBox.Show($"{Constants.PROJECT_NAME} is currently under maintenance and requires a license in order to access games. Would you like to look for the license file now?", Constants.PROJECT_NAME, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) : DialogResult.Yes;
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,7 @@ namespace Kiseki.Launcher.Windows
|
||||||
|
|
||||||
if (!Directory.Exists(Base))
|
if (!Directory.Exists(Base))
|
||||||
{
|
{
|
||||||
// just in case
|
Directory.CreateDirectory(Base); // just in case
|
||||||
Directory.CreateDirectory(Base);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Logs = Path.Combine(Base, "Logs");
|
Logs = Path.Combine(Base, "Logs");
|
||||||
|
|
|
||||||
|
|
@ -7,16 +7,15 @@ namespace Kiseki.Launcher.Windows
|
||||||
{
|
{
|
||||||
private readonly TaskDialogButton CloseButton;
|
private readonly TaskDialogButton CloseButton;
|
||||||
private readonly TaskDialogPage Page;
|
private readonly TaskDialogPage Page;
|
||||||
private readonly Controller Controller;
|
private readonly Bootstrapper Bootstrapper;
|
||||||
|
|
||||||
public MainWindow(string payload)
|
public MainWindow(string payload)
|
||||||
{
|
{
|
||||||
Controller = new Controller(payload);
|
Bootstrapper = new Bootstrapper(payload);
|
||||||
Controller.OnPageHeadingChange += Controller_PageHeadingChanged;
|
Bootstrapper.OnHeadingChange += Bootstrapper_HeadingChanged;
|
||||||
Controller.OnProgressBarAdd += Controller_ProgressBarAdded;
|
Bootstrapper.OnProgressBarAdd += Bootstrapper_ProgressBarAdded;
|
||||||
Controller.OnProgressBarStateChange += Controller_ProgressBarStateChanged;
|
Bootstrapper.OnProgressBarStateChange += Bootstrapper_ProgressBarStateChanged;
|
||||||
Controller.OnErrorShow += Controller_ErrorShown;
|
Bootstrapper.OnError += Bootstrapper_Errored;
|
||||||
Controller.OnLaunch += (s, e) => Environment.Exit(0);
|
|
||||||
|
|
||||||
CloseButton = TaskDialogButton.Close;
|
CloseButton = TaskDialogButton.Close;
|
||||||
Page = new TaskDialogPage()
|
Page = new TaskDialogPage()
|
||||||
|
|
@ -34,59 +33,51 @@ namespace Kiseki.Launcher.Windows
|
||||||
|
|
||||||
Page.Created += (s, e) =>
|
Page.Created += (s, e) =>
|
||||||
{
|
{
|
||||||
Controller.Start();
|
Bootstrapper.Run();
|
||||||
};
|
};
|
||||||
|
|
||||||
Page.Destroyed += (s, e) =>
|
ShowTaskDialog();
|
||||||
{
|
|
||||||
Controller.Dispose();
|
|
||||||
Environment.Exit(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
ShowProgressDialog();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CloseButton_Click(object? sender, EventArgs e)
|
private void ShowTaskDialog()
|
||||||
{
|
|
||||||
Controller.Dispose();
|
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Controller_PageHeadingChanged(object? sender, string heading)
|
|
||||||
{
|
|
||||||
Page.Heading = heading;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Controller_ProgressBarAdded(object? sender, int value)
|
|
||||||
{
|
|
||||||
Page.ProgressBar!.Value += value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Controller_ProgressBarStateChanged(object? sender, ProgressBarState state)
|
|
||||||
{
|
|
||||||
Page.ProgressBar!.State = state switch
|
|
||||||
{
|
|
||||||
ProgressBarState.Normal => TaskDialogProgressBarState.Normal,
|
|
||||||
ProgressBarState.Marquee => TaskDialogProgressBarState.Marquee,
|
|
||||||
_ => throw new NotImplementedException()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Controller_ErrorShown(object? sender, string[] texts)
|
|
||||||
{
|
|
||||||
Page.Icon = TaskDialogIcon.Error;
|
|
||||||
Page.Heading = texts[0];
|
|
||||||
Page.Text = texts[1];
|
|
||||||
|
|
||||||
Controller.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ShowProgressDialog()
|
|
||||||
{
|
{
|
||||||
TaskDialogIcon logo = new(Resources.IconKiseki);
|
TaskDialogIcon logo = new(Resources.IconKiseki);
|
||||||
Page.Icon = logo;
|
Page.Icon = logo;
|
||||||
|
|
||||||
TaskDialog.ShowDialog(Page);
|
TaskDialog.ShowDialog(Page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CloseButton_Click(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Bootstrapper.Abort();
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Bootstrapper_HeadingChanged(object? sender, string heading)
|
||||||
|
{
|
||||||
|
Page.Heading = heading;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Bootstrapper_ProgressBarAdded(object? sender, int value)
|
||||||
|
{
|
||||||
|
Page.ProgressBar!.Value += value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Bootstrapper_ProgressBarStateChanged(object? sender, Enums.ProgressBarState state)
|
||||||
|
{
|
||||||
|
Page.ProgressBar!.State = state switch
|
||||||
|
{
|
||||||
|
Enums.ProgressBarState.Normal => TaskDialogProgressBarState.Normal,
|
||||||
|
Enums.ProgressBarState.Marquee => TaskDialogProgressBarState.Marquee,
|
||||||
|
_ => throw new NotImplementedException()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Bootstrapper_Errored(object? sender, string[] texts)
|
||||||
|
{
|
||||||
|
Page.Icon = TaskDialogIcon.Error;
|
||||||
|
Page.Heading = texts[0];
|
||||||
|
Page.Text = texts[1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,11 +7,12 @@ namespace Kiseki.Launcher.Windows
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
// Initialize directories
|
||||||
string parentFolder = Path.GetDirectoryName(Application.ExecutablePath)!;
|
string parentFolder = Path.GetDirectoryName(Application.ExecutablePath)!;
|
||||||
|
|
||||||
if (Path.GetDirectoryName(parentFolder)!.ToLower().Contains(Constants.PROJECT_NAME.ToLower()))
|
if (Path.GetDirectoryName(parentFolder)!.ToLower().Contains(Constants.PROJECT_NAME.ToLower()))
|
||||||
{
|
{
|
||||||
// Set to the current directory (either user-installed or default; it has "Kiseki" in the path, so that's good enough for us)
|
// Set to the current directory (user likely has installed the launcher, seeing as parent folder name contains the project name)
|
||||||
Directories.Initialize(parentFolder);
|
Directories.Initialize(parentFolder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -23,40 +24,49 @@ namespace Kiseki.Launcher.Windows
|
||||||
bool isConnected = Web.Initialize();
|
bool isConnected = Web.Initialize();
|
||||||
if (!isConnected && Web.IsInMaintenance)
|
if (!isConnected && Web.IsInMaintenance)
|
||||||
{
|
{
|
||||||
// Try again with the maintenance domain
|
// Try licensing this launcher and attempt to connect again
|
||||||
Bootstrapper.TryLoadLicense();
|
Bootstrapper.License();
|
||||||
isConnected = Web.Initialize();
|
isConnected = Web.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isConnected)
|
if (!isConnected)
|
||||||
{
|
{
|
||||||
|
if (Web.IsInMaintenance)
|
||||||
|
{
|
||||||
|
// Unlicense this launcher
|
||||||
|
Bootstrapper.Unlicense();
|
||||||
|
}
|
||||||
|
|
||||||
MessageBox.Show($"Failed to connect to {Constants.PROJECT_NAME}. Please check your internet connection and try again.", Constants.PROJECT_NAME, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
MessageBox.Show($"Failed to connect to {Constants.PROJECT_NAME}. Please check your internet connection and try again.", Constants.PROJECT_NAME, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!File.Exists(Directories.Application))
|
if (!File.Exists(Directories.Application))
|
||||||
{
|
{
|
||||||
// The launcher is not installed, so let's run the install process - this will also exit the application
|
|
||||||
Bootstrapper.Install();
|
Bootstrapper.Install();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (args.Length == 0)
|
||||||
{
|
{
|
||||||
if (args.Length == 0)
|
// Nothing for us to do :P
|
||||||
|
Process.Start(new ProcessStartInfo()
|
||||||
{
|
{
|
||||||
// Nothing for us to do :P
|
FileName = Web.Url("/games"),
|
||||||
Process.Start($"open {Web.Url("/games")}");
|
UseShellExecute = true
|
||||||
return;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
if (args[0] == "-uninstall")
|
return;
|
||||||
{
|
|
||||||
Bootstrapper.Uninstall(args[0] == "-quiet");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ApplicationConfiguration.Initialize();
|
|
||||||
Application.Run(new MainWindow(args[0]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args[0] == "-uninstall")
|
||||||
|
{
|
||||||
|
Bootstrapper.Uninstall(args[0] == "-quiet");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplicationConfiguration.Initialize();
|
||||||
|
Application.Run(new MainWindow(args[0]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,112 +0,0 @@
|
||||||
using Kiseki.Launcher.Helpers;
|
|
||||||
|
|
||||||
namespace Kiseki.Launcher
|
|
||||||
{
|
|
||||||
public enum ProgressBarState
|
|
||||||
{
|
|
||||||
Normal,
|
|
||||||
Marquee
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Controller
|
|
||||||
{
|
|
||||||
private readonly Dictionary<string, string> Arguments = new();
|
|
||||||
|
|
||||||
public event EventHandler<string>? OnPageHeadingChange;
|
|
||||||
public event EventHandler<int>? OnProgressBarAdd;
|
|
||||||
public event EventHandler<ProgressBarState>? OnProgressBarStateChange;
|
|
||||||
public event EventHandler<string[]>? OnErrorShow;
|
|
||||||
public event EventHandler? OnLaunch;
|
|
||||||
|
|
||||||
public Controller(string payload)
|
|
||||||
{
|
|
||||||
if (!Base64.IsBase64String(payload))
|
|
||||||
{
|
|
||||||
ErrorShow($"Failed to launch {Constants.PROJECT_NAME}", $"Try launching {Constants.PROJECT_NAME} from the website again.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: The payload will soon include more members; update this accordingly
|
|
||||||
payload = Base64.ConvertBase64ToString(payload);
|
|
||||||
if (payload.Split("|").Length != 2)
|
|
||||||
{
|
|
||||||
ErrorShow($"Failed to launch {Constants.PROJECT_NAME}", $"Try launching {Constants.PROJECT_NAME} from the website again.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Arguments["JoinScriptURL"] = payload.Split("|")[0];
|
|
||||||
Arguments["Ticket"] = payload.Split("|")[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void Start()
|
|
||||||
{
|
|
||||||
PageHeadingChange("Connecting to Kiseki...");
|
|
||||||
|
|
||||||
bool marquee = true;
|
|
||||||
await foreach (int progressValue in StreamBackgroundOperationProgressAsync())
|
|
||||||
{
|
|
||||||
if (marquee)
|
|
||||||
{
|
|
||||||
PageHeadingChange("Downloading Kiseki...");
|
|
||||||
ProgressBarStateChange(ProgressBarState.Normal);
|
|
||||||
|
|
||||||
marquee = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressBarAdd(progressValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async IAsyncEnumerable<int> StreamBackgroundOperationProgressAsync()
|
|
||||||
{
|
|
||||||
await Task.Delay(2800);
|
|
||||||
|
|
||||||
yield return 4;
|
|
||||||
|
|
||||||
await Task.Delay(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
PageHeadingChange("Installing Kiseki...");
|
|
||||||
ProgressBarStateChange(ProgressBarState.Marquee);
|
|
||||||
|
|
||||||
await Task.Delay(2200);
|
|
||||||
PageHeadingChange("Configuring Kiseki...");
|
|
||||||
|
|
||||||
await Task.Delay(1200);
|
|
||||||
PageHeadingChange("Launching Kiseki...");
|
|
||||||
|
|
||||||
await Task.Delay(3000);
|
|
||||||
Launch();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void Dispose()
|
|
||||||
{
|
|
||||||
// TODO: This will only be called when the user closes the window OR we're done (i.e. the Launched event is called.)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void PageHeadingChange(string heading)
|
|
||||||
{
|
|
||||||
OnPageHeadingChange!.Invoke(this, heading);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void ProgressBarAdd(int value)
|
|
||||||
{
|
|
||||||
OnProgressBarAdd!.Invoke(this, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void ProgressBarStateChange(ProgressBarState state)
|
|
||||||
{
|
|
||||||
OnProgressBarStateChange!.Invoke(this, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void ErrorShow(string heading, string text)
|
|
||||||
{
|
|
||||||
// ugly hack for now (I don't want to derive EventHandler just for this)
|
|
||||||
OnErrorShow!.Invoke(this, new string[] { heading, text });
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Launch()
|
|
||||||
{
|
|
||||||
OnLaunch!.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Kiseki.Launcher.Enums
|
||||||
|
{
|
||||||
|
public enum PackageType
|
||||||
|
{
|
||||||
|
Bootstrapper,
|
||||||
|
Client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Kiseki.Launcher.Enums
|
||||||
|
{
|
||||||
|
public enum ProgressBarState
|
||||||
|
{
|
||||||
|
Normal,
|
||||||
|
Marquee
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,9 +2,27 @@ namespace Kiseki.Launcher
|
||||||
{
|
{
|
||||||
public interface IBootstrapper
|
public interface IBootstrapper
|
||||||
{
|
{
|
||||||
|
// These connect to MainWindow
|
||||||
|
event EventHandler<string>? OnHeadingChange;
|
||||||
|
event EventHandler<int>? OnProgressBarAdd;
|
||||||
|
event EventHandler<Enums.ProgressBarState>? OnProgressBarStateChange;
|
||||||
|
event EventHandler<string[]>? OnError;
|
||||||
|
|
||||||
|
// Actual bootstrapping
|
||||||
|
bool Initialize();
|
||||||
|
void Run();
|
||||||
|
void Abort();
|
||||||
|
|
||||||
|
// Installation (i.e. putting the launcher in the Kiseki folder)
|
||||||
static abstract void Install();
|
static abstract void Install();
|
||||||
static abstract void Uninstall(bool quiet = false);
|
static abstract void Uninstall(bool quiet = false);
|
||||||
|
|
||||||
|
// Registering the launcher onto the system (as well as creating shortcuts)
|
||||||
static abstract void Register();
|
static abstract void Register();
|
||||||
static abstract void Unregister();
|
static abstract void Unregister();
|
||||||
|
|
||||||
|
// Licensing the launcher
|
||||||
|
static abstract void License();
|
||||||
|
static abstract void Unlicense();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
namespace Kiseki.Launcher
|
namespace Kiseki.Launcher
|
||||||
{
|
{
|
||||||
|
// This is responsible for handling registration of the Kiseki protcool handler
|
||||||
public interface IProtocol
|
public interface IProtocol
|
||||||
{
|
{
|
||||||
static abstract void Register();
|
static abstract void Register();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue