diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftRoomSubScreen.cs
similarity index 94%
rename from osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs
rename to osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftRoomSubScreen.cs
index bceb6efac1..f56f78ce89 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftRoomSubScreen.cs
@@ -16,15 +16,15 @@ using osu.Game.Online.Multiplayer;
 using osu.Game.Rulesets;
 using osu.Game.Rulesets.Osu;
 using osu.Game.Screens.Multi;
-using osu.Game.Screens.Multi.Match;
 using osu.Game.Screens.Multi.Match.Components;
+using osu.Game.Screens.Multi.Timeshift;
 using osu.Game.Tests.Beatmaps;
 using osu.Game.Users;
 using osuTK.Input;
 
 namespace osu.Game.Tests.Visual.Multiplayer
 {
-    public class TestSceneMatchSubScreen : MultiplayerTestScene
+    public class TestSceneTimeshiftRoomSubScreen : MultiplayerTestScene
     {
         protected override bool UseOnlineAPI => true;
 
@@ -34,7 +34,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
         private BeatmapManager manager;
         private RulesetStore rulesets;
 
-        private TestMatchSubScreen match;
+        private TestTimeshiftRoomSubScreen match;
 
         [BackgroundDependencyLoader]
         private void load(GameHost host, AudioManager audio)
@@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
         [SetUpSteps]
         public void SetupSteps()
         {
-            AddStep("load match", () => LoadScreen(match = new TestMatchSubScreen(Room)));
+            AddStep("load match", () => LoadScreen(match = new TestTimeshiftRoomSubScreen(Room)));
             AddUntilStep("wait for load", () => match.IsCurrentScreen());
         }
 
@@ -131,13 +131,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
             AddAssert("match has original beatmap", () => match.Beatmap.Value.Beatmap.BeatmapInfo.BaseDifficulty.CircleSize != 1);
         }
 
-        private class TestMatchSubScreen : MatchSubScreen
+        private class TestTimeshiftRoomSubScreen : TimeshiftRoomSubScreen
         {
             public new Bindable<PlaylistItem> SelectedItem => base.SelectedItem;
 
             public new Bindable<WorkingBeatmap> Beatmap => base.Beatmap;
 
-            public TestMatchSubScreen(Room room)
+            public TestTimeshiftRoomSubScreen(Room room)
                 : base(room)
             {
             }
diff --git a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs
index 26e351fc2b..f4591d089e 100644
--- a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs
+++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs
@@ -13,7 +13,7 @@ using osu.Game.Graphics.UserInterface;
 using osu.Game.Online.Multiplayer;
 using osu.Game.Overlays;
 using osu.Game.Screens.Multi.Lounge.Components;
-using osu.Game.Screens.Multi.Match;
+using osu.Game.Screens.Multi.Timeshift;
 using osu.Game.Users;
 
 namespace osu.Game.Screens.Multi.Lounge
@@ -192,7 +192,7 @@ namespace osu.Game.Screens.Multi.Lounge
 
             selectedRoom.Value = room;
 
-            this.Push(new MatchSubScreen(room));
+            this.Push(new TimeshiftRoomSubScreen(room));
         }
 
         protected abstract FilterControl CreateFilterControl();
diff --git a/osu.Game/Screens/Multi/Match/RoomSubScreen.cs b/osu.Game/Screens/Multi/Match/RoomSubScreen.cs
new file mode 100644
index 0000000000..0cc9a4354e
--- /dev/null
+++ b/osu.Game/Screens/Multi/Match/RoomSubScreen.cs
@@ -0,0 +1,74 @@
+// 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 osu.Framework.Allocation;
+using osu.Framework.Bindables;
+using osu.Framework.Screens;
+using osu.Game.Audio;
+using osu.Game.Beatmaps;
+using osu.Game.Online.Multiplayer;
+using osu.Game.Rulesets.Mods;
+
+namespace osu.Game.Screens.Multi.Match
+{
+    [Cached(typeof(IPreviewTrackOwner))]
+    public abstract class RoomSubScreen : MultiplayerSubScreen, IPreviewTrackOwner
+    {
+        protected readonly Bindable<PlaylistItem> SelectedItem = new Bindable<PlaylistItem>();
+
+        public override bool DisallowExternalBeatmapRulesetChanges => true;
+
+        [Resolved(typeof(Room), nameof(Room.Playlist))]
+        protected BindableList<PlaylistItem> Playlist { get; private set; }
+
+        [Resolved]
+        private BeatmapManager beatmapManager { get; set; }
+
+        private IBindable<WeakReference<BeatmapSetInfo>> managerUpdated;
+
+        protected override void LoadComplete()
+        {
+            base.LoadComplete();
+
+            SelectedItem.BindValueChanged(_ => Scheduler.AddOnce(selectedItemChanged));
+            SelectedItem.Value = Playlist.FirstOrDefault();
+
+            managerUpdated = beatmapManager.ItemUpdated.GetBoundCopy();
+            managerUpdated.BindValueChanged(beatmapUpdated);
+        }
+
+        private void selectedItemChanged()
+        {
+            updateWorkingBeatmap();
+
+            var item = SelectedItem.Value;
+
+            Mods.Value = item?.RequiredMods?.ToArray() ?? Array.Empty<Mod>();
+
+            if (item?.Ruleset != null)
+                Ruleset.Value = item.Ruleset.Value;
+        }
+
+        private void beatmapUpdated(ValueChangedEvent<WeakReference<BeatmapSetInfo>> weakSet) => Schedule(updateWorkingBeatmap);
+
+        private void updateWorkingBeatmap()
+        {
+            var beatmap = SelectedItem.Value?.Beatmap.Value;
+
+            // Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info
+            var localBeatmap = beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID);
+
+            Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap);
+        }
+
+        public override bool OnExiting(IScreen next)
+        {
+            RoomManager?.PartRoom();
+            Mods.Value = Array.Empty<Mod>();
+
+            return base.OnExiting(next);
+        }
+    }
+}
diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs
index b37ee45b84..eae779421d 100644
--- a/osu.Game/Screens/Multi/Multiplayer.cs
+++ b/osu.Game/Screens/Multi/Multiplayer.cs
@@ -308,7 +308,7 @@ namespace osu.Game.Screens.Multi
                     headerBackground.MoveToX(0, MultiplayerSubScreen.X_MOVE_DURATION, Easing.OutQuint);
                     break;
 
