1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-13 19:27:31 +08:00

Use room watching functionality to receive realtime daily challenge updates

This commit is contained in:
Bartłomiej Dach 2024-06-04 15:36:30 +02:00
parent 81c6da98c2
commit df97215298
No known key found for this signature in database
8 changed files with 183 additions and 35 deletions

View File

@ -11,10 +11,11 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Utils;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Rooms;
using osu.Game.Overlays;
using osu.Game.Screens.OnlinePlay.DailyChallenge;
using osu.Game.Tests.Resources;
using osu.Game.Screens.OnlinePlay.DailyChallenge.Events;
namespace osu.Game.Tests.Visual.DailyChallenge
{
@ -129,19 +130,27 @@ namespace osu.Game.Tests.Visual.DailyChallenge
});
AddStep("add normal score", () =>
{
var testScore = TestResources.CreateTestScoreInfo();
testScore.TotalScore = RNG.Next(1_000_000);
var ev = new NewScoreEvent(1, new APIUser
{
Id = 2,
Username = "peppy",
CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
}, RNG.Next(1_000_000), null);
feed.AddNewScore(new DailyChallengeEventFeed.NewScoreEvent(testScore, null));
breakdown.AddNewScore(testScore);
feed.AddNewScore(ev);
breakdown.AddNewScore(ev);
});
AddStep("add new user best", () =>
{
var testScore = TestResources.CreateTestScoreInfo();
testScore.TotalScore = RNG.Next(1_000_000);
var ev = new NewScoreEvent(1, new APIUser
{
Id = 2,
Username = "peppy",
CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
}, RNG.Next(1_000_000), RNG.Next(1, 1000));
feed.AddNewScore(new DailyChallengeEventFeed.NewScoreEvent(testScore, RNG.Next(1, 1000)));
breakdown.AddNewScore(testScore);
feed.AddNewScore(ev);
breakdown.AddNewScore(ev);
});
}

View File

@ -7,8 +7,10 @@ using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Utils;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Screens.OnlinePlay.DailyChallenge;
using osu.Game.Screens.OnlinePlay.DailyChallenge.Events;
using osu.Game.Tests.Resources;
namespace osu.Game.Tests.Visual.DailyChallenge
@ -50,26 +52,41 @@ namespace osu.Game.Tests.Visual.DailyChallenge
AddStep("add normal score", () =>
{
var testScore = TestResources.CreateTestScoreInfo();
testScore.TotalScore = RNG.Next(1_000_000);
var ev = new NewScoreEvent(1, new APIUser
{
Id = 2,
Username = "peppy",
CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
}, RNG.Next(1_000_000), null);
feed.AddNewScore(new DailyChallengeEventFeed.NewScoreEvent(testScore, null));
feed.AddNewScore(ev);
});
AddStep("add new user best", () =>
{
var ev = new NewScoreEvent(1, new APIUser
{
Id = 2,
Username = "peppy",
CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
}, RNG.Next(1_000_000), RNG.Next(11, 1000));
var testScore = TestResources.CreateTestScoreInfo();
testScore.TotalScore = RNG.Next(1_000_000);
feed.AddNewScore(new DailyChallengeEventFeed.NewScoreEvent(testScore, RNG.Next(1, 1000)));
feed.AddNewScore(ev);
});
AddStep("add top 10 score", () =>
{
var testScore = TestResources.CreateTestScoreInfo();
testScore.TotalScore = RNG.Next(1_000_000);
var ev = new NewScoreEvent(1, new APIUser
{
Id = 2,
Username = "peppy",
CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
}, RNG.Next(1_000_000), RNG.Next(1, 10));
feed.AddNewScore(new DailyChallengeEventFeed.NewScoreEvent(testScore, RNG.Next(1, 10)));
feed.AddNewScore(ev);
});
}
}

View File

@ -7,9 +7,10 @@ using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Utils;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Screens.OnlinePlay.DailyChallenge;
using osu.Game.Tests.Resources;
using osu.Game.Screens.OnlinePlay.DailyChallenge.Events;
namespace osu.Game.Tests.Visual.DailyChallenge
{
@ -51,10 +52,14 @@ namespace osu.Game.Tests.Visual.DailyChallenge
AddStep("set initial data", () => breakdown.SetInitialCounts([1, 4, 9, 16, 25, 36, 49, 36, 25, 16, 9, 4, 1]));
AddStep("add new score", () =>
{
var testScore = TestResources.CreateTestScoreInfo();
testScore.TotalScore = RNG.Next(1_000_000);
var ev = new NewScoreEvent(1, new APIUser
{
Id = 2,
Username = "peppy",
CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
}, RNG.Next(1_000_000), null);
breakdown.AddNewScore(testScore);
breakdown.AddNewScore(ev);
});
}
}

