mirror of
https://github.com/ppy/osu.git
synced 2025-02-06 21:02:59 +08:00
Merge pull request #30838 from smoogipoo/better-room-status
Improve multiplayer room status handling
This commit is contained in:
commit
88241d5b95
@ -14,7 +14,6 @@ using osu.Game.Graphics.Sprites;
|
|||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Online.Rooms.RoomStatuses;
|
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Screens.OnlinePlay.Lounge;
|
using osu.Game.Screens.OnlinePlay.Lounge;
|
||||||
@ -76,7 +75,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
createLoungeRoom(new Room
|
createLoungeRoom(new Room
|
||||||
{
|
{
|
||||||
Name = "Multiplayer room",
|
Name = "Multiplayer room",
|
||||||
Status = new RoomStatusOpen(),
|
|
||||||
EndDate = DateTimeOffset.Now.AddDays(1),
|
EndDate = DateTimeOffset.Now.AddDays(1),
|
||||||
Type = MatchType.HeadToHead,
|
Type = MatchType.HeadToHead,
|
||||||
Playlist = [item1],
|
Playlist = [item1],
|
||||||
@ -85,7 +83,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
createLoungeRoom(new Room
|
createLoungeRoom(new Room
|
||||||
{
|
{
|
||||||
Name = "Private room",
|
Name = "Private room",
|
||||||
Status = new RoomStatusOpenPrivate(),
|
|
||||||
Password = "*",
|
Password = "*",
|
||||||
EndDate = DateTimeOffset.Now.AddDays(1),
|
EndDate = DateTimeOffset.Now.AddDays(1),
|
||||||
Type = MatchType.HeadToHead,
|
Type = MatchType.HeadToHead,
|
||||||
@ -95,36 +92,38 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
createLoungeRoom(new Room
|
createLoungeRoom(new Room
|
||||||
{
|
{
|
||||||
Name = "Playlist room with multiple beatmaps",
|
Name = "Playlist room with multiple beatmaps",
|
||||||
Status = new RoomStatusPlaying(),
|
Status = RoomStatus.Playing,
|
||||||
EndDate = DateTimeOffset.Now.AddDays(1),
|
EndDate = DateTimeOffset.Now.AddDays(1),
|
||||||
Playlist = [item1, item2],
|
Playlist = [item1, item2],
|
||||||
CurrentPlaylistItem = item1
|
CurrentPlaylistItem = item1
|
||||||
}),
|
}),
|
||||||
createLoungeRoom(new Room
|
createLoungeRoom(new Room
|
||||||
{
|
{
|
||||||
Name = "Finished room",
|
Name = "Closing soon",
|
||||||
Status = new RoomStatusEnded(),
|
EndDate = DateTimeOffset.Now.AddSeconds(5),
|
||||||
|
}),
|
||||||
|
createLoungeRoom(new Room
|
||||||
|
{
|
||||||
|
Name = "Closed room",
|
||||||
EndDate = DateTimeOffset.Now,
|
EndDate = DateTimeOffset.Now,
|
||||||
}),
|
}),
|
||||||
createLoungeRoom(new Room
|
createLoungeRoom(new Room
|
||||||
{
|
{
|
||||||
Name = "Spotlight room",
|
Name = "Spotlight room",
|
||||||
Status = new RoomStatusOpen(),
|
|
||||||
Category = RoomCategory.Spotlight,
|
Category = RoomCategory.Spotlight,
|
||||||
}),
|
}),
|
||||||
createLoungeRoom(new Room
|
createLoungeRoom(new Room
|
||||||
{
|
{
|
||||||
Name = "Featured artist room",
|
Name = "Featured artist room",
|
||||||
Status = new RoomStatusOpen(),
|
|
||||||
Category = RoomCategory.FeaturedArtist,
|
Category = RoomCategory.FeaturedArtist,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for panel load", () => rooms.Count == 6);
|
AddUntilStep("wait for panel load", () => rooms.Count == 7);
|
||||||
AddUntilStep("correct status text", () => rooms.ChildrenOfType<OsuSpriteText>().Count(s => s.Text.ToString().StartsWith("Currently playing", StringComparison.Ordinal)) == 2);
|
AddUntilStep("correct status text", () => rooms.ChildrenOfType<OsuSpriteText>().Count(s => s.Text.ToString().StartsWith("Currently playing", StringComparison.Ordinal)) == 2);
|
||||||
AddUntilStep("correct status text", () => rooms.ChildrenOfType<OsuSpriteText>().Count(s => s.Text.ToString().StartsWith("Ready to play", StringComparison.Ordinal)) == 4);
|
AddUntilStep("correct status text", () => rooms.ChildrenOfType<OsuSpriteText>().Count(s => s.Text.ToString().StartsWith("Ready to play", StringComparison.Ordinal)) == 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -136,7 +135,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddStep("create room", () => Child = drawableRoom = createLoungeRoom(room = new Room
|
AddStep("create room", () => Child = drawableRoom = createLoungeRoom(room = new Room
|
||||||
{
|
{
|
||||||
Name = "Room with password",
|
Name = "Room with password",
|
||||||
Status = new RoomStatusOpen(),
|
|
||||||
Type = MatchType.HeadToHead,
|
Type = MatchType.HeadToHead,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -1,149 +0,0 @@
|
|||||||
// 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 System.Linq;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Audio;
|
|
||||||
using osu.Framework.Extensions;
|
|
||||||
using osu.Framework.Platform;
|
|
||||||
using osu.Framework.Screens;
|
|
||||||
using osu.Framework.Testing;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osu.Game.Online.API;
|
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
|
||||||
using osu.Game.Online.Rooms;
|
|
||||||
using osu.Game.Online.Rooms.RoomStatuses;
|
|
||||||
using osu.Game.Rulesets;
|
|
||||||
using osu.Game.Rulesets.Osu.Mods;
|
|
||||||
using osu.Game.Scoring;
|
|
||||||
using osu.Game.Screens.OnlinePlay.Playlists;
|
|
||||||
using osu.Game.Tests.Resources;
|
|
||||||
using osu.Game.Tests.Visual.OnlinePlay;
|
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Playlists
|
|
||||||
{
|
|
||||||
public partial class TestScenePlaylistsRoomSubScreen : OnlinePlayTestScene
|
|
||||||
{
|
|
||||||
private const double track_length = 10000;
|
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private IAPIProvider api { get; set; } = null!;
|
|
||||||
|
|
||||||
protected new TestRoomManager RoomManager => (TestRoomManager)base.RoomManager;
|
|
||||||
|
|
||||||
private BeatmapManager beatmaps = null!;
|
|
||||||
private RulesetStore rulesets = null!;
|
|
||||||
private BeatmapSetInfo? importedSet;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(GameHost host, AudioManager audio)
|
|
||||||
{
|
|
||||||
Dependencies.Cache(rulesets = new RealmRulesetStore(Realm));
|
|
||||||
Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, Realm, null, audio, Resources, host, Beatmap.Default));
|
|
||||||
Dependencies.Cache(new ScoreManager(rulesets, () => beatmaps, LocalStorage, Realm, API));
|
|
||||||
Dependencies.Cache(Realm);
|
|
||||||
|
|
||||||
beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely();
|
|
||||||
|
|
||||||
Realm.Write(r =>
|
|
||||||
{
|
|
||||||
foreach (var set in r.All<BeatmapSetInfo>())
|
|
||||||
{
|
|
||||||
foreach (var b in set.Beatmaps)
|
|
||||||
{
|
|
||||||
// These will all have a virtual track length of 1000, see WorkingBeatmap.GetVirtualTrack().
|
|
||||||
b.Length = track_length - 1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
importedSet = beatmaps.GetAllUsableBeatmapSets().First();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestStatusUpdateOnEnter()
|
|
||||||
{
|
|
||||||
Room room = null!;
|
|
||||||
PlaylistsRoomSubScreen roomScreen = null!;
|
|
||||||
|
|
||||||
AddStep("create room", () =>
|
|
||||||
{
|
|
||||||
RoomManager.AddRoom(room = new Room
|
|
||||||
{
|
|
||||||
Name = @"Test Room",
|
|
||||||
Host = new APIUser { Username = @"Host" },
|
|
||||||
Category = RoomCategory.Normal,
|
|
||||||
EndDate = DateTimeOffset.Now.AddMinutes(-1)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
AddStep("push screen", () => LoadScreen(roomScreen = new PlaylistsRoomSubScreen(room)));
|
|
||||||
AddUntilStep("wait for screen load", () => roomScreen.IsCurrentScreen());
|
|
||||||
AddAssert("status is still ended", () => roomScreen.Room.Status, Is.TypeOf<RoomStatusEnded>);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestCloseButtonGoesAwayAfterGracePeriod()
|
|
||||||
{
|
|
||||||
Room room = null!;
|
|
||||||
PlaylistsRoomSubScreen roomScreen = null!;
|
|
||||||
|
|
||||||
AddStep("create room", () =>
|
|
||||||
{
|
|
||||||
RoomManager.AddRoom(room = new Room
|
|
||||||
{
|
|
||||||
Name = @"Test Room",
|
|
||||||
Host = api.LocalUser.Value,
|
|
||||||
Category = RoomCategory.Normal,
|
|
||||||
StartDate = DateTimeOffset.Now.AddMinutes(-5).AddSeconds(3),
|
|
||||||
EndDate = DateTimeOffset.Now.AddMinutes(30)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
AddStep("push screen", () => LoadScreen(roomScreen = new PlaylistsRoomSubScreen(room)));
|
|
||||||
AddUntilStep("wait for screen load", () => roomScreen.IsCurrentScreen());
|
|
||||||
AddAssert("close button present", () => roomScreen.ChildrenOfType<DangerousRoundedButton>().Any());
|
|
||||||
AddUntilStep("wait for close button to disappear", () => !roomScreen.ChildrenOfType<DangerousRoundedButton>().Any());
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase(120_000, true)] // Definitely enough time.
|
|
||||||
[TestCase(45_000, true)] // Enough time.
|
|
||||||
[TestCase(35_000, false)] // Not enough time to complete beatmap after lenience.
|
|
||||||
[TestCase(20_000, false)] // Not enough time.
|
|
||||||
[TestCase(5_000, false)] // Not enough time to complete beatmap before lenience.
|
|
||||||
[TestCase(37_500, true, 2)] // Enough time to complete beatmap after mods are applied.
|
|
||||||
public void TestReadyButtonEnablementPeriod(int offsetMs, bool enabled, double rate = 1)
|
|
||||||
{
|
|
||||||
Room room = null!;
|
|
||||||
PlaylistsRoomSubScreen roomScreen = null!;
|
|
||||||
|
|
||||||
AddStep("create room", () =>
|
|
||||||
{
|
|
||||||
RoomManager.AddRoom(room = new Room
|
|
||||||
{
|
|
||||||
Name = @"Test Room",
|
|
||||||
Host = api.LocalUser.Value,
|
|
||||||
Category = RoomCategory.Normal,
|
|
||||||
StartDate = DateTimeOffset.Now,
|
|
||||||
EndDate = DateTimeOffset.Now.AddMilliseconds(offsetMs),
|
|
||||||
Playlist =
|
|
||||||
[
|
|
||||||
new PlaylistItem(importedSet!.Beatmaps[0])
|
|
||||||
{
|
|
||||||
RequiredMods = rate == 1
|
|
||||||
? []
|
|
||||||
: [new APIMod(new OsuModDoubleTime { SpeedChange = { Value = rate } })]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
AddStep("push screen", () => LoadScreen(roomScreen = new PlaylistsRoomSubScreen(room)));
|
|
||||||
AddUntilStep("wait for screen load", () => roomScreen.IsCurrentScreen());
|
|
||||||
AddUntilStep("ready button enabled", () => roomScreen.ChildrenOfType<PlaylistsReadyButton>().SingleOrDefault()?.Enabled.Value, () => Is.EqualTo(enabled));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -195,6 +195,27 @@ namespace osu.Game.Graphics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the accent colour representing a <see cref="Room"/>'s current status.
|
||||||
|
/// </summary>
|
||||||
|
public Color4 ForRoomStatus(Room room)
|
||||||
|
{
|
||||||
|
if (room.HasEnded)
|
||||||
|
return YellowDarker;
|
||||||
|
|
||||||
|
switch (room.Status)
|
||||||
|
{
|
||||||
|
case RoomStatus.Playing:
|
||||||
|
return Purple;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (room.HasPassword)
|
||||||
|
return GreenDark;
|
||||||
|
|
||||||
|
return GreenLight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves colour for a <see cref="RankingTier"/>.
|
/// Retrieves colour for a <see cref="RankingTier"/>.
|
||||||
/// See https://www.figma.com/file/YHWhp9wZ089YXgB7pe6L1k/Tier-Colours
|
/// See https://www.figma.com/file/YHWhp9wZ089YXgB7pe6L1k/Tier-Colours
|
||||||
|
34
osu.Game/Localisation/RoomStatusPillStrings.cs
Normal file
34
osu.Game/Localisation/RoomStatusPillStrings.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// 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 osu.Framework.Localisation;
|
||||||
|
|
||||||
|
namespace osu.Game.Localisation
|
||||||
|
{
|
||||||
|
public static class RoomStatusPillStrings
|
||||||
|
{
|
||||||
|
private const string prefix = @"osu.Game.Resources.Localisation.RoomStatusPill";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Ended"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString Ended => new TranslatableString(getKey(@"ended"), @"Ended");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Playing"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString Playing => new TranslatableString(getKey(@"playing"), @"Playing");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Open (Private)"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString OpenPrivate => new TranslatableString(getKey(@"open_private"), @"Open (Private)");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Open"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString Open => new TranslatableString(getKey(@"open"), @"Open");
|
||||||
|
|
||||||
|
private static string getKey(string key) => $@"{prefix}:{key}";
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,6 @@ using osu.Game.Online.API.Requests;
|
|||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Online.Multiplayer.Countdown;
|
using osu.Game.Online.Multiplayer.Countdown;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Online.Rooms.RoomStatuses;
|
|
||||||
using osu.Game.Overlays.Notifications;
|
using osu.Game.Overlays.Notifications;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
@ -395,15 +394,17 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case MultiplayerRoomState.Open:
|
case MultiplayerRoomState.Open:
|
||||||
APIRoom.Status = APIRoom.HasPassword ? new RoomStatusOpenPrivate() : new RoomStatusOpen();
|
APIRoom.Status = RoomStatus.Idle;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MultiplayerRoomState.WaitingForLoad:
|
||||||
case MultiplayerRoomState.Playing:
|
case MultiplayerRoomState.Playing:
|
||||||
APIRoom.Status = new RoomStatusPlaying();
|
APIRoom.Status = RoomStatus.Playing;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MultiplayerRoomState.Closed:
|
case MultiplayerRoomState.Closed:
|
||||||
APIRoom.Status = new RoomStatusEnded();
|
APIRoom.EndDate = DateTimeOffset.Now;
|
||||||
|
APIRoom.Status = RoomStatus.Idle;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -821,7 +822,6 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
Room.Settings = settings;
|
Room.Settings = settings;
|
||||||
APIRoom.Name = Room.Settings.Name;
|
APIRoom.Name = Room.Settings.Name;
|
||||||
APIRoom.Password = Room.Settings.Password;
|
APIRoom.Password = Room.Settings.Password;
|
||||||
APIRoom.Status = string.IsNullOrEmpty(Room.Settings.Password) ? new RoomStatusOpen() : new RoomStatusOpenPrivate();
|
|
||||||
APIRoom.Type = Room.Settings.MatchType;
|
APIRoom.Type = Room.Settings.MatchType;
|
||||||
APIRoom.QueueMode = Room.Settings.QueueMode;
|
APIRoom.QueueMode = Room.Settings.QueueMode;
|
||||||
APIRoom.AutoStartDuration = Room.Settings.AutoStartDuration;
|
APIRoom.AutoStartDuration = Room.Settings.AutoStartDuration;
|
||||||
|
@ -6,12 +6,10 @@ using System.Collections.Generic;
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.Serialization;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using osu.Game.IO.Serialization.Converters;
|
using osu.Game.IO.Serialization.Converters;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Online.Rooms.RoomStatuses;
|
|
||||||
|
|
||||||
namespace osu.Game.Online.Rooms
|
namespace osu.Game.Online.Rooms
|
||||||
{
|
{
|
||||||
@ -248,7 +246,7 @@ namespace osu.Game.Online.Rooms
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current room status.
|
/// The current status of the room.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public RoomStatus Status
|
public RoomStatus Status
|
||||||
{
|
{
|
||||||
@ -265,18 +263,6 @@ namespace osu.Game.Online.Rooms
|
|||||||
set => SetField(ref availability, value);
|
set => SetField(ref availability, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[OnDeserialized]
|
|
||||||
private void onDeserialised(StreamingContext context)
|
|
||||||
{
|
|
||||||
// API doesn't populate status so let's do it here.
|
|
||||||
if (EndDate != null && DateTimeOffset.Now >= EndDate)
|
|
||||||
Status = new RoomStatusEnded();
|
|
||||||
else if (HasPassword)
|
|
||||||
Status = new RoomStatusOpenPrivate();
|
|
||||||
else
|
|
||||||
Status = new RoomStatusOpen();
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
private long? roomId;
|
private long? roomId;
|
||||||
|
|
||||||
@ -349,8 +335,9 @@ namespace osu.Game.Online.Rooms
|
|||||||
[JsonProperty("channel_id")]
|
[JsonProperty("channel_id")]
|
||||||
private int channelId;
|
private int channelId;
|
||||||
|
|
||||||
// Not serialised (see: GetRoomsRequest).
|
[JsonProperty("status")]
|
||||||
private RoomStatus status = new RoomStatusOpen();
|
[JsonConverter(typeof(SnakeCaseStringEnumConverter))]
|
||||||
|
private RoomStatus status;
|
||||||
|
|
||||||
// Not yet serialised (not implemented).
|
// Not yet serialised (not implemented).
|
||||||
private RoomAvailability availability;
|
private RoomAvailability availability;
|
||||||
@ -388,6 +375,15 @@ namespace osu.Game.Online.Rooms
|
|||||||
RecentParticipants = other.RecentParticipants;
|
RecentParticipants = other.RecentParticipants;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the room is no longer available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This property does not update in real-time and needs to be queried periodically.
|
||||||
|
/// Subscribe to <see cref="EndDate"/> to be notified of any immediate changes.
|
||||||
|
/// </remarks>
|
||||||
|
public bool HasEnded => DateTimeOffset.Now >= EndDate;
|
||||||
|
|
||||||
[JsonObject(MemberSerialization.OptIn)]
|
[JsonObject(MemberSerialization.OptIn)]
|
||||||
public class RoomPlaylistItemStats
|
public class RoomPlaylistItemStats
|
||||||
{
|
{
|
||||||
|
@ -1,19 +1,11 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Online.Rooms
|
namespace osu.Game.Online.Rooms
|
||||||
{
|
{
|
||||||
public abstract class RoomStatus
|
public enum RoomStatus
|
||||||
{
|
{
|
||||||
public abstract string Message { get; }
|
Idle,
|
||||||
public abstract Color4 GetAppropriateColour(OsuColour colours);
|
Playing,
|
||||||
|
|
||||||
public override int GetHashCode() => GetType().GetHashCode();
|
|
||||||
public override bool Equals(object obj) => GetType() == obj?.GetType();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
// 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 osu.Game.Graphics;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Online.Rooms.RoomStatuses
|
|
||||||
{
|
|
||||||
public class RoomStatusEnded : RoomStatus
|
|
||||||
{
|
|
||||||
public override string Message => "Ended";
|
|
||||||
public override Color4 GetAppropriateColour(OsuColour colours) => colours.YellowDarker;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
// 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 osu.Game.Graphics;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Online.Rooms.RoomStatuses
|
|
||||||
{
|
|
||||||
public class RoomStatusOpen : RoomStatus
|
|
||||||
{
|
|
||||||
public override string Message => "Open";
|
|
||||||
public override Color4 GetAppropriateColour(OsuColour colours) => colours.GreenLight;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
// 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 osu.Game.Graphics;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Online.Rooms.RoomStatuses
|
|
||||||
{
|
|
||||||
public class RoomStatusOpenPrivate : RoomStatus
|
|
||||||
{
|
|
||||||
public override string Message => "Open (Private)";
|
|
||||||
public override Color4 GetAppropriateColour(OsuColour colours) => colours.GreenDark;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
// 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 osu.Game.Graphics;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Online.Rooms.RoomStatuses
|
|
||||||
{
|
|
||||||
public class RoomStatusPlaying : RoomStatus
|
|
||||||
{
|
|
||||||
public override string Message => "Playing";
|
|
||||||
public override Color4 GetAppropriateColour(OsuColour colours) => colours.Purple;
|
|
||||||
}
|
|
||||||
}
|
|
@ -29,18 +29,28 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
|||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
room.PropertyChanged += onRoomPropertyChanged;
|
room.PropertyChanged += onRoomPropertyChanged;
|
||||||
|
|
||||||
|
// Timed update required to track rooms which have hit the end time, see `HasEnded`.
|
||||||
|
Scheduler.AddDelayed(updateRoomStatus, 1000, true);
|
||||||
updateRoomStatus();
|
updateRoomStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.PropertyName == nameof(Room.Status))
|
switch (e.PropertyName)
|
||||||
updateRoomStatus();
|
{
|
||||||
|
case nameof(Room.Category):
|
||||||
|
case nameof(Room.Status):
|
||||||
|
case nameof(Room.EndDate):
|
||||||
|
case nameof(Room.HasPassword):
|
||||||
|
updateRoomStatus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateRoomStatus()
|
private void updateRoomStatus()
|
||||||
{
|
{
|
||||||
this.FadeColour(colours.ForRoomCategory(room.Category) ?? room.Status.GetAppropriateColour(colours), transitionDuration);
|
this.FadeColour(colours.ForRoomCategory(room.Category) ?? colours.ForRoomStatus(room), transitionDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
|
@ -7,6 +7,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
|
using osu.Game.Localisation;
|
||||||
|
|
||||||
namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
||||||
{
|
{
|
||||||
@ -35,8 +36,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
|||||||
Pill.Background.Alpha = 1;
|
Pill.Background.Alpha = 1;
|
||||||
|
|
||||||
room.PropertyChanged += onRoomPropertyChanged;
|
room.PropertyChanged += onRoomPropertyChanged;
|
||||||
updateDisplay();
|
|
||||||
|
|
||||||
|
// Timed update required to track rooms which have hit the end time, see `HasEnded`.
|
||||||
|
Scheduler.AddDelayed(updateDisplay, 1000, true);
|
||||||
|
updateDisplay();
|
||||||
FinishTransforms(true);
|
FinishTransforms(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +49,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
|||||||
{
|
{
|
||||||
case nameof(Room.Status):
|
case nameof(Room.Status):
|
||||||
case nameof(Room.EndDate):
|
case nameof(Room.EndDate):
|
||||||
|
case nameof(Room.HasPassword):
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -53,8 +57,23 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
|||||||
|
|
||||||
private void updateDisplay()
|
private void updateDisplay()
|
||||||
{
|
{
|
||||||
Pill.Background.FadeColour(room.Status.GetAppropriateColour(colours), 100);
|
Pill.Background.FadeColour(colours.ForRoomStatus(room), 100);
|
||||||
TextFlow.Text = room.Status.Message;
|
|
||||||
|
if (room.HasEnded)
|
||||||
|
TextFlow.Text = RoomStatusPillStrings.Ended;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (room.Status)
|
||||||
|
{
|
||||||
|
case RoomStatus.Playing:
|
||||||
|
TextFlow.Text = RoomStatusPillStrings.Playing;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
TextFlow.Text = room.HasPassword ? RoomStatusPillStrings.OpenPrivate : RoomStatusPillStrings.Open;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
|
@ -26,7 +26,6 @@ using osu.Game.Input.Bindings;
|
|||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Online.Rooms.RoomStatuses;
|
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Screens.OnlinePlay.Components;
|
using osu.Game.Screens.OnlinePlay.Components;
|
||||||
using osu.Game.Screens.OnlinePlay.Lounge.Components;
|
using osu.Game.Screens.OnlinePlay.Lounge.Components;
|
||||||
@ -168,7 +167,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Room.Type == MatchType.Playlists && Room.Host?.Id == api.LocalUser.Value.Id && Room.StartDate?.AddMinutes(5) >= DateTimeOffset.Now && Room.Status is not RoomStatusEnded)
|
if (Room.Type == MatchType.Playlists && Room.Host?.Id == api.LocalUser.Value.Id && Room.StartDate?.AddMinutes(5) >= DateTimeOffset.Now && !Room.HasEnded)
|
||||||
{
|
{
|
||||||
items.Add(new OsuMenuItem("Close playlist", MenuItemType.Destructive, () =>
|
items.Add(new OsuMenuItem("Close playlist", MenuItemType.Destructive, () =>
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,6 @@ using osu.Framework.Extensions.ExceptionExtensions;
|
|||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Online.Rooms.RoomStatuses;
|
|
||||||
using osu.Game.Screens.OnlinePlay.Components;
|
using osu.Game.Screens.OnlinePlay.Components;
|
||||||
|
|
||||||
namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||||
@ -31,7 +30,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
|||||||
|
|
||||||
// this is done here as a pre-check to avoid clicking on already closed rooms in the lounge from triggering a server join.
|
// this is done here as a pre-check to avoid clicking on already closed rooms in the lounge from triggering a server join.
|
||||||
// should probably be done at a higher level, but due to the current structure of things this is the easiest place for now.
|
// should probably be done at a higher level, but due to the current structure of things this is the easiest place for now.
|
||||||
if (room.Status is RoomStatusEnded)
|
if (room.HasEnded)
|
||||||
{
|
{
|
||||||
onError?.Invoke("Cannot join an ended room.");
|
onError?.Invoke("Cannot join an ended room.");
|
||||||
return;
|
return;
|
||||||
|
@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Online.Rooms.RoomStatuses;
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Screens.OnlinePlay.Playlists
|
namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||||
@ -99,7 +98,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
|||||||
|
|
||||||
if (room.Host?.Id == api.LocalUser.Value.Id)
|
if (room.Host?.Id == api.LocalUser.Value.Id)
|
||||||
{
|
{
|
||||||
if (deletionGracePeriodRemaining > TimeSpan.Zero && room.Status is not RoomStatusEnded)
|
if (deletionGracePeriodRemaining > TimeSpan.Zero && !room.HasEnded)
|
||||||
{
|
{
|
||||||
closeButton.FadeIn();
|
closeButton.FadeIn();
|
||||||
using (BeginDelayedSequence(deletionGracePeriodRemaining.Value.TotalMilliseconds))
|
using (BeginDelayedSequence(deletionGracePeriodRemaining.Value.TotalMilliseconds))
|
||||||
|
@ -16,7 +16,6 @@ using osu.Game.Input;
|
|||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Online.Rooms.RoomStatuses;
|
|
||||||
using osu.Game.Screens.OnlinePlay.Components;
|
using osu.Game.Screens.OnlinePlay.Components;
|
||||||
using osu.Game.Screens.OnlinePlay.Match;
|
using osu.Game.Screens.OnlinePlay.Match;
|
||||||
using osu.Game.Screens.OnlinePlay.Match.Components;
|
using osu.Game.Screens.OnlinePlay.Match.Components;
|
||||||
@ -286,11 +285,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
|||||||
DialogOverlay?.Push(new ClosePlaylistDialog(Room, () =>
|
DialogOverlay?.Push(new ClosePlaylistDialog(Room, () =>
|
||||||
{
|
{
|
||||||
var request = new ClosePlaylistRequest(Room.RoomID!.Value);
|
var request = new ClosePlaylistRequest(Room.RoomID!.Value);
|
||||||
request.Success += () =>
|
request.Success += () => Room.EndDate = DateTimeOffset.UtcNow;
|
||||||
{
|
|
||||||
Room.Status = new RoomStatusEnded();
|
|
||||||
Room.EndDate = DateTimeOffset.UtcNow;
|
|
||||||
};
|
|
||||||
API.Queue(request);
|
API.Queue(request);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user