From 10c21037623b66ea57b7d4e6e855409110c4e5ba Mon Sep 17 00:00:00 2001 From: rjindael Date: Wed, 2 Aug 2023 01:20:34 -0700 Subject: [PATCH] chore: refactor project, bug fixes --- Kiseki.Launcher.Windows/Bootstrapper.cs | 86 ++++++++++++++- Kiseki.Launcher.Windows/Directories.cs | 3 +- Kiseki.Launcher.Windows/MainWindow.cs | 93 ++++++++-------- Kiseki.Launcher.Windows/Program.cs | 46 ++++---- Kiseki.Launcher/Controller.cs | 112 -------------------- Kiseki.Launcher/Enums/PackageType.cs | 8 ++ Kiseki.Launcher/Enums/ProgressBarState.cs | 8 ++ Kiseki.Launcher/Interfaces/IBootstrapper.cs | 18 ++++ Kiseki.Launcher/Interfaces/IProtocol.cs | 1 + 9 files changed, 190 insertions(+), 185 deletions(-) delete mode 100644 Kiseki.Launcher/Controller.cs create mode 100644 Kiseki.Launcher/Enums/PackageType.cs create mode 100644 Kiseki.Launcher/Enums/ProgressBarState.cs diff --git a/Kiseki.Launcher.Windows/Bootstrapper.cs b/Kiseki.Launcher.Windows/Bootstrapper.cs index ad90db3..82a9aee 100644 --- a/Kiseki.Launcher.Windows/Bootstrapper.cs +++ b/Kiseki.Launcher.Windows/Bootstrapper.cs @@ -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 Arguments = new(); + + public event EventHandler? OnHeadingChange; + public event EventHandler? OnProgressBarAdd; + public event EventHandler? OnProgressBarStateChange; + public event EventHandler? 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; diff --git a/Kiseki.Launcher.Windows/Directories.cs b/Kiseki.Launcher.Windows/Directories.cs index f3131fc..8dd85b8 100644 --- a/Kiseki.Launcher.Windows/Directories.cs +++ b/Kiseki.Launcher.Windows/Directories.cs @@ -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"); diff --git a/Kiseki.Launcher.Windows/MainWindow.cs b/Kiseki.Launcher.Windows/MainWindow.cs index 36f6925..b3029e2 100644 --- a/Kiseki.Launcher.Windows/MainWindow.cs +++ b/Kiseki.Launcher.Windows/MainWindow.cs @@ -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]; + } } } \ No newline at end of file diff --git a/Kiseki.Launcher.Windows/Program.cs b/Kiseki.Launcher.Windows/Program.cs index 969ac14..f409df8 100644 --- a/Kiseki.Launcher.Windows/Program.cs +++ b/Kiseki.Launcher.Windows/Program.cs @@ -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])); } } } \ No newline at end of file diff --git a/Kiseki.Launcher/Controller.cs b/Kiseki.Launcher/Controller.cs deleted file mode 100644 index 5c4fcaf..0000000 --- a/Kiseki.Launcher/Controller.cs +++ /dev/null @@ -1,112 +0,0 @@ -using Kiseki.Launcher.Helpers; - -namespace Kiseki.Launcher -{ - public enum ProgressBarState - { - Normal, - Marquee - } - - public class Controller - { - private readonly Dictionary Arguments = new(); - - public event EventHandler? OnPageHeadingChange; - public event EventHandler? OnProgressBarAdd; - public event EventHandler? OnProgressBarStateChange; - public event EventHandler? 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 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); - } - } -} \ No newline at end of file diff --git a/Kiseki.Launcher/Enums/PackageType.cs b/Kiseki.Launcher/Enums/PackageType.cs new file mode 100644 index 0000000..4079bf1 --- /dev/null +++ b/Kiseki.Launcher/Enums/PackageType.cs @@ -0,0 +1,8 @@ +namespace Kiseki.Launcher.Enums +{ + public enum PackageType + { + Bootstrapper, + Client, + } +} \ No newline at end of file diff --git a/Kiseki.Launcher/Enums/ProgressBarState.cs b/Kiseki.Launcher/Enums/ProgressBarState.cs new file mode 100644 index 0000000..79c1f39 --- /dev/null +++ b/Kiseki.Launcher/Enums/ProgressBarState.cs @@ -0,0 +1,8 @@ +namespace Kiseki.Launcher.Enums +{ + public enum ProgressBarState + { + Normal, + Marquee + } +} \ No newline at end of file diff --git a/Kiseki.Launcher/Interfaces/IBootstrapper.cs b/Kiseki.Launcher/Interfaces/IBootstrapper.cs index 4e2e602..a5c1115 100644 --- a/Kiseki.Launcher/Interfaces/IBootstrapper.cs +++ b/Kiseki.Launcher/Interfaces/IBootstrapper.cs @@ -2,9 +2,27 @@ namespace Kiseki.Launcher { public interface IBootstrapper { + // These connect to MainWindow + event EventHandler? OnHeadingChange; + event EventHandler? OnProgressBarAdd; + event EventHandler? OnProgressBarStateChange; + event EventHandler? 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(); } } \ No newline at end of file diff --git a/Kiseki.Launcher/Interfaces/IProtocol.cs b/Kiseki.Launcher/Interfaces/IProtocol.cs index 7ba76d9..f4cb6a2 100644 --- a/Kiseki.Launcher/Interfaces/IProtocol.cs +++ b/Kiseki.Launcher/Interfaces/IProtocol.cs @@ -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();