From 190092edc4b7a1f16e0d58bc54f3f2c42c26146e Mon Sep 17 00:00:00 2001 From: ILW8 Date: Thu, 9 May 2024 01:56:35 +0100 Subject: [PATCH 1/5] add !mp start (the immediate start variant) --- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index c7685ee35c..6126c7d350 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -340,12 +340,16 @@ private void postMessage(TextBox sender, bool newText) case @"timer": chatTimerHandler?.SetTimer(TimeSpan.FromSeconds(numericParam), Time.Current, Channel.Value); break; + + case @"start": + break; } } else { switch (parts[1]) { + // i don't think this belongs here in the first place... whatever // ReSharper disable once StringLiteralTypo case @"aborttimer": abortTimer(); @@ -486,6 +490,17 @@ private void postMessage(TextBox sender, bool newText) Client.AbortMatch().FireAndForget(); break; + + // start immediately + case @"start": + if (!Client.IsHost) + { + Logger.Log(@"Tried to start match when user is not host of the room. Cancelling!", LoggingTarget.Runtime, LogLevel.Important); + break; + } + + Client.StartMatch().FireAndForget(); + break; } break; From bc1f4fd57aa5bdaed127a5cd0e68f4544beeccaa Mon Sep 17 00:00:00 2001 From: ILW8 Date: Thu, 9 May 2024 02:10:23 +0100 Subject: [PATCH 2/5] add check to ensure at least one player is ready for mp start --- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 6126c7d350..43a1dcdfe0 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -499,6 +499,14 @@ private void postMessage(TextBox sender, bool newText) break; } + // no one is ready, server won't allow starting the map + if (Client.Room?.Users.All(u => u.State != MultiplayerUserState.Ready) ?? false) + { + Logger.Log(@"Tried to start match when no player is ready. Cancelling!", LoggingTarget.Runtime, LogLevel.Important); + botMessageQueue.Enqueue(new Tuple(@"No player ready, cannot start match.", Channel.Value)); + break; + } + Client.StartMatch().FireAndForget(); break; } From e939ecd1c14366e7bdeb558495ab4ac3f368557b Mon Sep 17 00:00:00 2001 From: ILW8 Date: Thu, 9 May 2024 02:10:50 +0100 Subject: [PATCH 3/5] clean up ChatTimerHandler, add message when overriding existing timer --- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 2 +- .../Multiplayer/MultiplayerMatchSubScreen.cs | 35 ++++++++++--------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 43a1dcdfe0..1ed5366e1c 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -338,7 +338,7 @@ private void postMessage(TextBox sender, bool newText) break; case @"timer": - chatTimerHandler?.SetTimer(TimeSpan.FromSeconds(numericParam), Time.Current, Channel.Value); + chatTimerHandler?.SetTimer(TimeSpan.FromSeconds(numericParam), Time.Current); break; case @"start": diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 3416221006..42ae45d270 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -70,20 +70,20 @@ public class Pool public partial class ChatTimerHandler : Component { - protected readonly MultiplayerCountdown MultiplayerChatTimerCountdown = new MatchStartCountdown { TimeRemaining = TimeSpan.Zero }; - protected double CountdownChangeTime; + private readonly MultiplayerCountdown multiplayerChatTimerCountdown = new MatchStartCountdown { TimeRemaining = TimeSpan.Zero }; + private double countdownChangeTime; private TimeSpan countdownTimeRemaining { get { - double timeElapsed = Time.Current - CountdownChangeTime; + double timeElapsed = Time.Current - countdownChangeTime; TimeSpan remaining; - if (timeElapsed > MultiplayerChatTimerCountdown.TimeRemaining.TotalMilliseconds) + if (timeElapsed > multiplayerChatTimerCountdown.TimeRemaining.TotalMilliseconds) remaining = TimeSpan.Zero; else - remaining = MultiplayerChatTimerCountdown.TimeRemaining - TimeSpan.FromMilliseconds(timeElapsed); + remaining = multiplayerChatTimerCountdown.TimeRemaining - TimeSpan.FromMilliseconds(timeElapsed); return remaining; } @@ -95,11 +95,6 @@ private TimeSpan countdownTimeRemaining [Resolved] protected MultiplayerClient Client { get; private set; } - [Resolved] - protected ChannelManager ChannelManager { get; private set; } - - protected Channel TargetChannel; - public event Action OnChatMessageDue; [BackgroundDependencyLoader] @@ -113,21 +108,27 @@ private void load() if (countdownUpdateDelegate == null) return; - Logger.Log($@"Timer scheduled delegate called, room state is {Client.Room?.State}"); + Logger.Log($@"Room state updated: {Client.Room?.State}. Aborting timer."); countdownUpdateDelegate?.Cancel(); countdownUpdateDelegate = null; OnChatMessageDue?.Invoke(@"Countdown aborted (game started)"); }; } - public void SetTimer(TimeSpan duration, double startTime, Channel targetChannel) + public void SetTimer(TimeSpan duration, double startTime) { - // OnChatMessageDue = null; - MultiplayerChatTimerCountdown.TimeRemaining = duration; - CountdownChangeTime = startTime; - TargetChannel = targetChannel; + multiplayerChatTimerCountdown.TimeRemaining = duration; + countdownChangeTime = startTime; + + Logger.Log($@"Starting new timer ({startTime}, {duration})"); + + if (countdownUpdateDelegate != null) + { + Logger.Log(@"Aborting existing timer"); + countdownUpdateDelegate.Cancel(); + OnChatMessageDue?.Invoke(@"Countdown aborted"); + } - countdownUpdateDelegate?.Cancel(); countdownUpdateDelegate = Scheduler.Add(sendTimerMessage); } From c3522e4487bbd05138fe7c3d6e2ba5ab24a90992 Mon Sep 17 00:00:00 2001 From: ILW8 Date: Thu, 9 May 2024 02:31:46 +0100 Subject: [PATCH 4/5] add delayed !mp start - add an optional prefix parameter for timer message - add timer completed callback --- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 36 +++++++++++-------- .../Multiplayer/MultiplayerMatchSubScreen.cs | 27 ++++++++++---- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 1ed5366e1c..97e8e3d0e4 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -342,6 +342,7 @@ private void postMessage(TextBox sender, bool newText) break; case @"start": + chatTimerHandler?.SetTimer(TimeSpan.FromSeconds(numericParam), Time.Current, messagePrefix: @"Match starts in", onTimerComplete: startMatch); break; } } @@ -493,21 +494,7 @@ private void postMessage(TextBox sender, bool newText) // start immediately case @"start": - if (!Client.IsHost) - { - Logger.Log(@"Tried to start match when user is not host of the room. Cancelling!", LoggingTarget.Runtime, LogLevel.Important); - break; - } - - // no one is ready, server won't allow starting the map - if (Client.Room?.Users.All(u => u.State != MultiplayerUserState.Ready) ?? false) - { - Logger.Log(@"Tried to start match when no player is ready. Cancelling!", LoggingTarget.Runtime, LogLevel.Important); - botMessageQueue.Enqueue(new Tuple(@"No player ready, cannot start match.", Channel.Value)); - break; - } - - Client.StartMatch().FireAndForget(); + startMatch(); break; } @@ -518,6 +505,25 @@ private void postMessage(TextBox sender, bool newText) TextBox.Text = string.Empty; } + private void startMatch() + { + if (!Client.IsHost) + { + Logger.Log(@"Tried to start match when user is not host of the room. Cancelling!", LoggingTarget.Runtime, LogLevel.Important); + return; + } + + // no one is ready, server won't allow starting the map + if (Client.Room?.Users.All(u => u.State != MultiplayerUserState.Ready) ?? false) + { + Logger.Log(@"Tried to start match when no player is ready. Cancelling!", LoggingTarget.Runtime, LogLevel.Important); + botMessageQueue.Enqueue(new Tuple(@"No player ready, cannot start match.", Channel.Value)); + return; + } + + Client.StartMatch().FireAndForget(); + } + private void abortTimer() { chatTimerHandler.Abort(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 42ae45d270..99a22dfe58 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -72,6 +72,7 @@ public partial class ChatTimerHandler : Component { private readonly MultiplayerCountdown multiplayerChatTimerCountdown = new MatchStartCountdown { TimeRemaining = TimeSpan.Zero }; private double countdownChangeTime; + private string countdownMessagePrefix; private TimeSpan countdownTimeRemaining { @@ -95,8 +96,12 @@ private TimeSpan countdownTimeRemaining [Resolved] protected MultiplayerClient Client { get; private set; } + [CanBeNull] public event Action OnChatMessageDue; + [CanBeNull] + public event Action OnTimerComplete; + [BackgroundDependencyLoader] private void load() { @@ -115,20 +120,23 @@ private void load() }; } - public void SetTimer(TimeSpan duration, double startTime) + public void SetTimer(TimeSpan duration, double startTime, string messagePrefix = @"Countdown ends in", Action onTimerComplete = null) { + Logger.Log($@"Starting new timer ({startTime}, {duration}, prefix: '{messagePrefix}', completeAction: {onTimerComplete?.Method.Name ?? @"null"})"); + multiplayerChatTimerCountdown.TimeRemaining = duration; countdownChangeTime = startTime; - Logger.Log($@"Starting new timer ({startTime}, {duration})"); - if (countdownUpdateDelegate != null) { Logger.Log(@"Aborting existing timer"); countdownUpdateDelegate.Cancel(); + countdownUpdateDelegate = null; OnChatMessageDue?.Invoke(@"Countdown aborted"); } + OnTimerComplete = onTimerComplete; + countdownMessagePrefix = messagePrefix; countdownUpdateDelegate = Scheduler.Add(sendTimerMessage); } @@ -152,12 +160,18 @@ private void processTimerEvent() private void sendTimerMessage() { int secondsRemaining = (int)Math.Round(countdownTimeRemaining.TotalSeconds); - string message = secondsRemaining == 0 ? @"Countdown finished" : $@"Countdown ends in {secondsRemaining} seconds"; + string message = secondsRemaining <= 0 ? @"Countdown finished" : $@"{countdownMessagePrefix} {secondsRemaining} seconds"; OnChatMessageDue?.Invoke(message); + Logger.Log($@"Sent timer message, {secondsRemaining} seconds remaining on timer."); - if (secondsRemaining <= 0) return; + if (secondsRemaining <= 0) + { + countdownUpdateDelegate = null; + OnTimerComplete?.Invoke(); + return; + } - Logger.Log($@"Sent timer message, {secondsRemaining} seconds remaining on timer. "); + Logger.Log($@"Scheduling {nameof(processTimerEvent)} in 100ms."); countdownUpdateDelegate = Scheduler.AddDelayed(processTimerEvent, 100); } @@ -484,6 +498,7 @@ public override void OnEntering(ScreenTransitionEvent e) public override bool OnExiting(ScreenExitEvent e) { chatTimerHandler.OnChatMessageDue -= chatDisplay.EnqueueBotMessage; + chatTimerHandler.Abort(); // room has not been created yet or we're offline; exit immediately. if (client.Room == null || !IsConnected) From 1506e1648cc8e294f1aef1d3b9d8a586d0360923 Mon Sep 17 00:00:00 2001 From: ILW8 Date: Thu, 9 May 2024 02:33:32 +0100 Subject: [PATCH 5/5] check user is host before scheduling !mp start timer --- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 97e8e3d0e4..dc6063cd7e 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -342,6 +342,13 @@ private void postMessage(TextBox sender, bool newText) break; case @"start": + // we intentionally do this check both in startMatch and here + if (!Client.IsHost) + { + Logger.Log(@"Tried to start match when user is not host of the room. Cancelling!", LoggingTarget.Runtime, LogLevel.Important); + return; + } + chatTimerHandler?.SetTimer(TimeSpan.FromSeconds(numericParam), Time.Current, messagePrefix: @"Match starts in", onTimerComplete: startMatch); break; }