From a46aa520c19ceaf4f9d1b4de55371947830ef96d Mon Sep 17 00:00:00 2001 From: Dan Oak <464887+DanDecrypted@users.noreply.github.com> Date: Sat, 6 Apr 2024 21:20:27 +0100 Subject: [PATCH] Feature/skip patch button (#4) * Allow skipping of patch * performance improvements * bump version --- readme.md | 2 +- .../EndlessOnlinePatcher.Desktop.csproj | 8 +- .../Main.Designer.cs | 23 +++++- src/EndlessOnlinePatcher.Desktop/Main.cs | 60 +++++++++++---- .../Properties/Resources.Designer.cs | 20 +++++ .../Properties/Resources.resx | 6 ++ .../Resources/eo-blank.png | Bin 0 -> 6615 bytes .../Resources/eo-blank.xcf | Bin 0 -> 18589 bytes .../Resources/skip-hover.png | Bin 0 -> 9104 bytes .../Resources/skip.bmp | Bin 0 -> 3382 bytes .../Resources/skip.png | Bin 0 -> 8199 bytes src/EndlessOnlinePatcher/Core/IPatcher.cs | 1 - src/EndlessOnlinePatcher/Core/Patcher.cs | 72 ++++++++++++------ src/EndlessOnlinePatcher/Core/Windows.cs | 3 +- .../EndlessOnlinePatcher.csproj | 2 +- 15 files changed, 148 insertions(+), 49 deletions(-) create mode 100644 src/EndlessOnlinePatcher.Desktop/Resources/eo-blank.png create mode 100644 src/EndlessOnlinePatcher.Desktop/Resources/eo-blank.xcf create mode 100644 src/EndlessOnlinePatcher.Desktop/Resources/skip-hover.png create mode 100644 src/EndlessOnlinePatcher.Desktop/Resources/skip.bmp create mode 100644 src/EndlessOnlinePatcher.Desktop/Resources/skip.png diff --git a/readme.md b/readme.md index da75bcf..96f1119 100644 --- a/readme.md +++ b/readme.md @@ -21,6 +21,7 @@ If your local version is older than the most recent version according to the cli * Ability to launch the game directly from the patcher * UI fits the theme of the game * Ignores the downloaded config so it doesn't overwrite the config you have locally +* Installs the game if not already installed ![New Version Available](./docs/img/new_version.png) @@ -31,6 +32,5 @@ If your local version is older than the most recent version according to the cli * Optional: Save this in some sort of config so it wouldn't need to be reset on every load * Checkbox for auto-launching the application after patch or if patching is not necessary * Optional: Save this in some sort of config so it wouldn't need to be reset on every load -* Install the game if it is not already there * Embed News? * Tests??? diff --git a/src/EndlessOnlinePatcher.Desktop/EndlessOnlinePatcher.Desktop.csproj b/src/EndlessOnlinePatcher.Desktop/EndlessOnlinePatcher.Desktop.csproj index 10f47d7..e527cc0 100644 --- a/src/EndlessOnlinePatcher.Desktop/EndlessOnlinePatcher.Desktop.csproj +++ b/src/EndlessOnlinePatcher.Desktop/EndlessOnlinePatcher.Desktop.csproj @@ -2,7 +2,7 @@ WinExe - net7.0-windows + net8.0-windows8.0 enable true enable @@ -12,8 +12,10 @@ OakTech Endless Online Patcher eo-patcher-icon.png - 0.0.0.4 - 0.0.0.4 + 0.0.0.5 + 0.0.0.5 + eopatcher + EndlessOnlinePatcher.Desktop.Program diff --git a/src/EndlessOnlinePatcher.Desktop/Main.Designer.cs b/src/EndlessOnlinePatcher.Desktop/Main.Designer.cs index 7e32278..487e285 100644 --- a/src/EndlessOnlinePatcher.Desktop/Main.Designer.cs +++ b/src/EndlessOnlinePatcher.Desktop/Main.Designer.cs @@ -35,10 +35,12 @@ private void InitializeComponent() pbxPatch = new PictureBox(); pbxLaunch = new PictureBox(); pbxExit = new PictureBox(); + pbxSkip = new PictureBox(); ((System.ComponentModel.ISupportInitialize)pbxLogout).BeginInit(); ((System.ComponentModel.ISupportInitialize)pbxPatch).BeginInit(); ((System.ComponentModel.ISupportInitialize)pbxLaunch).BeginInit(); ((System.ComponentModel.ISupportInitialize)pbxExit).BeginInit(); + ((System.ComponentModel.ISupportInitialize)pbxSkip).BeginInit(); SuspendLayout(); // // label1 @@ -118,7 +120,7 @@ private void InitializeComponent() // pbxExit.BackColor = Color.Transparent; pbxExit.Image = Properties.Resources.eo_exit; - pbxExit.Location = new Point(94, 86); + pbxExit.Location = new Point(90, 86); pbxExit.Name = "pbxExit"; pbxExit.Size = new Size(91, 30); pbxExit.TabIndex = 6; @@ -130,6 +132,22 @@ private void InitializeComponent() pbxExit.MouseLeave += pbxExit_MouseLeave; pbxExit.MouseUp += pbxExit_MouseUp; // + // pbxSkip + // + pbxSkip.BackColor = Color.Transparent; + pbxSkip.Image = Properties.Resources.skip; + pbxSkip.Location = new Point(187, 53); + pbxSkip.Name = "pbxSkip"; + pbxSkip.Size = new Size(91, 30); + pbxSkip.TabIndex = 7; + pbxSkip.TabStop = false; + pbxSkip.Visible = false; + pbxSkip.Click += pbxLaunch_Click; + pbxSkip.MouseDown += pbxSkip_MouseDown; + pbxSkip.MouseEnter += pbxSkip_MouseEnter; + pbxSkip.MouseLeave += pbxSkip_MouseLeave; + pbxSkip.MouseUp += pbxSkip_MouseUp; + // // Main // AutoScaleDimensions = new SizeF(7F, 15F); @@ -137,6 +155,7 @@ private void InitializeComponent() BackgroundImage = Properties.Resources.eo_popup; BackgroundImageLayout = ImageLayout.Center; ClientSize = new Size(290, 125); + Controls.Add(pbxSkip); Controls.Add(pbxExit); Controls.Add(pbxLaunch); Controls.Add(pbxPatch); @@ -159,6 +178,7 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)pbxPatch).EndInit(); ((System.ComponentModel.ISupportInitialize)pbxLaunch).EndInit(); ((System.ComponentModel.ISupportInitialize)pbxExit).EndInit(); + ((System.ComponentModel.ISupportInitialize)pbxSkip).EndInit(); ResumeLayout(false); PerformLayout(); } @@ -170,4 +190,5 @@ private void InitializeComponent() private PictureBox pbxPatch; private PictureBox pbxLaunch; private PictureBox pbxExit; + private PictureBox pbxSkip; } diff --git a/src/EndlessOnlinePatcher.Desktop/Main.cs b/src/EndlessOnlinePatcher.Desktop/Main.cs index 64e4189..2f559cd 100644 --- a/src/EndlessOnlinePatcher.Desktop/Main.cs +++ b/src/EndlessOnlinePatcher.Desktop/Main.cs @@ -33,8 +33,9 @@ private async void Main_Shown(object sender, EventArgs e) } else { - lblMessage.Text = $"A new version of the client is available (v{_localVersion} -> v{_remoteVersion})"; + lblMessage.Text = $"A new version of the client is available{Environment.NewLine}(v{_localVersion} -> v{_remoteVersion})"; pbxPatch.Visible = true; + pbxSkip.Visible = true; } pbxExit.Visible = true; } @@ -100,7 +101,7 @@ private void pbxLaunch_MouseLeave(object sender, EventArgs e) private async void pbxLaunch_Click(object sender, EventArgs e) { - await Windows.StartEO(); + await Core.Windows.StartEO(); Close(); } @@ -119,27 +120,42 @@ private void pbxExit_MouseLeave(object sender, EventArgs e) pbxExit.Image = Resources.eo_exit; } + private void pbxSkip_MouseEnter(object sender, EventArgs e) + { + pbxSkip.Image = Resources.skip_hover; + } + + private void pbxSkip_MouseLeave(object sender, EventArgs e) + { + pbxSkip.Image = Resources.skip; + } + + delegate void SetPatchTextCallback(string text); + private void SetPatchText(string text) + { + if (lblMessage.InvokeRequired) + { + + SetPatchTextCallback d = new SetPatchTextCallback(SetPatchText); + Invoke(d, new object[] { text }); + return; + } + + lblMessage.Text = text; + } + private async void pbxPatch_MouseClick(object sender, MouseEventArgs e) { if (_patching) return; _patching = true; + pbxSkip.Visible = false; pbxPatch.Image = Resources.eo_patching; - var status = () => "Downloading Latest Patch"; - using var patcher = new Patcher(new Progress(x => - { - if (x >= 99 && status().Contains("Extracting")) - { - // weird multithreading bug because of this I think - lblMessage.Text = "Patch applied! You are now on the latest version and can launch the game"; - return; - } - - lblMessage.Text = $"{status()}... {x}%."; - }), _downloadLink); + + using var patcher = new Patcher(_downloadLink, SetPatchText); + await patcher.Patch(_remoteVersion!); - status = () => "Extracting and Applying Latest Patch"; - patcher.ApplyPatch(_remoteVersion!); + _patching = false; pbxPatch.Visible = false; pbxLaunch.Visible = true; @@ -158,11 +174,13 @@ private void pbxExit_MouseDown(object sender, MouseEventArgs e) private void pbxPatch_MouseDown(object sender, MouseEventArgs e) { + if (_patching) return; _sndClickDown.Play(); } private void pbxPatch_MouseUp(object sender, MouseEventArgs e) { + if (_patching) return; _sndClickUp.Play(); } @@ -185,4 +203,14 @@ private void pbxLogout_MouseUp(object sender, MouseEventArgs e) { _sndClickUp.Play(); } + + private void pbxSkip_MouseDown(object sender, MouseEventArgs e) + { + _sndClickDown.Play(); + } + + private void pbxSkip_MouseUp(object sender, MouseEventArgs e) + { + _sndClickUp.Play(); + } } diff --git a/src/EndlessOnlinePatcher.Desktop/Properties/Resources.Designer.cs b/src/EndlessOnlinePatcher.Desktop/Properties/Resources.Designer.cs index 61399ce..7cce6ca 100644 --- a/src/EndlessOnlinePatcher.Desktop/Properties/Resources.Designer.cs +++ b/src/EndlessOnlinePatcher.Desktop/Properties/Resources.Designer.cs @@ -198,6 +198,26 @@ internal class Resources { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap skip { + get { + object obj = ResourceManager.GetObject("skip", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap skip_hover { + get { + object obj = ResourceManager.GetObject("skip_hover", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/src/EndlessOnlinePatcher.Desktop/Properties/Resources.resx b/src/EndlessOnlinePatcher.Desktop/Properties/Resources.resx index 1447002..8f449b0 100644 --- a/src/EndlessOnlinePatcher.Desktop/Properties/Resources.resx +++ b/src/EndlessOnlinePatcher.Desktop/Properties/Resources.resx @@ -160,6 +160,12 @@ ..\Resources\eo-popup.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\skip.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\skip-hover.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\text-window.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/src/EndlessOnlinePatcher.Desktop/Resources/eo-blank.png b/src/EndlessOnlinePatcher.Desktop/Resources/eo-blank.png new file mode 100644 index 0000000000000000000000000000000000000000..e155e0e7648d22b63de6834dc98f5ad44c46707c GIT binary patch literal 6615 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 S))ysze56lL>HohU>HlxSe%xLF literal 0 HcmV?d00001 diff --git a/src/EndlessOnlinePatcher.Desktop/Resources/skip-hover.png b/src/EndlessOnlinePatcher.Desktop/Resources/skip-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..30e91d209e88405e299557d30dd89ca1299ef79a GIT binary patch literal 9104 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 NYG`FpuIF*({{R&%R+9h# literal 0 HcmV?d00001 diff --git a/src/EndlessOnlinePatcher.Desktop/Resources/skip.bmp b/src/EndlessOnlinePatcher.Desktop/Resources/skip.bmp new file mode 100644 index 0000000000000000000000000000000000000000..55516c7aaa3591604865d4cd18379f8f650c3104 GIT binary patch literal 3382 zcmeIwA#&YN425B3CLjUbgJ57$uqM1+gO+lZkut%6E<(#F6wORPc)-i=r?4!c_Vwp; zZ3Fx2>gm_x54#?Zw`LE_etx;JyM1xL@%<_@PLnpcGPUluKQDjn-|L&12NJySLSxLr z;9wF7q0kt!G&lm>q)=$g*LR%^B!og^%$Qm^0tune7=F^=2qc6;W6U^h9D#&TXpDvN zo8~x1LMSw5m*!3e5<;OdyXkPr%u*^;D_frLmI06Zw(3st}a59h(3XRzqWFR3F8nf*xCj$wg(3oxIax#z*3XRz|Zzlr@q3r$RV$Z*g8j2NO iuBTlt#|(_)(Q$tsX9dm*oE11La8}@~z*&L+tOB3FDm>c& literal 0 HcmV?d00001 diff --git a/src/EndlessOnlinePatcher.Desktop/Resources/skip.png b/src/EndlessOnlinePatcher.Desktop/Resources/skip.png new file mode 100644 index 0000000000000000000000000000000000000000..cbfc003a58e458ba54d6e68c95ced14c9bbf3b15 GIT binary patch literal 8199 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 jcMh8;i-7C!4)=O>_>SrIWHPWT2kB~_)hJfGc _progress { get; } private string _link { get; } - public Patcher(IProgress progress, string downloadLink) + private Action _setPatchTextCallback; + + public Patcher(string downloadLink, Action setPatchTextCallback) { - _progress = progress; _link = downloadLink; + _setPatchTextCallback = setPatchTextCallback; } public async Task Patch(FileVersion version) { Clean(); - using var httpClient = new HttpClient(); - using var fileStream = new FileStream("patch.zip", FileMode.Create, FileAccess.Write); - await httpClient.DownloadAsync(_link, fileStream, _progress); - fileStream.Close(); + await DownloadPatch(); + await ApplyPatch(version); } - private string GetDirectoryFrom(string filePath) + private async Task DownloadPatch() { - var regex = new Regex("(.*)\\\\"); - return regex.Match(filePath).Value; + var progress = new Progress(x => _setPatchTextCallback($"Downloading... {x}%")); + using var httpClient = new HttpClient(); + using var fileStream = new FileStream("patch.zip", FileMode.Create, FileAccess.Write); + await httpClient.DownloadAsync(_link, fileStream, progress); + fileStream.Close(); } - public void ApplyPatch(FileVersion version) + private async Task ApplyPatch(FileVersion version) { + var localDirectory = EndlessOnlineDirectory.Get().FullName; var patchFolder = $"patch-{version}/"; + ZipFile.ExtractToDirectory("patch.zip", patchFolder); - var allExceptConfig = Directory.EnumerateFiles(patchFolder, "*", SearchOption.AllDirectories) + var patchFiles = Directory.EnumerateFiles(patchFolder, "*", SearchOption.AllDirectories) .Select(x => x.Remove(0, patchFolder.Length)) - .Where(x => !x.StartsWith("config")); + .ToList(); - var i = 0; - var localDirectory = EndlessOnlineDirectory.Get().FullName; - foreach (var file in allExceptConfig) - { - var relativeDirectory = $"{localDirectory}/{GetDirectoryFrom(file)}"; - if (!Directory.Exists(relativeDirectory)) - Directory.CreateDirectory(relativeDirectory); + var completed = 0; - File.Copy($"{patchFolder}/{file}", $"{localDirectory}/{file}", true); - i++; - _progress.Report(i / allExceptConfig.Count() * 100); - } + var extractTasks = patchFiles + .Select(file => Task.Run(() => + { + var relativeDirectory = $"{localDirectory}/{GetDirectoryFrom(file)}"; + if (!Directory.Exists(relativeDirectory)) + Directory.CreateDirectory(relativeDirectory); + + File.Copy($"{patchFolder}/{file}", $"{localDirectory}/{file}", true); + + completed++; + + var percent = 100f * completed / patchFiles.Count; +#if DEBUG + Debug.WriteLine($"Copying {file} to {localDirectory}/{file} {completed}/{patchFiles.Count} {percent}%"); +#endif + _setPatchTextCallback($"Extracting... {(int)percent}%"); + })); + + await Task.WhenAll(extractTasks); + + _setPatchTextCallback($"Patch applied! You are now on the latest version v{version}. Enjoy!"); + } + + private static string GetDirectoryFrom(string filePath) + { + var regex = new Regex("(.*)\\\\"); + return regex.Match(filePath).Value; } private static void Clean() diff --git a/src/EndlessOnlinePatcher/Core/Windows.cs b/src/EndlessOnlinePatcher/Core/Windows.cs index 62264dd..3e4dd57 100644 --- a/src/EndlessOnlinePatcher/Core/Windows.cs +++ b/src/EndlessOnlinePatcher/Core/Windows.cs @@ -1,5 +1,4 @@ -using System.Diagnostics; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; namespace EndlessOnlinePatcher.Core; diff --git a/src/EndlessOnlinePatcher/EndlessOnlinePatcher.csproj b/src/EndlessOnlinePatcher/EndlessOnlinePatcher.csproj index 512e3fa..6030140 100644 --- a/src/EndlessOnlinePatcher/EndlessOnlinePatcher.csproj +++ b/src/EndlessOnlinePatcher/EndlessOnlinePatcher.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 enable enable