Skip to content

Commit

Permalink
Merge branch 'master' into grids-4
Browse files Browse the repository at this point in the history
  • Loading branch information
peppy authored Oct 8, 2024
2 parents dc26773 + b658d9a commit 682023e
Show file tree
Hide file tree
Showing 33 changed files with 990 additions and 115 deletions.
27 changes: 25 additions & 2 deletions .github/workflows/diffcalc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,25 @@ env:
EXECUTION_ID: execution-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}

jobs:
master-environment:
name: Save master environment
runs-on: ubuntu-latest
outputs:
HEAD: ${{ steps.get-head.outputs.HEAD }}
steps:
- name: Checkout osu
uses: actions/checkout@v4
with:
ref: master
sparse-checkout: |
README.md
- name: Get HEAD ref
id: get-head
run: |
ref=$(git log -1 --format='%H')
echo "HEAD=https://github.com/${{ github.repository }}/commit/${ref}" >> "${GITHUB_OUTPUT}"
check-permissions:
name: Check permissions
runs-on: ubuntu-latest
Expand All @@ -121,7 +140,7 @@ jobs:
create-comment:
name: Create PR comment
needs: check-permissions
needs: [ master-environment, check-permissions ]
runs-on: ubuntu-latest
if: ${{ github.event_name == 'issue_comment' && github.event.issue.pull_request }}
steps:
Expand Down Expand Up @@ -158,7 +177,7 @@ jobs:
environment:
name: Setup environment
needs: directory
needs: [ master-environment, directory ]
runs-on: self-hosted
env:
VARS_JSON: ${{ toJSON(vars) }}
Expand All @@ -182,6 +201,10 @@ jobs:
fi
done
- name: Add master environment
run: |
sed -i "s;^OSU_A=.*$;OSU_A=${{ needs.master-environment.outputs.HEAD }};" "${{ needs.directory.outputs.GENERATOR_ENV }}"
- name: Add pull-request environment
if: ${{ github.event_name == 'issue_comment' && github.event.issue.pull_request }}
run: |
Expand Down
11 changes: 6 additions & 5 deletions osu.Android/GameplayScreenRotationLocker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,29 @@
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game;
using osu.Game.Screens.Play;