-                case MatchSubScreen _:
+                case RoomSubScreen _:
                     header.ResizeHeightTo(135, MultiplayerSubScreen.APPEAR_DURATION, Easing.OutQuint);
                     headerBackground.MoveToX(-MultiplayerSubScreen.X_SHIFT, MultiplayerSubScreen.X_MOVE_DURATION, Easing.OutQuint);
                     break;
@@ -330,7 +330,7 @@ namespace osu.Game.Screens.Multi
 
         private void updateTrack(ValueChangedEvent<WorkingBeatmap> _ = null)
         {
-            if (screenStack.CurrentScreen is MatchSubScreen)
+            if (screenStack.CurrentScreen is RoomSubScreen)
             {
                 var track = Beatmap.Value?.Track;
 
diff --git a/osu.Game/Screens/Multi/Timeshift/TimeshiftMultiplayer.cs b/osu.Game/Screens/Multi/Timeshift/TimeshiftMultiplayer.cs
index a38b2a931e..2ea4857799 100644
--- a/osu.Game/Screens/Multi/Timeshift/TimeshiftMultiplayer.cs
+++ b/osu.Game/Screens/Multi/Timeshift/TimeshiftMultiplayer.cs
@@ -29,7 +29,7 @@ namespace osu.Game.Screens.Multi.Timeshift
                         timeshiftManager.TimeBetweenSelectionPolls.Value = isIdle ? 120000 : 15000;
                         break;
 
-                    case MatchSubScreen _:
+                    case RoomSubScreen _:
                         timeshiftManager.TimeBetweenListingPolls.Value = 0;
                         timeshiftManager.TimeBetweenSelectionPolls.Value = isIdle ? 30000 : 5000;
                         break;
diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Timeshift/TimeshiftRoomSubScreen.cs
similarity index 78%
rename from osu.Game/Screens/Multi/Match/MatchSubScreen.cs
rename to osu.Game/Screens/Multi/Timeshift/TimeshiftRoomSubScreen.cs
index 2f8aad4e65..433a980d60 100644
--- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs
+++ b/osu.Game/Screens/Multi/Timeshift/TimeshiftRoomSubScreen.cs
@@ -1,7 +1,6 @@
-// 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.
 
-using System;
 using System.Diagnostics;
 using System.Linq;
 using osu.Framework.Allocation;
@@ -9,28 +8,21 @@ using osu.Framework.Bindables;
 using osu.Framework.Graphics;
 using osu.Framework.Graphics.Containers;
 using osu.Framework.Screens;
-using osu.Game.Audio;
-using osu.Game.Beatmaps;
 using osu.Game.Online.API;
 using osu.Game.Online.Multiplayer;
-using osu.Game.Online.Multiplayer.GameTypes;
-using osu.Game.Rulesets.Mods;
 using osu.Game.Screens.Multi.Components;
+using osu.Game.Screens.Multi.Match;
 using osu.Game.Screens.Multi.Match.Components;
 using osu.Game.Screens.Multi.Play;
 using osu.Game.Screens.Multi.Ranking;
 using osu.Game.Screens.Play;
 using osu.Game.Screens.Select;
 using osu.Game.Users;
-using Footer = osu.Game.Screens.Multi.Match.Components.Footer;
 
-namespace osu.Game.Screens.Multi.Match
+namespace osu.Game.Screens.Multi.Timeshift
 {
-    [Cached(typeof(IPreviewTrackOwner))]
-    public class MatchSubScreen : MultiplayerSubScreen, IPreviewTrackOwner
+    public class TimeshiftRoomSubScreen : RoomSubScreen
     {
-        public override bool DisallowExternalBeatmapRulesetChanges => true;
-
         public override string Title { get; }
 
         public override string ShortTitle => "room";
@@ -38,27 +30,15 @@ namespace osu.Game.Screens.Multi.Match
         [Resolved(typeof(Room), nameof(Room.RoomID))]
         private Bindable<int?> roomId { get; set; }
 
-        [Resolved(typeof(Room), nameof(Room.Type))]
-        private Bindable<GameType> type { get; set; }
-
-        [Resolved(typeof(Room), nameof(Room.Playlist))]
-        private BindableList<PlaylistItem> playlist { get; set; }
-
-        [Resolved]
-        private BeatmapManager beatmapManager { get; set; }
-
         [Resolved(canBeNull: true)]
         private Multiplayer multiplayer { get; set; }
 
-        protected readonly Bindable<PlaylistItem> SelectedItem = new Bindable<PlaylistItem>();
-
         private MatchSettingsOverlay settingsOverlay;
         private MatchLeaderboard leaderboard;
 
-        private IBindable<WeakReference<BeatmapSetInfo>> managerUpdated;
         private OverlinedHeader participantsHeader;
 
-        public MatchSubScreen(Room room)
+        public TimeshiftRoomSubScreen(Room room)
         {
             Title = room.RoomID.Value == null ? "New room" : room.Name.Value;
             Activity.Value = new UserActivity.InLobby(room);
@@ -96,7 +76,7 @@ namespace osu.Game.Screens.Multi.Match
                                     },
                                     Content = new[]
                                     {
-                                        new Drawable[] { new Components.Header() },
+                                        new Drawable[] { new Match.Components.Header() },
                                         new Drawable[]
                                         {
                                             participantsHeader = new OverlinedHeader("Participants")
@@ -141,7 +121,7 @@ namespace osu.Game.Screens.Multi.Match
                                                                         new DrawableRoomPlaylistWithResults
                                                                         {
                                                                             RelativeSizeAxes = Axes.Both,
-                                                                            Items = { BindTarget = playlist },
+                                                                            Items = { BindTarget = Playlist },
                                                                             SelectedItem = { BindTarget = SelectedItem },
                                                                             RequestShowResults = item =>
                                                                             {
@@ -195,7 +175,7 @@ namespace osu.Game.Screens.Multi.Match
                         },
                         new Drawable[]
                         {
-                            new Footer
+                            new Match.Components.Footer
                             {
                                 OnStart = onStart,
                                 SelectedItem = { BindTarget = SelectedItem }
@@ -234,61 +214,17 @@ namespace osu.Game.Screens.Multi.Match
 
                     // Set the first playlist item.
                     // This is scheduled since updating the room and playlist may happen in an arbitrary order (via Room.CopyFrom()).
-                    Schedule(() => SelectedItem.Value = playlist.FirstOrDefault());
+                    Schedule(() => SelectedItem.Value = Playlist.FirstOrDefault());
                 }
             }, true);
-
-            SelectedItem.BindValueChanged(_ => Scheduler.AddOnce(selectedItemChanged));
-            SelectedItem.Value = playlist.FirstOrDefault();
-
-            managerUpdated = beatmapManager.ItemUpdated.GetBoundCopy();
-            managerUpdated.BindValueChanged(beatmapUpdated);
-        }
-
-        public override bool OnExiting(IScreen next)
-        {
-            RoomManager?.PartRoom();
-            Mods.Value = Array.Empty<Mod>();
-
-            return base.OnExiting(next);
-        }
-
-        private void selectedItemChanged()
-        {
-            updateWorkingBeatmap();
-
-            var item = SelectedItem.Value;
-
-            Mods.Value = item?.RequiredMods?.ToArray() ?? Array.Empty<Mod>();
-
-            if (item?.Ruleset != null)
-                Ruleset.Value = item.Ruleset.Value;
-        }
-
-        private void beatmapUpdated(ValueChangedEvent<WeakReference<BeatmapSetInfo>> weakSet) => Schedule(updateWorkingBeatmap);
-
-        private void updateWorkingBeatmap()
-        {
-            var beatmap = SelectedItem.Value?.Beatmap.Value;
-
-            // Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info
-            var localBeatmap = beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID);
-
-            Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap);
         }
 
         private void onStart()
         {
-            switch (type.Value)
+            multiplayer?.Push(new PlayerLoader(() => new TimeshiftPlayer(SelectedItem.Value)
             {
-                default:
-                case GameTypeTimeshift _:
-                    multiplayer?.Push(new PlayerLoader(() => new TimeshiftPlayer(SelectedItem.Value)
-                    {
-                        Exited = () => leaderboard.RefreshScores()
-                    }));
-                    break;
-            }
+                Exited = () => leaderboard.RefreshScores()
+            }));
         }
     }
 }