2023-11-21 05:39:33 +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.
|
|
|
|
|
|
|
|
using System;
|
|
|
|
using osu.Framework.Allocation;
|
|
|
|
using osu.Framework.Bindables;
|
|
|
|
using osu.Framework.Extensions.ObjectExtensions;
|
|
|
|
using osu.Framework.Graphics;
|
|
|
|
using osu.Framework.Graphics.Sprites;
|
|
|
|
using osu.Framework.Screens;
|
|
|
|
using osu.Game.Online.API;
|
2023-12-06 17:24:31 +00:00
|
|
|
using osu.Game.Online.Metadata;
|
2023-11-21 05:39:33 +00:00
|
|
|
using osu.Game.Online.Multiplayer;
|
2024-01-26 09:51:52 +00:00
|
|
|
using osu.Game.Online.Notifications.WebSocket;
|
2023-11-21 05:39:33 +00:00
|
|
|
using osu.Game.Online.Spectator;
|
|
|
|
using osu.Game.Overlays;
|
|
|
|
using osu.Game.Overlays.Notifications;
|
|
|
|
using osu.Game.Screens.OnlinePlay;
|
|
|
|
|
|
|
|
namespace osu.Game.Online
|
|
|
|
{
|
2023-11-21 07:52:52 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Handles various scenarios where connection is lost and we need to let the user know what and why.
|
|
|
|
/// </summary>
|
2023-11-21 05:39:33 +00:00
|
|
|
public partial class OnlineStatusNotifier : Component
|
|
|
|
{
|
|
|
|
private readonly Func<IScreen> getCurrentScreen;
|
|
|
|
|
2024-01-26 09:51:52 +00:00
|
|
|
private INotificationsClient notificationsClient = null!;
|
|
|
|
|
2023-11-21 05:39:33 +00:00
|
|
|
[Resolved]
|
|
|
|
private MultiplayerClient multiplayerClient { get; set; } = null!;
|
|
|
|
|
|
|
|
[Resolved]
|
|
|
|
private SpectatorClient spectatorClient { get; set; } = null!;
|
|
|
|
|
2023-12-06 17:24:31 +00:00
|
|
|
[Resolved]
|
|
|
|
private MetadataClient metadataClient { get; set; } = null!;
|
|
|
|
|
2023-11-21 05:39:33 +00:00
|
|
|
[Resolved]
|
|
|
|
private INotificationOverlay? notificationOverlay { get; set; }
|
|
|
|
|
|
|
|
private IBindable<APIState> apiState = null!;
|
|
|
|
private IBindable<bool> multiplayerState = null!;
|
|
|
|
private IBindable<bool> spectatorState = null!;
|
2023-11-21 07:52:52 +00:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// This flag will be set to <c>true</c> when the user has been notified so we don't show more than one notification.
|
|
|
|
/// </summary>
|
|
|
|
private bool userNotified;
|
2023-11-21 05:39:33 +00:00
|
|
|
|
|
|
|
public OnlineStatusNotifier(Func<IScreen> getCurrentScreen)
|
|
|
|
{
|
|
|
|
this.getCurrentScreen = getCurrentScreen;
|
|
|
|
}
|
|
|
|
|
|
|
|
[BackgroundDependencyLoader]
|
|
|
|
private void load(IAPIProvider api)
|
|
|
|
{
|
|
|
|
apiState = api.State.GetBoundCopy();
|
2024-01-26 09:51:52 +00:00
|
|
|
notificationsClient = api.NotificationsClient;
|
2023-11-21 05:39:33 +00:00
|
|
|
multiplayerState = multiplayerClient.IsConnected.GetBoundCopy();
|
|
|
|
spectatorState = spectatorClient.IsConnected.GetBoundCopy();
|
|
|
|
|
2024-01-26 09:51:52 +00:00
|
|
|
notificationsClient.MessageReceived += notifyAboutForcedDisconnection;
|
2023-11-21 05:39:33 +00:00
|
|
|
multiplayerClient.Disconnecting += notifyAboutForcedDisconnection;
|
|
|
|
spectatorClient.Disconnecting += notifyAboutForcedDisconnection;
|
2023-12-06 17:24:31 +00:00
|
|
|
metadataClient.Disconnecting += notifyAboutForcedDisconnection;
|
2023-11-21 05:39:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected override void LoadComplete()
|
|
|
|
{
|
|
|
|
base.LoadComplete();
|
|
|
|
|
2023-11-21 07:52:52 +00:00
|
|
|
apiState.BindValueChanged(state =>
|
2023-11-21 05:39:33 +00:00
|
|
|
{
|
2023-11-21 07:52:52 +00:00
|
|
|
if (state.NewValue == APIState.Online)
|
|
|
|
{
|
|
|
|
userNotified = false;
|
|
|
|
return;
|
|
|
|
}
|
2023-11-21 05:39:33 +00:00
|
|
|
|
2023-11-21 07:52:52 +00:00
|
|
|
if (userNotified) return;
|
2023-11-21 05:39:33 +00:00
|
|
|
|
2023-11-21 07:52:52 +00:00
|
|
|
if (state.NewValue == APIState.Offline && getCurrentScreen() is OnlinePlayScreen)
|
|
|
|
{
|
|
|
|
userNotified = true;
|
|
|
|
notificationOverlay?.Post(new SimpleErrorNotification
|
|
|
|
{
|
|
|
|
Icon = FontAwesome.Solid.ExclamationCircle,
|
|
|
|
Text = "Connection to API was lost. Can't continue with online play."
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2023-11-21 05:39:33 +00:00
|
|
|
|
2023-11-21 07:52:52 +00:00
|
|
|
multiplayerState.BindValueChanged(connected => Schedule(() =>
|
2023-11-21 05:39:33 +00:00
|
|
|
{
|
2023-11-21 07:52:52 +00:00
|
|
|
if (connected.NewValue)
|
2023-11-21 05:39:33 +00:00
|
|
|
{
|
2023-11-21 07:52:52 +00:00
|
|
|
userNotified = false;
|
|
|
|
return;
|
|
|
|
}
|
2023-11-21 05:39:33 +00:00
|
|
|
|
2023-11-21 07:52:52 +00:00
|
|
|
if (userNotified) return;
|
|
|
|
|
|
|
|
if (multiplayerClient.Room != null)
|
2023-11-21 05:39:33 +00:00
|
|
|
{
|
2023-11-21 07:52:52 +00:00
|
|
|
userNotified = true;
|
|
|
|
notificationOverlay?.Post(new SimpleErrorNotification
|
|
|
|
{
|
|
|
|
Icon = FontAwesome.Solid.ExclamationCircle,
|
|
|
|
Text = "Connection to the multiplayer server was lost. Exiting multiplayer."
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
|
|
|
|
spectatorState.BindValueChanged(_ =>
|
|
|
|
{
|
|
|
|
// TODO: handle spectator server failure somehow?
|
|
|
|
});
|
|
|
|
}
|
2023-11-21 05:39:33 +00:00
|
|
|
|
2023-11-21 07:52:52 +00:00
|
|
|
private void notifyAboutForcedDisconnection()
|
|
|
|
{
|
|
|
|
if (userNotified) return;
|
|
|
|
|
|
|
|
userNotified = true;
|
|
|
|
notificationOverlay?.Post(new SimpleErrorNotification
|
|
|
|
{
|
|
|
|
Icon = FontAwesome.Solid.ExclamationCircle,
|
|
|
|
Text = "You have been logged out on this device due to a login to your account on another device."
|
|
|
|
});
|
2023-11-21 05:39:33 +00:00
|
|
|
}
|
|
|
|
|
2024-01-26 09:51:52 +00:00
|
|
|
private void notifyAboutForcedDisconnection(SocketMessage obj)
|
|
|
|
{
|
|
|
|
if (obj.Event != @"logout") return;
|
|
|
|
|
|
|
|
if (userNotified) return;
|
|
|
|
|
|
|
|
userNotified = true;
|
|
|
|
notificationOverlay?.Post(new SimpleErrorNotification
|
|
|
|
{
|
|
|
|
Icon = FontAwesome.Solid.ExclamationCircle,
|
|
|
|
Text = "You have been logged out due to a change to your account. Please log in again."
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-11-21 05:39:33 +00:00
|
|
|
protected override void Dispose(bool isDisposing)
|
|
|
|
{
|
|
|
|
base.Dispose(isDisposing);
|
|
|
|
|
2024-01-26 09:51:52 +00:00
|
|
|
if (notificationsClient.IsNotNull())
|
|
|
|
notificationsClient.MessageReceived += notifyAboutForcedDisconnection;
|
|
|
|
|
2023-11-21 05:39:33 +00:00
|
|
|
if (spectatorClient.IsNotNull())
|
|
|
|
spectatorClient.Disconnecting -= notifyAboutForcedDisconnection;
|
|
|
|
|
|
|
|
if (multiplayerClient.IsNotNull())
|
|
|
|
multiplayerClient.Disconnecting -= notifyAboutForcedDisconnection;
|
2023-12-06 17:24:31 +00:00
|
|
|
|
|
|
|
if (metadataClient.IsNotNull())
|
|
|
|
metadataClient.Disconnecting -= notifyAboutForcedDisconnection;
|
2023-11-21 05:39:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|