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:
parent
81c6da98c2
commit
df97215298
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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}");
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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; }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user