View File

@ -256,7 +256,7 @@ namespace osu.Game.Online.Metadata
throw new OperationCanceledException();
Debug.Assert(connection != null);
await connection.InvokeAsync(nameof(IMetadataServer.EndWatchingMultiplayerRoom)).ConfigureAwait(false);
await connection.InvokeAsync(nameof(IMetadataServer.EndWatchingMultiplayerRoom), id).ConfigureAwait(false);
}
public override async Task DisconnectRequested()

View File

@ -8,21 +8,29 @@ using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Logging;
using osu.Framework.Screens;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Metadata;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Rooms;
using osu.Game.Overlays;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Screens.OnlinePlay.Components;
using osu.Game.Screens.OnlinePlay.DailyChallenge.Events;
using osu.Game.Screens.OnlinePlay.Match;
using osu.Game.Screens.OnlinePlay.Match.Components;
using osu.Game.Screens.OnlinePlay.Playlists;
@ -47,6 +55,9 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
private Sample? sampleStart;
private IDisposable? userModsSelectOverlayRegistration;
private DailyChallengeScoreBreakdown breakdown = null!;
private DailyChallengeEventFeed feed = null!;
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Plum);
@ -68,6 +79,12 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
[Resolved]
private IOverlayManager? overlayManager { get; set; }
[Resolved]
private MetadataClient metadataClient { get; set; } = null!;
[Resolved]
private UserLookupCache userLookupCache { get; set; } = null!;
public override bool DisallowExternalBeatmapRulesetChanges => true;
public DailyChallenge(Room room)
@ -162,9 +179,39 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
{
new Drawable?[]
{
new DailyChallengeTimeRemainingRing
new GridContainer
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RowDimensions =
[
new Dimension(),
new Dimension()
],
Content = new[]
{
new Drawable[]
{
new DailyChallengeCarousel
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Children = new Drawable[]
{
new DailyChallengeTimeRemainingRing(),
breakdown = new DailyChallengeScoreBreakdown(),
}
}
},
[
feed = new DailyChallengeEventFeed
{
RelativeSizeAxes = Axes.Both,
}
],
},
},
null,
// Middle column (leaderboard)
@ -275,6 +322,33 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
var allowedMods = playlistItem.AllowedMods.Select(m => m.ToMod(rulesetInstance));
userModsSelectOverlay.IsValidMod = m => allowedMods.Any(a => a.GetType() == m.GetType());
}
metadataClient.MultiplayerRoomScoreSet += onRoomScoreSet;
}
private void onRoomScoreSet(MultiplayerRoomScoreSetEvent e)
{
if (e.RoomID != room.RoomID.Value || e.PlaylistItemID != playlistItem.ID)
return;
userLookupCache.GetUserAsync(e.UserID).ContinueWith(t =>
{
if (t.Exception != null)
{
Logger.Log($@"Could not display room score set event: {t.Exception}", LoggingTarget.Network);
return;
}
APIUser? user = t.GetResultSafely();
if (user == null) return;
var ev = new NewScoreEvent(e.ScoreID, user, e.TotalScore, e.NewRank);
Schedule(() =>
{
breakdown.AddNewScore(ev);
feed.AddNewScore(ev);
});
});
}
protected override void LoadComplete()
@ -294,6 +368,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
var beatmap = beatmapManager.QueryBeatmap(b => b.OnlineID == playlistItem.Beatmap.OnlineID);
Beatmap.Value = beatmapManager.GetWorkingBeatmap(beatmap); // this will gracefully fall back to dummy beatmap if missing locally.
Ruleset.Value = rulesets.GetRuleset(playlistItem.RulesetID);
applyLoopingToTrack();
}
public override void OnEntering(ScreenTransitionEvent e)
@ -303,6 +378,25 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
waves.Show();
roomManager.JoinRoom(room);
applyLoopingToTrack();
metadataClient.BeginWatchingMultiplayerRoom(room.RoomID.Value!.Value).ContinueWith(t =>
{
if (t.Exception != null)
{
Logger.Error(t.Exception, @"Failed to subscribe to room updates", LoggingTarget.Network);
return;
}
MultiplayerPlaylistItemStats[] stats = t.GetResultSafely();
var itemStats = stats.SingleOrDefault(item => item.PlaylistItemID == playlistItem.ID);
if (itemStats == null) return;
Schedule(() => breakdown.SetInitialCounts(itemStats.TotalScoreDistribution));
});
beatmapAvailabilityTracker.SelectedItem.Value = playlistItem;
beatmapAvailabilityTracker.Availability.BindValueChanged(_ => trySetDailyChallengeBeatmap(), true);
userModsSelectOverlay.SelectedItem.Value = playlistItem;
}
public override void OnResuming(ScreenTransitionEvent e)
@ -327,6 +421,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
this.Delay(WaveContainer.DISAPPEAR_DURATION).FadeOut();
roomManager.PartRoom();
metadataClient.EndWatchingMultiplayerRoom(room.RoomID.Value!.Value).FireAndForget();
return base.OnExiting(e);
}
@ -375,6 +470,9 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
base.Dispose(isDisposing);
userModsSelectOverlayRegistration?.Dispose();
if (metadataClient.IsNotNull())
metadataClient.MultiplayerRoomScoreSet -= onRoomScoreSet;
}
}
}

