chore: refactor project, bug fixes

This commit is contained in:
rjindael 2023-08-02 01:20:34 -07:00
parent 8dba3ab782
commit 10c2103762
No known key found for this signature in database
GPG Key ID: D069369C906CCF31
9 changed files with 190 additions and 185 deletions

View File

@ -9,7 +9,78 @@ namespace Kiseki.Launcher.Windows
{
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()
{
@ -97,6 +168,9 @@ namespace Kiseki.Launcher.Windows
}
}
#endregion
#region Registration
public static void Register()
{
using RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{Constants.PROJECT_NAME}");
@ -136,7 +210,7 @@ namespace Kiseki.Launcher.Windows
#endregion
#region Licensing
public static void TryLoadLicense()
public static void 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)
{
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;

View File

@ -16,8 +16,7 @@ namespace Kiseki.Launcher.Windows
if (!Directory.Exists(Base))
{
// just in case
Directory.CreateDirectory(Base);
Directory.CreateDirectory(Base); // just in case
}
Logs = Path.Combine(Base, "Logs");

View File

@ -7,16 +7,15 @@ namespace Kiseki.Launcher.Windows
{
private readonly TaskDialogButton CloseButton;
private readonly TaskDialogPage Page;
private readonly Controller Controller;
private readonly Bootstrapper Bootstrapper;
public MainWindow(string payload)
{
Controller = new Controller(payload);
Controller.OnPageHeadingChange += Controller_PageHeadingChanged;
Controller.OnProgressBarAdd += Controller_ProgressBarAdded;
Controller.OnProgressBarStateChange += Controller_ProgressBarStateChanged;
Controller.OnErrorShow += Controller_ErrorShown;
Controller.OnLaunch += (s, e) => Environment.Exit(0);
Bootstrapper = new Bootstrapper(payload);
Bootstrapper.OnHeadingChange += Bootstrapper_HeadingChanged;
Bootstrapper.OnProgressBarAdd += Bootstrapper_ProgressBarAdded;
Bootstrapper.OnProgressBarStateChange += Bootstrapper_ProgressBarStateChanged;
Bootstrapper.OnError += Bootstrapper_Errored;
CloseButton = TaskDialogButton.Close;
Page = new TaskDialogPage()
@ -34,59 +33,51 @@ namespace Kiseki.Launcher.Windows
Page.Created += (s, e) =>
{
Controller.Start();
};
Page.Destroyed += (s, e) =>
{
Controller.Dispose();
Environment.Exit(0);
Bootstrapper.Run();
};
ShowProgressDialog();
ShowTaskDialog();
}
private void CloseButton_Click(object? sender, EventArgs e)
{
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()
private void ShowTaskDialog()
{
TaskDialogIcon logo = new(Resources.IconKiseki);
Page.Icon = logo;
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];
}
}
}

View File

@ -7,11 +7,12 @@ namespace Kiseki.Launcher.Windows
[STAThread]
static void Main(string[] args)
{
// Initialize directories
string parentFolder = Path.GetDirectoryName(Application.ExecutablePath)!;
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);
}
else
@ -23,40 +24,49 @@ namespace Kiseki.Launcher.Windows
bool isConnected = Web.Initialize();
if (!isConnected && Web.IsInMaintenance)
{
// Try again with the maintenance domain
Bootstrapper.TryLoadLicense();
// Try licensing this launcher and attempt to connect again
Bootstrapper.License();
isConnected = Web.Initialize();
}
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);
return;
}
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();
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
Process.Start($"open {Web.Url("/games")}");
return;
}
FileName = Web.Url("/games"),
UseShellExecute = true
});
if (args[0] == "-uninstall")
{
Bootstrapper.Uninstall(args[0] == "-quiet");
return;
}
ApplicationConfiguration.Initialize();
Application.Run(new MainWindow(args[0]));
return;
}
if (args[0] == "-uninstall")
{
Bootstrapper.Uninstall(args[0] == "-quiet");
return;
}
ApplicationConfiguration.Initialize();
Application.Run(new MainWindow(args[0]));
}
}
}

View File

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

View File

@ -0,0 +1,8 @@
namespace Kiseki.Launcher.Enums
{
public enum PackageType
{
Bootstrapper,
Client,
}
}

View File

@ -0,0 +1,8 @@
namespace Kiseki.Launcher.Enums
{
public enum ProgressBarState
{
Normal,
Marquee
}
}

View File

@ -2,9 +2,27 @@ namespace Kiseki.Launcher
{
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 Uninstall(bool quiet = false);
// Registering the launcher onto the system (as well as creating shortcuts)
static abstract void Register();
static abstract void Unregister();
// Licensing the launcher
static abstract void License();
static abstract void Unlicense();
}
}

View File

@ -1,5 +1,6 @@
namespace Kiseki.Launcher
{
// This is responsible for handling registration of the Kiseki protcool handler
public interface IProtocol
{
static abstract void Register();