2017 04 13

published 13 Apr 2017

Bringing you the latest in osu! development

Fixes to screen interoperability

I had a lot planned today, but ended up spending most of my time following a yellow brick road to fix a reported bug which saw the game in a state of both paused and failed… at the same time. This, as you’d expect, should not be possible!

I spent almost five hours resolving this! It involved some very complex intertwined threading logic (which unfortunately is unavoidable in this context) and saw me finding at least three vaguely related bugs in the process:

  • Game screens were handling escape keys even when they were not the active screen.
  • The actual threading issues, caused by escape key presses being handled one level higher in the draw hierarchy than expected, in tandom with audio objects (when trated as an interpolating clock source) not correctly querying a cached IsRunning value.

If you didn’t understand any of what I just said, don’t worry! Explaining in words is hard… this was a complex situation.

Thanks to ocboogie for helping test this and finding an easily reproducible test scenario!

Fixes to gameplay cursor positioning

Until now, the gameplay cursor would start in a default position, not correctly updating it to the user’s current cursor position until the next time the input device was moved. This is really ugly, so I spent some time figuring out how to fix it up.

For a bit of background: all of our input events are event based. This unfortunately means that we can’t get an “initial” state for new screens/objects which are created, like the Player’s HitRenderer. As a temporary solution, we added an interface called IRequireHighFrequencyMousePosition. Anything implementing this interface would be guaranteed at least one MouseMove event per frame, regardless of whether the cursor was moved or not.

Inside a Player instance, we have a nested InputManager which is used to do key mapping (keys to mouse, mouse to keys etc.) and replay handling (injecting input frames from an external source). The bug here was caused by the fact that nested InputManagers weren’t implementing this interface correctly, which meant they wouldn’t correctly propagate it down to their children.

Before:

After:

May seem insignificant, but every detail counts!

Fixes to cursor trail display

Until now, the gameplay cursor’s trail has been using the audio clock, which can lead to some unexpected results, especially after pausing or on retrying a map. I decoupled the trail from the audio clock in order to fix this, so it should behave a lot closer to how you’d expect it to, regardless of the state of audio playback.

API in the background…

Have been working with nekodex on bringing the new API up to speed so we can begin to populate more data in-game. This includes beatmap ratings, fail/retry times, user flags, personal best scores and more. We’re almost ready to set things up for testing, so stay tuned for further progress on that.

Oh and yes, these API changes will eventually be exposed for public consumption. We’re aiming to provide a much more feature rich API and address the concerns people have with the existing public API over the coming months.

No release today

While fixing the above issues was some major forward progress as far as stability is concerned, the code has not yet been reviewed so there will be no release today!