Fix beatmap getting nulled due to failing web request

This commit is contained in:
smoogipoo 2021-03-01 17:24:54 +09:00
parent f7e4cfa4d0
commit 7adb33f40e
3 changed files with 65 additions and 18 deletions

View File

@ -9,7 +9,9 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR.Client; using Microsoft.AspNetCore.SignalR.Client;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Beatmaps;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.Rooms; using osu.Game.Online.Rooms;
namespace osu.Game.Online.Multiplayer namespace osu.Game.Online.Multiplayer
@ -121,6 +123,29 @@ namespace osu.Game.Online.Multiplayer
return connection.InvokeAsync(nameof(IMultiplayerServer.StartMatch)); return connection.InvokeAsync(nameof(IMultiplayerServer.StartMatch));
} }
protected override Task<BeatmapSetInfo> GetOnlineBeatmapSet(int beatmapId, CancellationToken cancellationToken = default)
{
var tcs = new TaskCompletionSource<BeatmapSetInfo>();
var req = new GetBeatmapSetRequest(beatmapId, BeatmapSetLookupType.BeatmapId);
req.Success += res =>
{
if (cancellationToken.IsCancellationRequested)
{
tcs.SetCanceled();
return;
}
tcs.SetResult(res.ToBeatmapSet(Rulesets));
};
req.Failure += e => tcs.SetException(e);
API.Queue(req);
return tcs.Task;
}
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
{ {
base.Dispose(isDisposing); base.Dispose(isDisposing);

View File

@ -17,8 +17,6 @@ using osu.Framework.Logging;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Rooms; using osu.Game.Online.Rooms;
using osu.Game.Online.Rooms.RoomStatuses; using osu.Game.Online.Rooms.RoomStatuses;
using osu.Game.Rulesets; using osu.Game.Rulesets;
@ -71,7 +69,7 @@ namespace osu.Game.Online.Multiplayer
/// <summary> /// <summary>
/// The <see cref="MultiplayerRoomUser"/> corresponding to the local player, if available. /// The <see cref="MultiplayerRoomUser"/> corresponding to the local player, if available.
/// </summary> /// </summary>
public MultiplayerRoomUser? LocalUser => Room?.Users.SingleOrDefault(u => u.User?.Id == api.LocalUser.Value.Id); public MultiplayerRoomUser? LocalUser => Room?.Users.SingleOrDefault(u => u.User?.Id == API.LocalUser.Value.Id);
/// <summary> /// <summary>
/// Whether the <see cref="LocalUser"/> is the host in <see cref="Room"/>. /// Whether the <see cref="LocalUser"/> is the host in <see cref="Room"/>.
@ -85,15 +83,15 @@ namespace osu.Game.Online.Multiplayer
} }
} }
[Resolved]
protected IAPIProvider API { get; private set; } = null!;
[Resolved]
protected RulesetStore Rulesets { get; private set; } = null!;
[Resolved] [Resolved]
private UserLookupCache userLookupCache { get; set; } = null!; private UserLookupCache userLookupCache { get; set; } = null!;
[Resolved]
private IAPIProvider api { get; set; } = null!;
[Resolved]
private RulesetStore rulesets { get; set; } = null!;
// Only exists for compatibility with old osu-server-spectator build. // Only exists for compatibility with old osu-server-spectator build.
// Todo: Can be removed on 2021/02/26. // Todo: Can be removed on 2021/02/26.
private long defaultPlaylistItemId; private long defaultPlaylistItemId;
@ -515,30 +513,26 @@ namespace osu.Game.Online.Multiplayer
RoomUpdated?.Invoke(); RoomUpdated?.Invoke();
var req = new GetBeatmapSetRequest(settings.BeatmapID, BeatmapSetLookupType.BeatmapId); GetOnlineBeatmapSet(settings.BeatmapID, cancellationToken).ContinueWith(set => Schedule(() =>
req.Success += res =>
{ {
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
return; return;
updatePlaylist(settings, res); updatePlaylist(settings, set.Result);
}; }), TaskContinuationOptions.OnlyOnRanToCompletion);
api.Queue(req);
}, cancellationToken); }, cancellationToken);
private void updatePlaylist(MultiplayerRoomSettings settings, APIBeatmapSet onlineSet) private void updatePlaylist(MultiplayerRoomSettings settings, BeatmapSetInfo beatmapSet)
{ {
if (Room == null || !Room.Settings.Equals(settings)) if (Room == null || !Room.Settings.Equals(settings))
return; return;
Debug.Assert(apiRoom != null); Debug.Assert(apiRoom != null);
var beatmapSet = onlineSet.ToBeatmapSet(rulesets);
var beatmap = beatmapSet.Beatmaps.Single(b => b.OnlineBeatmapID == settings.BeatmapID); var beatmap = beatmapSet.Beatmaps.Single(b => b.OnlineBeatmapID == settings.BeatmapID);
beatmap.MD5Hash = settings.BeatmapChecksum; beatmap.MD5Hash = settings.BeatmapChecksum;
var ruleset = rulesets.GetRuleset(settings.RulesetID).CreateInstance(); var ruleset = Rulesets.GetRuleset(settings.RulesetID).CreateInstance();
var mods = settings.RequiredMods.Select(m => m.ToMod(ruleset)); var mods = settings.RequiredMods.Select(m => m.ToMod(ruleset));
var allowedMods = settings.AllowedMods.Select(m => m.ToMod(ruleset)); var allowedMods = settings.AllowedMods.Select(m => m.ToMod(ruleset));
@ -568,6 +562,14 @@ namespace osu.Game.Online.Multiplayer
} }
} }
/// <summary>
/// Retrieves a <see cref="BeatmapSetInfo"/> from an online source.
/// </summary>
/// <param name="beatmapId">The beatmap set ID.</param>
/// <param name="cancellationToken">A token to cancel the request.</param>
/// <returns>The <see cref="BeatmapSetInfo"/> retrieval task.</returns>
protected abstract Task<BeatmapSetInfo> GetOnlineBeatmapSet(int beatmapId, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// For the provided user ID, update whether the user is included in <see cref="CurrentMatchPlayingUserIds"/>. /// For the provided user ID, update whether the user is included in <see cref="CurrentMatchPlayingUserIds"/>.
/// </summary> /// </summary>

View File

@ -3,12 +3,15 @@
#nullable enable #nullable enable
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Beatmaps;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Online.Rooms; using osu.Game.Online.Rooms;
@ -28,6 +31,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Resolved] [Resolved]
private Room apiRoom { get; set; } = null!; private Room apiRoom { get; set; } = null!;
[Resolved]
private BeatmapManager beatmaps { get; set; } = null!;
public void Connect() => isConnected.Value = true; public void Connect() => isConnected.Value = true;
public void Disconnect() => isConnected.Value = false; public void Disconnect() => isConnected.Value = false;
@ -168,5 +174,19 @@ namespace osu.Game.Tests.Visual.Multiplayer
return ((IMultiplayerClient)this).LoadRequested(); return ((IMultiplayerClient)this).LoadRequested();
} }
protected override Task<BeatmapSetInfo> GetOnlineBeatmapSet(int beatmapId, CancellationToken cancellationToken = default)
{
Debug.Assert(Room != null);
Debug.Assert(apiRoom != null);
var set = apiRoom.Playlist.FirstOrDefault(p => p.BeatmapID == beatmapId)?.Beatmap.Value.BeatmapSet
?? beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == beatmapId)?.BeatmapSet;
if (set == null)
throw new InvalidOperationException("Beatmap not found.");
return Task.FromResult(set);
}
} }
} }