diff --git a/osu.Server.Spectator/Database/DatabaseAccess.cs b/osu.Server.Spectator/Database/DatabaseAccess.cs
index fb4c3336..3e893582 100644
--- a/osu.Server.Spectator/Database/DatabaseAccess.cs
+++ b/osu.Server.Spectator/Database/DatabaseAccess.cs
@@ -103,6 +103,18 @@ public async Task UpdateRoomSettingsAsync(MultiplayerRoom room)
});
}
+ public async Task UpdateRoomStatusAsync(MultiplayerRoom room)
+ {
+ var connection = await getConnectionAsync();
+
+ await connection.ExecuteAsync("UPDATE multiplayer_rooms SET status = @Status WHERE id = @RoomID", new
+ {
+ RoomID = room.RoomID,
+ // needs ToString() to store as enums correctly, see https://github.com/DapperLib/Dapper/issues/813.
+ Status = room.State.ToDatabaseRoomStatus().ToString(),
+ });
+ }
+
public async Task UpdateRoomHostAsync(MultiplayerRoom room)
{
var connection = await getConnectionAsync();
diff --git a/osu.Server.Spectator/Database/IDatabaseAccess.cs b/osu.Server.Spectator/Database/IDatabaseAccess.cs
index 31e75f2f..8df0f0f6 100644
--- a/osu.Server.Spectator/Database/IDatabaseAccess.cs
+++ b/osu.Server.Spectator/Database/IDatabaseAccess.cs
@@ -56,6 +56,11 @@ public interface IDatabaseAccess : IDisposable
///
Task UpdateRoomSettingsAsync(MultiplayerRoom room);
+ ///
+ /// Updates the current status of in the database.
+ ///
+ Task UpdateRoomStatusAsync(MultiplayerRoom room);
+
///
/// Updates the current host of in the database.
///
diff --git a/osu.Server.Spectator/Database/Models/database_room_status.cs b/osu.Server.Spectator/Database/Models/database_room_status.cs
new file mode 100644
index 00000000..5529d8f4
--- /dev/null
+++ b/osu.Server.Spectator/Database/Models/database_room_status.cs
@@ -0,0 +1,36 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System;
+using osu.Game.Online.Multiplayer;
+
+namespace osu.Server.Spectator.Database.Models
+{
+ // ReSharper disable once InconsistentNaming
+ [Serializable]
+ public enum database_room_status
+ {
+ idle,
+ playing
+ }
+
+ public static class DatabaseRoomStatusExtensions
+ {
+ public static database_room_status ToDatabaseRoomStatus(this MultiplayerRoomState state)
+ {
+ switch (state)
+ {
+ case MultiplayerRoomState.Open:
+ case MultiplayerRoomState.Closed:
+ return database_room_status.idle;
+
+ case MultiplayerRoomState.WaitingForLoad:
+ case MultiplayerRoomState.Playing:
+ return database_room_status.playing;
+
+ default:
+ throw new ArgumentOutOfRangeException(nameof(state), state, null);
+ }
+ }
+ }
+}
diff --git a/osu.Server.Spectator/Database/Models/multiplayer_room.cs b/osu.Server.Spectator/Database/Models/multiplayer_room.cs
index f4ffd97b..46087bf4 100644
--- a/osu.Server.Spectator/Database/Models/multiplayer_room.cs
+++ b/osu.Server.Spectator/Database/Models/multiplayer_room.cs
@@ -23,6 +23,7 @@ public class multiplayer_room
public DateTimeOffset? updated_at { get; set; }
public DateTimeOffset? deleted_at { get; set; }
public room_category category { get; set; }
+ public database_room_status status { get; set; }
public database_match_type type { get; set; }
public database_queue_mode queue_mode { get; set; }
public ushort auto_start_duration { get; set; }
diff --git a/osu.Server.Spectator/Hubs/Multiplayer/MultiplayerHub.cs b/osu.Server.Spectator/Hubs/Multiplayer/MultiplayerHub.cs
index 0004b715..e2d5837e 100644
--- a/osu.Server.Spectator/Hubs/Multiplayer/MultiplayerHub.cs
+++ b/osu.Server.Spectator/Hubs/Multiplayer/MultiplayerHub.cs
@@ -38,7 +38,7 @@ public MultiplayerHub(
Rooms = rooms;
this.databaseFactory = databaseFactory;
this.chatFilters = chatFilters;
- HubContext = new MultiplayerHubContext(hubContext, rooms, users, loggerFactory);
+ HubContext = new MultiplayerHubContext(hubContext, rooms, users, databaseFactory, loggerFactory);
}
public Task JoinRoom(long roomId) => JoinRoomWithPassword(roomId, string.Empty);
diff --git a/osu.Server.Spectator/Hubs/Multiplayer/MultiplayerHubContext.cs b/osu.Server.Spectator/Hubs/Multiplayer/MultiplayerHubContext.cs
index d9bf0be2..01c7da43 100644
--- a/osu.Server.Spectator/Hubs/Multiplayer/MultiplayerHubContext.cs
+++ b/osu.Server.Spectator/Hubs/Multiplayer/MultiplayerHubContext.cs
@@ -12,6 +12,7 @@
using osu.Game.Online.API;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Rooms;
+using osu.Server.Spectator.Database;
using osu.Server.Spectator.Entities;
using osu.Server.Spectator.Extensions;
@@ -30,17 +31,20 @@ public class MultiplayerHubContext : IMultiplayerHubContext
private readonly IHubContext context;
private readonly EntityStore rooms;
private readonly EntityStore users;
+ private readonly IDatabaseFactory databaseFactory;
private readonly ILogger logger;
public MultiplayerHubContext(
IHubContext context,
EntityStore rooms,
EntityStore users,
+ IDatabaseFactory databaseFactory,
ILoggerFactory loggerFactory)
{
this.context = context;
this.rooms = rooms;
this.users = users;
+ this.databaseFactory = databaseFactory;
logger = loggerFactory.CreateLogger(nameof(MultiplayerHub).Replace("Hub", string.Empty));
}
@@ -161,7 +165,11 @@ public async Task ChangeAndBroadcastUserBeatmapAvailability(ServerMultiplayerRoo
public async Task ChangeRoomState(ServerMultiplayerRoom room, MultiplayerRoomState newState)
{
log(room, null, $"Room state changing from {room.State} to {newState}");
+
room.State = newState;
+ using (var db = databaseFactory.GetInstance())
+ await db.UpdateRoomStatusAsync(room);
+
await context.Clients.Group(MultiplayerHub.GetGroupId(room.RoomID)).SendAsync(nameof(IMultiplayerClient.RoomStateChanged), newState);
}