namespace osu.Android
{
public partial class GameplayScreenRotationLocker : Component
{
private Bindable<bool> localUserPlaying = null!;
private IBindable<LocalUserPlayingState> localUserPlaying = null!;

[Resolved]
private OsuGameActivity gameActivity { get; set; } = null!;

[BackgroundDependencyLoader]
private void load(OsuGame game)
private void load(ILocalUserPlayInfo localUserPlayInfo)
{
localUserPlaying = game.LocalUserPlaying.GetBoundCopy();
localUserPlaying = localUserPlayInfo.PlayingState.GetBoundCopy();
localUserPlaying.BindValueChanged(updateLock, true);
}

private void updateLock(ValueChangedEvent<bool> userPlaying)
private void updateLock(ValueChangedEvent<LocalUserPlayingState> userPlaying)
{
gameActivity.RunOnUiThread(() =>
{
gameActivity.RequestedOrientation = userPlaying.NewValue ? ScreenOrientation.Locked : gameActivity.DefaultOrientation;
gameActivity.RequestedOrientation = userPlaying.NewValue != LocalUserPlayingState.NotPlaying ? ScreenOrientation.Locked : gameActivity.DefaultOrientation;
});
}
}
Expand Down
40 changes: 24 additions & 16 deletions osu.Desktop/Updater/VelopackUpdateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public partial class VelopackUpdateManager : Game.Updater.UpdateManager
[Resolved]
private ILocalUserPlayInfo? localUserInfo { get; set; }

private bool isInGameplay => localUserInfo?.PlayingState.Value != LocalUserPlayingState.NotPlaying;

private UpdateInfo? pendingUpdate;

public VelopackUpdateManager()
Expand All @@ -43,18 +45,18 @@ private void load(INotificationOverlay notifications)

protected override async Task<bool> PerformUpdateCheck() => await checkForUpdateAsync().ConfigureAwait(false);

private async Task<bool> checkForUpdateAsync(UpdateProgressNotification? notification = null)
private async Task<bool> checkForUpdateAsync()
{
// whether to check again in 30 minutes. generally only if there's an error or no update was found (yet).
bool scheduleRecheck = false;

try
{
// Avoid any kind of update checking while gameplay is running.
if (localUserInfo?.IsPlaying.Value == true)
if (isInGameplay)
{
scheduleRecheck = true;
return false;
return true;
}

// TODO: we should probably be checking if there's a more recent update, rather than shortcutting here.
Expand Down Expand Up @@ -84,27 +86,22 @@ private async Task<bool> checkForUpdateAsync(UpdateProgressNotification? notific
}

// An update is found, let's notify the user and start downloading it.
if (notification == null)
UpdateProgressNotification notification = new UpdateProgressNotification
{
notification = new UpdateProgressNotification
CompletionClickAction = () =>
{
CompletionClickAction = () =>
{
Task.Run(restartToApplyUpdate);
return true;
},
};

Schedule(() => notificationOverlay.Post(notification));
}
Task.Run(restartToApplyUpdate);
return true;
},
};

runOutsideOfGameplay(() => notificationOverlay.Post(notification));
notification.StartDownload();

try
{
await updateManager.DownloadUpdatesAsync(pendingUpdate, p => notification.Progress = p / 100f).ConfigureAwait(false);

notification.State = ProgressNotificationState.Completed;
runOutsideOfGameplay(() => notification.State = ProgressNotificationState.Completed);
}
catch (Exception e)
{
Expand All @@ -131,6 +128,17 @@ private async Task<bool> checkForUpdateAsync(UpdateProgressNotification? notific
return true;
}

private void runOutsideOfGameplay(Action action)
{
if (isInGameplay)
{
Scheduler.AddDelayed(() => runOutsideOfGameplay(action), 1000);
return;
}

action();
}

private async Task restartToApplyUpdate()
{
await updateManager.WaitExitThenApplyUpdatesAsync(pendingUpdate?.TargetFullRelease).ConfigureAwait(false);
Expand Down
6 changes: 3 additions & 3 deletions osu.Desktop/Windows/GameplayWinKeyBlocker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace osu.Desktop.Windows
public partial class GameplayWinKeyBlocker : Component
{
private Bindable<bool> disableWinKey = null!;
private IBindable<bool> localUserPlaying = null!;
private IBindable<LocalUserPlayingState> localUserPlaying = null!;
private IBindable<bool> isActive = null!;

[Resolved]
Expand All @@ -22,7 +22,7 @@ public partial class GameplayWinKeyBlocker : Component
[BackgroundDependencyLoader]
private void load(ILocalUserPlayInfo localUserInfo, OsuConfigManager config)
{
localUserPlaying = localUserInfo.IsPlaying.GetBoundCopy();
localUserPlaying = localUserInfo.PlayingState.GetBoundCopy();
localUserPlaying.BindValueChanged(_ => updateBlocking());

isActive = host.IsActive.GetBoundCopy();
Expand All @@ -34,7 +34,7 @@ private void load(ILocalUserPlayInfo localUserInfo, OsuConfigManager config)

private void updateBlocking()
{
bool shouldDisable = isActive.Value && disableWinKey.Value && localUserPlaying.Value;
bool shouldDisable = isActive.Value && disableWinKey.Value && localUserPlaying.Value == LocalUserPlayingState.Playing;

if (shouldDisable)
host.InputThread.Scheduler.Add(WindowsKey.Disable);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class ManiaDifficultyCalculator : DifficultyCalculator
private readonly bool isForCurrentRuleset;
private readonly double originalOverallDifficulty;

public override int Version => 20230817;
public override int Version => 20241007;

public ManiaDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
: base(ruleset, beatmap)
Expand Down
12 changes: 11 additions & 1 deletion osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ public class OsuDifficultyAttributes : DifficultyAttributes
[JsonProperty("slider_factor")]
public double SliderFactor { get; set; }

[JsonProperty("aim_difficult_strain_count")]
public double AimDifficultStrainCount { get; set; }

[JsonProperty("speed_difficult_strain_count")]
public double SpeedDifficultStrainCount { get; set; }

/// <summary>
/// The perceived approach rate inclusive of rate-adjusting mods (DT/HT/etc).
/// </summary>
Expand Down Expand Up @@ -99,6 +105,9 @@ public class OsuDifficultyAttributes : DifficultyAttributes
yield return (ATTRIB_ID_FLASHLIGHT, FlashlightDifficulty);

yield return (ATTRIB_ID_SLIDER_FACTOR, SliderFactor);

yield return (ATTRIB_ID_AIM_DIFFICULT_STRAIN_COUNT, AimDifficultStrainCount);
yield return (ATTRIB_ID_SPEED_DIFFICULT_STRAIN_COUNT, SpeedDifficultStrainCount);
yield return (ATTRIB_ID_SPEED_NOTE_COUNT, SpeedNoteCount);
}

Expand All @@ -113,8 +122,9 @@ public override void FromDatabaseAttributes(IReadOnlyDictionary<int, double> val
StarRating = values[ATTRIB_ID_DIFFICULTY];
FlashlightDifficulty = values.GetValueOrDefault(ATTRIB_ID_FLASHLIGHT);
SliderFactor = values[ATTRIB_ID_SLIDER_FACTOR];
AimDifficultStrainCount = values[ATTRIB_ID_AIM_DIFFICULT_STRAIN_COUNT];
SpeedDifficultStrainCount = values[ATTRIB_ID_SPEED_DIFFICULT_STRAIN_COUNT];
SpeedNoteCount = values[ATTRIB_ID_SPEED_NOTE_COUNT];

DrainRate = onlineInfo.DrainRate;
HitCircleCount = onlineInfo.CircleCount;
SliderCount = onlineInfo.SliderCount;
Expand Down
7 changes: 6 additions & 1 deletion osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class OsuDifficultyCalculator : DifficultyCalculator
{
private const double difficulty_multiplier = 0.0675;

public override int Version => 20220902;
public override int Version => 20241007;

public OsuDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
: base(ruleset, beatmap)
Expand All @@ -48,6 +48,9 @@ protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beat

double sliderFactor = aimRating > 0 ? aimRatingNoSliders / aimRating : 1;

double aimDifficultyStrainCount = ((OsuStrainSkill)skills[0]).CountDifficultStrains();
double speedDifficultyStrainCount = ((OsuStrainSkill)skills[2]).CountDifficultStrains();

if (mods.Any(m => m is OsuModTouchDevice))
{
aimRating = Math.Pow(aimRating, 0.8);
Expand Down Expand Up @@ -100,6 +103,8 @@ protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beat
SpeedNoteCount = speedNotes,
FlashlightDifficulty = flashlightRating,
SliderFactor = sliderFactor,
AimDifficultStrainCount = aimDifficultyStrainCount,
SpeedDifficultStrainCount = speedDifficultyStrainCount,
ApproachRate = preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5,
OverallDifficulty = (80 - hitWindowGreat) / 6,
DrainRate = drainRate,
Expand Down
14 changes: 6 additions & 8 deletions osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,8 @@ private double computeAimValue(ScoreInfo score, OsuDifficultyAttributes attribut
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0);
aimValue *= lengthBonus;

// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (effectiveMissCount > 0)
aimValue *= 0.97 * Math.Pow(1 - Math.Pow(effectiveMissCount / totalHits, 0.775), effectiveMissCount);

aimValue *= getComboScalingFactor(attributes);
aimValue *= calculateMissPenalty(effectiveMissCount, attributes.AimDifficultStrainCount);

double approachRateFactor = 0.0;
if (attributes.ApproachRate > 10.33)
Expand Down Expand Up @@ -150,11 +147,8 @@ private double computeSpeedValue(ScoreInfo score, OsuDifficultyAttributes attrib
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0);
speedValue *= lengthBonus;

// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (effectiveMissCount > 0)
speedValue *= 0.97 * Math.Pow(1 - Math.Pow(effectiveMissCount / totalHits, 0.775), Math.Pow(effectiveMissCount, .875));

speedValue *= getComboScalingFactor(attributes);
speedValue *= calculateMissPenalty(effectiveMissCount, attributes.SpeedDifficultStrainCount);

double approachRateFactor = 0.0;
if (attributes.ApproachRate > 10.33)
Expand Down Expand Up @@ -271,6 +265,10 @@ private double calculateEffectiveMissCount(OsuDifficultyAttributes attributes)
return Math.Max(countMiss, comboBasedMissCount);
}

// Miss penalty assumes that a player will miss on the hardest parts of a map,
// so we use the amount of relatively difficult sections to adjust miss penalty
// to make it more punishing on maps with lower amount of hard sections.
private double calculateMissPenalty(double missCount, double difficultStrainCount) => 0.96 / ((missCount / (4 * Math.Pow(Math.Log(difficultStrainCount), 0.94))) + 1);
private double getComboScalingFactor(OsuDifficultyAttributes attributes) => attributes.MaxCombo <= 0 ? 1.0 : Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(attributes.MaxCombo, 0.8), 1.0);
private int totalHits => countGreat + countOk + countMeh + countMiss;
}
Expand Down
1 change: 1 addition & 0 deletions osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ protected override double StrainValueAt(DifficultyHitObject current)
{
currentStrain *= strainDecay(current.DeltaTime);
currentStrain += AimEvaluator.EvaluateDifficultyOf(current, withSliders) * skillMultiplier;
ObjectStrains.Add(currentStrain);

return currentStrain;
}
Expand Down
23 changes: 20 additions & 3 deletions osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,17 @@ public abstract class OsuStrainSkill : StrainSkill
/// </summary>
protected virtual double ReducedStrainBaseline => 0.75;

protected List<double> ObjectStrains = new List<double>();
protected double Difficulty;

protected OsuStrainSkill(Mod[] mods)
: base(mods)
{
}

public override double DifficultyValue()
{
double difficulty = 0;
Difficulty = 0;
double weight = 1;

// Sections with 0 strain are excluded to avoid worst-case time complexity of the following sort (e.g. /b/2351871).
Expand All @@ -50,11 +53,25 @@ public override double DifficultyValue()
// We're sorting from highest to lowest strain.
foreach (double strain in strains.OrderDescending())
{
difficulty += strain * weight;
Difficulty += strain * weight;
weight *= DecayWeight;
}

return difficulty;
return Difficulty;
}

/// <summary>
/// Returns the number of strains weighted against the top strain.
/// The result is scaled by clock rate as it affects the total number of strains.
/// </summary>
public double CountDifficultStrains()
{
if (Difficulty == 0)
return 0.0;

double consistentTopStrain = Difficulty / 10; // What would the top strain be if all strain values were identical
// Use a weighted sum of all strains. Constants are arbitrary and give nice values
return ObjectStrains.Sum(s => 1.1 / (1 + Math.Exp(-10 * (s / consistentTopStrain - 0.88))));
}

public static double DifficultyToPerformance(double difficulty) => Math.Pow(5.0 * Math.Max(1.0, difficulty / 0.0675) - 4.0, 3.0) / 100000.0;
Expand Down
Loading

0 comments on commit 682023e

Please sign in to comment.