2021-05-20 07:30:56 +00:00
|
|
|
// 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.
|
|
|
|
|
2022-02-15 04:40:58 +00:00
|
|
|
using System.Diagnostics;
|
2021-05-20 07:30:56 +00:00
|
|
|
using System.Threading.Tasks;
|
2022-05-26 09:03:41 +00:00
|
|
|
using Microsoft.AspNetCore.SignalR;
|
2021-05-20 07:30:56 +00:00
|
|
|
using Microsoft.AspNetCore.SignalR.Client;
|
|
|
|
using osu.Framework.Allocation;
|
|
|
|
using osu.Framework.Bindables;
|
|
|
|
using osu.Game.Online.API;
|
2022-05-26 09:03:41 +00:00
|
|
|
using osu.Game.Online.Multiplayer;
|
2021-05-20 07:30:56 +00:00
|
|
|
|
|
|
|
namespace osu.Game.Online.Spectator
|
|
|
|
{
|
|
|
|
public class OnlineSpectatorClient : SpectatorClient
|
|
|
|
{
|
|
|
|
private readonly string endpoint;
|
|
|
|
|
|
|
|
private IHubClientConnector? connector;
|
|
|
|
|
|
|
|
public override IBindable<bool> IsConnected { get; } = new BindableBool();
|
|
|
|
|
|
|
|
private HubConnection? connection => connector?.CurrentConnection;
|
|
|
|
|
|
|
|
public OnlineSpectatorClient(EndpointConfiguration endpoints)
|
|
|
|
{
|
|
|
|
endpoint = endpoints.SpectatorEndpointUrl;
|
|
|
|
}
|
|
|
|
|
|
|
|
[BackgroundDependencyLoader]
|
|
|
|
private void load(IAPIProvider api)
|
|
|
|
{
|
|
|
|
connector = api.GetHubConnector(nameof(SpectatorClient), endpoint);
|
|
|
|
|
|
|
|
if (connector != null)
|
|
|
|
{
|
|
|
|
connector.ConfigureConnection = connection =>
|
|
|
|
{
|
|
|
|
// until strong typed client support is added, each method must be manually bound
|
|
|
|
// (see https://github.com/dotnet/aspnetcore/issues/15198)
|
|
|
|
connection.On<int, SpectatorState>(nameof(ISpectatorClient.UserBeganPlaying), ((ISpectatorClient)this).UserBeganPlaying);
|
|
|
|
connection.On<int, FrameDataBundle>(nameof(ISpectatorClient.UserSentFrames), ((ISpectatorClient)this).UserSentFrames);
|
|
|
|
connection.On<int, SpectatorState>(nameof(ISpectatorClient.UserFinishedPlaying), ((ISpectatorClient)this).UserFinishedPlaying);
|
|
|
|
};
|
|
|
|
|
|
|
|
IsConnected.BindTo(connector.IsConnected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-26 09:03:41 +00:00
|
|
|
protected override async Task BeginPlayingInternal(SpectatorState state)
|
2021-05-20 07:30:56 +00:00
|
|
|
{
|
|
|
|
if (!IsConnected.Value)
|
2022-05-26 09:03:41 +00:00
|
|
|
return;
|
2021-05-20 07:30:56 +00:00
|
|
|
|
2022-02-15 04:40:58 +00:00
|
|
|
Debug.Assert(connection != null);
|
|
|
|
|
2022-05-26 09:03:41 +00:00
|
|
|
try
|
|
|
|
{
|
2022-07-16 20:20:05 +00:00
|
|
|
await connection.InvokeAsync(nameof(ISpectatorServer.BeginPlaySession), state);
|
2022-05-26 09:03:41 +00:00
|
|
|
}
|
|
|
|
catch (HubException exception)
|
|
|
|
{
|
|
|
|
if (exception.GetHubExceptionMessage() == HubClientConnector.SERVER_SHUTDOWN_MESSAGE)
|
2022-07-16 19:35:41 +00:00
|
|
|
{
|
|
|
|
Debug.Assert(connector != null);
|
|
|
|
|
|
|
|
await connector.Reconnect();
|
|
|
|
await BeginPlayingInternal(state);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-26 09:03:41 +00:00
|
|
|
throw;
|
|
|
|
}
|
2021-05-20 07:30:56 +00:00
|
|
|
}
|
|
|
|
|
2022-02-23 17:19:37 +00:00
|
|
|
protected override Task SendFramesInternal(FrameDataBundle bundle)
|
2021-05-20 07:30:56 +00:00
|
|
|
{
|
|
|
|
if (!IsConnected.Value)
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
2022-02-15 04:40:58 +00:00
|
|
|
Debug.Assert(connection != null);
|
|
|
|
|
2022-07-18 05:34:02 +00:00
|
|
|
return connection.InvokeAsync(nameof(ISpectatorServer.SendFrameData), bundle);
|
2021-05-20 07:30:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected override Task EndPlayingInternal(SpectatorState state)
|
|
|
|
{
|
|
|
|
if (!IsConnected.Value)
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
2022-02-15 04:40:58 +00:00
|
|
|
Debug.Assert(connection != null);
|
|
|
|
|
2022-07-18 05:34:02 +00:00
|
|
|
return connection.InvokeAsync(nameof(ISpectatorServer.EndPlaySession), state);
|
2021-05-20 07:30:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected override Task WatchUserInternal(int userId)
|
|
|
|
{
|
|
|
|
if (!IsConnected.Value)
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
2022-02-15 04:40:58 +00:00
|
|
|
Debug.Assert(connection != null);
|
|
|
|
|
2022-07-18 05:34:02 +00:00
|
|
|
return connection.InvokeAsync(nameof(ISpectatorServer.StartWatchingUser), userId);
|
2021-05-20 07:30:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected override Task StopWatchingUserInternal(int userId)
|
|
|
|
{
|
|
|
|
if (!IsConnected.Value)
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
2022-02-15 04:40:58 +00:00
|
|
|
Debug.Assert(connection != null);
|
|
|
|
|
2022-07-18 05:34:02 +00:00
|
|
|
return connection.InvokeAsync(nameof(ISpectatorServer.EndWatchingUser), userId);
|
2021-05-20 07:30:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|