diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 80adc8787f..f290830334 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components { private const float transition_duration = 100; - public readonly Bindable Room = new Bindable(); + public readonly IBindable Room = new Bindable(); private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 }; private readonly Bindable nameBind = new Bindable(); diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index bde76a01df..b17ddca21d 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -17,10 +17,12 @@ namespace osu.Game.Screens.Multi.Lounge.Components { public class RoomsContainer : CompositeDrawable, IHasFilterableChildren { - public Action OpenRequested; + public Action JoinRequested; + + private readonly Bindable selectedRoom = new Bindable(); + public IBindable SelectedRoom => selectedRoom; private readonly IBindableCollection rooms = new BindableCollection(); - private readonly Bindable currentRoom = new Bindable(); private readonly FillFlowContainer roomFlow; @@ -44,15 +46,12 @@ namespace osu.Game.Screens.Multi.Lounge.Components [BackgroundDependencyLoader] private void load() { - currentRoom.BindTo(manager.Current); rooms.BindTo(manager.Rooms); rooms.ItemsAdded += addRooms; rooms.ItemsRemoved += removeRooms; addRooms(rooms); - - currentRoom.BindValueChanged(selectRoom, true); } private FilterCriteria currentFilter; @@ -100,8 +99,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components roomFlow.Remove(toRemove); - if (currentRoom.Value == r) - currentRoom.Value = null; + selectRoom(null); } } @@ -110,12 +108,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components var drawable = roomFlow.FirstOrDefault(r => r.Room == room); if (drawable != null && drawable.State == SelectionState.Selected) - OpenRequested?.Invoke(room); + JoinRequested?.Invoke(room); else - { - currentRoom.Value = room; roomFlow.Children.ForEach(r => r.State = r.Room == room ? SelectionState.Selected : SelectionState.NotSelected); - } + + selectedRoom.Value = room; } public IEnumerable FilterTerms => Enumerable.Empty(); diff --git a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs index 408c02f805..562dfaa347 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Multi.Lounge { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Child = rooms = new RoomsContainer { OpenRequested = Open } + Child = rooms = new RoomsContainer { JoinRequested = r => manager?.JoinRoom(r) } }, }, inspector = new RoomInspector @@ -68,10 +68,10 @@ namespace osu.Game.Screens.Multi.Lounge }, }, }, - manager = new RoomManager() + manager = new RoomManager { OpenRequested = Open } }; - inspector.Room.BindTo(manager.Current); + inspector.Room.BindTo(rooms.SelectedRoom); Filter.Search.Current.ValueChanged += s => filterRooms(); Filter.Tabs.Current.ValueChanged += t => filterRooms(); @@ -103,15 +103,17 @@ namespace osu.Game.Screens.Multi.Lounge protected override bool OnExiting(Screen next) { + manager?.PartRoom(); + Filter.Search.HoldFocus = false; return base.OnExiting(next); } protected override void OnResuming(Screen last) { - base.OnResuming(last); + manager?.PartRoom(); - Filter.Search.HoldFocus = true; + base.OnResuming(last); } protected override void OnSuspending(Screen next) diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 656402d0f3..b33c871fad 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Game.Beatmaps; -using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Play; @@ -52,12 +51,12 @@ namespace osu.Game.Screens.Multi.Match [Resolved] private BeatmapManager beatmapManager { get; set; } - [Resolved] - private APIAccess api { get; set; } - [Resolved] private OsuGame game { get; set; } + [Resolved(CanBeNull = true)] + private RoomManager manager { get; set; } + public MatchScreen(Room room, Action pushGameplayScreen) { this.room = room; diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 0239042241..9339c6693f 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -27,6 +27,7 @@ namespace osu.Game.Screens.Multi public override bool AllowBeatmapRulesetChange => currentScreen?.AllowBeatmapRulesetChange ?? base.AllowBeatmapRulesetChange; private readonly OsuButton createButton; + private readonly LoungeScreen loungeScreen; private OsuScreen currentScreen; @@ -37,7 +38,6 @@ namespace osu.Game.Screens.Multi RelativeSizeAxes = Axes.Both, }; - LoungeScreen loungeScreen; waves.AddRange(new Drawable[] { new Container @@ -102,6 +102,9 @@ namespace osu.Game.Screens.Multi if (track != null) track.Looping = false; + loungeScreen.MakeCurrent(); + loungeScreen.Exit(); + return base.OnExiting(next); } diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 8e887e51e1..b3bb9cb147 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; @@ -16,15 +17,18 @@ using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; using osu.Game.Screens.Multi.Lounge.Components; +using osu.Game.Users; namespace osu.Game.Screens.Multi { public class RoomManager : PollingComponent { + public Action OpenRequested; + public IBindableCollection Rooms => rooms; private readonly BindableCollection rooms = new BindableCollection(); - public readonly Bindable Current = new Bindable(); + private Room currentRoom; private FilterCriteria currentFilter = new FilterCriteria(); @@ -47,12 +51,40 @@ namespace osu.Game.Screens.Multi room.Host.Value = api.LocalUser; var req = new CreateRoomRequest(room); - req.Success += result => addRoom(room, result); req.Failure += exception => Logger.Log($"Failed to create room: {exception}"); + api.Queue(req); } + private JoinRoomRequest currentJoinRoomRequest; + + public void JoinRoom(Room room) + { + currentJoinRoomRequest?.Cancel(); + currentJoinRoomRequest = null; + + currentJoinRoomRequest = new JoinRoomRequest(room, api.LocalUser.Value); + currentJoinRoomRequest.Success += () => + { + currentRoom = room; + OpenRequested?.Invoke(room); + }; + + currentJoinRoomRequest.Failure += exception => Logger.Log($"Failed to join room: {exception}"); + + api.Queue(currentJoinRoomRequest); + } + + public void PartRoom() + { + if (currentRoom == null) + return; + + api.Queue(new PartRoomRequest(currentRoom, api.LocalUser.Value)); + currentRoom = null; + } + public void Filter(FilterCriteria criteria) { currentFilter = criteria; @@ -141,6 +173,48 @@ namespace osu.Game.Screens.Multi protected override string Target => "rooms"; } + private class JoinRoomRequest : APIRequest + { + private readonly Room room; + private readonly User user; + + public JoinRoomRequest(Room room, User user) + { + this.room = room; + this.user = user; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = HttpMethod.Put; + return req; + } + + protected override string Target => $"rooms/{room.RoomID.Value}/users/{user.Id}"; + } + + private class PartRoomRequest : APIRequest + { + private readonly Room room; + private readonly User user; + + public PartRoomRequest(Room room, User user) + { + this.room = room; + this.user = user; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = HttpMethod.Delete; + return req; + } + + protected override string Target => $"rooms/{room.RoomID.Value}/users/{user.Id}"; + } + private class GetRoomsRequest : APIRequest> { private readonly PrimaryFilter primaryFilter;