1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 05:02:55 +08:00

Add client/server models for allowing clients to receive realtime playlist updates

This commit is contained in:
Bartłomiej Dach 2024-06-27 10:44:28 +02:00
parent 00d66ad561
commit d6e7781be1
No known key found for this signature in database
8 changed files with 139 additions and 1 deletions

View File

@ -26,5 +26,11 @@ namespace osu.Game.Online.Metadata
/// Null value means there is no "daily challenge" currently active.
/// </summary>
Task DailyChallengeUpdated(DailyChallengeInfo? info);
/// <summary>
/// Delivers information that a multiplayer score was set in a watched room.
/// To receive these, the client must call <see cref="IMetadataServer.BeginWatchingMultiplayerRoom"/> for a given room first.
/// </summary>
Task MultiplayerRoomScoreSet(MultiplayerRoomScoreSetEvent roomScoreSetEvent);
}
}

View File

@ -43,5 +43,15 @@ namespace osu.Game.Online.Metadata
/// Signals to the server that the current user would like to stop receiving updates on other users' online presence.
/// </summary>
Task EndWatchingUserPresence();
/// <summary>
/// Signals to the server that the current user would like to begin receiving updates about the state of the multiplayer room with the given <paramref name="id"/>.
/// </summary>
Task<MultiplayerPlaylistItemStats[]> BeginWatchingMultiplayerRoom(long id);
/// <summary>
/// Signals to the server that the current user would like to stop receiving updates about the state of the multiplayer room with the given <paramref name="id"/>.
/// </summary>
Task EndWatchingMultiplayerRoom(long id);
}
}

View File

@ -68,6 +68,24 @@ namespace osu.Game.Online.Metadata
#endregion
#region Multiplayer room watching
public abstract Task<MultiplayerPlaylistItemStats[]> BeginWatchingMultiplayerRoom(long id);
public abstract Task EndWatchingMultiplayerRoom(long id);
public event Action<MultiplayerRoomScoreSetEvent>? MultiplayerRoomScoreSet;
Task IMetadataClient.MultiplayerRoomScoreSet(MultiplayerRoomScoreSetEvent roomScoreSetEvent)
{
if (MultiplayerRoomScoreSet != null)
Schedule(MultiplayerRoomScoreSet, roomScoreSetEvent);
return Task.CompletedTask;
}
#endregion
#region Disconnection handling
public event Action? Disconnecting;

View File

@ -0,0 +1,29 @@
// 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 MessagePack;
namespace osu.Game.Online.Metadata
{
[MessagePackObject]
[Serializable]
public class MultiplayerPlaylistItemStats
{
public const int TOTAL_SCORE_DISTRIBUTION_BINS = 13;
/// <summary>
/// The ID of the playlist item which these stats pertain to.
/// </summary>
[Key(0)]
public long PlaylistItemID { get; set; }
/// <summary>
/// The count of scores with given total ranges in the room.
/// The ranges are bracketed into <see cref="TOTAL_SCORE_DISTRIBUTION_BINS"/> bins, each of 100,000 score width.
/// The last bin will contain count of all scores with total of 1,200,000 or larger.
/// </summary>
[Key(1)]
public long[] TotalScoreDistribution { get; set; } = new long[TOTAL_SCORE_DISTRIBUTION_BINS];
}
}

View File

@ -0,0 +1,50 @@
// 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 MessagePack;
namespace osu.Game.Online.Metadata
{
[Serializable]
[MessagePackObject]
public class MultiplayerRoomScoreSetEvent
{
/// <summary>
/// The ID of the room in which the score was set.
/// </summary>
[Key(0)]
public long RoomID { get; set; }
/// <summary>
/// The ID of the playlist item on which the score was set.
/// </summary>
[Key(1)]
public long PlaylistItemID { get; set; }
/// <summary>
/// The ID of the score set.
/// </summary>
[Key(2)]
public long ScoreID { get; set; }
/// <summary>
/// The ID of the user who set the score.
/// </summary>
[Key(3)]
public int UserID { get; set; }
/// <summary>
/// The total score set by the player.
/// </summary>
[Key(4)]
public long TotalScore { get; set; }
/// <summary>
/// If the set score is the user's new best on a playlist item, this member will contain the user's new rank in the room overall.
/// Otherwise, it will contain <see langword="null"/>.
/// </summary>
[Key(5)]
public int? NewRank { get; set; }
}
}

View File

@ -62,6 +62,7 @@ namespace osu.Game.Online.Metadata
connection.On<BeatmapUpdates>(nameof(IMetadataClient.BeatmapSetsUpdated), ((IMetadataClient)this).BeatmapSetsUpdated);
connection.On<int, UserPresence?>(nameof(IMetadataClient.UserPresenceUpdated), ((IMetadataClient)this).UserPresenceUpdated);
connection.On<DailyChallengeInfo?>(nameof(IMetadataClient.DailyChallengeUpdated), ((IMetadataClient)this).DailyChallengeUpdated);
connection.On<MultiplayerRoomScoreSetEvent>(nameof(IMetadataClient.MultiplayerRoomScoreSet), ((IMetadataClient)this).MultiplayerRoomScoreSet);
connection.On(nameof(IStatefulUserHubClient.DisconnectRequested), ((IMetadataClient)this).DisconnectRequested);
};
@ -240,6 +241,24 @@ namespace osu.Game.Online.Metadata
return Task.CompletedTask;
}
public override async Task<MultiplayerPlaylistItemStats[]> BeginWatchingMultiplayerRoom(long id)
{
if (connector?.IsConnected.Value != true)
throw new OperationCanceledException();
Debug.Assert(connection != null);
return await connection.InvokeAsync<MultiplayerPlaylistItemStats[]>(nameof(IMetadataServer.BeginWatchingMultiplayerRoom), id).ConfigureAwait(false);
}
public override async Task EndWatchingMultiplayerRoom(long id)
{
if (connector?.IsConnected.Value != true)
throw new OperationCanceledException();
Debug.Assert(connection != null);
await connection.InvokeAsync(nameof(IMetadataServer.EndWatchingMultiplayerRoom)).ConfigureAwait(false);
}
public override async Task DisconnectRequested()
{
await base.DisconnectRequested().ConfigureAwait(false);

View File

@ -11,6 +11,7 @@ using osu.Framework.Localisation;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.Metadata;
using osu.Game.Overlays;
using osu.Game.Scoring;
using osuTK;
@ -21,7 +22,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
{
private FillFlowContainer<Bar> barsContainer = null!;
private const int bin_count = 13;
private const int bin_count = MultiplayerPlaylistItemStats.TOTAL_SCORE_DISTRIBUTION_BINS;
private long[] bins = new long[bin_count];
[BackgroundDependencyLoader]

View File

@ -86,5 +86,10 @@ namespace osu.Game.Tests.Visual.Metadata
dailyChallengeInfo.Value = info;
return Task.CompletedTask;
}
public override Task<MultiplayerPlaylistItemStats[]> BeginWatchingMultiplayerRoom(long id)
=> Task.FromResult(new MultiplayerPlaylistItemStats[MultiplayerPlaylistItemStats.TOTAL_SCORE_DISTRIBUTION_BINS]);
public override Task EndWatchingMultiplayerRoom(long id) => Task.CompletedTask;
}
}