diff --git a/.github/workflows/dotnet-desktop.yml b/.github/workflows/dotnet-desktop.yml index a319cc6..7915ec6 100644 --- a/.github/workflows/dotnet-desktop.yml +++ b/.github/workflows/dotnet-desktop.yml @@ -71,7 +71,7 @@ jobs: uses: mathieudutour/github-tag-action@v6.0 with: github_token: ${{ secrets.TOKEN }} - default_bump: minor + default_bump: patch # Install the .NET Core workload - name: Install .NET Core diff --git a/LittleWarGameClient/AddOns.js b/LittleWarGameClient/AddOns.js index 35f51f6..6c610c8 100644 --- a/LittleWarGameClient/AddOns.js +++ b/LittleWarGameClient/AddOns.js @@ -127,6 +127,7 @@ addons.init = { function(mouseLock, clientVersion) { this.addExitButton(); + this.changeQuitButtonText(); this.addClientVersion(clientVersion); this.replaceMouseLockCheckbox(mouseLock); var fullScreenButton = document.getElementById("optionsFullscreenButton"); @@ -135,6 +136,7 @@ addons.init = { }; this.addClientMadeBy(); console.log("Addons loaded"); + this.jsInitComplete(); }, addClientMadeBy: function () { @@ -190,5 +192,20 @@ addons.init = { addons.pressMouseLockCheckbox(this); }; } + }, + + changeQuitButtonText: function () { + document.getElementById("optionsQuitButton").innerText = "Surrender"; + addons.addCustomHotkeyToInnerText("optionsQuitButton", "N"); + }, + + jsInitComplete: function () { + window.chrome.webview.postMessage( + JSON.stringify({ + Id: "", + Value: "", + Type: "InitComplete" + }) + ); } }; \ No newline at end of file diff --git a/LittleWarGameClient/AudioManager.cs b/LittleWarGameClient/AudioManager.cs new file mode 100644 index 0000000..66a9fbc --- /dev/null +++ b/LittleWarGameClient/AudioManager.cs @@ -0,0 +1,155 @@ +using NAudio.CoreAudioApi; +using NAudio.CoreAudioApi.Interfaces; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Management; +using System.Text; +using System.Threading.Tasks; + +namespace LittleWarGameClient +{ + internal class AudioManager : IAudioSessionEventsHandler + { + private MMDevice? mainDevice; + private AudioSessionControl? currentSession; + private readonly Form form; + + public AudioManager(Form form) + { + this.form = form; + var etor = new MMDeviceEnumerator(); + this.mainDevice = etor.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia); + if (mainDevice != null) + { + var sessions = mainDevice.AudioSessionManager.Sessions; + for (int i = 0; i < sessions.Count; i++) + { + var session = sessions[i]; + ChangeTextAndIcon(session); + } + mainDevice.AudioSessionManager.OnSessionCreated += AudioSessionManager_OnSessionCreated; + } + } + internal void DestroySession() + { + var sess = this.currentSession; + this.currentSession = null; + this.UnregisterFromSession(sess); + if (mainDevice != null) + { + mainDevice.AudioSessionManager.OnSessionCreated -= this.AudioSessionManager_OnSessionCreated; + mainDevice.Dispose(); + } + } + + private void UnregisterFromSession(AudioSessionControl? session) + { + if (session != null) + { + session.UnRegisterEventClient(this); + session.Dispose(); + } + } + + private void ChangeTextAndIcon(AudioSessionControl session) + { + if (session.IsSystemSoundsSession) + return; + + var proc = Process.GetProcessById((int)session.GetProcessID); + if (proc == null) + return; + + var currentProc = Process.GetCurrentProcess(); + Process? parentProc = proc; + bool isSubProc = false; + while (parentProc != null && parentProc.Id != 0) + { + parentProc = GetParentProcess(parentProc); + if (parentProc != null && parentProc.Id == currentProc.Id) + { + isSubProc = true; + break; + } + } + if (!isSubProc) + return; + + session.DisplayName = form.Text; + session.IconPath = GetType().Assembly.Location; + this.currentSession = session; + this.currentSession.RegisterEventClient(this); + } + + private void AudioSessionManager_OnSessionCreated(object sender, IAudioSessionControl newSession) + { + AudioSessionControl managedControl = new AudioSessionControl(newSession); + ChangeTextAndIcon(managedControl); + } + + private Process? GetParentProcess(Process process) + { + try + { + using (var query = new ManagementObjectSearcher( + "SELECT * " + + "FROM Win32_Process " + + "WHERE ProcessId=" + process.Id)) + { + using (var collection = query.Get()) + { + var mo = collection.OfType().FirstOrDefault(); + if (mo != null) + { + using (mo) + { + var p = Process.GetProcessById((int)(uint)mo["ParentProcessId"]); + return p; + } + } + + } + return null; + } + } + catch + { + return null; + } + } + + void IAudioSessionEventsHandler.OnVolumeChanged(float volume, bool isMuted) { } + void IAudioSessionEventsHandler.OnDisplayNameChanged(string displayName) { } + void IAudioSessionEventsHandler.OnChannelVolumeChanged(uint channelCount, nint newVolumes, uint channelIndex) { } + void IAudioSessionEventsHandler.OnGroupingParamChanged(ref Guid groupingId) { } + void IAudioSessionEventsHandler.OnIconPathChanged(string iconPath) { } + + void IAudioSessionEventsHandler.OnStateChanged(AudioSessionState state) + { + if (state == AudioSessionState.AudioSessionStateExpired) + { + this.ReleaseSessionDelayed(this.currentSession); + } + } + + void IAudioSessionEventsHandler.OnSessionDisconnected(AudioSessionDisconnectReason disconnectReason) + { + this.ReleaseSessionDelayed(this.currentSession); + } + + private void ReleaseSessionDelayed(AudioSessionControl? session) + { + var timer = new System.Windows.Forms.Timer(); + void TimerTick(object? sender, EventArgs e) + { + timer.Stop(); + timer.Tick -= TimerTick; + UnregisterFromSession(session); + }; + timer.Interval = 100; + timer.Tick += TimerTick; + } + } +} diff --git a/LittleWarGameClient/Form1.Designer.cs b/LittleWarGameClient/Form1.Designer.cs index 21092e1..2d74696 100644 --- a/LittleWarGameClient/Form1.Designer.cs +++ b/LittleWarGameClient/Form1.Designer.cs @@ -28,11 +28,14 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { + components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); webView = new Microsoft.Web.WebView2.WinForms.WebView2(); loaderImage = new PictureBox(); loadingPanel = new Panel(); + loadingText = new TextBox(); mainImage = new PictureBox(); + loadingTimer = new System.Windows.Forms.Timer(components); ((System.ComponentModel.ISupportInitialize)webView).BeginInit(); ((System.ComponentModel.ISupportInitialize)loaderImage).BeginInit(); loadingPanel.SuspendLayout(); @@ -56,18 +59,21 @@ private void InitializeComponent() // // loaderImage // - loaderImage.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; + loaderImage.Anchor = AnchorStyles.None; loaderImage.ErrorImage = null; - loaderImage.Image = Properties.Resources.loader; - loaderImage.Location = new Point(1164, 581); + loaderImage.Image = Properties.Resources.wolfRunning; + loaderImage.InitialImage = null; + loaderImage.Location = new Point(390, 560); + loaderImage.MaximumSize = new Size(480, 100); loaderImage.Name = "loaderImage"; - loaderImage.Size = new Size(100, 100); + loaderImage.Size = new Size(480, 100); loaderImage.SizeMode = PictureBoxSizeMode.StretchImage; loaderImage.TabIndex = 1; loaderImage.TabStop = false; // // loadingPanel // + loadingPanel.Controls.Add(loadingText); loadingPanel.Controls.Add(mainImage); loadingPanel.Controls.Add(loaderImage); loadingPanel.Dock = DockStyle.Fill; @@ -77,18 +83,40 @@ private void InitializeComponent() loadingPanel.TabIndex = 2; loadingPanel.Visible = false; // + // loadingText + // + loadingText.Anchor = AnchorStyles.None; + loadingText.BackColor = Color.Black; + loadingText.BorderStyle = BorderStyle.None; + loadingText.Font = new Font("LCD Solid", 48F, FontStyle.Regular, GraphicsUnit.Point); + loadingText.ForeColor = Color.White; + loadingText.Location = new Point(432, 474); + loadingText.Name = "loadingText"; + loadingText.Size = new Size(400, 64); + loadingText.TabIndex = 3; + loadingText.Text = "Loading"; + loadingText.TextAlign = HorizontalAlignment.Center; + // // mainImage // - mainImage.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; + mainImage.Anchor = AnchorStyles.None; mainImage.ErrorImage = null; mainImage.Image = Properties.Resources.soldier; - mainImage.Location = new Point(432, 140); + mainImage.InitialImage = null; + mainImage.Location = new Point(432, 52); + mainImage.MaximumSize = new Size(400, 400); mainImage.Name = "mainImage"; mainImage.Size = new Size(400, 400); mainImage.SizeMode = PictureBoxSizeMode.StretchImage; mainImage.TabIndex = 2; mainImage.TabStop = false; // + // loadingTimer + // + loadingTimer.Enabled = true; + loadingTimer.Interval = 1000; + loadingTimer.Tick += loadingTimer_Tick; + // // Form1 // AutoScaleDimensions = new SizeF(7F, 15F); @@ -102,11 +130,13 @@ private void InitializeComponent() Name = "Form1"; Text = "Littlewargame"; Activated += Form1_Activated; + FormClosing += Form1_FormClosing; ResizeEnd += Form1_ResizeEnd; Resize += Form1_Resize; ((System.ComponentModel.ISupportInitialize)webView).EndInit(); ((System.ComponentModel.ISupportInitialize)loaderImage).EndInit(); loadingPanel.ResumeLayout(false); + loadingPanel.PerformLayout(); ((System.ComponentModel.ISupportInitialize)mainImage).EndInit(); ResumeLayout(false); } @@ -117,5 +147,7 @@ private void InitializeComponent() private PictureBox loaderImage; private Panel loadingPanel; private PictureBox mainImage; + private TextBox loadingText; + private System.Windows.Forms.Timer loadingTimer; } } diff --git a/LittleWarGameClient/Form1.cs b/LittleWarGameClient/Form1.cs index 7eb6f07..43ac05f 100644 --- a/LittleWarGameClient/Form1.cs +++ b/LittleWarGameClient/Form1.cs @@ -7,6 +7,9 @@ using System.IO; using System.Reflection.Metadata; using System.Reflection; +using System.Data; +using System.Diagnostics; +using NAudio.CoreAudioApi; namespace LittleWarGameClient { @@ -16,13 +19,17 @@ internal partial class Form1 : Form private readonly Fullscreen fullScreen; private readonly KeyboardHandler kbHandler; private readonly VersionHandler vHandler; + private readonly AudioManager audioMngr; + private bool wasSmallWindow = false; private bool gameHasLoaded = false; private bool mouseLocked; + public Form1() { InitializeComponent(); InitWebView(); + audioMngr = new AudioManager(this); settings = new Settings(); this.Size = settings.GetWindowSize(); fullScreen = new Fullscreen(this, settings); @@ -53,7 +60,6 @@ private void webView_NavigationCompleted(object sender, Microsoft.Web.WebView2.C kbHandler.InitHotkeyNames(settings); gameHasLoaded = true; ResizeGameWindows(); - this.Controls.Remove(loadingPanel); } private void webView_WebMessageReceived(object sender, Microsoft.Web.WebView2.Core.CoreWebView2WebMessageReceivedEventArgs e) @@ -78,7 +84,9 @@ private void webView_WebMessageReceived(object sender, Microsoft.Web.WebView2.Co settings.SaveAsync(); CaptureCursor(); break; - default: + case ButtonType.InitComplete: + this.Controls.Remove(loadingPanel); + loadingTimer.Enabled = false; break; } } @@ -135,5 +143,18 @@ private void ResizeGameWindows() } } } + + private void Form1_FormClosing(object sender, FormClosingEventArgs e) + { + audioMngr.DestroySession(); + } + + private void loadingTimer_Tick(object sender, EventArgs e) + { + if (loadingText.Visible) + loadingText.Visible = false; + else + loadingText.Visible = true; + } } } diff --git a/LittleWarGameClient/Form1.resx b/LittleWarGameClient/Form1.resx index 47486a4..4d514b2 100644 --- a/LittleWarGameClient/Form1.resx +++ b/LittleWarGameClient/Form1.resx @@ -117,6 +117,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 17, 17 + diff --git a/LittleWarGameClient/LittleWarGameClient.csproj b/LittleWarGameClient/LittleWarGameClient.csproj index 555e8b3..4691c93 100644 --- a/LittleWarGameClient/LittleWarGameClient.csproj +++ b/LittleWarGameClient/LittleWarGameClient.csproj @@ -23,23 +23,21 @@ - PreserveNewest - - Never - + + diff --git a/LittleWarGameClient/Properties/Resources.Designer.cs b/LittleWarGameClient/Properties/Resources.Designer.cs index 2082d3b..92f048d 100644 --- a/LittleWarGameClient/Properties/Resources.Designer.cs +++ b/LittleWarGameClient/Properties/Resources.Designer.cs @@ -63,9 +63,9 @@ internal Resources() { /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap loader { + internal static System.Drawing.Bitmap soldier { get { - object obj = ResourceManager.GetObject("loader", resourceCulture); + object obj = ResourceManager.GetObject("soldier", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } @@ -73,9 +73,9 @@ internal static System.Drawing.Bitmap loader { /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap soldier { + internal static System.Drawing.Bitmap wolfRunning { get { - object obj = ResourceManager.GetObject("soldier", resourceCulture); + object obj = ResourceManager.GetObject("wolfRunning", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } diff --git a/LittleWarGameClient/Properties/Resources.resx b/LittleWarGameClient/Properties/Resources.resx index 5de5fec..519d0f2 100644 --- a/LittleWarGameClient/Properties/Resources.resx +++ b/LittleWarGameClient/Properties/Resources.resx @@ -118,10 +118,10 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - ..\loader.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\soldier.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\wolfRunning.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/LittleWarGameClient/WebMessage.cs b/LittleWarGameClient/WebMessage.cs index 25d1bb3..f1ba381 100644 --- a/LittleWarGameClient/WebMessage.cs +++ b/LittleWarGameClient/WebMessage.cs @@ -26,6 +26,8 @@ internal enum ButtonType [EnumMember(Value = "Exit")] Exit, [EnumMember(Value = "MouseLock")] - MouseLock + MouseLock, + [EnumMember(Value = "InitComplete")] + InitComplete } } diff --git a/LittleWarGameClient/font/LcdSolid-VPzB.ttf b/LittleWarGameClient/font/LcdSolid-VPzB.ttf new file mode 100644 index 0000000..808f3ee Binary files /dev/null and b/LittleWarGameClient/font/LcdSolid-VPzB.ttf differ diff --git a/LittleWarGameClient/font/info.txt b/LittleWarGameClient/font/info.txt new file mode 100644 index 0000000..a5acbe8 --- /dev/null +++ b/LittleWarGameClient/font/info.txt @@ -0,0 +1,2 @@ +license: Public Domain +link: https://www.fontspace.com/lcd-solid-font-f11346 \ No newline at end of file diff --git a/LittleWarGameClient/loader.gif b/LittleWarGameClient/loader.gif deleted file mode 100644 index c84af09..0000000 Binary files a/LittleWarGameClient/loader.gif and /dev/null differ diff --git a/LittleWarGameClient/wolfRunning.gif b/LittleWarGameClient/wolfRunning.gif new file mode 100644 index 0000000..b9e5377 Binary files /dev/null and b/LittleWarGameClient/wolfRunning.gif differ