Skip to content

Conversation

@pull
Copy link

@pull pull bot commented Feb 8, 2022

See Commits and Changes for more details.


Created by pull[bot]

Can you help keep this open source service alive? 💖 Please sponsor : )

@pull pull bot added the ⤵️ pull label Feb 8, 2022
peppy and others added 29 commits January 4, 2026 02:22
…otifications

Localise friend presence notifications
…is exactly zero.

Previously, there if two consecutive hitobjects were 50ms apart both mechanisms to make sure that the input buttons are alternated would fail.
This produced a replay frame which lifts the current button, followed by a frame which presses the same button again, at the same time as it was lifted.
The key-up frame would always get skipped without frame-stability, leading to hitsounds and hit animations not getting played in the editor.
Additionally to fix the options button, I could either cache the
interface in PlaylistsSongSelectV2 or make the interface cache itself. I
went with the latter option.
* Fix play button starting wrong beatmap before selection loads

When clicking the osu! cookie (play button) before a newly selected beatmap finishes loading, the previous beatmap would be played instead of the currently selected one. 

This was caused by the cookie reading from the global beatmap state which is debounced by 150ms, while the Enter key correctly used the carousel's current selection.

The fix makes the cookie use the same beatmap source as Enter - the carousel's current selection - which is always up-to-date regardless of debounce timing.

Closes #36074

* Use ensureGlobalBeatmapValid() for logo and Enter key actions

* Add test for beatmap selection timing bug

Tests the fix for issue #36074 where clicking the play button immediately after selecting a different difficulty would start the wrong beatmap due to the 150ms selection debounce.
…tans

Fix `OsuAutoGenerator` failing to alternate when objects are exactly 50ms apart
Happens when initial timing is undone.

Regressed in
12170df.
Closes #36228.
Adjust quick play player panels for long usernames
…-importer

Localise notifications in `LegacyCollectionImporter`
Co-authored-by: Dean Herbert <pe@ppy.sh>
Co-authored-by: Dean Herbert <pe@ppy.sh>
Uses the same method of displaying the mod selection as the old song
select (as an overlay of the entire game).
The scheduled events don't fire because the content is hidden.
The important one is the required mod selection, whose overlay contents
overlap with the add button. The free mod selection would otherwise be
fine, if not for consistency.
Fix editor crashing on undoing after hit object placement
peppy and others added 30 commits January 28, 2026 14:22
This was attempted to be fixed by frenzibyte using some hack workaround
logic, but this is the true fix.

Things were never matching due to `UpdateSize` spamming `Resize`
transforms every frame, causing the fade out to complete before
transforms have reached a final state.
I don't want to have to update things in multiple places with different
code in each place.

This also closes #36412.
Fix dropdown margins and animations being weird
This removes the disabled sound, but I think that's fine. If we want
that, it should be handled by `HoverClickSounds` (which I'm currently
intentionally not using because it can be a bit noisy).

Closes #36503.
Fix "ALL MODS" display not displaying in new playlist song select
Fix `FormCheckbox` playing sounds twice
Add server-side models for ranked play
…chooser

Localise "Custom sample sets" caption in `FormSampleSetChooser` dropdown
If we've run an update since we can cancel the scheduled debounce run.
Removes the previous `AppIcon.appiconset` bundle and replaces it with
all of the necessary asset slices to enable all of the Liquid Glass
variants of the app icon on iOS 26, while also preserving backwards
compatibility with older iOS versions.

<img width="1164" height="388" alt="LiquidGlass"
src="https://github.com/user-attachments/assets/7d6e7a90-3fe5-4853-9c63-35144359f49e"
/>

---------

Co-authored-by: Dean Herbert <pe@ppy.sh>
Fix star ratings sometimes not updating after editing a beatmap
…ryboard

Localise "Show storyboard" in `Editor`
Effectively closing #21471 as a
wontfix.

The issue is demonstrated by the following test case:

<details>
<summary>patch</summary>

