mirror of
https://github.com/ppy/osu.git
synced 2025-01-14 00:42:55 +08:00
Merge branch 'master' into mod-overlay/panel
This commit is contained in:
commit
769dc9b00b
@ -18,7 +18,6 @@
|
||||
<ItemGroup Label="Code Analysis">
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3" PrivateAssets="All" />
|
||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)CodeAnalysis\BannedSymbols.txt" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="6.0.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Code Analysis">
|
||||
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)CodeAnalysis\osu.ruleset</CodeAnalysisRuleSet>
|
||||
|
@ -121,6 +121,17 @@ namespace osu.Game.Tests.Online
|
||||
Assert.That((deserialised?.Mods[0])?.Settings["speed_change"], Is.EqualTo(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAPIModDetachedFromSource()
|
||||
{
|
||||
var mod = new OsuModDoubleTime { SpeedChange = { Value = 1.01 } };
|
||||
var apiMod = new APIMod(mod);
|
||||
|
||||
mod.SpeedChange.Value = 1.5;
|
||||
|
||||
Assert.That(apiMod.Settings["speed_change"], Is.EqualTo(1.01d));
|
||||
}
|
||||
|
||||
private class TestRuleset : Ruleset
|
||||
{
|
||||
public override IEnumerable<Mod> GetModsFor(ModType type) => new Mod[]
|
||||
|
@ -36,6 +36,8 @@ namespace osu.Game.Online.API
|
||||
|
||||
public string WebsiteRootUrl { get; }
|
||||
|
||||
public int APIVersion => 20220217; // We may want to pull this from the game version eventually.
|
||||
|
||||
public Exception LastLoginError { get; private set; }
|
||||
|
||||
public string ProvidedUsername { get; private set; }
|
||||
|
@ -42,7 +42,7 @@ namespace osu.Game.Online.API
|
||||
var bindable = (IBindable)property.GetValue(mod);
|
||||
|
||||
if (!bindable.IsDefault)
|
||||
Settings.Add(property.Name.Underscore(), bindable);
|
||||
Settings.Add(property.Name.Underscore(), ModUtils.GetSettingUnderlyingValue(bindable));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.IO.Network;
|
||||
@ -112,6 +113,9 @@ namespace osu.Game.Online.API
|
||||
WebRequest = CreateWebRequest();
|
||||
WebRequest.Failed += Fail;
|
||||
WebRequest.AllowRetryOnTimeout = false;
|
||||
|
||||
WebRequest.AddHeader("x-api-version", API.APIVersion.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
if (!string.IsNullOrEmpty(API.AccessToken))
|
||||
WebRequest.AddHeader("Authorization", $"Bearer {API.AccessToken}");
|
||||
|
||||
|
@ -33,6 +33,8 @@ namespace osu.Game.Online.API
|
||||
|
||||
public string WebsiteRootUrl => "http://localhost";
|
||||
|
||||
public int APIVersion => int.Parse(DateTime.Now.ToString("yyyyMMdd"));
|
||||
|
||||
public Exception LastLoginError { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -57,6 +57,11 @@ namespace osu.Game.Online.API
|
||||
/// </summary>
|
||||
string WebsiteRootUrl { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The version of the API.
|
||||
/// </summary>
|
||||
int APIVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The last login error that occurred, if any.
|
||||
/// </summary>
|
||||
|
@ -12,6 +12,7 @@ using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Online.API.Requests.Responses
|
||||
{
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class APIUser : IEquatable<APIUser>, IUser
|
||||
{
|
||||
[JsonProperty(@"id")]
|
||||
|
@ -618,7 +618,7 @@ namespace osu.Game.Online.Chat
|
||||
var req = new MarkChannelAsReadRequest(channel, message);
|
||||
|
||||
req.Success += () => channel.LastReadId = message.Id;
|
||||
req.Failure += e => Logger.Error(e, $"Failed to mark channel {channel} up to '{message}' as read");
|
||||
req.Failure += e => Logger.Log($"Failed to mark channel {channel} up to '{message}' as read ({e.Message})", LoggingTarget.Network);
|
||||
|
||||
api.Queue(req);
|
||||
}
|
||||
|
@ -62,6 +62,10 @@ namespace osu.Game.Online.Rooms
|
||||
[JsonProperty("beatmap_id")]
|
||||
private int onlineBeatmapId => Beatmap.OnlineID;
|
||||
|
||||
/// <summary>
|
||||
/// A beatmap representing this playlist item.
|
||||
/// In many cases, this will *not* contain any usable information apart from OnlineID.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public IBeatmapInfo Beatmap { get; set; } = null!;
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
@ -15,6 +14,7 @@ using osu.Game.Utils;
|
||||
|
||||
namespace osu.Game.Online.Rooms
|
||||
{
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class Room : IDeepCloneable<Room>
|
||||
{
|
||||
[Cached]
|
||||
@ -37,8 +37,19 @@ namespace osu.Game.Online.Rooms
|
||||
[JsonProperty("channel_id")]
|
||||
public readonly Bindable<int> ChannelId = new Bindable<int>();
|
||||
|
||||
[JsonProperty("current_playlist_item")]
|
||||
[Cached]
|
||||
public readonly Bindable<PlaylistItem> CurrentPlaylistItem = new Bindable<PlaylistItem>();
|
||||
|
||||
[JsonProperty("playlist_item_stats")]
|
||||
[Cached]
|
||||
public readonly Bindable<RoomPlaylistItemStats> PlaylistItemStats = new Bindable<RoomPlaylistItemStats>();
|
||||
|
||||
[JsonProperty("difficulty_range")]
|
||||
[Cached]
|
||||
public readonly Bindable<RoomDifficultyRange> DifficultyRange = new Bindable<RoomDifficultyRange>();
|
||||
|
||||
[Cached]
|
||||
[JsonIgnore]
|
||||
public readonly Bindable<RoomCategory> Category = new Bindable<RoomCategory>();
|
||||
|
||||
// Todo: osu-framework bug (https://github.com/ppy/osu-framework/issues/4106)
|
||||
@ -51,19 +62,15 @@ namespace osu.Game.Online.Rooms
|
||||
}
|
||||
|
||||
[Cached]
|
||||
[JsonIgnore]
|
||||
public readonly Bindable<int?> MaxAttempts = new Bindable<int?>();
|
||||
|
||||
[Cached]
|
||||
[JsonIgnore]
|
||||
public readonly Bindable<RoomStatus> Status = new Bindable<RoomStatus>(new RoomStatusOpen());
|
||||
|
||||
[Cached]
|
||||
[JsonIgnore]
|
||||
public readonly Bindable<RoomAvailability> Availability = new Bindable<RoomAvailability>();
|
||||
|
||||
[Cached]
|
||||
[JsonIgnore]
|
||||
public readonly Bindable<MatchType> Type = new Bindable<MatchType>();
|
||||
|
||||
// Todo: osu-framework bug (https://github.com/ppy/osu-framework/issues/4106)
|
||||
@ -76,7 +83,6 @@ namespace osu.Game.Online.Rooms
|
||||
}
|
||||
|
||||
[Cached]
|
||||
[JsonIgnore]
|
||||
public readonly Bindable<QueueMode> QueueMode = new Bindable<QueueMode>();
|
||||
|
||||
[JsonConverter(typeof(SnakeCaseStringEnumConverter))]
|
||||
@ -88,7 +94,6 @@ namespace osu.Game.Online.Rooms
|
||||
}
|
||||
|
||||
[Cached]
|
||||
[JsonIgnore]
|
||||
public readonly Bindable<int?> MaxParticipants = new Bindable<int?>();
|
||||
|
||||
[Cached]
|
||||
@ -113,7 +118,6 @@ namespace osu.Game.Online.Rooms
|
||||
public readonly Bindable<string> Password = new Bindable<string>();
|
||||
|
||||
[Cached]
|
||||
[JsonIgnore]
|
||||
public readonly Bindable<TimeSpan?> Duration = new Bindable<TimeSpan?>();
|
||||
|
||||
[JsonProperty("duration")]
|
||||
@ -158,6 +162,8 @@ namespace osu.Game.Online.Rooms
|
||||
var copy = new Room();
|
||||
|
||||
copy.CopyFrom(this);
|
||||
|
||||
// ID must be unset as we use this as a marker for whether this is a client-side (not-yet-created) room or not.
|
||||
copy.RoomID.Value = null;
|
||||
|
||||
return copy;
|
||||
@ -183,6 +189,9 @@ namespace osu.Game.Online.Rooms
|
||||
EndDate.Value = other.EndDate.Value;
|
||||
UserScore.Value = other.UserScore.Value;
|
||||
QueueMode.Value = other.QueueMode.Value;
|
||||
DifficultyRange.Value = other.DifficultyRange.Value;
|
||||
PlaylistItemStats.Value = other.PlaylistItemStats.Value;
|
||||
CurrentPlaylistItem.Value = other.CurrentPlaylistItem.Value;
|
||||
|
||||
if (EndDate.Value != null && DateTimeOffset.Now >= EndDate.Value)
|
||||
Status.Value = new RoomStatusEnded();
|
||||
@ -211,21 +220,27 @@ namespace osu.Game.Online.Rooms
|
||||
Playlist.RemoveAll(i => i.Expired);
|
||||
}
|
||||
|
||||
#region Newtonsoft.Json implicit ShouldSerialize() methods
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class RoomPlaylistItemStats
|
||||
{
|
||||
[JsonProperty("count_active")]
|
||||
public int CountActive;
|
||||
|
||||
// The properties in this region are used implicitly by Newtonsoft.Json to not serialise certain fields in some cases.
|
||||
// They rely on being named exactly the same as the corresponding fields (casing included) and as such should NOT be renamed
|
||||
// unless the fields are also renamed.
|
||||
[JsonProperty("count_total")]
|
||||
public int CountTotal;
|
||||
|
||||
[UsedImplicitly]
|
||||
public bool ShouldSerializeRoomID() => false;
|
||||
[JsonProperty("ruleset_ids")]
|
||||
public int[] RulesetIDs;
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
public bool ShouldSerializeHost() => false;
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class RoomDifficultyRange
|
||||
{
|
||||
[JsonProperty("min")]
|
||||
public double Min;
|
||||
|
||||
[UsedImplicitly]
|
||||
public bool ShouldSerializeEndDate() => false;
|
||||
|
||||
#endregion
|
||||
[JsonProperty("max")]
|
||||
public double Max;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ namespace osu.Game.Online
|
||||
|
||||
// This should not be required. The fallback should work. But something is weird with the way caching is done.
|
||||
// For future adventurers, I would not advise looking into this further. It's likely not worth the effort.
|
||||
baseMap = baseMap.Concat(baseMap.Select(t => (t.baseType, t.baseType)));
|
||||
baseMap = baseMap.Concat(baseMap.Select(t => (t.baseType, t.baseType)).Distinct());
|
||||
|
||||
return new Dictionary<Type, IMessagePackFormatter>(baseMap.Select(t =>
|
||||
{
|
||||
|
@ -23,6 +23,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
{
|
||||
InternalChild = sprite = CreateBackgroundSprite();
|
||||
|
||||
CurrentPlaylistItem.BindValueChanged(_ => updateBeatmap());
|
||||
Playlist.CollectionChanged += (_, __) => updateBeatmap();
|
||||
|
||||
updateBeatmap();
|
||||
@ -30,7 +31,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
|
||||
private void updateBeatmap()
|
||||
{
|
||||
sprite.Beatmap.Value = Playlist.GetCurrentItem()?.Beatmap;
|
||||
sprite.Beatmap.Value = CurrentPlaylistItem.Value?.Beatmap ?? Playlist.GetCurrentItem()?.Beatmap;
|
||||
}
|
||||
|
||||
protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both };
|
||||
|
@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
@ -75,15 +74,29 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Playlist.BindCollectionChanged(updateRange, true);
|
||||
DifficultyRange.BindValueChanged(_ => updateRange());
|
||||
Playlist.BindCollectionChanged((_, __) => updateRange(), true);
|
||||
}
|
||||
|
||||
private void updateRange(object sender, NotifyCollectionChangedEventArgs e)
|
||||
private void updateRange()
|
||||
{
|
||||
var orderedDifficulties = Playlist.Select(p => p.Beatmap).OrderBy(b => b.StarRating).ToArray();
|
||||
StarDifficulty minDifficulty;
|
||||
StarDifficulty maxDifficulty;
|
||||
|
||||
StarDifficulty minDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[0].StarRating : 0, 0);
|
||||
StarDifficulty maxDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[^1].StarRating : 0, 0);
|
||||
if (DifficultyRange.Value != null)
|
||||
{
|
||||
minDifficulty = new StarDifficulty(DifficultyRange.Value.Min, 0);
|
||||
maxDifficulty = new StarDifficulty(DifficultyRange.Value.Max, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// In multiplayer rooms, the beatmaps of playlist items will not be populated to a point this can be correct.
|
||||
// Either populating them via BeatmapLookupCache or polling the API for the room's DifficultyRange will be required.
|
||||
var orderedDifficulties = Playlist.Select(p => p.Beatmap).OrderBy(b => b.StarRating).ToArray();
|
||||
|
||||
minDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[0].StarRating : 0, 0);
|
||||
maxDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[^1].StarRating : 0, 0);
|
||||
}
|
||||
|
||||
minDisplay.Current.Value = minDifficulty;
|
||||
maxDisplay.Current.Value = maxDifficulty;
|
||||
|
@ -388,7 +388,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
SelectedItem.BindValueChanged(onSelectedItemChanged, true);
|
||||
CurrentPlaylistItem.BindValueChanged(onSelectedItemChanged, true);
|
||||
}
|
||||
|
||||
private CancellationTokenSource beatmapLookupCancellation;
|
||||
|
@ -1,7 +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.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using Humanizer;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.LocalisationExtensions;
|
||||
@ -41,15 +41,22 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Playlist.BindCollectionChanged(updateCount, true);
|
||||
PlaylistItemStats.BindValueChanged(_ => updateCount());
|
||||
Playlist.BindCollectionChanged((_, __) => updateCount(), true);
|
||||
}
|
||||
|
||||
private void updateCount(object sender, NotifyCollectionChangedEventArgs e)
|
||||
private void updateCount()
|
||||
{
|
||||
int activeItems = Playlist.Count > 0 || PlaylistItemStats.Value == null
|
||||
// For now, use the playlist as the source of truth if it has any items.
|
||||
// This allows the count to display correctly on the room screen (after joining a room).
|
||||
? Playlist.Count(i => !i.Expired)
|
||||
: PlaylistItemStats.Value.CountActive;
|
||||
|
||||
count.Clear();
|
||||
count.AddText(Playlist.Count.ToLocalisableString(), s => s.Font = s.Font.With(weight: FontWeight.Bold));
|
||||
count.AddText(activeItems.ToLocalisableString(), s => s.Font = s.Font.With(weight: FontWeight.Bold));
|
||||
count.AddText(" ");
|
||||
count.AddText("Beatmap".ToQuantity(Playlist.Count, ShowQuantityAs.None));
|
||||
count.AddText("Beatmap".ToQuantity(activeItems, ShowQuantityAs.None));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
||||
{
|
||||
bool matchingFilter = true;
|
||||
|
||||
matchingFilter &= r.Room.Playlist.Count == 0 || criteria.Ruleset == null || r.Room.Playlist.Any(i => i.RulesetID == criteria.Ruleset.OnlineID);
|
||||
matchingFilter &= criteria.Ruleset == null || r.Room.PlaylistItemStats.Value?.RulesetIDs.Any(id => id == criteria.Ruleset.OnlineID) != false;
|
||||
|
||||
if (!string.IsNullOrEmpty(criteria.SearchString))
|
||||
matchingFilter &= r.FilterTerms.Any(term => term.Contains(criteria.SearchString, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
@ -343,7 +343,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
base.LoadComplete();
|
||||
|
||||
drawablePlaylist.Items.BindTo(Playlist);
|
||||
drawablePlaylist.SelectedItem.BindTo(SelectedItem);
|
||||
drawablePlaylist.SelectedItem.BindTo(CurrentPlaylistItem);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
@ -419,7 +419,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
if (text.StartsWith(not_found_prefix, StringComparison.Ordinal))
|
||||
{
|
||||
ErrorText.Text = "The selected beatmap is not available online.";
|
||||
SelectedItem.Value.MarkInvalid();
|
||||
CurrentPlaylistItem.Value.MarkInvalid();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -67,7 +67,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
SelectedItem.BindValueChanged(_ => updateState());
|
||||
CurrentPlaylistItem.BindValueChanged(_ => updateState());
|
||||
}
|
||||
|
||||
protected override void OnRoomUpdated()
|
||||
@ -111,7 +111,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
|
||||
bool enableButton =
|
||||
Room?.State == MultiplayerRoomState.Open
|
||||
&& SelectedItem.Value?.ID == Room.Settings.PlaylistItemId
|
||||
&& CurrentPlaylistItem.Value?.ID == Room.Settings.PlaylistItemId
|
||||
&& !Room.Playlist.Single(i => i.ID == Room.Settings.PlaylistItemId).Expired
|
||||
&& !operationInProgress.Value;
|
||||
|
||||
|
@ -52,14 +52,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist
|
||||
queueList = new MultiplayerQueueList
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
SelectedItem = { BindTarget = SelectedItem },
|
||||
SelectedItem = { BindTarget = CurrentPlaylistItem },
|
||||
RequestEdit = item => RequestEdit?.Invoke(item)
|
||||
},
|
||||
historyList = new MultiplayerHistoryList
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
SelectedItem = { BindTarget = SelectedItem }
|
||||
SelectedItem = { BindTarget = CurrentPlaylistItem }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,9 +32,22 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<MatchType> Type { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The currently selected item in the <see cref="RoomSubScreen"/>, or the current item from <see cref="Playlist"/>
|
||||
/// if this <see cref="OnlinePlayComposite"/> is not within a <see cref="RoomSubScreen"/>.
|
||||
/// </summary>
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<PlaylistItem> CurrentPlaylistItem { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<Room.RoomPlaylistItemStats> PlaylistItemStats { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected BindableList<PlaylistItem> Playlist { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<Room.RoomDifficultyRange> DifficultyRange { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<RoomCategory> Category { get; private set; }
|
||||
|
||||
@ -71,12 +84,6 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
[Resolved(CanBeNull = true)]
|
||||
private IBindable<PlaylistItem> subScreenSelectedItem { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The currently selected item in the <see cref="RoomSubScreen"/>, or the current item from <see cref="Playlist"/>
|
||||
/// if this <see cref="OnlinePlayComposite"/> is not within a <see cref="RoomSubScreen"/>.
|
||||
/// </summary>
|
||||
protected readonly Bindable<PlaylistItem> SelectedItem = new Bindable<PlaylistItem>();
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
@ -85,9 +92,13 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
Playlist.BindCollectionChanged((_, __) => UpdateSelectedItem(), true);
|
||||
}
|
||||
|
||||
protected virtual void UpdateSelectedItem()
|
||||
=> SelectedItem.Value = RoomID.Value == null || subScreenSelectedItem == null
|
||||
? Playlist.GetCurrentItem()
|
||||
: subScreenSelectedItem.Value;
|
||||
protected void UpdateSelectedItem()
|
||||
{
|
||||
// null room ID means this is a room in the process of being created.
|
||||
if (RoomID.Value == null)
|
||||
CurrentPlaylistItem.Value = Playlist.GetCurrentItem();
|
||||
else if (subScreenSelectedItem != null)
|
||||
CurrentPlaylistItem.Value = subScreenSelectedItem.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Scoring;
|
||||
@ -40,8 +39,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
if (ruleset.Value.OnlineID != PlaylistItem.RulesetID)
|
||||
throw new InvalidOperationException("Current Ruleset does not match PlaylistItem's Ruleset");
|
||||
|
||||
var localMods = Mods.Value.Select(m => new APIMod(m)).ToArray();
|
||||
if (!PlaylistItem.RequiredMods.All(m => localMods.Any(m.Equals)))
|
||||
var requiredLocalMods = PlaylistItem.RequiredMods.Select(m => m.ToMod(GameplayState.Ruleset));
|
||||
if (!requiredLocalMods.All(m => Mods.Value.Any(m.Equals)))
|
||||
throw new InvalidOperationException("Current Mods do not match PlaylistItem's RequiredMods");
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,11 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
||||
|
||||
if (ruleset != null)
|
||||
{
|
||||
room.PlaylistItemStats.Value = new Room.RoomPlaylistItemStats
|
||||
{
|
||||
RulesetIDs = new[] { ruleset.OnlineID },
|
||||
};
|
||||
|
||||
room.Playlist.Add(new PlaylistItem(new BeatmapInfo { Metadata = new BeatmapMetadata() })
|
||||
{
|
||||
RulesetID = ruleset.OnlineID,
|
||||
|
Loading…
Reference in New Issue
Block a user