mirror of
https://github.com/ppy/osu.git
synced 2025-03-11 03:37:20 +08:00
Merge pull request #31637 from smoogipoo/room-management-lio
Create, join, and part multiplayer rooms only via the multiplayer server
This commit is contained in:
commit
58a671decb
@ -9,7 +9,6 @@ using osu.Framework.Testing;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
|
||||
namespace osu.Game.Tests.NonVisual.Multiplayer
|
||||
@ -73,10 +72,6 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
|
||||
|
||||
AddStep("create room initially in gameplay", () =>
|
||||
{
|
||||
var newRoom = new Room();
|
||||
newRoom.CopyFrom(SelectedRoom.Value!);
|
||||
|
||||
newRoom.RoomID = null;
|
||||
MultiplayerClient.RoomSetupAction = room =>
|
||||
{
|
||||
room.State = MultiplayerRoomState.Playing;
|
||||
@ -87,7 +82,7 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
|
||||
});
|
||||
};
|
||||
|
||||
RoomManager.CreateRoom(newRoom);
|
||||
MultiplayerClient.JoinRoom(MultiplayerClient.ServerSideRooms.Single()).ConfigureAwait(false);
|
||||
});
|
||||
|
||||
AddUntilStep("wait for room join", () => RoomJoined);
|
||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
Bindable<LocalUserPlayingState> playingState = new Bindable<LocalUserPlayingState>();
|
||||
GameplayState gameplayState = new GameplayState(new Beatmap(), new OsuRuleset(), healthProcessor: new OsuHealthProcessor(0), localUserPlayingState: playingState);
|
||||
TestSpectatorClient spectatorClient = new TestSpectatorClient();
|
||||
TestMultiplayerClient multiplayerClient = new TestMultiplayerClient(new TestMultiplayerRoomManager(new TestRoomRequestsHandler()));
|
||||
TestMultiplayerClient multiplayerClient = new TestMultiplayerClient(new TestRoomRequestsHandler());
|
||||
|
||||
AddStep("create spectator list", () =>
|
||||
{
|
||||
|
@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
var mockLounge = new Mock<LoungeSubScreen>();
|
||||
var mockLounge = new Mock<IOnlinePlayLounge>();
|
||||
mockLounge
|
||||
.Setup(l => l.Join(It.IsAny<Room>(), It.IsAny<string>(), It.IsAny<Action<Room>>(), It.IsAny<Action<string>>()))
|
||||
.Callback<Room, string, Action<Room>, Action<string>>((_, _, _, d) =>
|
||||
|
@ -58,7 +58,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
private TestMultiplayerComponents multiplayerComponents = null!;
|
||||
|
||||
private TestMultiplayerClient multiplayerClient => multiplayerComponents.MultiplayerClient;
|
||||
private TestMultiplayerRoomManager roomManager => multiplayerComponents.RoomManager;
|
||||
|
||||
[Resolved]
|
||||
private OsuConfigManager config { get; set; } = null!;
|
||||
@ -257,7 +256,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
AddStep("create room", () =>
|
||||
{
|
||||
roomManager.AddServerSideRoom(new Room
|
||||
multiplayerClient.AddServerSideRoom(new Room
|
||||
{
|
||||
Name = "Test Room",
|
||||
Playlist =
|
||||
@ -286,7 +285,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
AddStep("create room", () =>
|
||||
{
|
||||
roomManager.AddServerSideRoom(new Room
|
||||
multiplayerClient.AddServerSideRoom(new Room
|
||||
{
|
||||
Name = "Test Room",
|
||||
Playlist =
|
||||
@ -336,7 +335,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
AddStep("create room", () =>
|
||||
{
|
||||
roomManager.AddServerSideRoom(new Room
|
||||
multiplayerClient.AddServerSideRoom(new Room
|
||||
{
|
||||
Name = "Test Room",
|
||||
Password = "password",
|
||||
@ -789,7 +788,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
AddStep("create room", () =>
|
||||
{
|
||||
roomManager.AddServerSideRoom(new Room
|
||||
multiplayerClient.AddServerSideRoom(new Room
|
||||
{
|
||||
Name = "Test Room",
|
||||
QueueMode = QueueMode.AllPlayers,
|
||||
@ -810,8 +809,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("disable polling", () => this.ChildrenOfType<ListingPollingComponent>().Single().TimeBetweenPolls.Value = 0);
|
||||
AddStep("change server-side settings", () =>
|
||||
{
|
||||
roomManager.ServerSideRooms[0].Name = "New name";
|
||||
roomManager.ServerSideRooms[0].Playlist =
|
||||
multiplayerClient.ServerSideRooms[0].Name = "New name";
|
||||
multiplayerClient.ServerSideRooms[0].Playlist =
|
||||
[
|
||||
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||
{
|
||||
@ -828,7 +827,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddAssert("local room has correct settings", () =>
|
||||
{
|
||||
var localRoom = this.ChildrenOfType<MultiplayerMatchSubScreen>().Single().Room;
|
||||
return localRoom.Name == roomManager.ServerSideRooms[0].Name && localRoom.Playlist.Single().ID == 2;
|
||||
return localRoom.Name == multiplayerClient.ServerSideRooms[0].Name && localRoom.Playlist.Single().ID == 2;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -8,36 +8,33 @@ using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Lounge;
|
||||
using osu.Game.Screens.OnlinePlay.Lounge.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||
using osu.Game.Tests.Visual.OnlinePlay;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
public partial class TestSceneMultiplayerLoungeSubScreen : OnlinePlayTestScene
|
||||
public partial class TestSceneMultiplayerLoungeSubScreen : MultiplayerTestScene
|
||||
{
|
||||
protected new TestRoomManager RoomManager => (TestRoomManager)base.RoomManager;
|
||||
|
||||
private LoungeSubScreen loungeScreen = null!;
|
||||
private Room? lastJoinedRoom;
|
||||
private string? lastJoinedPassword;
|
||||
|
||||
private RoomsContainer roomsContainer => loungeScreen.ChildrenOfType<RoomsContainer>().First();
|
||||
|
||||
public TestSceneMultiplayerLoungeSubScreen()
|
||||
: base(false)
|
||||
{
|
||||
}
|
||||
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("push screen", () => LoadScreen(loungeScreen = new MultiplayerLoungeSubScreen()));
|
||||
|
||||
AddUntilStep("wait for present", () => loungeScreen.IsCurrentScreen());
|
||||
|
||||
AddStep("bind to event", () =>
|
||||
{
|
||||
lastJoinedRoom = null;
|
||||
lastJoinedPassword = null;
|
||||
RoomManager.JoinRoomRequested = onRoomJoined;
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -47,8 +44,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("select room", () => InputManager.Key(Key.Down));
|
||||
AddStep("join room", () => InputManager.Key(Key.Enter));
|
||||
|
||||
AddAssert("room join requested", () => lastJoinedRoom == RoomManager.Rooms.First());
|
||||
AddAssert("room join password correct", () => lastJoinedPassword == null);
|
||||
AddAssert("room joined", () => MultiplayerClient.RoomJoined);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -67,6 +63,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
AddStep("hit escape", () => InputManager.Key(Key.Escape));
|
||||
AddUntilStep("password prompt hidden", () => !InputManager.ChildrenOfType<DrawableLoungeRoom.PasswordEntryPopover>().Any());
|
||||
|
||||
AddAssert("room not joined", () => !MultiplayerClient.RoomJoined);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -79,6 +77,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddUntilStep("password prompt appeared", () => InputManager.ChildrenOfType<DrawableLoungeRoom.PasswordEntryPopover>().Any());
|
||||
AddStep("exit screen", () => Stack.Exit());
|
||||
AddUntilStep("password prompt hidden", () => !InputManager.ChildrenOfType<DrawableLoungeRoom.PasswordEntryPopover>().Any());
|
||||
|
||||
AddAssert("room not joined", () => !MultiplayerClient.RoomJoined);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -93,9 +93,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("enter password in text box", () => passwordEntryPopover.ChildrenOfType<TextBox>().First().Text = "wrong");
|
||||
AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType<OsuButton>().First().TriggerClick());
|
||||
|
||||
AddAssert("room not joined", () => loungeScreen.IsCurrentScreen());
|
||||
AddAssert("still at lounge", () => loungeScreen.IsCurrentScreen());
|
||||
AddUntilStep("password prompt still visible", () => passwordEntryPopover!.State.Value == Visibility.Visible);
|
||||
AddAssert("textbox still focused", () => InputManager.FocusedDrawable is OsuPasswordTextBox);
|
||||
|
||||
AddAssert("room not joined", () => !MultiplayerClient.RoomJoined);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -110,9 +112,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("enter password in text box", () => passwordEntryPopover.ChildrenOfType<TextBox>().First().Text = "wrong");
|
||||
AddStep("press enter", () => InputManager.Key(Key.Enter));
|
||||
|
||||
AddAssert("room not joined", () => loungeScreen.IsCurrentScreen());
|
||||
AddAssert("still at lounge", () => loungeScreen.IsCurrentScreen());
|
||||
AddUntilStep("password prompt still visible", () => passwordEntryPopover!.State.Value == Visibility.Visible);
|
||||
AddAssert("textbox still focused", () => InputManager.FocusedDrawable is OsuPasswordTextBox);
|
||||
|
||||
AddAssert("room not joined", () => !MultiplayerClient.RoomJoined);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -127,8 +131,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("enter password in text box", () => passwordEntryPopover.ChildrenOfType<TextBox>().First().Text = "password");
|
||||
AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType<OsuButton>().First().TriggerClick());
|
||||
|
||||
AddAssert("room join requested", () => lastJoinedRoom == RoomManager.Rooms.First());
|
||||
AddAssert("room join password correct", () => lastJoinedPassword == "password");
|
||||
AddUntilStep("room joined", () => MultiplayerClient.RoomJoined);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -143,14 +146,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("enter password in text box", () => passwordEntryPopover.ChildrenOfType<TextBox>().First().Text = "password");
|
||||
AddStep("press enter", () => InputManager.Key(Key.Enter));
|
||||
|
||||
AddAssert("room join requested", () => lastJoinedRoom == RoomManager.Rooms.First());
|
||||
AddAssert("room join password correct", () => lastJoinedPassword == "password");
|
||||
AddAssert("room joined", () => MultiplayerClient.RoomJoined);
|
||||
}
|
||||
|
||||
private void onRoomJoined(Room room, string? password)
|
||||
{
|
||||
lastJoinedRoom = room;
|
||||
lastJoinedPassword = password;
|
||||
}
|
||||
protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new MultiplayerTestSceneDependencies();
|
||||
}
|
||||
}
|
||||
|
@ -317,6 +317,29 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddAssert("score multiplier = 1.20", () => this.ChildrenOfType<RankingInformationDisplay>().Single().ModMultiplier.Value, () => Is.EqualTo(1.2).Within(0.01));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestChangeSettingsButtonVisibleForHost()
|
||||
{
|
||||
AddStep("add playlist item", () =>
|
||||
{
|
||||
SelectedRoom.Value!.Playlist =
|
||||
[
|
||||
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
|
||||
{
|
||||
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||
}
|
||||
];
|
||||
});
|
||||
ClickButtonWhenEnabled<MultiplayerMatchSettingsOverlay.CreateOrUpdateButton>();
|
||||
|
||||
AddUntilStep("wait for join", () => RoomJoined);
|
||||
|
||||
AddUntilStep("button visible", () => this.ChildrenOfType<DrawableMatchRoom>().Single().ChangeSettingsButton?.Alpha, () => Is.GreaterThan(0));
|
||||
AddStep("join other user", void () => MultiplayerClient.AddUser(new APIUser { Id = PLAYER_1_ID }));
|
||||
AddStep("make other user host", () => MultiplayerClient.TransferHost(PLAYER_1_ID));
|
||||
AddAssert("button hidden", () => this.ChildrenOfType<DrawableMatchRoom>().Single().ChangeSettingsButton?.Alpha, () => Is.EqualTo(0));
|
||||
}
|
||||
|
||||
private partial class TestMultiplayerMatchSubScreen : MultiplayerMatchSubScreen
|
||||
{
|
||||
[Resolved(canBeNull: true)]
|
||||
|
@ -127,7 +127,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
addItemStep();
|
||||
AddStep("finish current item", () => MultiplayerClient.FinishCurrentItem().WaitSafely());
|
||||
|
||||
AddStep("leave room", () => RoomManager.PartRoom());
|
||||
AddStep("leave room", () => MultiplayerClient.LeaveRoom());
|
||||
AddUntilStep("wait for room part", () => !RoomJoined);
|
||||
|
||||
AddUntilStep("item 0 not in lists", () => !inHistoryList(0) && !inQueueList(0));
|
||||
@ -148,7 +148,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("finish current item", () => MultiplayerClient.FinishCurrentItem().WaitSafely());
|
||||
assertQueueTabCount(2);
|
||||
|
||||
AddStep("leave room", () => RoomManager.PartRoom());
|
||||
AddStep("leave room", () => MultiplayerClient.LeaveRoom());
|
||||
AddUntilStep("wait for room part", () => !RoomJoined);
|
||||
assertQueueTabCount(0);
|
||||
}
|
||||
@ -157,12 +157,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
[Test]
|
||||
public void TestJoinRoomWithMixedItemsAddedInCorrectLists()
|
||||
{
|
||||
AddStep("leave room", () => RoomManager.PartRoom());
|
||||
AddStep("leave room", () => MultiplayerClient.LeaveRoom());
|
||||
AddUntilStep("wait for room part", () => !RoomJoined);
|
||||
|
||||
AddStep("join room with items", () =>
|
||||
{
|
||||
RoomManager.CreateRoom(new Room
|
||||
API.Queue(new CreateRoomRequest(new Room
|
||||
{
|
||||
Name = "test name",
|
||||
Playlist =
|
||||
@ -177,7 +177,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
Expired = true
|
||||
}
|
||||
]
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
AddUntilStep("wait for room join", () => RoomJoined);
|
||||
|
@ -36,6 +36,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
public void TestManyRooms()
|
||||
{
|
||||
AddStep("add rooms", () => RoomManager.AddRooms(500));
|
||||
AddUntilStep("wait for rooms", () => roomsContainer.Rooms.Count == 500);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -75,6 +76,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
public void TestEnteringRoomTakesLeaseOnSelection()
|
||||
{
|
||||
AddStep("add rooms", () => RoomManager.AddRooms(1));
|
||||
AddUntilStep("wait for rooms", () => roomsContainer.Rooms.Count == 1);
|
||||
|
||||
AddAssert("selected room is not disabled", () => !loungeScreen.SelectedRoom.Disabled);
|
||||
|
||||
|
@ -3,14 +3,13 @@
|
||||
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay;
|
||||
using osu.Game.Screens.OnlinePlay.Playlists;
|
||||
using osu.Game.Tests.Visual.OnlinePlay;
|
||||
|
||||
@ -21,13 +20,33 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
protected new TestRoomManager RoomManager => (TestRoomManager)base.RoomManager;
|
||||
|
||||
private TestRoomSettings settings = null!;
|
||||
|
||||
protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies();
|
||||
private Func<Room, string?>? handleRequest;
|
||||
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("setup api", () =>
|
||||
{
|
||||
handleRequest = null;
|
||||
((DummyAPIAccess)API).HandleRequest = req =>
|
||||
{
|
||||
if (req is not CreateRoomRequest createReq || handleRequest == null)
|
||||
return false;
|
||||
|
||||
if (handleRequest(createReq.Room) is string errorText)
|
||||
createReq.TriggerFailure(new APIException(errorText, null));
|
||||
else
|
||||
{
|
||||
var createdRoom = new APICreatedRoom();
|
||||
createdRoom.CopyFrom(createReq.Room);
|
||||
createReq.TriggerSuccess(createdRoom);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
});
|
||||
|
||||
AddStep("create overlay", () =>
|
||||
{
|
||||
SelectedRoom.Value = new Room();
|
||||
@ -75,10 +94,10 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
settings.DurationField.Current.Value = expectedDuration;
|
||||
SelectedRoom.Value!.Playlist = [new PlaylistItem(CreateBeatmap(Ruleset.Value).BeatmapInfo)];
|
||||
|
||||
RoomManager.CreateRequested = r =>
|
||||
handleRequest = r =>
|
||||
{
|
||||
createdRoom = r;
|
||||
return string.Empty;
|
||||
return null;
|
||||
};
|
||||
});
|
||||
|
||||
@ -103,7 +122,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
|
||||
errorMessage = $"{not_found_prefix} {beatmap.OnlineID}";
|
||||
|
||||
RoomManager.CreateRequested = _ => errorMessage;
|
||||
handleRequest = _ => errorMessage;
|
||||
});
|
||||
|
||||
AddAssert("error not displayed", () => !settings.ErrorText.IsPresent);
|
||||
@ -128,7 +147,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
SelectedRoom.Value!.Name = "Test Room";
|
||||
SelectedRoom.Value!.Playlist = [new PlaylistItem(CreateBeatmap(Ruleset.Value).BeatmapInfo)];
|
||||
|
||||
RoomManager.CreateRequested = _ => failText;
|
||||
handleRequest = _ => failText;
|
||||
});
|
||||
AddAssert("error not displayed", () => !settings.ErrorText.IsPresent);
|
||||
|
||||
@ -159,48 +178,5 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class TestDependencies : OnlinePlayTestSceneDependencies
|
||||
{
|
||||
protected override IRoomManager CreateRoomManager() => new TestRoomManager();
|
||||
}
|
||||
|
||||
protected class TestRoomManager : IRoomManager
|
||||
{
|
||||
public Func<Room, string>? CreateRequested;
|
||||
|
||||
public event Action RoomsUpdated
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
|
||||
public IBindable<bool> InitialRoomsReceived { get; } = new Bindable<bool>(true);
|
||||
|
||||
public IBindableList<Room> Rooms => null!;
|
||||
|
||||
public void AddOrUpdateRoom(Room room) => throw new NotImplementedException();
|
||||
|
||||
public void RemoveRoom(Room room) => throw new NotImplementedException();
|
||||
|
||||
public void ClearRooms() => throw new NotImplementedException();
|
||||
|
||||
public void CreateRoom(Room room, Action<Room>? onSuccess = null, Action<string>? onError = null)
|
||||
{
|
||||
if (CreateRequested == null)
|
||||
return;
|
||||
|
||||
string error = CreateRequested.Invoke(room);
|
||||
|
||||
if (!string.IsNullOrEmpty(error))
|
||||
onError?.Invoke(error);
|
||||
else
|
||||
onSuccess?.Invoke(room);
|
||||
}
|
||||
|
||||
public void JoinRoom(Room room, string? password, Action<Room>? onSuccess = null, Action<string>? onError = null) => throw new NotImplementedException();
|
||||
|
||||
public void PartRoom() => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
using osu.Game.Tests.Visual.OnlinePlay;
|
||||
|
||||
@ -26,15 +25,12 @@ namespace osu.Game.Tests.Visual
|
||||
/// <item>Provides a <see cref="TestMultiplayerClient"/> to be resolved as a dependency in the <see cref="Screens.OnlinePlay.Multiplayer.Multiplayer"/> screen,
|
||||
/// which is typically a part of <see cref="OsuGameBase"/>.</item>
|
||||
/// <item>Rebinds the <see cref="DummyAPIAccess"/> to handle requests via a <see cref="TestRoomRequestsHandler"/>.</item>
|
||||
/// <item>Provides a <see cref="TestMultiplayerRoomManager"/> for the <see cref="Screens.OnlinePlay.Multiplayer.Multiplayer"/> screen.</item>
|
||||
/// </list>
|
||||
/// </p>
|
||||
/// </summary>
|
||||
public partial class TestMultiplayerComponents : OsuScreen
|
||||
{
|
||||
public Screens.OnlinePlay.Multiplayer.Multiplayer MultiplayerScreen => multiplayerScreen;
|
||||
|
||||
public TestMultiplayerRoomManager RoomManager => multiplayerScreen.RoomManager;
|
||||
public Screens.OnlinePlay.Multiplayer.Multiplayer MultiplayerScreen { get; }
|
||||
|
||||
public IScreen CurrentScreen => screenStack.CurrentScreen;
|
||||
|
||||
@ -53,17 +49,17 @@ namespace osu.Game.Tests.Visual
|
||||
private BeatmapManager beatmapManager { get; set; }
|
||||
|
||||
private readonly OsuScreenStack screenStack;
|
||||
private readonly TestMultiplayer multiplayerScreen;
|
||||
private readonly TestRoomRequestsHandler requestsHandler = new TestRoomRequestsHandler();
|
||||
|
||||
public TestMultiplayerComponents()
|
||||
{
|
||||
multiplayerScreen = new TestMultiplayer();
|
||||
MultiplayerScreen = new Screens.OnlinePlay.Multiplayer.Multiplayer();
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
userLookupCache,
|
||||
beatmapLookupCache,
|
||||
MultiplayerClient = new TestMultiplayerClient(RoomManager),
|
||||
MultiplayerClient = new TestMultiplayerClient(requestsHandler),
|
||||
screenStack = new OsuScreenStack
|
||||
{
|
||||
Name = nameof(TestMultiplayerComponents),
|
||||
@ -71,13 +67,13 @@ namespace osu.Game.Tests.Visual
|
||||
}
|
||||
};
|
||||
|
||||
screenStack.Push(multiplayerScreen);
|
||||
screenStack.Push(MultiplayerScreen);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IAPIProvider api)
|
||||
{
|
||||
((DummyAPIAccess)api).HandleRequest = request => multiplayerScreen.RequestsHandler.HandleRequest(request, api.LocalUser.Value, beatmapManager);
|
||||
((DummyAPIAccess)api).HandleRequest = request => requestsHandler.HandleRequest(request, api.LocalUser.Value, beatmapManager);
|
||||
}
|
||||
|
||||
public override bool OnBackButton() => (screenStack.CurrentScreen as OsuScreen)?.OnBackButton() ?? base.OnBackButton();
|
||||
@ -90,13 +86,5 @@ namespace osu.Game.Tests.Visual
|
||||
screenStack.Exit();
|
||||
return true;
|
||||
}
|
||||
|
||||
private partial class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer
|
||||
{
|
||||
public new TestMultiplayerRoomManager RoomManager { get; private set; }
|
||||
public TestRoomRequestsHandler RequestsHandler { get; private set; }
|
||||
|
||||
protected override RoomManager CreateRoomManager() => RoomManager = new TestMultiplayerRoomManager(RequestsHandler = new TestRoomRequestsHandler());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,13 @@ namespace osu.Game.Online.Multiplayer
|
||||
/// </summary>
|
||||
public interface IMultiplayerLoungeServer
|
||||
{
|
||||
/// <summary>
|
||||
/// Request to create a multiplayer room.
|
||||
/// </summary>
|
||||
/// <param name="room">The room to create.</param>
|
||||
/// <returns>The created multiplayer room.</returns>
|
||||
Task<MultiplayerRoom> CreateRoom(MultiplayerRoom room);
|
||||
|
||||
/// <summary>
|
||||
/// Request to join a multiplayer room.
|
||||
/// </summary>
|
||||
|
@ -171,42 +171,73 @@ namespace osu.Game.Online.Multiplayer
|
||||
private CancellationTokenSource? joinCancellationSource;
|
||||
|
||||
/// <summary>
|
||||
/// Joins the <see cref="MultiplayerRoom"/> for a given API <see cref="Room"/>.
|
||||
/// Creates and joins a <see cref="MultiplayerRoom"/> described by an API <see cref="Room"/>.
|
||||
/// </summary>
|
||||
/// <param name="room">The API <see cref="Room"/>.</param>
|
||||
/// <param name="password">An optional password to use for the join operation.</param>
|
||||
public async Task JoinRoom(Room room, string? password = null)
|
||||
/// <param name="room">The API <see cref="Room"/> describing the room to create.</param>
|
||||
/// <exception cref="InvalidOperationException">If the current user is already in another room.</exception>
|
||||
public async Task CreateRoom(Room room)
|
||||
{
|
||||
if (Room != null)
|
||||
throw new InvalidOperationException("Cannot join a multiplayer room while already in one.");
|
||||
throw new InvalidOperationException("Cannot create a multiplayer room while already in one.");
|
||||
|
||||
var cancellationSource = joinCancellationSource = new CancellationTokenSource();
|
||||
|
||||
await joinOrLeaveTaskChain.Add(async () =>
|
||||
{
|
||||
Debug.Assert(room.RoomID != null);
|
||||
var multiplayerRoom = await CreateRoomInternal(new MultiplayerRoom(room)).ConfigureAwait(false);
|
||||
await setupJoinedRoom(room, multiplayerRoom, cancellationSource.Token).ConfigureAwait(false);
|
||||
}, cancellationSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
// Join the server-side room.
|
||||
var joinedRoom = await JoinRoom(room.RoomID.Value, password ?? room.Password).ConfigureAwait(false);
|
||||
Debug.Assert(joinedRoom != null);
|
||||
/// <summary>
|
||||
/// Joins the <see cref="MultiplayerRoom"/> for a given API <see cref="Room"/>.
|
||||
/// </summary>
|
||||
/// <param name="room">The API <see cref="Room"/>.</param>
|
||||
/// <param name="password">An optional password to use for the join operation.</param>
|
||||
/// <exception cref="InvalidOperationException">If the current user is already in another room, or <paramref name="room"/> does not represent an active room.</exception>
|
||||
public async Task JoinRoom(Room room, string? password = null)
|
||||
{
|
||||
if (Room != null)
|
||||
throw new InvalidOperationException("Cannot join a multiplayer room while already in one.");
|
||||
|
||||
if (room.RoomID == null)
|
||||
throw new InvalidOperationException("Cannot join an inactive room.");
|
||||
|
||||
var cancellationSource = joinCancellationSource = new CancellationTokenSource();
|
||||
|
||||
await joinOrLeaveTaskChain.Add(async () =>
|
||||
{
|
||||
var multiplayerRoom = await JoinRoomInternal(room.RoomID.Value, password ?? room.Password).ConfigureAwait(false);
|
||||
await setupJoinedRoom(room, multiplayerRoom, cancellationSource.Token).ConfigureAwait(false);
|
||||
}, cancellationSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs post-join setup of a <see cref="MultiplayerRoom"/>.
|
||||
/// </summary>
|
||||
/// <param name="apiRoom">The incoming API <see cref="Room"/> that was requested to be joined.</param>
|
||||
/// <param name="joinedRoom">The resuling <see cref="MultiplayerRoom"/> that was joined.</param>
|
||||
/// <param name="cancellationToken">A token to cancel the process.</param>
|
||||
private async Task setupJoinedRoom(Room apiRoom, MultiplayerRoom joinedRoom, CancellationToken cancellationToken)
|
||||
{
|
||||
// Populate users.
|
||||
Debug.Assert(joinedRoom.Users != null);
|
||||
await PopulateUsers(joinedRoom.Users).ConfigureAwait(false);
|
||||
if (joinedRoom.Host != null)
|
||||
await PopulateUsers([joinedRoom.Host]).ConfigureAwait(false);
|
||||
|
||||
// Update the stored room (must be done on update thread for thread-safety).
|
||||
await runOnUpdateThreadAsync(() =>
|
||||
{
|
||||
Debug.Assert(Room == null);
|
||||
Debug.Assert(APIRoom == null);
|
||||
|
||||
Room = joinedRoom;
|
||||
APIRoom = room;
|
||||
|
||||
Debug.Assert(joinedRoom.Playlist.Count > 0);
|
||||
APIRoom = apiRoom;
|
||||
|
||||
APIRoom.RoomID = joinedRoom.RoomID;
|
||||
APIRoom.Host = joinedRoom.Host?.User;
|
||||
APIRoom.Playlist = joinedRoom.Playlist.Select(item => new PlaylistItem(item)).ToArray();
|
||||
APIRoom.CurrentPlaylistItem = APIRoom.Playlist.Single(item => item.ID == joinedRoom.Settings.PlaylistItemId);
|
||||
|
||||
// The server will null out the end date upon the host joining the room, but the null value is never communicated to the client.
|
||||
APIRoom.EndDate = null;
|
||||
|
||||
@ -221,8 +252,7 @@ namespace osu.Game.Online.Multiplayer
|
||||
postServerShuttingDownNotification();
|
||||
|
||||
OnRoomJoined();
|
||||
}, cancellationSource.Token).ConfigureAwait(false);
|
||||
}, cancellationSource.Token).ConfigureAwait(false);
|
||||
}, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -232,16 +262,11 @@ namespace osu.Game.Online.Multiplayer
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Joins the <see cref="MultiplayerRoom"/> with a given ID.
|
||||
/// </summary>
|
||||
/// <param name="roomId">The room ID.</param>
|
||||
/// <param name="password">An optional password to use when joining the room.</param>
|
||||
/// <returns>The joined <see cref="MultiplayerRoom"/>.</returns>
|
||||
protected abstract Task<MultiplayerRoom> JoinRoom(long roomId, string? password = null);
|
||||
|
||||
public Task LeaveRoom()
|
||||
{
|
||||
if (Room == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
// The join may have not completed yet, so certain tasks that either update the room or reference the room should be cancelled.
|
||||
// This includes the setting of Room itself along with the initial update of the room settings on join.
|
||||
joinCancellationSource?.Cancel();
|
||||
@ -265,6 +290,24 @@ namespace osu.Game.Online.Multiplayer
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the <see cref="MultiplayerRoom"/> with the given settings.
|
||||
/// </summary>
|
||||
/// <param name="room">The room.</param>
|
||||
/// <returns>The joined <see cref="MultiplayerRoom"/></returns>
|
||||
protected abstract Task<MultiplayerRoom> CreateRoomInternal(MultiplayerRoom room);
|
||||
|
||||
/// <summary>
|
||||
/// Joins the <see cref="MultiplayerRoom"/> with a given ID.
|
||||
/// </summary>
|
||||
/// <param name="roomId">The room ID.</param>
|
||||
/// <param name="password">An optional password to use when joining the room.</param>
|
||||
/// <returns>The joined <see cref="MultiplayerRoom"/>.</returns>
|
||||
protected abstract Task<MultiplayerRoom> JoinRoomInternal(long roomId, string? password = null);
|
||||
|
||||
/// <summary>
|
||||
/// Leaves the currently-joined <see cref="MultiplayerRoom"/>.
|
||||
/// </summary>
|
||||
protected abstract Task LeaveRoomInternal();
|
||||
|
||||
public abstract Task InvitePlayer(int userId);
|
||||
|
@ -5,6 +5,7 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using osu.Framework.Extensions.ExceptionExtensions;
|
||||
using osu.Framework.Logging;
|
||||
|
||||
namespace osu.Game.Online.Multiplayer
|
||||
@ -16,12 +17,8 @@ namespace osu.Game.Online.Multiplayer
|
||||
{
|
||||
if (t.IsFaulted)
|
||||
{
|
||||
Exception? exception = t.Exception;
|
||||
|
||||
if (exception is AggregateException ae)
|
||||
exception = ae.InnerException;
|
||||
|
||||
Debug.Assert(exception != null);
|
||||
Debug.Assert(t.Exception != null);
|
||||
Exception exception = t.Exception.AsSingular();
|
||||
|
||||
if (exception.GetHubExceptionMessage() is string message)
|
||||
// Hub exceptions generally contain something we can show the user directly.
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MessagePack;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Game.Online.Rooms;
|
||||
@ -65,6 +66,14 @@ namespace osu.Game.Online.Multiplayer
|
||||
RoomID = roomId;
|
||||
}
|
||||
|
||||
public MultiplayerRoom(Room room)
|
||||
{
|
||||
RoomID = room.RoomID ?? 0;
|
||||
Settings = new MultiplayerRoomSettings(room);
|
||||
Host = room.Host != null ? new MultiplayerRoomUser(room.Host.OnlineID) : null;
|
||||
Playlist = room.Playlist.Select(p => new MultiplayerPlaylistItem(p)).ToArray();
|
||||
}
|
||||
|
||||
public override string ToString() => $"RoomID:{RoomID} Host:{Host?.UserID} Users:{Users.Count} State:{State} Settings: [{Settings}]";
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,20 @@ namespace osu.Game.Online.Multiplayer
|
||||
[IgnoreMember]
|
||||
public bool AutoStartEnabled => AutoStartDuration != TimeSpan.Zero;
|
||||
|
||||
public MultiplayerRoomSettings()
|
||||
{
|
||||
}
|
||||
|
||||
public MultiplayerRoomSettings(Room room)
|
||||
{
|
||||
Name = room.Name;
|
||||
Password = room.Password ?? string.Empty;
|
||||
MatchType = room.Type;
|
||||
QueueMode = room.QueueMode;
|
||||
AutoStartDuration = room.AutoStartDuration;
|
||||
AutoSkip = room.AutoSkip;
|
||||
}
|
||||
|
||||
public bool Equals(MultiplayerRoomSettings? other)
|
||||
{
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
|
@ -76,7 +76,32 @@ namespace osu.Game.Online.Multiplayer
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task<MultiplayerRoom> JoinRoom(long roomId, string? password = null)
|
||||
protected override async Task<MultiplayerRoom> CreateRoomInternal(MultiplayerRoom room)
|
||||
{
|
||||
if (!IsConnected.Value)
|
||||
throw new OperationCanceledException();
|
||||
|
||||
Debug.Assert(connection != null);
|
||||
|
||||
try
|
||||
{
|
||||
return await connection.InvokeAsync<MultiplayerRoom>(nameof(IMultiplayerServer.CreateRoom), room).ConfigureAwait(false);
|
||||
}
|
||||
catch (HubException exception)
|
||||
{
|
||||
if (exception.GetHubExceptionMessage() == HubClientConnector.SERVER_SHUTDOWN_MESSAGE)
|
||||
{
|
||||
Debug.Assert(connector != null);
|
||||
|
||||
await connector.Reconnect().ConfigureAwait(false);
|
||||
return await CreateRoomInternal(room).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task<MultiplayerRoom> JoinRoomInternal(long roomId, string? password = null)
|
||||
{
|
||||
if (!IsConnected.Value)
|
||||
throw new OperationCanceledException();
|
||||
@ -94,7 +119,7 @@ namespace osu.Game.Online.Multiplayer
|
||||
Debug.Assert(connector != null);
|
||||
|
||||
await connector.Reconnect().ConfigureAwait(false);
|
||||
return await JoinRoom(roomId, password).ConfigureAwait(false);
|
||||
return await JoinRoomInternal(roomId, password).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
throw;
|
||||
|
@ -15,6 +15,9 @@ namespace osu.Game.Online.Rooms
|
||||
public CreateRoomRequest(Room room)
|
||||
{
|
||||
Room = room;
|
||||
|
||||
// Also copy back to the source model, since it is likely to have been stored elsewhere.
|
||||
Success += r => Room.CopyFrom(r);
|
||||
}
|
||||
|
||||
protected override WebRequest CreateWebRequest()
|
||||
@ -23,7 +26,6 @@ namespace osu.Game.Online.Rooms
|
||||
|
||||
req.ContentType = "application/json";
|
||||
req.Method = HttpMethod.Post;
|
||||
|
||||
req.AddRaw(JsonConvert.SerializeObject(Room));
|
||||
|
||||
return req;
|
||||
|
@ -16,6 +16,9 @@ namespace osu.Game.Online.Rooms
|
||||
{
|
||||
Room = room;
|
||||
Password = password;
|
||||
|
||||
// Also copy back to the source model, since it is likely to have been stored elsewhere.
|
||||
Success += r => Room.CopyFrom(r);
|
||||
}
|
||||
|
||||
protected override WebRequest CreateWebRequest()
|
||||
|
@ -66,5 +66,20 @@ namespace osu.Game.Online.Rooms
|
||||
public MultiplayerPlaylistItem()
|
||||
{
|
||||
}
|
||||
|
||||
public MultiplayerPlaylistItem(PlaylistItem item)
|
||||
{
|
||||
ID = item.ID;
|
||||
OwnerID = item.OwnerID;
|
||||
BeatmapID = item.Beatmap.OnlineID;
|
||||
BeatmapChecksum = item.Beatmap.MD5Hash;
|
||||
RulesetID = item.RulesetID;
|
||||
RequiredMods = item.RequiredMods.ToArray();
|
||||
AllowedMods = item.AllowedMods.ToArray();
|
||||
Expired = item.Expired;
|
||||
PlaylistOrder = item.PlaylistOrder ?? 0;
|
||||
PlayedAt = item.PlayedAt;
|
||||
StarRating = item.Beatmap.StarRating;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -342,6 +342,23 @@ namespace osu.Game.Online.Rooms
|
||||
// Not yet serialised (not implemented).
|
||||
private RoomAvailability availability;
|
||||
|
||||
public Room()
|
||||
{
|
||||
}
|
||||
|
||||
public Room(MultiplayerRoom room)
|
||||
{
|
||||
RoomID = room.RoomID;
|
||||
Name = room.Settings.Name;
|
||||
Password = room.Settings.Password;
|
||||
Type = room.Settings.MatchType;
|
||||
QueueMode = room.Settings.QueueMode;
|
||||
AutoStartDuration = room.Settings.AutoStartDuration;
|
||||
AutoSkip = room.Settings.AutoSkip;
|
||||
Host = room.Host != null ? new APIUser { Id = room.Host.UserID } : null;
|
||||
Playlist = room.Playlist.Select(p => new PlaylistItem(p)).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies values from another <see cref="Room"/> into this one.
|
||||
/// </summary>
|
||||
|
@ -5,16 +5,15 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Development;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Rooms;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Components
|
||||
{
|
||||
// Todo: This class should be inlined into the lounge.
|
||||
public partial class RoomManager : Component, IRoomManager
|
||||
{
|
||||
public event Action? RoomsUpdated;
|
||||
@ -23,89 +22,11 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
|
||||
public IBindableList<Room> Rooms => rooms;
|
||||
|
||||
protected IBindable<Room?> JoinedRoom => joinedRoom;
|
||||
private readonly Bindable<Room?> joinedRoom = new Bindable<Room?>();
|
||||
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; } = null!;
|
||||
|
||||
public RoomManager()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
PartRoom();
|
||||
}
|
||||
|
||||
public virtual void CreateRoom(Room room, Action<Room>? onSuccess = null, Action<string>? onError = null)
|
||||
{
|
||||
room.Host = api.LocalUser.Value;
|
||||
|
||||
var req = new CreateRoomRequest(room);
|
||||
|
||||
req.Success += result =>
|
||||
{
|
||||
joinedRoom.Value = room;
|
||||
|
||||
AddOrUpdateRoom(result);
|
||||
room.CopyFrom(result); // Also copy back to the source model, since this is likely to have been stored elsewhere.
|
||||
|
||||
// The server may not contain all properties (such as password), so invoke success with the given room.
|
||||
onSuccess?.Invoke(room);
|
||||
};
|
||||
|
||||
req.Failure += exception =>
|
||||
{
|
||||
onError?.Invoke(req.Response?.Error ?? exception.Message);
|
||||
};
|
||||
|
||||
api.Queue(req);
|
||||
}
|
||||
|
||||
private JoinRoomRequest? currentJoinRoomRequest;
|
||||
|
||||
public virtual void JoinRoom(Room room, string? password = null, Action<Room>? onSuccess = null, Action<string>? onError = null)
|
||||
{
|
||||
currentJoinRoomRequest?.Cancel();
|
||||
currentJoinRoomRequest = new JoinRoomRequest(room, password);
|
||||
|
||||
currentJoinRoomRequest.Success += result =>
|
||||
{
|
||||
joinedRoom.Value = room;
|
||||
|
||||
AddOrUpdateRoom(result);
|
||||
room.CopyFrom(result); // Also copy back to the source model, since this is likely to have been stored elsewhere.
|
||||
|
||||
onSuccess?.Invoke(room);
|
||||
};
|
||||
|
||||
currentJoinRoomRequest.Failure += exception =>
|
||||
{
|
||||
if (exception is OperationCanceledException)
|
||||
return;
|
||||
|
||||
onError?.Invoke(exception.Message);
|
||||
};
|
||||
|
||||
api.Queue(currentJoinRoomRequest);
|
||||
}
|
||||
|
||||
public virtual void PartRoom()
|
||||
{
|
||||
currentJoinRoomRequest?.Cancel();
|
||||
|
||||
if (joinedRoom.Value == null)
|
||||
return;
|
||||
|
||||
if (api.State.Value == APIState.Online)
|
||||
api.Queue(new PartRoomRequest(joinedRoom.Value));
|
||||
|
||||
joinedRoom.Value = null;
|
||||
}
|
||||
|
||||
private readonly HashSet<long> ignoredRooms = new HashSet<long>();
|
||||
|
||||
public void AddOrUpdateRoom(Room room)
|
||||
|
@ -34,7 +34,6 @@ using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Screens.OnlinePlay.DailyChallenge.Events;
|
||||
using osu.Game.Screens.OnlinePlay.Match;
|
||||
using osu.Game.Screens.OnlinePlay.Match.Components;
|
||||
@ -71,9 +70,6 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Plum);
|
||||
|
||||
[Cached(Type = typeof(IRoomManager))]
|
||||
private RoomManager roomManager { get; set; }
|
||||
|
||||
[Cached]
|
||||
private readonly OnlinePlayBeatmapAvailabilityTracker beatmapAvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker();
|
||||
|
||||
@ -115,7 +111,6 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
{
|
||||
this.room = room;
|
||||
playlistItem = room.Playlist.Single();
|
||||
roomManager = new RoomManager();
|
||||
Padding = new MarginPadding { Horizontal = -HORIZONTAL_OVERFLOW_PADDING };
|
||||
}
|
||||
|
||||
@ -131,7 +126,6 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
roomManager,
|
||||
beatmapAvailabilityTracker,
|
||||
new ScreenStack(new RoomBackgroundScreen(playlistItem))
|
||||
{
|
||||
@ -426,7 +420,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
base.OnEntering(e);
|
||||
|
||||
waves.Show();
|
||||
roomManager.JoinRoom(room);
|
||||
API.Queue(new JoinRoomRequest(room, null));
|
||||
startLoopingTrack(this, musicController);
|
||||
|
||||
metadataClient.BeginWatchingMultiplayerRoom(room.RoomID!.Value).ContinueWith(t =>
|
||||
@ -480,7 +474,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
previewTrackManager.StopAnyPlaying(this);
|
||||
this.Delay(WaveContainer.DISAPPEAR_DURATION).FadeOut();
|
||||
|
||||
roomManager.PartRoom();
|
||||
API.Queue(new PartRoomRequest(room));
|
||||
metadataClient.EndWatchingMultiplayerRoom(room.RoomID!.Value).FireAndForget();
|
||||
|
||||
return base.OnExiting(e);
|
||||
|
@ -38,27 +38,5 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
/// Removes all <see cref="Room"/>s from this <see cref="IRoomManager"/>.
|
||||
/// </summary>
|
||||
void ClearRooms();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="Room"/>.
|
||||
/// </summary>
|
||||
/// <param name="room">The <see cref="Room"/> to create.</param>
|
||||
/// <param name="onSuccess">An action to be invoked if the creation succeeds.</param>
|
||||
/// <param name="onError">An action to be invoked if an error occurred.</param>
|
||||
void CreateRoom(Room room, Action<Room>? onSuccess = null, Action<string>? onError = null);
|
||||
|
||||
/// <summary>
|
||||
/// Joins a <see cref="Room"/>.
|
||||
/// </summary>
|
||||
/// <param name="room">The <see cref="Room"/> to join. <see cref="Room.RoomID"/> must be populated.</param>
|
||||
/// <param name="password">An optional password to use for the join operation.</param>
|
||||
/// <param name="onSuccess"></param>
|
||||
/// <param name="onError"></param>
|
||||
void JoinRoom(Room room, string? password = null, Action<Room>? onSuccess = null, Action<string>? onError = null);
|
||||
|
||||
/// <summary>
|
||||
/// Parts the currently-joined <see cref="Room"/>.
|
||||
/// </summary>
|
||||
void PartRoom();
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
@ -51,7 +50,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
}
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
private LoungeSubScreen? lounge { get; set; }
|
||||
private IOnlinePlayLounge? lounge { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private IDialogOverlay? dialogOverlay { get; set; }
|
||||
@ -170,12 +169,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
{
|
||||
items.Add(new OsuMenuItem("Close playlist", MenuItemType.Destructive, () =>
|
||||
{
|
||||
dialogOverlay?.Push(new ClosePlaylistDialog(Room, () =>
|
||||
{
|
||||
var request = new ClosePlaylistRequest(Room.RoomID!.Value);
|
||||
request.Success += () => lounge?.RefreshRooms();
|
||||
api.Queue(request);
|
||||
}));
|
||||
dialogOverlay?.Push(new ClosePlaylistDialog(Room, () => lounge?.Close(Room)));
|
||||
}));
|
||||
}
|
||||
|
||||
@ -238,7 +232,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
private readonly Room room;
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
private LoungeSubScreen? lounge { get; set; }
|
||||
private IOnlinePlayLounge? lounge { get; set; }
|
||||
|
||||
public override bool HandleNonPositionalInput => true;
|
||||
|
||||
|
32
osu.Game/Screens/OnlinePlay/Lounge/IOnlinePlayLounge.cs
Normal file
32
osu.Game/Screens/OnlinePlay/Lounge/IOnlinePlayLounge.cs
Normal file
@ -0,0 +1,32 @@
|
||||
// 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 osu.Game.Online.Rooms;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
{
|
||||
public interface IOnlinePlayLounge
|
||||
{
|
||||
/// <summary>
|
||||
/// Attempts to join the given room.
|
||||
/// </summary>
|
||||
/// <param name="room">The room to join.</param>
|
||||
/// <param name="password">The password.</param>
|
||||
/// <param name="onSuccess">A delegate to invoke if the user joined the room.</param>
|
||||
/// <param name="onFailure">A delegate to invoke if the user is not able join the room.</param>
|
||||
void Join(Room room, string? password, Action<Room>? onSuccess = null, Action<string>? onFailure = null);
|
||||
|
||||
/// <summary>
|
||||
/// Copies the given room and opens it as a fresh (not-yet-created) one.
|
||||
/// </summary>
|
||||
/// <param name="room">The room to copy.</param>
|
||||
void OpenCopy(Room room);
|
||||
|
||||
/// <summary>
|
||||
/// Closes the given room.
|
||||
/// </summary>
|
||||
/// <param name="room">The room to close.</param>
|
||||
void Close(Room room);
|
||||
}
|
||||
}
|
@ -33,7 +33,8 @@ using osuTK;
|
||||
namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
{
|
||||
[Cached]
|
||||
public abstract partial class LoungeSubScreen : OnlinePlaySubScreen
|
||||
[Cached(typeof(IOnlinePlayLounge))]
|
||||
public abstract partial class LoungeSubScreen : OnlinePlaySubScreen, IOnlinePlayLounge
|
||||
{
|
||||
public override string Title => "Lounge";
|
||||
|
||||
@ -263,6 +264,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
music.EnsurePlayingSomething();
|
||||
|
||||
onReturning();
|
||||
|
||||
// Poll for any newly-created rooms (including potentially the user's own).
|
||||
ListingPollingComponent.PollImmediately();
|
||||
}
|
||||
|
||||
public override bool OnExiting(ScreenExitEvent e)
|
||||
@ -297,14 +301,14 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
popoverContainer.HidePopover();
|
||||
}
|
||||
|
||||
public virtual void Join(Room room, string? password, Action<Room>? onSuccess = null, Action<string>? onFailure = null) => Schedule(() =>
|
||||
public void Join(Room room, string? password, Action<Room>? onSuccess = null, Action<string>? onFailure = null) => Schedule(() =>
|
||||
{
|
||||
if (joiningRoomOperation != null)
|
||||
return;
|
||||
|
||||
joiningRoomOperation = ongoingOperationTracker?.BeginOperation();
|
||||
|
||||
RoomManager?.JoinRoom(room, password, _ =>
|
||||
JoinInternal(room, password, r =>
|
||||
{
|
||||
Open(room);
|
||||
joiningRoomOperation?.Dispose();
|
||||
@ -318,10 +322,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
});
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Copies a room and opens it as a fresh (not-yet-created) one.
|
||||
/// </summary>
|
||||
/// <param name="room">The room to copy.</param>
|
||||
protected abstract void JoinInternal(Room room, string? password, Action<Room> onSuccess, Action<string> onFailure);
|
||||
|
||||
public void OpenCopy(Room room)
|
||||
{
|
||||
Debug.Assert(room.RoomID != null);
|
||||
@ -358,6 +360,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
api.Queue(req);
|
||||
}
|
||||
|
||||
public abstract void Close(Room room);
|
||||
|
||||
/// <summary>
|
||||
/// Push a room as a new subscreen.
|
||||
/// </summary>
|
||||
|
@ -25,12 +25,13 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
set => selectedItem.Current = value;
|
||||
}
|
||||
|
||||
public Drawable? ChangeSettingsButton { get; private set; }
|
||||
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; } = null!;
|
||||
|
||||
private readonly BindableWithCurrent<PlaylistItem?> selectedItem = new BindableWithCurrent<PlaylistItem?>();
|
||||
private readonly bool allowEdit;
|
||||
private Drawable? editButton;
|
||||
|
||||
public DrawableMatchRoom(Room room, bool allowEdit = true)
|
||||
: base(room)
|
||||
@ -45,7 +46,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
{
|
||||
if (allowEdit)
|
||||
{
|
||||
ButtonsContainer.Add(editButton = new PurpleRoundedButton
|
||||
ButtonsContainer.Add(ChangeSettingsButton = new PurpleRoundedButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Anchor = Anchor.Centre,
|
||||
@ -73,8 +74,8 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
|
||||
private void updateRoomHost()
|
||||
{
|
||||
if (editButton != null)
|
||||
editButton.Alpha = Room.Host?.Equals(api.LocalUser.Value) == true ? 1 : 0;
|
||||
if (ChangeSettingsButton != null)
|
||||
ChangeSettingsButton.Alpha = Room.Host?.Equals(api.LocalUser.Value) == true ? 1 : 0;
|
||||
}
|
||||
|
||||
protected override UpdateableBeatmapBackgroundSprite CreateBackground() => base.CreateBackground().With(d =>
|
||||
|
@ -360,7 +360,9 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
if (!ensureExitConfirmed())
|
||||
return true;
|
||||
|
||||
RoomManager?.PartRoom();
|
||||
if (Room.RoomID != null)
|
||||
PartRoom();
|
||||
|
||||
Mods.Value = Array.Empty<Mod>();
|
||||
|
||||
onLeaving();
|
||||
@ -368,6 +370,11 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
return base.OnExiting(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parts from the current room.
|
||||
/// </summary>
|
||||
protected abstract void PartRoom();
|
||||
|
||||
private bool ensureExitConfirmed()
|
||||
{
|
||||
if (ExitConfirmed)
|
||||
|
@ -29,12 +29,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
{
|
||||
public partial class MultiplayerMatchSettingsOverlay : RoomSettingsOverlay
|
||||
{
|
||||
public required Bindable<PlaylistItem?> SelectedItem
|
||||
{
|
||||
get => selectedItem;
|
||||
set => selectedItem.Current = value;
|
||||
}
|
||||
|
||||
protected override OsuButton SubmitButton => settings.ApplyButton;
|
||||
protected override bool IsLoading => ongoingOperationTracker.InProgress.Value;
|
||||
|
||||
@ -56,7 +50,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RelativePositionAxes = Axes.Y,
|
||||
SettingsApplied = Hide,
|
||||
SelectedItem = { BindTarget = SelectedItem }
|
||||
};
|
||||
|
||||
protected partial class MatchSettings : CompositeDrawable
|
||||
@ -65,7 +58,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
|
||||
public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks;
|
||||
|
||||
public readonly Bindable<PlaylistItem?> SelectedItem = new Bindable<PlaylistItem?>();
|
||||
public Action? SettingsApplied;
|
||||
|
||||
public OsuTextBox NameField = null!;
|
||||
@ -86,9 +78,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
[Resolved]
|
||||
private MultiplayerMatchSubScreen matchSubScreen { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private IRoomManager manager { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private MultiplayerClient client { get; set; } = null!;
|
||||
|
||||
@ -279,7 +268,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = DrawableRoomPlaylistItem.HEIGHT,
|
||||
SelectedItem = { BindTarget = SelectedItem }
|
||||
},
|
||||
selectBeatmapButton = new RoundedButton
|
||||
{
|
||||
@ -456,7 +444,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
if (!ApplyButton.Enabled.Value)
|
||||
return;
|
||||
|
||||
hideError();
|
||||
ErrorText.FadeOut(50);
|
||||
|
||||
Debug.Assert(applyingSettingsOperation == null);
|
||||
applyingSettingsOperation = ongoingOperationTracker.BeginOperation();
|
||||
@ -475,32 +463,24 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
.ContinueWith(t => Schedule(() =>
|
||||
{
|
||||
if (t.IsCompletedSuccessfully)
|
||||
onSuccess(room);
|
||||
onSuccess();
|
||||
else
|
||||
onError(t.Exception?.AsSingular().Message ?? "Error changing settings.");
|
||||
onError(t.Exception, "Error changing settings");
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
room.Name = NameField.Text;
|
||||
room.Type = TypePicker.Current.Value;
|
||||
room.Password = PasswordTextBox.Current.Value;
|
||||
room.QueueMode = QueueModeDropdown.Current.Value;
|
||||
room.AutoStartDuration = TimeSpan.FromSeconds((int)startModeDropdown.Current.Value);
|
||||
room.AutoSkip = AutoSkipCheckbox.Current.Value;
|
||||
|
||||
if (int.TryParse(MaxParticipantsField.Text, out int max))
|
||||
room.MaxParticipants = max;
|
||||
client.CreateRoom(room).ContinueWith(t => Schedule(() =>
|
||||
{
|
||||
if (t.IsCompletedSuccessfully)
|
||||
onSuccess();
|
||||
else
|
||||
room.MaxParticipants = null;
|
||||
|
||||
manager.CreateRoom(room, onSuccess, onError);
|
||||
onError(t.Exception, "Error creating room");
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private void hideError() => ErrorText.FadeOut(50);
|
||||
|
||||
private void onSuccess(Room room) => Schedule(() =>
|
||||
private void onSuccess() => Schedule(() =>
|
||||
{
|
||||
Debug.Assert(applyingSettingsOperation != null);
|
||||
|
||||
@ -510,28 +490,34 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
applyingSettingsOperation = null;
|
||||
});
|
||||
|
||||
private void onError(string text) => Schedule(() =>
|
||||
private void onError(Exception? exception, string description)
|
||||
{
|
||||
if (exception is AggregateException aggregateException)
|
||||
exception = aggregateException.AsSingular();
|
||||
|
||||
string message = exception?.GetHubExceptionMessage() ?? $"{description} ({exception?.Message})";
|
||||
|
||||
Schedule(() =>
|
||||
{
|
||||
Debug.Assert(applyingSettingsOperation != null);
|
||||
|
||||
// see https://github.com/ppy/osu-web/blob/2c97aaeb64fb4ed97c747d8383a35b30f57428c7/app/Models/Multiplayer/PlaylistItem.php#L48.
|
||||
const string not_found_prefix = "beatmaps not found:";
|
||||
|
||||
if (text.StartsWith(not_found_prefix, StringComparison.Ordinal))
|
||||
if (message.StartsWith(not_found_prefix, StringComparison.Ordinal))
|
||||
{
|
||||
ErrorText.Text = "The selected beatmap is not available online.";
|
||||
SelectedItem.Value?.MarkInvalid();
|
||||
room.Playlist.SingleOrDefault()?.MarkInvalid();
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorText.Text = text;
|
||||
}
|
||||
ErrorText.Text = message;
|
||||
|
||||
ErrorText.FadeIn(50);
|
||||
|
||||
applyingSettingsOperation.Dispose();
|
||||
applyingSettingsOperation = null;
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
|
@ -8,7 +8,6 @@ using osu.Framework.Logging;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Lounge;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
@ -97,8 +96,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
|
||||
protected override string ScreenTitle => "Multiplayer";
|
||||
|
||||
protected override RoomManager CreateRoomManager() => new MultiplayerRoomManager();
|
||||
|
||||
protected override LoungeSubScreen CreateLounge() => new MultiplayerLoungeSubScreen();
|
||||
|
||||
public void Join(Room room, string? password) => Schedule(() => Lounge.Join(room, password));
|
||||
|
@ -1,12 +1,13 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ExceptionExtensions;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Configuration;
|
||||
@ -32,19 +33,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
private Dropdown<RoomPermissionsFilter> roomAccessTypeDropdown = null!;
|
||||
private OsuCheckbox showInProgress = null!;
|
||||
|
||||
public override void OnResuming(ScreenTransitionEvent e)
|
||||
{
|
||||
base.OnResuming(e);
|
||||
|
||||
// Upon having left a room, we don't know whether we were the only participant, and whether the room is now closed as a result of leaving it.
|
||||
// To work around this, temporarily remove the room and trigger an immediate listing poll.
|
||||
if (e.Last is MultiplayerMatchSubScreen match)
|
||||
{
|
||||
RoomManager?.RemoveRoom(match.Room);
|
||||
ListingPollingComponent.PollImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
protected override IEnumerable<Drawable> CreateFilterControls()
|
||||
{
|
||||
foreach (var control in base.CreateFilterControls())
|
||||
@ -93,6 +81,27 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
|
||||
protected override ListingPollingComponent CreatePollingComponent() => new MultiplayerListingPollingComponent();
|
||||
|
||||
protected override void JoinInternal(Room room, string? password, Action<Room> onSuccess, Action<string> onFailure)
|
||||
{
|
||||
client.JoinRoom(room, password).ContinueWith(result =>
|
||||
{
|
||||
if (result.IsCompletedSuccessfully)
|
||||
onSuccess(room);
|
||||
else
|
||||
{
|
||||
const string message = "Failed to join multiplayer room.";
|
||||
|
||||
if (result.Exception != null)
|
||||
Logger.Error(result.Exception, message);
|
||||
|
||||
onFailure.Invoke(result.Exception?.AsSingular().Message ?? message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public override void Close(Room room)
|
||||
=> throw new NotSupportedException("Cannot close multiplayer rooms.");
|
||||
|
||||
protected override void OpenNewRoom(Room room)
|
||||
{
|
||||
if (!client.IsConnected.Value)
|
||||
|
@ -259,10 +259,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
SelectedItem = SelectedItem
|
||||
};
|
||||
|
||||
protected override RoomSettingsOverlay CreateRoomSettingsOverlay(Room room) => new MultiplayerMatchSettingsOverlay(room)
|
||||
{
|
||||
SelectedItem = SelectedItem
|
||||
};
|
||||
protected override RoomSettingsOverlay CreateRoomSettingsOverlay(Room room) => new MultiplayerMatchSettingsOverlay(room);
|
||||
|
||||
protected override APIMod[] GetGameplayMods()
|
||||
{
|
||||
@ -313,6 +310,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
return base.OnExiting(e);
|
||||
}
|
||||
|
||||
protected override void PartRoom() => client.LeaveRoom();
|
||||
|
||||
private ModSettingChangeTracker? modSettingChangeTracker;
|
||||
private ScheduledDelegate? debouncedModSettingsUpdate;
|
||||
|
||||
|
@ -1,72 +0,0 @@
|
||||
// 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 osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.ExceptionExtensions;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
{
|
||||
public partial class MultiplayerRoomManager : RoomManager
|
||||
{
|
||||
[Resolved]
|
||||
private MultiplayerClient multiplayerClient { get; set; } = null!;
|
||||
|
||||
public override void CreateRoom(Room room, Action<Room>? onSuccess = null, Action<string>? onError = null)
|
||||
=> base.CreateRoom(room, r => joinMultiplayerRoom(r, r.Password, onSuccess, onError), onError);
|
||||
|
||||
public override void JoinRoom(Room room, string? password = null, Action<Room>? onSuccess = null, Action<string>? onError = null)
|
||||
{
|
||||
if (!multiplayerClient.IsConnected.Value)
|
||||
{
|
||||
onError?.Invoke("Not currently connected to the multiplayer server.");
|
||||
return;
|
||||
}
|
||||
|
||||
// this is done here as a pre-check to avoid clicking on already closed rooms in the lounge from triggering a server join.
|
||||
// should probably be done at a higher level, but due to the current structure of things this is the easiest place for now.
|
||||
if (room.HasEnded)
|
||||
{
|
||||
onError?.Invoke("Cannot join an ended room.");
|
||||
return;
|
||||
}
|
||||
|
||||
base.JoinRoom(room, password, r => joinMultiplayerRoom(r, password, onSuccess, onError), onError);
|
||||
}
|
||||
|
||||
public override void PartRoom()
|
||||
{
|
||||
if (JoinedRoom.Value == null)
|
||||
return;
|
||||
|
||||
base.PartRoom();
|
||||
multiplayerClient.LeaveRoom();
|
||||
}
|
||||
|
||||
private void joinMultiplayerRoom(Room room, string? password, Action<Room>? onSuccess = null, Action<string>? onError = null)
|
||||
{
|
||||
Debug.Assert(room.RoomID != null);
|
||||
|
||||
multiplayerClient.JoinRoom(room, password).ContinueWith(t =>
|
||||
{
|
||||
if (t.IsCompletedSuccessfully)
|
||||
Schedule(() => onSuccess?.Invoke(room));
|
||||
else if (t.IsFaulted)
|
||||
{
|
||||
const string message = "Failed to join multiplayer room.";
|
||||
|
||||
if (t.Exception != null)
|
||||
Logger.Error(t.Exception, message);
|
||||
|
||||
PartRoom();
|
||||
Schedule(() => onError?.Invoke(t.Exception?.AsSingular().Message ?? message));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -36,12 +36,12 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
private readonly ScreenStack screenStack = new OnlinePlaySubScreenStack { RelativeSizeAxes = Axes.Both };
|
||||
private OnlinePlayScreenWaveContainer waves = null!;
|
||||
|
||||
[Cached(Type = typeof(IRoomManager))]
|
||||
protected RoomManager RoomManager { get; private set; }
|
||||
|
||||
[Cached]
|
||||
private readonly OngoingOperationTracker ongoingOperationTracker = new OngoingOperationTracker();
|
||||
|
||||
[Cached(Type = typeof(IRoomManager))]
|
||||
private readonly RoomManager roomManager = new RoomManager();
|
||||
|
||||
[Resolved]
|
||||
protected IAPIProvider API { get; private set; } = null!;
|
||||
|
||||
@ -51,8 +51,6 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
Origin = Anchor.Centre;
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Padding = new MarginPadding { Horizontal = -HORIZONTAL_OVERFLOW_PADDING };
|
||||
|
||||
RoomManager = CreateRoomManager();
|
||||
}
|
||||
|
||||
private readonly IBindable<APIState> apiState = new Bindable<APIState>();
|
||||
@ -67,7 +65,7 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
{
|
||||
screenStack,
|
||||
new Header(ScreenTitle, screenStack),
|
||||
RoomManager,
|
||||
roomManager,
|
||||
ongoingOperationTracker,
|
||||
}
|
||||
};
|
||||
@ -165,8 +163,6 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
subScreen.Exit();
|
||||
}
|
||||
|
||||
RoomManager.PartRoom();
|
||||
|
||||
waves.Hide();
|
||||
|
||||
this.Delay(WaveContainer.DISAPPEAR_DURATION).FadeOut();
|
||||
@ -224,8 +220,6 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
|
||||
protected abstract string ScreenTitle { get; }
|
||||
|
||||
protected virtual RoomManager CreateRoomManager() => new RoomManager();
|
||||
|
||||
protected abstract LoungeSubScreen CreateLounge();
|
||||
|
||||
ScreenStack IHasSubScreenStack.SubScreenStack => screenStack;
|
||||
|
@ -1,7 +1,6 @@
|
||||
// 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 osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Screens;
|
||||
|
||||
@ -15,9 +14,6 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
|
||||
protected sealed override bool PlayExitSound => false;
|
||||
|
||||
[Resolved]
|
||||
protected IRoomManager? RoomManager { get; private set; }
|
||||
|
||||
protected OnlinePlaySubScreen()
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
|
@ -1,14 +1,17 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Lounge;
|
||||
@ -59,6 +62,29 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
return criteria;
|
||||
}
|
||||
|
||||
protected override void JoinInternal(Room room, string? password, Action<Room> onSuccess, Action<string> onFailure)
|
||||
{
|
||||
var joinRoomRequest = new JoinRoomRequest(room, password);
|
||||
|
||||
joinRoomRequest.Success += r => onSuccess(r);
|
||||
joinRoomRequest.Failure += exception =>
|
||||
{
|
||||
if (exception is not OperationCanceledException)
|
||||
onFailure(exception.Message);
|
||||
};
|
||||
|
||||
api.Queue(joinRoomRequest);
|
||||
}
|
||||
|
||||
public override void Close(Room room)
|
||||
{
|
||||
Debug.Assert(room.RoomID != null);
|
||||
|
||||
var request = new ClosePlaylistRequest(room.RoomID.Value);
|
||||
request.Success += RefreshRooms;
|
||||
api.Queue(request);
|
||||
}
|
||||
|
||||
protected override OsuButton CreateNewRoomButton() => new CreatePlaylistsRoomButton();
|
||||
|
||||
protected override Room CreateNewRoom()
|
||||
|
@ -75,9 +75,6 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
|
||||
private PurpleRoundedButton editPlaylistButton = null!;
|
||||
|
||||
[Resolved]
|
||||
private IRoomManager? manager { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; } = null!;
|
||||
|
||||
@ -440,7 +437,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
if (!ApplyButton.Enabled.Value)
|
||||
return;
|
||||
|
||||
hideError();
|
||||
ErrorText.FadeOut(50);
|
||||
|
||||
room.Name = NameField.Text;
|
||||
room.Availability = AvailabilityPicker.Current.Value;
|
||||
@ -449,13 +446,13 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
room.Duration = DurationField.Current.Value;
|
||||
|
||||
loadingLayer.Show();
|
||||
manager?.CreateRoom(room, onSuccess, onError);
|
||||
|
||||
var req = new CreateRoomRequest(room);
|
||||
req.Success += _ => loadingLayer.Hide();
|
||||
req.Failure += e => onError(req.Response?.Error ?? e.Message);
|
||||
api.Queue(req);
|
||||
}
|
||||
|
||||
private void hideError() => ErrorText.FadeOut(50);
|
||||
|
||||
private void onSuccess(Room room) => loadingLayer.Hide();
|
||||
|
||||
private void onError(string text)
|
||||
{
|
||||
// see https://github.com/ppy/osu-web/blob/2c97aaeb64fb4ed97c747d8383a35b30f57428c7/app/Models/Multiplayer/PlaylistItem.php#L48.
|
||||
|
@ -344,6 +344,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
}));
|
||||
}
|
||||
|
||||
protected override void PartRoom() => api.Queue(new PartRoomRequest(Room));
|
||||
|
||||
protected override Screen CreateGameplayScreen(PlaylistItem selectedItem)
|
||||
{
|
||||
return new PlayerLoader(() => new PlaylistsPlayer(Room, selectedItem)
|
||||
|
@ -1,7 +1,6 @@
|
||||
// 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 osu.Game.Screens.OnlinePlay;
|
||||
using osu.Game.Tests.Visual.OnlinePlay;
|
||||
using osu.Game.Tests.Visual.Spectator;
|
||||
|
||||
@ -17,11 +16,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
/// </summary>
|
||||
TestMultiplayerClient MultiplayerClient { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The cached <see cref="IRoomManager"/>.
|
||||
/// </summary>
|
||||
new TestMultiplayerRoomManager RoomManager { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The cached <see cref="osu.Game.Online.Spectator.SpectatorClient"/>.
|
||||
/// </summary>
|
||||
|
@ -17,7 +17,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
public const int PLAYER_2_ID = 56;
|
||||
|
||||
public TestMultiplayerClient MultiplayerClient => OnlinePlayDependencies.MultiplayerClient;
|
||||
public new TestMultiplayerRoomManager RoomManager => OnlinePlayDependencies.RoomManager;
|
||||
public TestSpectatorClient SpectatorClient => OnlinePlayDependencies.SpectatorClient;
|
||||
|
||||
protected new MultiplayerTestSceneDependencies OnlinePlayDependencies => (MultiplayerTestSceneDependencies)base.OnlinePlayDependencies;
|
||||
@ -56,7 +55,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("join room", () =>
|
||||
{
|
||||
SelectedRoom.Value = CreateRoom();
|
||||
RoomManager.CreateRoom(SelectedRoom.Value);
|
||||
MultiplayerClient.CreateRoom(SelectedRoom.Value).ConfigureAwait(false);
|
||||
});
|
||||
|
||||
AddUntilStep("wait for room join", () => RoomJoined);
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Spectator;
|
||||
using osu.Game.Screens.OnlinePlay;
|
||||
using osu.Game.Tests.Visual.OnlinePlay;
|
||||
using osu.Game.Tests.Visual.Spectator;
|
||||
|
||||
@ -16,19 +15,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
public TestMultiplayerClient MultiplayerClient { get; }
|
||||
public TestSpectatorClient SpectatorClient { get; }
|
||||
public new TestMultiplayerRoomManager RoomManager => (TestMultiplayerRoomManager)base.RoomManager;
|
||||
|
||||
public MultiplayerTestSceneDependencies()
|
||||
{
|
||||
MultiplayerClient = new TestMultiplayerClient(RoomManager);
|
||||
MultiplayerClient = new TestMultiplayerClient(RequestsHandler);
|
||||
SpectatorClient = CreateSpectatorClient();
|
||||
|
||||
CacheAs<MultiplayerClient>(MultiplayerClient);
|
||||
CacheAs<SpectatorClient>(SpectatorClient);
|
||||
}
|
||||
|
||||
protected override IRoomManager CreateRoomManager() => new TestMultiplayerRoomManager(RequestsHandler);
|
||||
|
||||
protected virtual TestSpectatorClient CreateSpectatorClient() => new TestSpectatorClient();
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ using MessagePack;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
@ -17,6 +18,7 @@ using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Tests.Visual.OnlinePlay;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
@ -65,15 +67,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; } = null!;
|
||||
|
||||
private readonly TestMultiplayerRoomManager roomManager;
|
||||
|
||||
private MultiplayerPlaylistItem? currentItem => ServerRoom?.Playlist[currentIndex];
|
||||
private int currentIndex;
|
||||
private long lastPlaylistItemId;
|
||||
|
||||
public TestMultiplayerClient(TestMultiplayerRoomManager roomManager)
|
||||
private readonly TestRoomRequestsHandler apiRequestHandler;
|
||||
|
||||
public TestMultiplayerClient(TestRoomRequestsHandler? apiRequestHandler = null)
|
||||
{
|
||||
this.roomManager = roomManager;
|
||||
this.apiRequestHandler = apiRequestHandler ?? new TestRoomRequestsHandler();
|
||||
}
|
||||
|
||||
public void Connect() => isConnected.Value = true;
|
||||
@ -206,7 +208,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
((IMultiplayerClient)this).UserBeatmapAvailabilityChanged(clone(userId), clone(user.BeatmapAvailability));
|
||||
}
|
||||
|
||||
protected override async Task<MultiplayerRoom> JoinRoom(long roomId, string? password = null)
|
||||
protected override async Task<MultiplayerRoom> JoinRoomInternal(long roomId, string? password = null)
|
||||
{
|
||||
if (RoomJoined || ServerAPIRoom != null)
|
||||
throw new InvalidOperationException("Already joined a room");
|
||||
@ -214,7 +216,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
roomId = clone(roomId);
|
||||
password = clone(password);
|
||||
|
||||
ServerAPIRoom = roomManager.ServerSideRooms.Single(r => r.RoomID == roomId);
|
||||
ServerAPIRoom = ServerSideRooms.Single(r => r.RoomID == roomId);
|
||||
|
||||
if (password != ServerAPIRoom.Password)
|
||||
throw new InvalidOperationException("Invalid password.");
|
||||
@ -500,6 +502,19 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
public override Task RemovePlaylistItem(long playlistItemId) => RemoveUserPlaylistItem(api.LocalUser.Value.OnlineID, clone(playlistItemId));
|
||||
|
||||
protected override Task<MultiplayerRoom> CreateRoomInternal(MultiplayerRoom room)
|
||||
{
|
||||
Room apiRoom = new Room(room)
|
||||
{
|
||||
Type = room.Settings.MatchType == MatchType.Playlists
|
||||
? MatchType.HeadToHead
|
||||
: room.Settings.MatchType
|
||||
};
|
||||
|
||||
AddServerSideRoom(apiRoom, api.LocalUser.Value);
|
||||
return JoinRoomInternal(apiRoom.RoomID!.Value, room.Settings.Password);
|
||||
}
|
||||
|
||||
private async Task changeMatchType(MatchType type)
|
||||
{
|
||||
Debug.Assert(ServerRoom != null);
|
||||
@ -692,5 +707,18 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
isConnected.Value = false;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
#region API Room Handling
|
||||
|
||||
public IReadOnlyList<Room> ServerSideRooms
|
||||
=> apiRequestHandler.ServerSideRooms;
|
||||
|
||||
public void AddServerSideRoom(Room room, APIUser host)
|
||||
=> apiRequestHandler.AddServerSideRoom(room, host);
|
||||
|
||||
public bool HandleRequest(APIRequest request, APIUser localUser, BeatmapManager beatmapManager)
|
||||
=> apiRequestHandler.HandleRequest(request, localUser, beatmapManager);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -1,42 +0,0 @@
|
||||
// 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.Collections.Generic;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||
using osu.Game.Tests.Visual.OnlinePlay;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="RoomManager"/> for use in multiplayer test scenes.
|
||||
/// Should generally not be used by itself outside of a <see cref="MultiplayerTestScene"/>.
|
||||
/// </summary>
|
||||
public partial class TestMultiplayerRoomManager : MultiplayerRoomManager
|
||||
{
|
||||
private readonly TestRoomRequestsHandler requestsHandler;
|
||||
|
||||
public TestMultiplayerRoomManager(TestRoomRequestsHandler requestsHandler)
|
||||
{
|
||||
this.requestsHandler = requestsHandler;
|
||||
}
|
||||
|
||||
public IReadOnlyList<Room> ServerSideRooms => requestsHandler.ServerSideRooms;
|
||||
|
||||
public override void CreateRoom(Room room, Action<Room>? onSuccess = null, Action<string>? onError = null)
|
||||
=> base.CreateRoom(room, r => onSuccess?.Invoke(r), onError);
|
||||
|
||||
public override void JoinRoom(Room room, string? password = null, Action<Room>? onSuccess = null, Action<string>? onError = null)
|
||||
=> base.JoinRoom(room, password, r => onSuccess?.Invoke(r), onError);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a room to a local "server-side" list that's returned when a <see cref="GetRoomsRequest"/> is fired.
|
||||
/// </summary>
|
||||
/// <param name="room">The room.</param>
|
||||
/// <param name="host">The host.</param>
|
||||
public void AddServerSideRoom(Room room, APIUser host) => requestsHandler.AddServerSideRoom(room, host);
|
||||
}
|
||||
}
|
@ -40,7 +40,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
||||
RequestsHandler = new TestRoomRequestsHandler();
|
||||
OngoingOperationTracker = new OngoingOperationTracker();
|
||||
AvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker();
|
||||
RoomManager = CreateRoomManager();
|
||||
RoomManager = new TestRoomManager();
|
||||
UserLookupCache = new TestUserLookupCache();
|
||||
BeatmapLookupCache = new BeatmapLookupCache();
|
||||
|
||||
@ -80,7 +80,5 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
||||
if (instance is Drawable drawable)
|
||||
drawableComponents.Add(drawable);
|
||||
}
|
||||
|
||||
protected virtual IRoomManager CreateRoomManager() => new TestRoomManager();
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,9 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets;
|
||||
@ -15,18 +17,19 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
||||
/// </summary>
|
||||
public partial class TestRoomManager : RoomManager
|
||||
{
|
||||
public Action<Room, string?>? JoinRoomRequested;
|
||||
|
||||
private int currentRoomId;
|
||||
|
||||
public override void JoinRoom(Room room, string? password = null, Action<Room>? onSuccess = null, Action<string>? onError = null)
|
||||
{
|
||||
JoinRoomRequested?.Invoke(room, password);
|
||||
base.JoinRoom(room, password, onSuccess, onError);
|
||||
}
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private RulesetStore rulesets { get; set; } = null!;
|
||||
|
||||
public void AddRooms(int count, RulesetInfo? ruleset = null, bool withPassword = false, bool withSpotlightRooms = false)
|
||||
{
|
||||
// Can't reference Osu ruleset project here.
|
||||
ruleset ??= rulesets.GetRuleset(0)!;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
AddRoom(new Room
|
||||
@ -36,12 +39,8 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
||||
Duration = TimeSpan.FromSeconds(10),
|
||||
Category = withSpotlightRooms && i % 2 == 0 ? RoomCategory.Spotlight : RoomCategory.Normal,
|
||||
Password = withPassword ? @"password" : null,
|
||||
PlaylistItemStats = ruleset == null
|
||||
? null
|
||||
: new Room.RoomPlaylistItemStats { RulesetIDs = [ruleset.OnlineID] },
|
||||
Playlist = ruleset == null
|
||||
? Array.Empty<PlaylistItem>()
|
||||
: [new PlaylistItem(new BeatmapInfo { Metadata = new BeatmapMetadata() }) { RulesetID = ruleset.OnlineID }]
|
||||
PlaylistItemStats = new Room.RoomPlaylistItemStats { RulesetIDs = [ruleset.OnlineID] },
|
||||
Playlist = [new PlaylistItem(new BeatmapInfo { Metadata = new BeatmapMetadata() }) { RulesetID = ruleset.OnlineID }]
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -49,7 +48,11 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
||||
public void AddRoom(Room room)
|
||||
{
|
||||
room.RoomID = -currentRoomId;
|
||||
CreateRoom(room);
|
||||
|
||||
var req = new CreateRoomRequest(room);
|
||||
req.Success += AddOrUpdateRoom;
|
||||
api.Queue(req);
|
||||
|
||||
currentRoomId++;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user