```diff
diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFreezeFrame.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFreezeFrame.cs
index 3149829..36b4fe5122 100644
--- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFreezeFrame.cs
+++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFreezeFrame.cs
@@ -55,5 +55,49 @@ public void TestSkipToFirstSpinnerNotSuppressed()
                 PassCondition = () => Player.GameplayClockContainer.GameplayStartTime > 0
             });
         }
+
+        [Test]
+        public void TestFreezeFrameAppliedBeforeHidden()
+        {
+            CreateModTest(new ModTestData
+            {
+                Mods =
+                [
+                    new OsuModFreezeFrame(),
+                    new OsuModHidden(),
+                ],
+                CreateBeatmap = () => new OsuBeatmap
+                {
+                    HitObjects =
+                    {
+                        new HitCircle { StartTime = 3000, Position = OsuPlayfield.BASE_SIZE / 2, NewCombo = true },
+                        new HitCircle { StartTime = 5000, Position = OsuPlayfield.BASE_SIZE / 2 },
+                    }
+                },
+                PassCondition = () => ((HitCircle)Player.GameplayState.Beatmap.HitObjects[1]).TimeFadeIn == 480
+            });
+        }
+
+        [Test]
+        public void TestFreezeFrameAppliedAfterHidden()
+        {
+            CreateModTest(new ModTestData
+            {
+                Mods =
+                [
+                    new OsuModHidden(),
+                    new OsuModFreezeFrame(),
+                ],
+                CreateBeatmap = () => new OsuBeatmap
+                {
+                    HitObjects =
+                    {
+                        new HitCircle { StartTime = 3000, Position = OsuPlayfield.BASE_SIZE / 2, NewCombo = true },
+                        new HitCircle { StartTime = 5000, Position = OsuPlayfield.BASE_SIZE / 2 },
+                    }
+                },
+                PassCondition = () => ((HitCircle)Player.GameplayState.Beatmap.HitObjects[1]).TimeFadeIn == 480
+            });
+        }
     }
 }

```

</details>

The reason that this is happening is a data dependency. Freeze Frame
modifies `TimePreempt` of hitobjects:


https://github.com/ppy/osu/blob/54c0b2c20c3209f1f17be81b8883ef66ec8a83bb/osu.Game.Rulesets.Osu/Mods/OsuModFreezeFrame.cs#L53

while Hidden uses `TimePreempt` to set `TimeFadeIn`:


https://github.com/ppy/osu/blob/54c0b2c20c3209f1f17be81b8883ef66ec8a83bb/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs#L45

Therefore the final value of `TimeFadeIn` with these two mods active
depends on the order of application.

The reason why I'm bothering to do this is that I was pinged from the PP
development server about this again in the context of some ongoing
'rework' and I wish to get ahead of this before it becomes a bigger
problem than it already is.

The current order of application of these mods as done in `Player` is
constant, but essentially undefined. I'm not even sure what even
enforces the current order. It's currently Hidden, then Freeze Frame. If
I were to guess, the thing "enforcing" (insert 400 tonne solid lead air
quotes) it is probably the mod select overlay with its "I need to own
all of the mod instances in the global bindable" substitution logic.

I'm already getting pushback for this from the PP server crowd who are
attempting to justify the current "behaviour" by saying that the player
base wants this or by saying that it's already broken so it should
remain that way forever. I am however not willing to accept
[stable-taiko-tier stupidity
again](#27136 (comment))
and am not willing to accept the complexity this would invite everywhere
else.

I do not see any other easy way of fixing this problem at this point in
time. I had hoped that I could inline the `TimePreempt` read in
`OsuModHidden`, but it's not that easy because it's set in multiple
places.

Existing HDFF scores would probably need to be delisted from the
leaderboards. I'm not even sure I can get myself to pretend to care.
Closes #36490.

While I'm out here already taking heat for deleting mod combinations let
me do more of that.

The main problem with the mod combination here, again, is that the
application of the mods does not commute.

- The current behaviour is that TP is applied first, then DA. This is,
again, "enforced" by the mod select overlay implicitly enforcing order
of the mod instances in the global mod bindable to match the display
order of mods inside it.

Even this doesn't "work" correctly as is, because as the bug reporter
points out, if they throw on DA with no changes expecting the map's
default AR to be applied, it still gets halved. This is because DA works
in a way wherein if you don't touch the AR slider, DA does not touch AR.
Which means that the DA slider should *really* be at *half* of the map's
base AR by default in this case because TP is active. How do you program
this?

- The *alternative* behaviour would be that DA is applied first, then
TP. This in turn would mean that the effective range of AR adjustment
offered by DA when TP is active would be halved to [0, 5] (or [-5, 5.5]
with extended ranges). How do you program this?

The above is just client-side concerns, while leaving out the other
giant concern, which is "how do you get every single place in the game
that may want to apply mods to a beatmap to apply them *in the same
order*?". Then extend that to server-side components, then extend that
to every external library that may want to re-implement SR/PP
calculations, etc. etc.

One additional remark:
What the bug reporter *did not* say however, but I am saying, is that
there's an elephant in the room, and that is the Easy mod, which *also*
changes AR, but also *happens* to apply commutatively with Target
Practice simply because both mods are implemented to halve the AR, which
means that the order of application doesn't matter. If I were *really*
bent on being a bad guy and just deleting mod combinations
indiscriminately, I'd delete that one as well. But I'm not doing that.
Fix multiplayer team display becoming inconsistent
…36512)

