1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 19:27:24 +08:00

Merge branch 'master' into complete-disable-velopack

This commit is contained in:
smallketchup82 2024-09-08 21:32:57 -04:00
commit bf3597f711
No known key found for this signature in database
GPG Key ID: 7345B7C561243F1E
18 changed files with 196 additions and 72 deletions

View File

@ -10,7 +10,7 @@
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ppy.osu.Framework.Android" Version="2024.904.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2024.907.1" />
</ItemGroup>
<PropertyGroup>
<!-- Fody does not handle Android build well, and warns when unchanged.

View File

@ -3,6 +3,7 @@
using System;
using System.IO;
using System.Runtime.Versioning;
using osu.Desktop.LegacyIpc;
using osu.Desktop.Windows;
using osu.Framework;
@ -176,12 +177,20 @@ namespace osu.Desktop
return;
}
VelopackApp
.Build()
.WithFirstRun(v =>
{
if (OperatingSystem.IsWindows()) WindowsAssociationManager.InstallAssociations();
}).Run();
var app = VelopackApp.Build();
if (OperatingSystem.IsWindows())
configureWindows(app);
app.Run();
}
[SupportedOSPlatform("windows")]
private static void configureWindows(VelopackApp app)
{
app.WithFirstRun(_ => WindowsAssociationManager.InstallAssociations());
app.WithAfterUpdateFastCallback(_ => WindowsAssociationManager.UpdateAssociations());
app.WithBeforeUninstallFastCallback(_ => WindowsAssociationManager.UninstallAssociations());
}
}
}

View File

@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Configuration
SetDefault(OsuRulesetSetting.ReplayFrameMarkersEnabled, false);
SetDefault(OsuRulesetSetting.ReplayCursorPathEnabled, false);
SetDefault(OsuRulesetSetting.ReplayCursorHideEnabled, false);
SetDefault(OsuRulesetSetting.ReplayAnalysisDisplayLength, 750);
SetDefault(OsuRulesetSetting.ReplayAnalysisDisplayLength, 800);
}
}

View File

@ -8,7 +8,9 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
using osu.Framework.Graphics.Containers;
using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Online.API;
using osu.Game.Online.Rooms;
@ -26,6 +28,7 @@ using osu.Game.Scoring;
using osu.Game.Screens.Play;
using osu.Game.Screens.Ranking;
using osu.Game.Tests.Beatmaps;
using osuTK.Input;
namespace osu.Game.Tests.Visual.Gameplay
{
@ -177,6 +180,30 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert("ensure no submission", () => Player.SubmittedScore == null);
}
[Test]
public void TestEmptyFailStillImports()
{
prepareTestAPI(true);
createPlayerTest(true);
AddUntilStep("wait for token request", () => Player.TokenCreationRequested);
AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed);
AddUntilStep("wait for fail overlay", () => Player.FailOverlay.State.Value, () => Is.EqualTo(Visibility.Visible));
AddStep("attempt import", () =>
{
InputManager.MoveMouseTo(Player.ChildrenOfType<SaveFailedScoreButton>().Single());
InputManager.Click(MouseButton.Left);
});
AddUntilStep("wait for import to start", () => Player.ScoreImportStarted);
AddStep("allow import", () => Player.AllowImportCompletion.Release());
AddUntilStep("import completed", () => Player.ImportedScore, () => Is.Not.Null);
AddAssert("ensure no submission", () => Player.SubmittedScore, () => Is.Null);
}
[Test]
public void TestSubmissionOnFail()
{
@ -378,6 +405,8 @@ namespace osu.Game.Tests.Visual.Gameplay
public SemaphoreSlim AllowImportCompletion { get; }
public Score ImportedScore { get; private set; }
public new FailOverlay FailOverlay => base.FailOverlay;
public FakeImportingPlayer(bool allowPause = true, bool showResults = true, bool pauseOnFocusLost = false)
: base(allowPause, showResults, pauseOnFocusLost)
{

View File

@ -66,8 +66,8 @@ namespace osu.Game.Tests.Visual.Online
[Test]
public void TestPlayCountRankingTier()
{
AddAssert("1 before silver", () => DailyChallengeStatsDisplay.TierForPlayCount(30) == RankingTier.Bronze);
AddAssert("first silver", () => DailyChallengeStatsDisplay.TierForPlayCount(31) == RankingTier.Silver);
AddAssert("1 before silver", () => DailyChallengeStatsTooltip.TierForPlayCount(30) == RankingTier.Bronze);
AddAssert("first silver", () => DailyChallengeStatsTooltip.TierForPlayCount(31) == RankingTier.Silver);
}
}
}

