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); }