diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 2d5496c5c1..de17c012eb 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -239,7 +239,9 @@ namespace osu.Game.Online.Multiplayer /// The new password, if any. /// The type of the match, if any. /// The new queue mode, if any. - public Task ChangeSettings(Optional name = default, Optional password = default, Optional matchType = default, Optional queueMode = default) + /// The new auto-start countdown duration, if any. + public Task ChangeSettings(Optional name = default, Optional password = default, Optional matchType = default, Optional queueMode = default, + Optional autoStartDuration = default) { if (Room == null) throw new InvalidOperationException("Must be joined to a match to change settings."); @@ -250,6 +252,7 @@ namespace osu.Game.Online.Multiplayer Password = password.GetOr(Room.Settings.Password), MatchType = matchType.GetOr(Room.Settings.MatchType), QueueMode = queueMode.GetOr(Room.Settings.QueueMode), + AutoStartDuration = autoStartDuration.GetOr(Room.Settings.AutoStartDuration), }); } diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs index c392260a22..f8b238d61b 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs @@ -28,6 +28,9 @@ namespace osu.Game.Online.Multiplayer [Key(4)] public QueueMode QueueMode { get; set; } = QueueMode.HostOnly; + [Key(5)] + public TimeSpan AutoStartDuration { get; set; } + public bool Equals(MultiplayerRoomSettings? other) { if (ReferenceEquals(this, other)) return true; @@ -37,13 +40,15 @@ namespace osu.Game.Online.Multiplayer && Name.Equals(other.Name, StringComparison.Ordinal) && PlaylistItemId == other.PlaylistItemId && MatchType == other.MatchType - && QueueMode == other.QueueMode; + && QueueMode == other.QueueMode + && AutoStartDuration == other.AutoStartDuration; } public override string ToString() => $"Name:{Name}" + $" Password:{(string.IsNullOrEmpty(Password) ? "no" : "yes")}" + $" Type:{MatchType}" + $" Item:{PlaylistItemId}" - + $" Queue:{QueueMode}"; + + $" Queue:{QueueMode}" + + $" Start:{AutoStartDuration}"; } } diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index 543b176b51..76bac44242 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -92,6 +92,16 @@ namespace osu.Game.Online.Rooms set => QueueMode.Value = value; } + [Cached] + public readonly Bindable AutoStartDuration = new Bindable(); + + [JsonProperty("start_duration")] + private ushort autoStartDuration + { + get => (ushort)AutoStartDuration.Value.TotalSeconds; + set => AutoStartDuration.Value = TimeSpan.FromSeconds(value); + } + [Cached] public readonly Bindable MaxParticipants = new Bindable(); @@ -172,6 +182,7 @@ namespace osu.Game.Online.Rooms EndDate.Value = other.EndDate.Value; UserScore.Value = other.UserScore.Value; QueueMode.Value = other.QueueMode.Value; + AutoStartDuration.Value = other.AutoStartDuration.Value; DifficultyRange.Value = other.DifficultyRange.Value; PlaylistItemStats.Value = other.PlaylistItemStats.Value; CurrentPlaylistItem.Value = other.CurrentPlaylistItem.Value; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index be98a9d4e9..2918e066c1 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.ComponentModel; using System.Diagnostics; using JetBrains.Annotations; using osu.Framework.Allocation; @@ -21,6 +22,7 @@ using osu.Game.Online.Rooms; using osu.Game.Overlays; using osu.Game.Screens.OnlinePlay.Match.Components; using osuTK; +using Container = osu.Framework.Graphics.Containers.Container; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { @@ -64,6 +66,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match public OsuSpriteText ErrorText; + private OsuEnumDropdown startModeDropdown; private OsuSpriteText typeLabel; private LoadingLayer loadingLayer; @@ -204,6 +207,18 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match RelativeSizeAxes = Axes.X } } + }, + new Section("Auto start") + { + Child = new Container + { + RelativeSizeAxes = Axes.X, + Height = 40, + Child = startModeDropdown = new OsuEnumDropdown + { + RelativeSizeAxes = Axes.X + } + } } }, }, @@ -327,6 +342,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match RoomID.BindValueChanged(roomId => playlistContainer.Alpha = roomId.NewValue == null ? 1 : 0, true); Password.BindValueChanged(password => PasswordTextBox.Text = password.NewValue ?? string.Empty, true); QueueMode.BindValueChanged(mode => QueueModeDropdown.Current.Value = mode.NewValue, true); + AutoStartDuration.BindValueChanged(duration => startModeDropdown.Current.Value = (StartMode)(int)duration.NewValue.TotalSeconds, true); operationInProgress.BindTo(ongoingOperationTracker.InProgress); operationInProgress.BindValueChanged(v => @@ -363,6 +379,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match Debug.Assert(applyingSettingsOperation == null); applyingSettingsOperation = ongoingOperationTracker.BeginOperation(); + TimeSpan autoStartDuration = TimeSpan.FromSeconds((int)startModeDropdown.Current.Value); + // If the client is already in a room, update via the client. // Otherwise, update the room directly in preparation for it to be submitted to the API on match creation. if (client.Room != null) @@ -371,7 +389,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match name: NameField.Text, password: PasswordTextBox.Text, matchType: TypePicker.Current.Value, - queueMode: QueueModeDropdown.Current.Value) + queueMode: QueueModeDropdown.Current.Value, + autoStartDuration: autoStartDuration) .ContinueWith(t => Schedule(() => { if (t.IsCompletedSuccessfully) @@ -387,6 +406,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match room.Type.Value = TypePicker.Current.Value; room.Password.Value = PasswordTextBox.Current.Value; room.QueueMode.Value = QueueModeDropdown.Current.Value; + room.AutoStartDuration.Value = autoStartDuration; if (int.TryParse(MaxParticipantsField.Text, out int max)) room.MaxParticipants.Value = max; @@ -452,5 +472,23 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match Triangles.ColourDark = colours.YellowDark; } } + + private enum StartMode + { + [Description("Off")] + Off = 0, + + [Description("30 seconds")] + Seconds_30 = 30, + + [Description("1 minute")] + Seconds_60 = 60, + + [Description("3 minutes")] + Seconds_180 = 180, + + [Description("5 minutes")] + Seconds_300 = 300 + } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs index 381c5ea712..930ddc3d64 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs @@ -120,7 +120,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match clickOperation = ongoingOperationTracker.BeginOperation(); // Ensure the current user becomes ready before being able to do anything else (start match, stop countdown, unready). - if (!isReady() || !Client.IsHost) + if (!isReady() || !Client.IsHost || Room.Settings.AutoStartDuration != TimeSpan.Zero) { toggleReady(); return; @@ -183,7 +183,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match int newCountReady = Room.Users.Count(u => u.State == MultiplayerUserState.Ready); int newCountTotal = Room.Users.Count(u => u.State != MultiplayerUserState.Spectating); - if (Room.Countdown != null) + if (Room.Countdown != null || Room.Settings.AutoStartDuration != TimeSpan.Zero) countdownButton.Alpha = 0; else { diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs index 95d9b2af15..88354c8646 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs @@ -81,6 +81,9 @@ namespace osu.Game.Screens.OnlinePlay [Resolved(typeof(Room))] protected Bindable QueueMode { get; private set; } + [Resolved(typeof(Room))] + protected Bindable AutoStartDuration { get; private set; } + [Resolved(CanBeNull = true)] private IBindable subScreenSelectedItem { get; set; }