View File

@ -520,6 +520,17 @@ namespace osu.Game.Tests.Visual.SongSelect
waitForSelection(set_count);
}
[Test]
public void TestDifficultiesSplitOutOnLoad()
{
loadBeatmaps(new List<BeatmapSetInfo> { TestResources.CreateTestBeatmapSetInfo(diff_count) }, () => new FilterCriteria
{
Sort = SortMode.Difficulty,
});
checkVisibleItemCount(false, 3);
}
[Test]
public void TestAddRemoveDifficultySort()
{
@ -1120,6 +1131,32 @@ namespace osu.Game.Tests.Visual.SongSelect
AddAssert("Selection was remembered", () => eagerSelectedIDs.Count == 1);
}
[Test]
public void TestCarouselRetainsSelectionFromDifficultySort()
{
List<BeatmapSetInfo> manySets = new List<BeatmapSetInfo>();
AddStep("Populate beatmap sets", () =>
{
manySets.Clear();
for (int i = 1; i <= 50; i++)
manySets.Add(TestResources.CreateTestBeatmapSetInfo(diff_count));
});
loadBeatmaps(manySets);
BeatmapInfo chosenBeatmap = null!;
AddStep("select given beatmap", () => carousel.SelectBeatmap(chosenBeatmap = manySets[20].Beatmaps[0]));
AddUntilStep("selection changed", () => carousel.SelectedBeatmapInfo, () => Is.EqualTo(chosenBeatmap));
AddStep("sort by difficulty", () => carousel.FilterImmediately(new FilterCriteria { Sort = SortMode.Difficulty }));
AddAssert("selection retained", () => carousel.SelectedBeatmapInfo, () => Is.EqualTo(chosenBeatmap));
AddStep("sort by title", () => carousel.FilterImmediately(new FilterCriteria { Sort = SortMode.Title }));
AddAssert("selection retained", () => carousel.SelectedBeatmapInfo, () => Is.EqualTo(chosenBeatmap));
}
[Test]
public void TestFilteringByUserStarDifficulty()
{

View File

@ -242,7 +242,7 @@ namespace osu.Game.Overlays.BeatmapSet
title.Clear();
artist.Clear();
title.AddLink(titleText, LinkAction.SearchBeatmapSet, titleText);
title.AddLink(titleText, LinkAction.SearchBeatmapSet, $@"title=""""{titleText}""""");
title.AddArbitraryDrawable(Empty().With(d => d.Width = 5));
title.AddArbitraryDrawable(externalLink = new ExternalLinkButton());
@ -259,7 +259,7 @@ namespace osu.Game.Overlays.BeatmapSet
title.AddArbitraryDrawable(new SpotlightBeatmapBadge());
}
artist.AddLink(artistText, LinkAction.SearchBeatmapSet, artistText);
artist.AddLink(artistText, LinkAction.SearchBeatmapSet, $@"artist=""""{artistText}""""");
if (setInfo.NewValue.TrackId != null)
{

View File

@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.LocalisationExtensions;
@ -14,7 +13,6 @@ using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Localisation;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Scoring;
namespace osu.Game.Overlays.Profile.Header.Components
{
@ -99,7 +97,7 @@ namespace osu.Game.Overlays.Profile.Header.Components
private void updateDisplay()
{
if (User.Value == null || User.Value.Ruleset.OnlineID != 0)
if (User.Value == null)
{
Hide();
return;
@ -107,19 +105,20 @@ namespace osu.Game.Overlays.Profile.Header.Components
APIUserDailyChallengeStatistics stats = User.Value.User.DailyChallengeStatistics;
if (stats.PlayCount == 0)
{
Hide();
return;
}
dailyPlayCount.Text = DailyChallengeStatsDisplayStrings.UnitDay(stats.PlayCount.ToLocalisableString("N0"));
dailyPlayCount.Colour = colours.ForRankingTier(TierForPlayCount(stats.PlayCount));
dailyPlayCount.Colour = colours.ForRankingTier(DailyChallengeStatsTooltip.TierForPlayCount(stats.PlayCount));
TooltipContent = new DailyChallengeTooltipData(colourProvider, stats);
Show();
}
// Rounding up is needed here to ensure the overlay shows the same colour as osu-web for the play count.
// This is because, for example, 31 / 3 > 10 in JavaScript because floats are used, while here it would
// get truncated to 10 with an integer division and show a lower tier.
public static RankingTier TierForPlayCount(int playCount) => DailyChallengeStatsTooltip.TierForDaily((int)Math.Ceiling(playCount / 3.0d));
public ITooltip<DailyChallengeTooltipData> GetCustomTooltip() => new DailyChallengeStatsTooltip();
}
}

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Extensions.LocalisationExtensions;
@ -26,6 +27,7 @@ namespace osu.Game.Overlays.Profile.Header.Components
{
private StreakPiece currentDaily = null!;
private StreakPiece currentWeekly = null!;
private StreakPiece totalParticipation = null!;
private StatisticsPiece bestDaily = null!;
private StatisticsPiece bestWeekly = null!;
private StatisticsPiece topTen = null!;
@ -80,6 +82,7 @@ namespace osu.Game.Overlays.Profile.Header.Components
Spacing = new Vector2(30f),
Children = new[]
{
totalParticipation = new StreakPiece(UsersStrings.ShowDailyChallengePlaycount),
currentDaily = new StreakPiece(UsersStrings.ShowDailyChallengeDailyStreakCurrent),
currentWeekly = new StreakPiece(UsersStrings.ShowDailyChallengeWeeklyStreakCurrent),
}
@ -113,6 +116,9 @@ namespace osu.Game.Overlays.Profile.Header.Components
background.Colour = colourProvider.Background4;
topBackground.Colour = colourProvider.Background5;
totalParticipation.Value = DailyChallengeStatsDisplayStrings.UnitDay(statistics.PlayCount.ToLocalisableString(@"N0"));
totalParticipation.ValueColour = colours.ForRankingTier(TierForPlayCount(statistics.PlayCount));
currentDaily.Value = DailyChallengeStatsDisplayStrings.UnitDay(content.Statistics.DailyStreakCurrent.ToLocalisableString(@"N0"));
currentDaily.ValueColour = colours.ForRankingTier(TierForDaily(statistics.DailyStreakCurrent));
@ -132,7 +138,13 @@ namespace osu.Game.Overlays.Profile.Header.Components
topFifty.ValueColour = colourProvider.Content2;
}
// reference: https://github.com/ppy/osu-web/blob/8206e0e91eeea80ccf92f0586561346dd40e085e/resources/js/profile-page/daily-challenge.tsx#L13-L43
// reference: https://github.com/ppy/osu-web/blob/adf1e94754ba9625b85eba795f4a310caf169eec/resources/js/profile-page/daily-challenge.tsx#L13-L47
// Rounding up is needed here to ensure the overlay shows the same colour as osu-web for the play count.
// This is because, for example, 31 / 3 > 10 in JavaScript because floats are used, while here it would
// get truncated to 10 with an integer division and show a lower tier.
public static RankingTier TierForPlayCount(int playCount) => TierForDaily((int)Math.Ceiling(playCount / 3.0d));
public static RankingTier TierForDaily(int daily)
{
if (daily > 360)

View File

@ -7,17 +7,21 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Overlays;
using osuTK;
namespace osu.Game.Screens.Edit.Timing
{
public partial class ControlPointList : CompositeDrawable
{
private ControlPointTable table = null!;
private Container controls = null!;
private OsuButton deleteButton = null!;
private RoundedButton addButton = null!;
@ -31,63 +35,77 @@ namespace osu.Game.Screens.Edit.Timing
private Bindable<ControlPointGroup?> selectedGroup { get; set; } = null!;
[BackgroundDependencyLoader]
private void load(OsuColour colours)
private void load(OsuColour colours, OverlayColourProvider colourProvider)
{
RelativeSizeAxes = Axes.Both;
const float margins = 10;
InternalChildren = new Drawable[]
{
new ControlPointTable
table = new ControlPointTable
{
RelativeSizeAxes = Axes.Both,
Groups = { BindTarget = Beatmap.ControlPointInfo.Groups, },
},
new FillFlowContainer
controls = new Container
{
AutoSizeAxes = Axes.Both,
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Direction = FillDirection.Horizontal,
Margin = new MarginPadding(margins),
Spacing = new Vector2(5),
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
Children = new Drawable[]
{
new RoundedButton
new Box
{
Text = "Select closest to current time",
Action = goToCurrentGroup,
Size = new Vector2(220, 30),
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
RelativeSizeAxes = Axes.Both,
Colour = colourProvider.Background2,
},
}
},
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
Direction = FillDirection.Horizontal,
Margin = new MarginPadding(margins),
Spacing = new Vector2(5),
Children = new Drawable[]
{
deleteButton = new RoundedButton
new FillFlowContainer
{
Text = "-",
Size = new Vector2(30, 30),
Action = delete,
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
BackgroundColour = colours.Red3,
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Padding = new MarginPadding { Left = margins, Vertical = margins, },
Children = new Drawable[]
{
new RoundedButton
{
Text = "Select closest to current time",
Action = goToCurrentGroup,
Size = new Vector2(220, 30),
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
},
}
},
addButton = new RoundedButton
new FillFlowContainer
{
Action = addNew,
Size = new Vector2(160, 30),
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Spacing = new Vector2(5),
Padding = new MarginPadding { Right = margins, Vertical = margins, },
Children = new Drawable[]
{
deleteButton = new RoundedButton
{
Text = "-",
Size = new Vector2(30, 30),
Action = delete,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
BackgroundColour = colours.Red3,
},
addButton = new RoundedButton
{
Action = addNew,
Size = new Vector2(160, 30),
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
},
}
},
}
},
@ -119,6 +137,7 @@ namespace osu.Game.Screens.Edit.Timing
base.Update();
addButton.Enabled.Value = clock.CurrentTimeAccurate != selectedGroup.Value?.Time;
table.Padding = new MarginPadding { Bottom = controls.DrawHeight };
}
private void goToCurrentGroup()

View File

@ -28,6 +28,12 @@ namespace osu.Game.Screens.Edit.Timing
{
public BindableList<ControlPointGroup> Groups { get; } = new BindableList<ControlPointGroup>();
public new MarginPadding Padding
{
get => base.Padding;
set => base.Padding = value;
}
[Cached]
private Bindable<TimingControlPoint?> activeTimingPoint { get; } = new Bindable<TimingControlPoint?>();

View File

@ -56,7 +56,7 @@ namespace osu.Game.Screens.Edit.Timing
isRebinding = true;
kiai.Current = newEffectPoint.KiaiModeBindable;
scrollSpeedSlider.Current = new BindableDouble
scrollSpeedSlider.Current = new BindableDouble(1)
{
MinValue = 0.01,
MaxValue = 10,

View File

@ -5,6 +5,7 @@ using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Screens;
using osu.Game.Beatmaps.Drawables.Cards;
using osu.Game.Configuration;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Rooms;
using osu.Game.Overlays.Notifications;
@ -25,13 +26,17 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
}
[BackgroundDependencyLoader]
private void load(OsuGame? game)
private void load(OsuGame? game, SessionStatics statics)
{
Text = DailyChallengeStrings.ChallengeLiveNotification;
Content.Add(card = new BeatmapCardNano((APIBeatmapSet)room.Playlist.Single().Beatmap.BeatmapSet!));
Activated = () =>
{
game?.PerformFromScreen(s => s.Push(new DailyChallenge(room)), [typeof(MainMenu)]);
if (statics.Get<bool>(Static.DailyChallengeIntroPlayed))
game?.PerformFromScreen(s => s.Push(new DailyChallenge(room)), [typeof(MainMenu)]);
else
game?.PerformFromScreen(s => s.Push(new DailyChallengeIntro(room)), [typeof(MainMenu)]);
return true;
};
}

View File

@ -274,6 +274,16 @@ namespace osu.Game.Screens.Play
return Task.CompletedTask;
}
// if the user never hit anything, this score should not be counted in any way.
if (!score.ScoreInfo.Statistics.Any(s => s.Key.IsHit() && s.Value > 0))
{
Logger.Log("No hits registered, skipping score submission");
return Task.CompletedTask;
}
// mind the timing of this.
// once `scoreSubmissionSource` is created, it is presumed that submission is taking place in the background,
// so all exceptional circumstances that would disallow submission must be handled above.
lock (scoreSubmissionLock)
{
if (scoreSubmissionSource != null)
@ -282,10 +292,6 @@ namespace osu.Game.Screens.Play
scoreSubmissionSource = new TaskCompletionSource<bool>();
}
// if the user never hit anything, this score should not be counted in any way.
if (!score.ScoreInfo.Statistics.Any(s => s.Key.IsHit() && s.Value > 0))
return Task.CompletedTask;
Logger.Log($"Beginning score submission (token:{token.Value})...");
var request = CreateSubmissionRequest(score, token.Value);

View File

@ -39,6 +39,7 @@ namespace osu.Game.Screens.Ranking
new OsuMenu(Direction.Vertical, true)
{
Items = items,
MaxHeight = 375,
},
};
}

View File

@ -137,11 +137,13 @@ namespace osu.Game.Screens.Select
private void loadNewRoot()
{
beatmapsSplitOut = activeCriteria.SplitOutDifficulties;
// Ensure no changes are made to the list while we are initialising items.
// We'll catch up on changes via subscriptions anyway.
BeatmapSetInfo[] loadableSets = detachedBeatmapSets!.ToArray();
if (selectedBeatmapSet != null && !loadableSets.Contains(selectedBeatmapSet.BeatmapSet))
if (selectedBeatmapSet != null && !loadableSets.Contains(selectedBeatmapSet.BeatmapSet, EqualityComparer<BeatmapSetInfo>.Default))
selectedBeatmapSet = null;
var selectedBeatmapBefore = selectedBeatmap?.BeatmapInfo;
@ -726,7 +728,6 @@ namespace osu.Game.Screens.Select
if (activeCriteria.SplitOutDifficulties != beatmapsSplitOut)
{
beatmapsSplitOut = activeCriteria.SplitOutDifficulties;
loadNewRoot();
return;
}

View File

@ -35,7 +35,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Realm" Version="11.5.0" />
<PackageReference Include="ppy.osu.Framework" Version="2024.904.0" />
<PackageReference Include="ppy.osu.Framework" Version="2024.907.1" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2024.904.0" />
<PackageReference Include="Sentry" Version="4.3.0" />
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->

View File

@ -17,6 +17,6 @@
<MtouchInterpreter>-all</MtouchInterpreter>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ppy.osu.Framework.iOS" Version="2024.904.0" />
<PackageReference Include="ppy.osu.Framework.iOS" Version="2024.907.1" />
</ItemGroup>
</Project>