mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 23:12:56 +08:00
Extract room request handling logic to its own class
This commit is contained in:
parent
0e2f3dff4d
commit
f4ae587a33
@ -1,150 +1,36 @@
|
||||
// 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.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"/>.
|
||||
/// 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>
|
||||
/// <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
|
||||
{
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; }
|
||||
public IReadOnlyList<Room> ServerSideRooms => handler.ServerSideRooms;
|
||||
|
||||
[Resolved]
|
||||
private OsuGameBase game { get; set; }
|
||||
|
||||
public IReadOnlyList<Room> ServerSideRooms => serverSideRooms;
|
||||
private readonly List<Room> serverSideRooms = new List<Room>();
|
||||
|
||||
private int currentRoomId;
|
||||
private int currentPlaylistItemId;
|
||||
private readonly TestRoomRequestsHandler handler = new TestRoomRequestsHandler();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private void load(IAPIProvider api, OsuGameBase game)
|
||||
{
|
||||
int currentScoreId = 0;
|
||||
|
||||
// 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;
|
||||
};
|
||||
((DummyAPIAccess)api).HandleRequest = request => handler.HandleRequest(request, api.LocalUser.Value, game);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
/// <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) => handler.AddServerSideRoom(room);
|
||||
}
|
||||
}
|
||||
|
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…
Reference in New Issue
Block a user