View File

@ -9,8 +9,7 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Scoring;
using osu.Game.Screens.OnlinePlay.DailyChallenge.Events;
using osu.Game.Users.Drawables;
using osuTK;
@ -70,8 +69,6 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
}
}
public record NewScoreEvent(IScoreInfo Score, int? NewRank);
private partial class DailyChallengeEventFeedFlow : FillFlowContainer
{
public override IEnumerable<Drawable> FlowingChildren => base.FlowingChildren.Reverse();
@ -98,8 +95,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
InternalChildren = new Drawable[]
{
// TODO: cast is temporary, will be removed later
new ClickableAvatar((APIUser)newScore.Score.User)
new ClickableAvatar(newScore.User)
{
Size = new Vector2(16),
Masking = true,
@ -117,9 +113,9 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
}
};
text.AddUserLink(newScore.Score.User);
text.AddUserLink(newScore.User);
text.AddText(" got ");
text.AddLink($"{newScore.Score.TotalScore:N0} points", () => { }); // TODO: present the score here
text.AddLink($"{newScore.TotalScore:N0} points", () => { }); // TODO: present the score here
if (newScore.NewRank != null)
text.AddText($" and achieved rank #{newScore.NewRank.Value:N0}");

View File

@ -13,7 +13,7 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.Metadata;
using osu.Game.Overlays;
using osu.Game.Scoring;
using osu.Game.Screens.OnlinePlay.DailyChallenge.Events;
using osuTK;
namespace osu.Game.Screens.OnlinePlay.DailyChallenge
@ -67,15 +67,15 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
}
}
public void AddNewScore(IScoreInfo scoreInfo)
public void AddNewScore(NewScoreEvent newScoreEvent)
{
int targetBin = (int)Math.Clamp(Math.Floor((float)scoreInfo.TotalScore / 100000), 0, bin_count - 1);
int targetBin = (int)Math.Clamp(Math.Floor((float)newScoreEvent.TotalScore / 100000), 0, bin_count - 1);
bins[targetBin] += 1;
updateCounts();
var text = new OsuSpriteText
{
Text = scoreInfo.TotalScore.ToString(@"N0"),
Text = newScoreEvent.TotalScore.ToString(@"N0"),
Anchor = Anchor.TopCentre,
Origin = Anchor.BottomCentre,
Font = OsuFont.Default.With(size: 30),
@ -108,7 +108,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
private void updateCounts()
{
long max = bins.Max();
long max = Math.Max(bins.Max(), 1);
for (int i = 0; i < bin_count; ++i)
barsContainer[i].UpdateCounts(bins[i], max);
}

View File

@ -0,0 +1,23 @@
// 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 osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Screens.OnlinePlay.DailyChallenge.Events
{
public class NewScoreEvent
{
public NewScoreEvent(long scoreID, APIUser user, long totalScore, int? newRank)
{
ScoreID = scoreID;
User = user;
TotalScore = totalScore;
NewRank = newRank;
}
public long ScoreID { get; }
public APIUser User { get; }
public long TotalScore { get; }
public int? NewRank { get; }
}
}