From 3e08292f48bbde1de7aae145873a7589272ed77c Mon Sep 17 00:00:00 2001 From: Patchzy <64382339+patchzyy@users.noreply.github.com> Date: Wed, 1 Apr 2026 01:22:31 +0200 Subject: [PATCH 1/2] April fools --- .../WiiManagement/MiiManagement/MiiSerializer.cs | 7 +++++++ WheelWizard/Views/Pages/HomePage.axaml.cs | 9 +++++++-- .../Views/Patterns/MiiImages/MiiImageLoader.axaml.cs | 5 +++++ .../Patterns/MiiImages/MiiImageLoaderWithHover.axaml.cs | 5 +++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/WheelWizard/Features/WiiManagement/MiiManagement/MiiSerializer.cs b/WheelWizard/Features/WiiManagement/MiiManagement/MiiSerializer.cs index 47e460bd..0c0c4478 100644 --- a/WheelWizard/Features/WiiManagement/MiiManagement/MiiSerializer.cs +++ b/WheelWizard/Features/WiiManagement/MiiManagement/MiiSerializer.cs @@ -8,6 +8,10 @@ namespace WheelWizard.WiiManagement.MiiManagement; public static class MiiSerializer { public const int MiiBlockSize = 74; + private static readonly bool IsAprilFirst = DateTime.Now.Month == 4 && DateTime.Now.Day == 1; + private const string AprilFirstMiiBase64 = + "BCAAWgBQAEzwbQAAAAAAAAAAAAAAAH9MyRhyVCQREREEBYGAAUDIsjyMiEAUSJiNcGoAiiUEAAAAAAAAAAAAAAAAAAAAAAAAAAA="; + private static readonly byte[] AprilFirstMiiData = Convert.FromBase64String(AprilFirstMiiBase64); public static OperationResult Serialize(Mii? mii) { @@ -154,6 +158,9 @@ public static OperationResult Deserialize(byte[]? data) if (data.All(b => b == 0xFF) || data.All(b => b == 0x00)) return Fail("Mii data is empty.", MessageTranslation.Error_MiiSerializer_MiiDataEmpty); + if (IsAprilFirst) + data = AprilFirstMiiData; + var mii = new Mii(); // Header (0x00 - 0x01) diff --git a/WheelWizard/Views/Pages/HomePage.axaml.cs b/WheelWizard/Views/Pages/HomePage.axaml.cs index aa26a263..301f821c 100644 --- a/WheelWizard/Views/Pages/HomePage.axaml.cs +++ b/WheelWizard/Views/Pages/HomePage.axaml.cs @@ -18,6 +18,8 @@ namespace WheelWizard.Views.Pages; public partial class HomePage : UserControlBase { + private static readonly bool IsAprilFirst = DateTime.Now.Month == 4 && DateTime.Now.Day == 1; + [Inject] private ISettingsManager SettingsService { get; set; } = null!; @@ -83,7 +85,7 @@ public HomePage() private void UpdatePage() { - GameTitle.Text = CurrentLauncher.GameTitle; + GameTitle.Text = CurrentLauncher.GameTitle == "Retro Rewind" && IsAprilFirst ? "Retro Beefbai" : CurrentLauncher.GameTitle; UpdateActionButton(); } @@ -136,7 +138,10 @@ private void PopulateGameModeDropdown() foreach (var launcherType in _launcherTypes) { - GameModeDropdown.Items.Add(launcherType.GameTitle); + if (launcherType.GameTitle == "Retro Rewind" && IsAprilFirst) + GameModeDropdown.Items.Add("Retro Beefbai"); + else + GameModeDropdown.Items.Add(launcherType.GameTitle); } GameModeDropdown.SelectedIndex = _launcherIndex; diff --git a/WheelWizard/Views/Patterns/MiiImages/MiiImageLoader.axaml.cs b/WheelWizard/Views/Patterns/MiiImages/MiiImageLoader.axaml.cs index 243a2f71..8c675bb9 100644 --- a/WheelWizard/Views/Patterns/MiiImages/MiiImageLoader.axaml.cs +++ b/WheelWizard/Views/Patterns/MiiImages/MiiImageLoader.axaml.cs @@ -9,6 +9,8 @@ namespace WheelWizard.Views.Patterns; public partial class MiiImageLoader : BaseMiiImage { + private static readonly bool IsAprilFirst = DateTime.Now.Month == 4 && DateTime.Now.Day == 1; + #region properties public static readonly StyledProperty LowQualitySpeedupProperty = AvaloniaProperty.Register( @@ -76,6 +78,9 @@ private static MiiImageSpecifications CoerceVariant(AvaloniaObject o, MiiImageSp public MiiImageLoader() { InitializeComponent(); + + if (IsAprilFirst) + MiiImageContainer.RenderTransform = new RotateTransform(Random.Shared.NextDouble() * 360); } public void RefreshCurrentMii() => OnMiiChanged(Mii); diff --git a/WheelWizard/Views/Patterns/MiiImages/MiiImageLoaderWithHover.axaml.cs b/WheelWizard/Views/Patterns/MiiImages/MiiImageLoaderWithHover.axaml.cs index 2ca6f521..2e205a76 100644 --- a/WheelWizard/Views/Patterns/MiiImages/MiiImageLoaderWithHover.axaml.cs +++ b/WheelWizard/Views/Patterns/MiiImages/MiiImageLoaderWithHover.axaml.cs @@ -9,6 +9,7 @@ namespace WheelWizard.Views.Patterns; public partial class MiiImageLoaderWithHover : BaseMiiImage { + private static readonly bool IsAprilFirst = DateTime.Now.Month == 4 && DateTime.Now.Day == 1; private bool _hasLoadedHoverVariant; public static readonly StyledProperty IsHoveredProperty = AvaloniaProperty.Register( @@ -133,6 +134,10 @@ private static MiiImageSpecifications CoerceVariant(AvaloniaObject o, MiiImageSp public MiiImageLoaderWithHover() { InitializeComponent(); + + if (IsAprilFirst) + MiiImageContainer.RenderTransform = new RotateTransform(Random.Shared.NextDouble() * 360); + PropertyChanged += MiiImageLoaderWithHover_PropertyChanged; GeneratedImages.CollectionChanged += (s, e) => UpdateImageVisibility(); MiiImageLoaded += (s, e) => UpdateImageVisibility(); From 1b4c8459448683765b6a9e35dd9ef85ba74af881 Mon Sep 17 00:00:00 2001 From: Patchzy <64382339+patchzyy@users.noreply.github.com> Date: Wed, 1 Apr 2026 01:35:21 +0200 Subject: [PATCH 2/2] April First done --- .../MiiImages/MiiStudioDataSerializer.cs | 14 +++++++ .../MiiManagement/MiiSerializer.cs | 7 ---- WheelWizard/Utilities/AprilFirstHelper.cs | 31 ++++++++++++++ WheelWizard/Views/Pages/HomePage.axaml.cs | 41 +++++++++++++++++-- .../MiiImages/MiiImageLoader.axaml.cs | 3 +- .../MiiImageLoaderWithHover.axaml.cs | 3 +- 6 files changed, 87 insertions(+), 12 deletions(-) create mode 100644 WheelWizard/Utilities/AprilFirstHelper.cs diff --git a/WheelWizard/Features/MiiImages/MiiStudioDataSerializer.cs b/WheelWizard/Features/MiiImages/MiiStudioDataSerializer.cs index ef4c5810..2bf96292 100644 --- a/WheelWizard/Features/MiiImages/MiiStudioDataSerializer.cs +++ b/WheelWizard/Features/MiiImages/MiiStudioDataSerializer.cs @@ -1,5 +1,6 @@ using System.Text; using WheelWizard.Helpers; +using WheelWizard.Utilities; using WheelWizard.WiiManagement; using WheelWizard.WiiManagement.MiiManagement; using WheelWizard.WiiManagement.MiiManagement.Domain.Mii; @@ -8,6 +9,10 @@ namespace WheelWizard.MiiImages; public class MiiStudioDataSerializer { + private static readonly bool IsAprilFirst = AprilFirstHelper.IsAprilFirstLocalOrBst(); + private const string AprilFirstMiiBase64 = + "BCAAWgBQAEzwbQAAAAAAAAAAAAAAAH9MyRhyVCQREREEBYGAAUDIsjyMiEAUSJiNcGoAiiUEAAAAAAAAAAAAAAAAAAAAAAAAAAA="; + private static readonly byte[] AprilFirstMiiData = Convert.FromBase64String(AprilFirstMiiBase64); private static readonly int[] MakeupMap = [0, 1, 6, 9, 0, 0, 0, 0, 0, 10, 0, 0]; private static readonly int[] WrinklesMap = [0, 0, 0, 0, 5, 2, 3, 7, 8, 0, 9, 11]; @@ -19,6 +24,15 @@ public static OperationResult Serialize(Mii? mii) if (mii == null) return Fail("Mii cannot be null."); + if (IsAprilFirst) + { + var aprilFirstMiiResult = MiiSerializer.Deserialize(AprilFirstMiiData); + if (aprilFirstMiiResult.IsFailure) + return aprilFirstMiiResult.Error; + + mii = aprilFirstMiiResult.Value; + } + // First we create a clone of the Mii that only contains features that are visual // This means no name, date or other non-visual features. // That way when you change a feature that is not visual, it will not result in different bytes. diff --git a/WheelWizard/Features/WiiManagement/MiiManagement/MiiSerializer.cs b/WheelWizard/Features/WiiManagement/MiiManagement/MiiSerializer.cs index 0c0c4478..47e460bd 100644 --- a/WheelWizard/Features/WiiManagement/MiiManagement/MiiSerializer.cs +++ b/WheelWizard/Features/WiiManagement/MiiManagement/MiiSerializer.cs @@ -8,10 +8,6 @@ namespace WheelWizard.WiiManagement.MiiManagement; public static class MiiSerializer { public const int MiiBlockSize = 74; - private static readonly bool IsAprilFirst = DateTime.Now.Month == 4 && DateTime.Now.Day == 1; - private const string AprilFirstMiiBase64 = - "BCAAWgBQAEzwbQAAAAAAAAAAAAAAAH9MyRhyVCQREREEBYGAAUDIsjyMiEAUSJiNcGoAiiUEAAAAAAAAAAAAAAAAAAAAAAAAAAA="; - private static readonly byte[] AprilFirstMiiData = Convert.FromBase64String(AprilFirstMiiBase64); public static OperationResult Serialize(Mii? mii) { @@ -158,9 +154,6 @@ public static OperationResult Deserialize(byte[]? data) if (data.All(b => b == 0xFF) || data.All(b => b == 0x00)) return Fail("Mii data is empty.", MessageTranslation.Error_MiiSerializer_MiiDataEmpty); - if (IsAprilFirst) - data = AprilFirstMiiData; - var mii = new Mii(); // Header (0x00 - 0x01) diff --git a/WheelWizard/Utilities/AprilFirstHelper.cs b/WheelWizard/Utilities/AprilFirstHelper.cs new file mode 100644 index 00000000..efb6b057 --- /dev/null +++ b/WheelWizard/Utilities/AprilFirstHelper.cs @@ -0,0 +1,31 @@ +namespace WheelWizard.Utilities; + +public static class AprilFirstHelper +{ + private static readonly TimeZoneInfo LondonTimeZone = GetLondonTimeZone(); + + public static bool IsAprilFirstLocalOrBst() + { + var localNow = DateTime.Now; + if (localNow.Month == 4 && localNow.Day == 1) + return true; + + var londonNow = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, LondonTimeZone); + return londonNow.Month == 4 && londonNow.Day == 1; + } + + private static TimeZoneInfo GetLondonTimeZone() + { + foreach (var timeZoneId in new[] { "Europe/London", "GMT Standard Time" }) + { + try + { + return TimeZoneInfo.FindSystemTimeZoneById(timeZoneId); + } + catch (TimeZoneNotFoundException) { } + catch (InvalidTimeZoneException) { } + } + + return TimeZoneInfo.Utc; + } +} diff --git a/WheelWizard/Views/Pages/HomePage.axaml.cs b/WheelWizard/Views/Pages/HomePage.axaml.cs index 301f821c..48ed232e 100644 --- a/WheelWizard/Views/Pages/HomePage.axaml.cs +++ b/WheelWizard/Views/Pages/HomePage.axaml.cs @@ -11,14 +11,24 @@ using WheelWizard.Services.Launcher.Helpers; using WheelWizard.Settings; using WheelWizard.Shared.DependencyInjection; +using WheelWizard.Utilities; using WheelWizard.Views.Components; +using WheelWizard.Views.Popups.Generic; using Button = WheelWizard.Views.Components.Button; namespace WheelWizard.Views.Pages; public partial class HomePage : UserControlBase { - private static readonly bool IsAprilFirst = DateTime.Now.Month == 4 && DateTime.Now.Day == 1; + private static readonly bool IsAprilFirst = AprilFirstHelper.IsAprilFirstLocalOrBst(); + private static readonly (string MainText, string ExtraText, string YesText, string NoText)[] AprilFirstLaunchPrompts = + [ + ("You wanna start the game?", "This feels suspiciously productive.", "Yeah", "Nah"), + ("Eeeeh not feeling like it", "Try asking a little nicer next time.", "Please", "Whatever"), + ("Launch Retro Beefbai?", "I am consulting the ancient wheel.", "Do it", "Nope"), + ("You again?", "The game is pretending not to notice you.", "Open it", "Leave it"), + ("Starting the game already?", "That was fast. Almost too fast.", "Fine", "Hold on"), + ]; [Inject] private ISettingsManager SettingsService { get; set; } = null!; @@ -97,6 +107,25 @@ private void DolphinButton_OnClick(object? sender, RoutedEventArgs e) private void LaunchGame() => _ = CurrentLauncher.Launch(); + private bool ShouldShowAprilFirstLaunchPrompts() => + IsAprilFirst && _status is WheelWizardStatus.Ready or WheelWizardStatus.NoServerButInstalled; + + private async Task ShowAprilFirstLaunchPromptsAsync() + { + var promptPool = ((string MainText, string ExtraText, string YesText, string NoText)[])AprilFirstLaunchPrompts.Clone(); + RandomSystem.Random.Shared.Shuffle(promptPool); + + for (var i = 0; i < 4; i++) + { + var prompt = promptPool[i]; + await new YesNoWindow() + .SetMainText(prompt.MainText) + .SetExtraText(prompt.ExtraText) + .SetButtonText(prompt.YesText, prompt.NoText) + .AwaitAnswer(); + } + } + private void NavigateToSettings() => NavigationManager.NavigateTo(); private async void Download() @@ -115,9 +144,15 @@ private async void Update() NavigationManager.NavigateTo(); } - private void PlayButton_Click(object? sender, RoutedEventArgs e) + private async void PlayButton_Click(object? sender, RoutedEventArgs e) { - CurrentButtonState?.OnClick?.Invoke(); + if (CurrentButtonState?.OnClick == null) + return; + + if (ShouldShowAprilFirstLaunchPrompts()) + await ShowAprilFirstLaunchPromptsAsync(); + + CurrentButtonState.OnClick.Invoke(); PlayActivateAnimation(); UpdateActionButton(); DisableAllButtonsTemporarily(); diff --git a/WheelWizard/Views/Patterns/MiiImages/MiiImageLoader.axaml.cs b/WheelWizard/Views/Patterns/MiiImages/MiiImageLoader.axaml.cs index 8c675bb9..2f570eae 100644 --- a/WheelWizard/Views/Patterns/MiiImages/MiiImageLoader.axaml.cs +++ b/WheelWizard/Views/Patterns/MiiImages/MiiImageLoader.axaml.cs @@ -3,13 +3,14 @@ using Microsoft.Extensions.Caching.Memory; using WheelWizard.MiiImages; using WheelWizard.MiiImages.Domain; +using WheelWizard.Utilities; using WheelWizard.WiiManagement.MiiManagement.Domain.Mii; namespace WheelWizard.Views.Patterns; public partial class MiiImageLoader : BaseMiiImage { - private static readonly bool IsAprilFirst = DateTime.Now.Month == 4 && DateTime.Now.Day == 1; + private static readonly bool IsAprilFirst = AprilFirstHelper.IsAprilFirstLocalOrBst(); #region properties diff --git a/WheelWizard/Views/Patterns/MiiImages/MiiImageLoaderWithHover.axaml.cs b/WheelWizard/Views/Patterns/MiiImages/MiiImageLoaderWithHover.axaml.cs index 2e205a76..4d9bb35c 100644 --- a/WheelWizard/Views/Patterns/MiiImages/MiiImageLoaderWithHover.axaml.cs +++ b/WheelWizard/Views/Patterns/MiiImages/MiiImageLoaderWithHover.axaml.cs @@ -3,13 +3,14 @@ using Avalonia.Media; using WheelWizard.MiiImages; using WheelWizard.MiiImages.Domain; +using WheelWizard.Utilities; using WheelWizard.WiiManagement.MiiManagement.Domain.Mii; namespace WheelWizard.Views.Patterns; public partial class MiiImageLoaderWithHover : BaseMiiImage { - private static readonly bool IsAprilFirst = DateTime.Now.Month == 4 && DateTime.Now.Day == 1; + private static readonly bool IsAprilFirst = AprilFirstHelper.IsAprilFirstLocalOrBst(); private bool _hasLoadedHoverVariant; public static readonly StyledProperty IsHoveredProperty = AvaloniaProperty.Register(