Probably closes #36492.

This is dumb but it's in large part my stupidity.

To begin with, the immediate direct offending call that causes the
observed symptoms is


https://github.com/ppy/osu/blob/a401c7d5e9d6d8b05b2ec293145ad308dfe9d6d0/osu.Game/Screens/Edit/Components/FormSampleSet.cs#L296

The reason why this "invalidation" affects sample volume is that in the
framework implementation, the call [removes the relevant sample factory
from the sample store which is an audio
component](https://github.com/ppy/osu-framework/blob/5b716dcbef6f99e03188a7a7706361fa8445c754/osu.Framework/Audio/Sample/SampleStore.cs#L65-L72).
In the process it also [unbinds audio
adjustments](https://github.com/ppy/osu-framework/blob/5b716dcbef6f99e03188a7a7706361fa8445c754/osu.Framework/Audio/AudioCollectionManager.cs#L37-L38),
which *would* have the effect of resetting the sample volume to 100%,
effectively (and I've pretty much confirmed that that's what happens).

Now for why this call sometimes does the right thing and sometimes
doesn't: Sometimes the call is made in response to an *actual* change to
the beatmap skin, which is correct and expected, if very indirect, but
sometimes it is made *over-eagerly* when there is no reason to recycle
anything yet.

One such circumstance is entering the setup screen, which will still
"invalidate" (read: remove) the samples, but the compose tab hasn't seen
any change to the beatmap skin, so when it is returned to, it has no
reason to retrieve the sample again, and as such it will try to play
samples which are for better or worse in a completely undefined state
because they're not supposed to be *in use* anymore.

Therefore, the right thing here would seem to be to take the
responsibility of invalidation from a random component, and move it to a
place that's *actually* correlated to every other component needing to
recycle samples, e.g. `EditorBeatmapSkin` responding to changes in the
beatmap resources via raising `BeatmapSkinChanged`.

Unfortunately, because of the structure of everything, this recycle
needs to go from targeted to individual samples, to nuking the entire
store. The reason for this is that `RealmBackedResourceStore` does not
provide information as to *what* resources changed, it just says that
*the set of them* did.

For the recycle to be smarter, `EditorBeatmapSkin` would need to know
not only which samples were added or replaced, but also which ones were
*removed*, so that users don't hear phantom samples that no longer exist
in the editor later. That would however be a lot of hassle for nothing,
so I just recycle everything here and hope it won't matter.

As to why I could only reproduce this on this one beatmap - I'm not
super sure. The failure does not seem to be specific to beatmaps, but it
may be exacerbated by certain patterns of accessing samples which means
that beatmaps with high BPM like the one I managed to reproduce this on
may just be more susceptible to this.

As a final note, I do realise that this is not fundamentally improving
the surrounding systems and it's still a pretty rickety thing to do.
It's still on the consumers to know and respond to the sample store
recycle and this is likely to fail if a consumer ever doesn't. That
said, I have no brighter ideas at this point in time that won't involve
me spending a week refactoring audio.
Regressed in d6bf4fd.

One very visible instance of this regression is the login form.


https://github.com/user-attachments/assets/5ba10ac5-4cb1-49af-b55c-89cf58ca0b44

The `CommentEditor` usage was discovered with one of my favourite tricks
which is doing

```diff
diff --git a/osu.Game/Graphics/UserInterface/OsuTextBox.cs b/osu.Game/Graphics/UserInterface/OsuTextBox.cs
index fefe776..c17cca726b 100644
--- a/osu.Game/Graphics/UserInterface/OsuTextBox.cs
+++ b/osu.Game/Graphics/UserInterface/OsuTextBox.cs
@@ -42,6 +42,12 @@ public partial class OsuTextBox : BasicTextBox
             Margin = new MarginPadding { Left = 2 },
         };
 
+        public new bool Masking
+        {
+            get => base.Masking;
+            set => base.Masking = value;
+        }
+
         protected bool DrawBorder { get; init; } = true;
 
         private OsuCaret? caret;

```

and then looking for usages of the setter. That's all due diligence
you're getting here, I'm not auditing every single text box in the game.

And yes, the `CommentEditor` usage is OMEGA dodgy but the change applied
here is the only one that preserves its visual appearance. I'm not
putting in time to fix it.
- depends on ppy/osu-framework#6700
- closes #36340
- supersedes and closes #36352

<img width="676" height="451" alt="image"
src="https://github.com/user-attachments/assets/4f11c761-175b-495a-8b24-16fb6c481a15"
/>

---------

Co-authored-by: Dean Herbert <pe@ppy.sh>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.