mirror of
https://github.com/ppy/osu.git
synced 2025-03-28 10:17:19 +08:00
Merge pull request #14378 from frenzibyte/fix-lounge-loading
Fix lounge sub screen loading layer displaying in the background
This commit is contained in:
commit
0c978bf9e9
@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
public class TestSceneLoungeRoomsContainer : OnlinePlayTestScene
|
public class TestSceneLoungeRoomsContainer : OnlinePlayTestScene
|
||||||
{
|
{
|
||||||
protected new BasicTestRoomManager RoomManager => (BasicTestRoomManager)base.RoomManager;
|
protected new TestRequestHandlingRoomManager RoomManager => (TestRequestHandlingRoomManager)base.RoomManager;
|
||||||
|
|
||||||
private RoomsContainer container;
|
private RoomsContainer container;
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddStep("add rooms", () => RoomManager.AddRooms(3));
|
AddStep("add rooms", () => RoomManager.AddRooms(3));
|
||||||
|
|
||||||
AddAssert("has 3 rooms", () => container.Rooms.Count == 3);
|
AddAssert("has 3 rooms", () => container.Rooms.Count == 3);
|
||||||
AddStep("remove first room", () => RoomManager.Rooms.Remove(RoomManager.Rooms.FirstOrDefault()));
|
AddStep("remove first room", () => RoomManager.RemoveRoom(RoomManager.Rooms.FirstOrDefault()));
|
||||||
AddAssert("has 2 rooms", () => container.Rooms.Count == 2);
|
AddAssert("has 2 rooms", () => container.Rooms.Count == 2);
|
||||||
AddAssert("first room removed", () => container.Rooms.All(r => r.Room.RoomID.Value != 0));
|
AddAssert("first room removed", () => container.Rooms.All(r => r.Room.RoomID.Value != 0));
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
public class TestSceneMultiplayerLoungeSubScreen : OnlinePlayTestScene
|
public class TestSceneMultiplayerLoungeSubScreen : OnlinePlayTestScene
|
||||||
{
|
{
|
||||||
protected new BasicTestRoomManager RoomManager => (BasicTestRoomManager)base.RoomManager;
|
protected new TestRequestHandlingRoomManager RoomManager => (TestRequestHandlingRoomManager)base.RoomManager;
|
||||||
|
|
||||||
private LoungeSubScreen loungeScreen;
|
private LoungeSubScreen loungeScreen;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
{
|
{
|
||||||
public class TestScenePlaylistsLoungeSubScreen : OnlinePlayTestScene
|
public class TestScenePlaylistsLoungeSubScreen : OnlinePlayTestScene
|
||||||
{
|
{
|
||||||
protected new BasicTestRoomManager RoomManager => (BasicTestRoomManager)base.RoomManager;
|
protected new TestRequestHandlingRoomManager RoomManager => (TestRequestHandlingRoomManager)base.RoomManager;
|
||||||
|
|
||||||
private LoungeSubScreen loungeScreen;
|
private LoungeSubScreen loungeScreen;
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ using osu.Framework.Platform;
|
|||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Online.API;
|
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
@ -35,18 +34,6 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
{
|
{
|
||||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default));
|
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default));
|
||||||
|
|
||||||
((DummyAPIAccess)API).HandleRequest = req =>
|
|
||||||
{
|
|
||||||
switch (req)
|
|
||||||
{
|
|
||||||
case CreateRoomScoreRequest createRoomScoreRequest:
|
|
||||||
createRoomScoreRequest.TriggerSuccess(new APIScoreToken { ID = 1 });
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[SetUpSteps]
|
[SetUpSteps]
|
||||||
|
@ -76,6 +76,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
|||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
private void load([CanBeNull] IdleTracker idleTracker)
|
private void load([CanBeNull] IdleTracker idleTracker)
|
||||||
{
|
{
|
||||||
|
const float controls_area_height = 25f;
|
||||||
|
|
||||||
if (idleTracker != null)
|
if (idleTracker != null)
|
||||||
isIdle.BindTo(idleTracker.IsIdle);
|
isIdle.BindTo(idleTracker.IsIdle);
|
||||||
|
|
||||||
@ -84,86 +86,73 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
|||||||
InternalChildren = new Drawable[]
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
ListingPollingComponent = CreatePollingComponent().With(c => c.Filter.BindTarget = filter),
|
ListingPollingComponent = CreatePollingComponent().With(c => c.Filter.BindTarget = filter),
|
||||||
loadingLayer = new LoadingLayer(true),
|
|
||||||
new Container
|
new Container
|
||||||
{
|
{
|
||||||
|
Name = @"Rooms area",
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Padding = new MarginPadding
|
Padding = new MarginPadding
|
||||||
{
|
{
|
||||||
Left = WaveOverlayContainer.WIDTH_PADDING,
|
Horizontal = WaveOverlayContainer.WIDTH_PADDING,
|
||||||
Right = WaveOverlayContainer.WIDTH_PADDING,
|
Top = Header.HEIGHT + controls_area_height + 20,
|
||||||
},
|
},
|
||||||
Child = new GridContainer
|
Child = scrollContainer = new OsuScrollContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
RowDimensions = new[]
|
ScrollbarOverlapsContent = false,
|
||||||
|
Child = roomsContainer = new RoomsContainer
|
||||||
{
|
{
|
||||||
new Dimension(GridSizeMode.Absolute, Header.HEIGHT),
|
Filter = { BindTarget = filter }
|
||||||
new Dimension(GridSizeMode.Absolute, 25),
|
}
|
||||||
new Dimension(GridSizeMode.Absolute, 20)
|
},
|
||||||
|
},
|
||||||
|
loadingLayer = new LoadingLayer(true),
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
Name = @"Header area flow",
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Padding = new MarginPadding { Horizontal = WaveOverlayContainer.WIDTH_PADDING },
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = Header.HEIGHT,
|
||||||
|
Child = searchTextBox = new LoungeSearchTextBox
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreRight,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Width = 0.6f,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Content = new[]
|
new Container
|
||||||
{
|
{
|
||||||
new Drawable[]
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = controls_area_height,
|
||||||
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
searchTextBox = new LoungeSearchTextBox
|
Buttons.WithChild(CreateNewRoomButton().With(d =>
|
||||||
{
|
{
|
||||||
Anchor = Anchor.CentreRight,
|
d.Anchor = Anchor.BottomLeft;
|
||||||
Origin = Anchor.CentreRight,
|
d.Origin = Anchor.BottomLeft;
|
||||||
RelativeSizeAxes = Axes.X,
|
d.Size = new Vector2(150, 37.5f);
|
||||||
Width = 0.6f,
|
d.Action = () => Open();
|
||||||
},
|
})),
|
||||||
},
|
new FillFlowContainer
|
||||||
new Drawable[]
|
|
||||||
{
|
|
||||||
new Container
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
Anchor = Anchor.TopRight,
|
||||||
Depth = float.MinValue, // Contained filters should appear over the top of rooms.
|
Origin = Anchor.TopRight,
|
||||||
Children = new Drawable[]
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Spacing = new Vector2(10),
|
||||||
|
ChildrenEnumerable = CreateFilterControls().Select(f => f.With(d =>
|
||||||
{
|
{
|
||||||
Buttons.WithChild(CreateNewRoomButton().With(d =>
|
d.Anchor = Anchor.TopRight;
|
||||||
{
|
d.Origin = Anchor.TopRight;
|
||||||
d.Anchor = Anchor.BottomLeft;
|
}))
|
||||||
d.Origin = Anchor.BottomLeft;
|
|
||||||
d.Size = new Vector2(150, 37.5f);
|
|
||||||
d.Action = () => Open();
|
|
||||||
})),
|
|
||||||
new FillFlowContainer
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
Origin = Anchor.TopRight,
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Direction = FillDirection.Horizontal,
|
|
||||||
Spacing = new Vector2(10),
|
|
||||||
ChildrenEnumerable = CreateFilterControls().Select(f => f.With(d =>
|
|
||||||
{
|
|
||||||
d.Anchor = Anchor.TopRight;
|
|
||||||
d.Origin = Anchor.TopRight;
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
null,
|
|
||||||
new Drawable[]
|
|
||||||
{
|
|
||||||
new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
scrollContainer = new OsuScrollContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
ScrollbarOverlapsContent = false,
|
|
||||||
Child = roomsContainer = new RoomsContainer
|
|
||||||
{
|
|
||||||
Filter = { BindTarget = filter }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,150 +1,36 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests;
|
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
using osu.Game.Scoring;
|
|
||||||
using osu.Game.Screens.OnlinePlay.Components;
|
using osu.Game.Screens.OnlinePlay.Components;
|
||||||
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||||
|
using osu.Game.Tests.Visual.OnlinePlay;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Multiplayer
|
namespace osu.Game.Tests.Visual.Multiplayer
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A <see cref="RoomManager"/> for use in multiplayer test scenes. Should generally not be used by itself outside of a <see cref="MultiplayerTestScene"/>.
|
/// A <see cref="RoomManager"/> for use in multiplayer test scenes, backed by a <see cref="TestRoomRequestsHandler"/>.
|
||||||
|
/// Should generally not be used by itself outside of a <see cref="MultiplayerTestScene"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
|
||||||
/// This implementation will pretend to be a server, handling room retrieval and manipulation requests
|
|
||||||
/// and returning a roughly expected state, without the need for a server to be running.
|
|
||||||
/// </remarks>
|
|
||||||
public class TestRequestHandlingMultiplayerRoomManager : MultiplayerRoomManager
|
public class TestRequestHandlingMultiplayerRoomManager : MultiplayerRoomManager
|
||||||
{
|
{
|
||||||
[Resolved]
|
public IReadOnlyList<Room> ServerSideRooms => handler.ServerSideRooms;
|
||||||
private IAPIProvider api { get; set; }
|
|
||||||
|
|
||||||
[Resolved]
|
private readonly TestRoomRequestsHandler handler = new TestRoomRequestsHandler();
|
||||||
private OsuGameBase game { get; set; }
|
|
||||||
|
|
||||||
public IReadOnlyList<Room> ServerSideRooms => serverSideRooms;
|
|
||||||
private readonly List<Room> serverSideRooms = new List<Room>();
|
|
||||||
|
|
||||||
private int currentRoomId;
|
|
||||||
private int currentPlaylistItemId;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load(IAPIProvider api, OsuGameBase game)
|
||||||
{
|
{
|
||||||
int currentScoreId = 0;
|
((DummyAPIAccess)api).HandleRequest = request => handler.HandleRequest(request, api.LocalUser.Value, game);
|
||||||
|
|
||||||
// Handling here is pretending to be a server, while also updating the local state to match
|
|
||||||
// how the server would eventually respond and update the RoomManager.
|
|
||||||
((DummyAPIAccess)api).HandleRequest = req =>
|
|
||||||
{
|
|
||||||
switch (req)
|
|
||||||
{
|
|
||||||
case CreateRoomRequest createRoomRequest:
|
|
||||||
var apiRoom = new Room();
|
|
||||||
|
|
||||||
apiRoom.CopyFrom(createRoomRequest.Room);
|
|
||||||
|
|
||||||
// Passwords are explicitly not copied between rooms.
|
|
||||||
apiRoom.HasPassword.Value = !string.IsNullOrEmpty(createRoomRequest.Room.Password.Value);
|
|
||||||
apiRoom.Password.Value = createRoomRequest.Room.Password.Value;
|
|
||||||
|
|
||||||
AddServerSideRoom(apiRoom);
|
|
||||||
|
|
||||||
var responseRoom = new APICreatedRoom();
|
|
||||||
responseRoom.CopyFrom(createResponseRoom(apiRoom, false));
|
|
||||||
|
|
||||||
createRoomRequest.TriggerSuccess(responseRoom);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case JoinRoomRequest joinRoomRequest:
|
|
||||||
{
|
|
||||||
var room = ServerSideRooms.Single(r => r.RoomID.Value == joinRoomRequest.Room.RoomID.Value);
|
|
||||||
|
|
||||||
if (joinRoomRequest.Password != room.Password.Value)
|
|
||||||
{
|
|
||||||
joinRoomRequest.TriggerFailure(new InvalidOperationException("Invalid password."));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
joinRoomRequest.TriggerSuccess();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
case PartRoomRequest partRoomRequest:
|
|
||||||
partRoomRequest.TriggerSuccess();
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case GetRoomsRequest getRoomsRequest:
|
|
||||||
var roomsWithoutParticipants = new List<Room>();
|
|
||||||
|
|
||||||
foreach (var r in ServerSideRooms)
|
|
||||||
roomsWithoutParticipants.Add(createResponseRoom(r, false));
|
|
||||||
|
|
||||||
getRoomsRequest.TriggerSuccess(roomsWithoutParticipants);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case GetRoomRequest getRoomRequest:
|
|
||||||
getRoomRequest.TriggerSuccess(createResponseRoom(ServerSideRooms.Single(r => r.RoomID.Value == getRoomRequest.RoomId), true));
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case GetBeatmapSetRequest getBeatmapSetRequest:
|
|
||||||
var onlineReq = new GetBeatmapSetRequest(getBeatmapSetRequest.ID, getBeatmapSetRequest.Type);
|
|
||||||
onlineReq.Success += res => getBeatmapSetRequest.TriggerSuccess(res);
|
|
||||||
onlineReq.Failure += e => getBeatmapSetRequest.TriggerFailure(e);
|
|
||||||
|
|
||||||
// Get the online API from the game's dependencies.
|
|
||||||
game.Dependencies.Get<IAPIProvider>().Queue(onlineReq);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case CreateRoomScoreRequest createRoomScoreRequest:
|
|
||||||
createRoomScoreRequest.TriggerSuccess(new APIScoreToken { ID = 1 });
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case SubmitRoomScoreRequest submitRoomScoreRequest:
|
|
||||||
submitRoomScoreRequest.TriggerSuccess(new MultiplayerScore
|
|
||||||
{
|
|
||||||
ID = currentScoreId++,
|
|
||||||
Accuracy = 1,
|
|
||||||
EndedAt = DateTimeOffset.Now,
|
|
||||||
Passed = true,
|
|
||||||
Rank = ScoreRank.S,
|
|
||||||
MaxCombo = 1000,
|
|
||||||
TotalScore = 1000000,
|
|
||||||
User = api.LocalUser.Value,
|
|
||||||
Statistics = new Dictionary<HitResult, int>()
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddServerSideRoom(Room room)
|
/// <summary>
|
||||||
{
|
/// Adds a room to a local "server-side" list that's returned when a <see cref="GetRoomsRequest"/> is fired.
|
||||||
room.RoomID.Value ??= currentRoomId++;
|
/// </summary>
|
||||||
for (int i = 0; i < room.Playlist.Count; i++)
|
/// <param name="room">The room.</param>
|
||||||
room.Playlist[i].ID = currentPlaylistItemId++;
|
public void AddServerSideRoom(Room room) => handler.AddServerSideRoom(room);
|
||||||
|
|
||||||
serverSideRooms.Add(room);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Room createResponseRoom(Room room, bool withParticipants)
|
|
||||||
{
|
|
||||||
var responseRoom = new Room();
|
|
||||||
responseRoom.CopyFrom(room);
|
|
||||||
responseRoom.Password.Value = null;
|
|
||||||
if (!withParticipants)
|
|
||||||
responseRoom.RecentParticipants.Clear();
|
|
||||||
return responseRoom;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,111 +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.Linq;
|
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Online.Rooms;
|
|
||||||
using osu.Game.Rulesets;
|
|
||||||
using osu.Game.Screens.OnlinePlay;
|
|
||||||
using osu.Game.Screens.OnlinePlay.Components;
|
|
||||||
using osu.Game.Users;
|
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.OnlinePlay
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A very simple <see cref="RoomManager"/> for use in online play test scenes.
|
|
||||||
/// </summary>
|
|
||||||
public class BasicTestRoomManager : IRoomManager
|
|
||||||
{
|
|
||||||
public event Action RoomsUpdated;
|
|
||||||
|
|
||||||
public readonly BindableList<Room> Rooms = new BindableList<Room>();
|
|
||||||
|
|
||||||
public Action<Room, string> JoinRoomRequested;
|
|
||||||
|
|
||||||
public IBindable<bool> InitialRoomsReceived { get; } = new Bindable<bool>(true);
|
|
||||||
|
|
||||||
IBindableList<Room> IRoomManager.Rooms => Rooms;
|
|
||||||
|
|
||||||
private int currentRoomId;
|
|
||||||
|
|
||||||
public void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null)
|
|
||||||
{
|
|
||||||
room.RoomID.Value ??= Rooms.Select(r => r.RoomID.Value).Where(id => id != null).Select(id => id.Value).DefaultIfEmpty().Max() + 1;
|
|
||||||
onSuccess?.Invoke(room);
|
|
||||||
|
|
||||||
AddOrUpdateRoom(room);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddOrUpdateRoom(Room room)
|
|
||||||
{
|
|
||||||
var existing = Rooms.FirstOrDefault(r => r.RoomID.Value != null && r.RoomID.Value == room.RoomID.Value);
|
|
||||||
|
|
||||||
if (existing != null)
|
|
||||||
existing.CopyFrom(room);
|
|
||||||
else
|
|
||||||
Rooms.Add(room);
|
|
||||||
|
|
||||||
RoomsUpdated?.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveRoom(Room room)
|
|
||||||
{
|
|
||||||
Rooms.Remove(room);
|
|
||||||
RoomsUpdated?.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearRooms()
|
|
||||||
{
|
|
||||||
Rooms.Clear();
|
|
||||||
RoomsUpdated?.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void JoinRoom(Room room, string password, Action<Room> onSuccess = null, Action<string> onError = null)
|
|
||||||
{
|
|
||||||
JoinRoomRequested?.Invoke(room, password);
|
|
||||||
onSuccess?.Invoke(room);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PartRoom()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddRooms(int count, RulesetInfo ruleset = null, bool withPassword = false)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
var room = new Room
|
|
||||||
{
|
|
||||||
RoomID = { Value = currentRoomId },
|
|
||||||
Position = { Value = currentRoomId },
|
|
||||||
Name = { Value = $"Room {currentRoomId}" },
|
|
||||||
Host = { Value = new User { Username = "Host" } },
|
|
||||||
EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) },
|
|
||||||
Category = { Value = i % 2 == 0 ? RoomCategory.Spotlight : RoomCategory.Normal },
|
|
||||||
Password = { Value = withPassword ? "password" : string.Empty }
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ruleset != null)
|
|
||||||
{
|
|
||||||
room.Playlist.Add(new PlaylistItem
|
|
||||||
{
|
|
||||||
Ruleset = { Value = ruleset },
|
|
||||||
Beatmap =
|
|
||||||
{
|
|
||||||
Value = new BeatmapInfo
|
|
||||||
{
|
|
||||||
Metadata = new BeatmapMetadata()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateRoom(room);
|
|
||||||
|
|
||||||
currentRoomId++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -71,6 +71,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
|||||||
drawableComponents.Add(drawable);
|
drawableComponents.Add(drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual IRoomManager CreateRoomManager() => new BasicTestRoomManager();
|
protected virtual IRoomManager CreateRoomManager() => new TestRequestHandlingRoomManager();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
// 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.Framework.Allocation;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.Rooms;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Screens.OnlinePlay.Components;
|
||||||
|
using osu.Game.Users;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.OnlinePlay
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A very simple <see cref="RoomManager"/> for use in online play test scenes.
|
||||||
|
/// </summary>
|
||||||
|
public class TestRequestHandlingRoomManager : RoomManager
|
||||||
|
{
|
||||||
|
public Action<Room, string> JoinRoomRequested;
|
||||||
|
|
||||||
|
private int currentRoomId;
|
||||||
|
|
||||||
|
private readonly TestRoomRequestsHandler handler = new TestRoomRequestsHandler();
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(IAPIProvider api, OsuGameBase game)
|
||||||
|
{
|
||||||
|
((DummyAPIAccess)api).HandleRequest = request => handler.HandleRequest(request, api.LocalUser.Value, game);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRooms(int count, RulesetInfo ruleset = null, bool withPassword = false)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
var room = new Room
|
||||||
|
{
|
||||||
|
RoomID = { Value = -currentRoomId },
|
||||||
|
Name = { Value = $@"Room {currentRoomId}" },
|
||||||
|
Host = { Value = new User { Username = @"Host" } },
|
||||||
|
EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) },
|
||||||
|
Category = { Value = i % 2 == 0 ? RoomCategory.Spotlight : RoomCategory.Normal },
|
||||||
|
};
|
||||||
|
|
||||||
|
if (withPassword)
|
||||||
|
room.Password.Value = @"password";
|
||||||
|
|
||||||
|
if (ruleset != null)
|
||||||
|
{
|
||||||
|
room.Playlist.Add(new PlaylistItem
|
||||||
|
{
|
||||||
|
Ruleset = { Value = ruleset },
|
||||||
|
Beatmap =
|
||||||
|
{
|
||||||
|
Value = new BeatmapInfo
|
||||||
|
{
|
||||||
|
Metadata = new BeatmapMetadata()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateRoom(room);
|
||||||
|
|
||||||
|
currentRoomId++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
147
osu.Game/Tests/Visual/OnlinePlay/TestRoomRequestsHandler.cs
Normal file
147
osu.Game/Tests/Visual/OnlinePlay/TestRoomRequestsHandler.cs
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.API.Requests;
|
||||||
|
using osu.Game.Online.Rooms;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
using osu.Game.Screens.OnlinePlay.Components;
|
||||||
|
using osu.Game.Users;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.OnlinePlay
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a handler which pretends to be a server, handling room retrieval and manipulation requests
|
||||||
|
/// and returning a roughly expected state, without the need for a server to be running.
|
||||||
|
/// </summary>
|
||||||
|
public class TestRoomRequestsHandler
|
||||||
|
{
|
||||||
|
public IReadOnlyList<Room> ServerSideRooms => serverSideRooms;
|
||||||
|
|
||||||
|
private readonly List<Room> serverSideRooms = new List<Room>();
|
||||||
|
|
||||||
|
private int currentRoomId;
|
||||||
|
private int currentPlaylistItemId;
|
||||||
|
private int currentScoreId;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles an API request, while also updating the local state to match
|
||||||
|
/// how the server would eventually respond and update an <see cref="RoomManager"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">The API request to handle.</param>
|
||||||
|
/// <param name="localUser">The local user to store in responses where required.</param>
|
||||||
|
/// <param name="game">The game base for cases where actual online requests need to be sent.</param>
|
||||||
|
/// <returns>Whether the request was successfully handled.</returns>
|
||||||
|
public bool HandleRequest(APIRequest request, User localUser, OsuGameBase game)
|
||||||
|
{
|
||||||
|
switch (request)
|
||||||
|
{
|
||||||
|
case CreateRoomRequest createRoomRequest:
|
||||||
|
var apiRoom = new Room();
|
||||||
|
|
||||||
|
apiRoom.CopyFrom(createRoomRequest.Room);
|
||||||
|
|
||||||
|
// Passwords are explicitly not copied between rooms.
|
||||||
|
apiRoom.HasPassword.Value = !string.IsNullOrEmpty(createRoomRequest.Room.Password.Value);
|
||||||
|
apiRoom.Password.Value = createRoomRequest.Room.Password.Value;
|
||||||
|
|
||||||
|
AddServerSideRoom(apiRoom);
|
||||||
|
|
||||||
|
var responseRoom = new APICreatedRoom();
|
||||||
|
responseRoom.CopyFrom(createResponseRoom(apiRoom, false));
|
||||||
|
|
||||||
|
createRoomRequest.TriggerSuccess(responseRoom);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case JoinRoomRequest joinRoomRequest:
|
||||||
|
{
|
||||||
|
var room = ServerSideRooms.Single(r => r.RoomID.Value == joinRoomRequest.Room.RoomID.Value);
|
||||||
|
|
||||||
|
if (joinRoomRequest.Password != room.Password.Value)
|
||||||
|
{
|
||||||
|
joinRoomRequest.TriggerFailure(new InvalidOperationException("Invalid password."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
joinRoomRequest.TriggerSuccess();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PartRoomRequest partRoomRequest:
|
||||||
|
partRoomRequest.TriggerSuccess();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case GetRoomsRequest getRoomsRequest:
|
||||||
|
var roomsWithoutParticipants = new List<Room>();
|
||||||
|
|
||||||
|
foreach (var r in ServerSideRooms)
|
||||||
|
roomsWithoutParticipants.Add(createResponseRoom(r, false));
|
||||||
|
|
||||||
|
getRoomsRequest.TriggerSuccess(roomsWithoutParticipants);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case GetRoomRequest getRoomRequest:
|
||||||
|
getRoomRequest.TriggerSuccess(createResponseRoom(ServerSideRooms.Single(r => r.RoomID.Value == getRoomRequest.RoomId), true));
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case GetBeatmapSetRequest getBeatmapSetRequest:
|
||||||
|
var onlineReq = new GetBeatmapSetRequest(getBeatmapSetRequest.ID, getBeatmapSetRequest.Type);
|
||||||
|
onlineReq.Success += res => getBeatmapSetRequest.TriggerSuccess(res);
|
||||||
|
onlineReq.Failure += e => getBeatmapSetRequest.TriggerFailure(e);
|
||||||
|
|
||||||
|
// Get the online API from the game's dependencies.
|
||||||
|
game.Dependencies.Get<IAPIProvider>().Queue(onlineReq);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case CreateRoomScoreRequest createRoomScoreRequest:
|
||||||
|
createRoomScoreRequest.TriggerSuccess(new APIScoreToken { ID = 1 });
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case SubmitRoomScoreRequest submitRoomScoreRequest:
|
||||||
|
submitRoomScoreRequest.TriggerSuccess(new MultiplayerScore
|
||||||
|
{
|
||||||
|
ID = currentScoreId++,
|
||||||
|
Accuracy = 1,
|
||||||
|
EndedAt = DateTimeOffset.Now,
|
||||||
|
Passed = true,
|
||||||
|
Rank = ScoreRank.S,
|
||||||
|
MaxCombo = 1000,
|
||||||
|
TotalScore = 1000000,
|
||||||
|
User = localUser,
|
||||||
|
Statistics = new Dictionary<HitResult, int>()
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
public void AddServerSideRoom(Room room)
|
||||||
|
{
|
||||||
|
room.RoomID.Value ??= currentRoomId++;
|
||||||
|
for (int i = 0; i < room.Playlist.Count; i++)
|
||||||
|
room.Playlist[i].ID = currentPlaylistItemId++;
|
||||||
|
|
||||||
|
serverSideRooms.Add(room);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Room createResponseRoom(Room room, bool withParticipants)
|
||||||
|
{
|
||||||
|
var responseRoom = new Room();
|
||||||
|
responseRoom.CopyFrom(room);
|
||||||
|
responseRoom.Password.Value = null;
|
||||||
|
if (!withParticipants)
|
||||||
|
responseRoom.RecentParticipants.Clear();
|
||||||
|
return responseRoom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user