Skip to content

feat: clone and optimize all ppy/osu-resources in release workflow - #307

Merged
winnerspiros merged 19 commits into
masterfrom
copilot/optimize-for-android-performance
May 7, 2026
Merged

feat: clone and optimize all ppy/osu-resources in release workflow#307
winnerspiros merged 19 commits into
masterfrom
copilot/optimize-for-android-performance

Conversation

Copilot AI commented May 7, 2026

Copy link
Copy Markdown
  • Fix previous CI errors (RendererType.OpenGLLegacy, naming, IDE0032)
  • Fix CS8766: TrackingStore.Get/GetAsync return nullable byte[]?/Task<byte[]?> but IResourceStore<byte[]> interface requires non-nullable; updated GetStream to track RequestedNames directly

Copilot AI and others added 17 commits May 6, 2026 23:10
Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/f919cfa6-de78-4276-a40a-fd1c88808032

Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/f919cfa6-de78-4276-a40a-fd1c88808032

Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/f919cfa6-de78-4276-a40a-fd1c88808032

Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
…defaults

Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/c832fee6-e852-40a1-987b-3fbc924ccf6c

Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
…ed quality and compatibility-safe fallback

Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/c832fee6-e852-40a1-987b-3fbc924ccf6c

Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/a5dbb608-4e8f-4de0-a728-3d7770f3f3c1

Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
…mageFallbackRules

Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/5df7b393-ed8a-4cbb-80aa-f77e7c93f8dc

Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
…pping (framework handles internally)

Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/1916a68a-ef99-4b62-bda4-b6412084ab3a

Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
…ection in multiplayer (ppy#37646)

Fixes a bug that allowed for selecting the same mod twice in multiplayer
if the playlist entry has non-default settings for a required mod.
This happens due to a strict equality mod check in the mod set
compatibility check function, which only considers mods duplicates if
their settings are exactly the same. Replacing with a more lenient
`Type` check fixes this.

Adds a regression test for this behavior

Fixes ppy#37625.

---------

Co-authored-by: Bartłomiej Dach <dach.bartlomiej@gmail.com>
Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
…e screen (ppy#37658)

Until now the queue screen basically did nothing to let the user knowing
they were disconnected from the server. Now the various components will
correctly clear state and show a roughly competent "i'm trying to
reconnect" state.

https://github.com/user-attachments/assets/bff1b241-a6a2-445a-9ffa-b5682f2a3656

---

Can be tested using the following patch (hit `F7` to reconnect, with a 5
second delay to show the disconnected state too):

```diff
diff --git a/osu.Game/Online/PersistentEndpointClientConnector.cs b/osu.Game/Online/PersistentEndpointClientConnector.cs
index 7064906..ae539aba8d 100644
--- a/osu.Game/Online/PersistentEndpointClientConnector.cs
+++ b/osu.Game/Online/PersistentEndpointClientConnector.cs
@@ -99,6 +99,8 @@ private async Task connect()
                     // this will also create a new cancellation token source.
                     await disconnect(false).ConfigureAwait(false);

+                    await Task.Delay(5000).ConfigureAwait(false);
+
                     // this token will be valid for the scope of this connection.
                     // if cancelled, we can be sure that a disconnect or reconnect is handled elsewhere.
                     var cancellationToken = connectCancelSource.Token;
diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs
index 703444a..fb467472d3 100644
--- a/osu.Game/OsuGameBase.cs
+++ b/osu.Game/OsuGameBase.cs
@@ -22,6 +22,7 @@
 using osu.Framework.Graphics.Containers;
 using osu.Framework.Graphics.Textures;
 using osu.Framework.Input;
+using osu.Framework.Input.Events;
 using osu.Framework.Input.Handlers;
 using osu.Framework.Input.Handlers.Joystick;
 using osu.Framework.Input.Handlers.Midi;
@@ -65,6 +66,7 @@
 using osu.Game.Scoring;
 using osu.Game.Skinning;
 using osu.Game.Utils;
+using osuTK.Input;
 using RuntimeInfo = osu.Framework.RuntimeInfo;

 namespace osu.Game
@@ -104,7 +106,7 @@ public partial class OsuGameBase : Framework.Game, ICanAcceptFiles, IBeatSyncPro
         /// </summary>
         private const double global_track_volume_adjust = 0.8;

-        public virtual bool UseDevelopmentServer => DebugUtils.IsDebugBuild;
+        public virtual bool UseDevelopmentServer => false;

         public virtual EndpointConfiguration CreateEndpoints() =>
             UseDevelopmentServer ? new DevelopmentEndpointConfiguration() : new ProductionEndpointConfiguration();
@@ -466,6 +468,20 @@ private void addFilesWarning()
             }
         }

+        protected override bool OnKeyDown(KeyDownEvent e)
+        {
+            if (e.Key == Key.F7)
+            {
+                Logger.Log("Forcing reconnect!", level: LogLevel.Important);
+
+                ((IStatefulUserHubClient)MultiplayerClient).ServerShuttingDown();
+                ((IStatefulUserHubClient)SpectatorClient).ServerShuttingDown();
+                ((IStatefulUserHubClient)metadataClient).ServerShuttingDown();
+            }
+
+            return base.OnKeyDown(e);
+        }
+
         private void onTrackChanged(WorkingBeatmap beatmap, TrackChangeDirection direction) => beatmapClock.ChangeSource(beatmap.Track);

         protected virtual void InitialiseFonts()

```

Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
Matches stable.

---

Addresses ppy#37580.
Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
Copilot AI requested a review from winnerspiros May 7, 2026 15:30
Copilot AI requested a review from winnerspiros May 7, 2026 15:46
@winnerspiros
winnerspiros marked this pull request as ready for review May 7, 2026 16:02
Copilot AI review requested due to automatic review settings May 7, 2026 16:02
@winnerspiros
winnerspiros merged commit eeddea9 into master May 7, 2026
21 checks passed
@gitar-bot

gitar-bot Bot commented May 7, 2026

Copy link
Copy Markdown

Important

You are using the Gitar free plan. Upgrade to unlock code review, CI analysis, auto-apply, custom automations, and more.

Gitar

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a workflow-time media optimisation + budgeting pipeline (including optionally repacking ppy/osu-resources for release), and introduces an OptimisedMediaResourceStore wrapper to enable transparent extension fallbacks (e.g. .png.avif/.webp) for raw IResourceStore<byte[]> lookups.

Changes:

  • Add ffmpeg-based optimisation and budget-check scripts + wire them into CI/release workflows (including cloning and repacking optimised osu-resources in release).
  • Introduce OptimisedMediaResourceStore and apply it to local overrides and several raw byte[] lookup paths (beatmaps/storyboards).
  • Fix/adjust assorted gameplay + online UI behaviours (mod compatibility self-check, matchmaking queue connectivity handling, pause/fail overlay sample stopping).

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
scripts/optimize_resource_overrides.py New ffmpeg-based media conversion script (png/jpg→webp, wav/mp3→ogg, mp4→webm) with reporting.
scripts/check_resource_budgets.py New script to compute media-size reports and fail CI on configured budget regressions.
osu.iOS.props Bump ppy.osu.Framework.iOS to 2026.507.1.
osu.Android.props Bump ppy.osu.Framework.Android to 2026.507.1.
osu.Game/osu.Game.csproj Bump ppy.osu.Framework to 2026.507.1 and update related comment.
osu.Game/Utils/ModUtils.cs Change self-compatibility detection from Equals() to type equality.
osu.Game/Storyboards/Drawables/DrawableStoryboard.cs Wrap storyboard resource lookup store with OptimisedMediaResourceStore.
osu.Game/Skinning/ResourceStoreBackedSkin.cs Formatting-only change to texture store creation.
osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs Formatting-only change to texture store creation.
osu.Game/Screens/Play/Player.cs Stop fail overlay samples on exit (in addition to pause overlay).
osu.Game/Screens/Play/PauseOverlay.cs Remove pause-loop sound handling (moved to base overlay).
osu.Game/Screens/Play/GameplayMenuOverlay.cs Add pause-loop sound handling to the base gameplay menu overlay.
osu.Game/Screens/OnlinePlay/Matchmaking/Queue/ScreenQueue.cs Improve connectivity handling (disable UI / clear state when disconnected) and refactor lobby refresh.
osu.Game/Screens/OnlinePlay/Matchmaking/Queue/PoolSelector.cs Add loading spinner and support null pool list to represent “loading/disconnected”.
osu.Game/Screens/OnlinePlay/Matchmaking/Queue/CloudVisualisation.cs Refresh visualisation automatically when users update and after load.
osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs Remove filtering of RendererType.OpenGLLegacy from renderer selection.
osu.Game/OsuGameBase.cs Add local override resource store before upstream resources and wrap it for extension fallbacks.
osu.Game/IO/Stores/OptimisedMediaResourceStore.cs New resource store wrapper implementing extension-preference probing.
osu.Game/Beatmaps/WorkingBeatmapCache.cs Wrap beatmap file store with OptimisedMediaResourceStore for fallback behaviour.
osu.Game/Beatmaps/BeatmapManager.cs Wrap realm-backed user resource store with OptimisedMediaResourceStore.
osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs Add test case for non-default mod settings visibility in mod select overlay.
osu.Game.Tests/Mods/ModUtilsTest.cs Add test to ensure mods conflict with themselves even when settings differ.
osu.Game.Tests/IO/OptimisedMediaResourceStoreTest.cs New unit tests covering extension probing and Wrap() idempotency.
MOBILE_RESOURCE_POLICY.md Document goals/strategy for mobile resource overrides and budgets.
.github/workflows/ci.yml Add a dedicated job to optimise + budget-check local overrides.
.github/workflows/release.yml Install ffmpeg, optimise + (attempt to) locally repack optimised osu-resources, then run budgets (source + APK).
.github/resource-optimizer/README.md Document optimiser config and behaviour.
.github/resource-optimizer/config.json Optimiser config for local overrides (osu.Game/Resources).
.github/resource-optimizer/osu-resources-config.json Optimiser config for repacking upstream osu-resources (keep originals disabled).
.github/resource-budgets/source-overrides.json New budgets for osu.Game/Resources overrides.
.github/resource-budgets/android-apk-media.json New budgets for media inside the final Android APK (and total APK size).
.github/resource-budgets/README.md Document what the budget files enforce and when they’re evaluated.
osu.Game/Resources/README.md Document local override loading order and extension-fallback behaviour.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 176 to +188
protected override void PopIn()
{
this.FadeIn(TRANSITION_DURATION, Easing.In);
updateInfoText();

startPauseLoop();
}

protected override void PopOut() => this.FadeOut(TRANSITION_DURATION, Easing.In);
protected override void PopOut()
{
this.FadeOut(TRANSITION_DURATION, Easing.In);
stopPauseLoop();
}
Comment thread osu.Game/OsuGameBase.cs
Comment on lines +378 to +379
// the framework's built-in OptimizedResourceStore with the same fallback rules, so all media loading paths
// benefit from optimised format lookups without requiring explicit wrapping at each call site.
Comment on lines +2 to +6
import argparse
import json
import os
import sys
import zipfile
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants