1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-15 23:42:55 +08:00

Merge branch 'master' into multiplayer-no-playlist-mangling

This commit is contained in:
smoogipoo 2021-02-17 19:29:01 +09:00
commit 8930ff4465
11 changed files with 149 additions and 20 deletions

View File

@ -69,6 +69,20 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddAssert("last room joined", () => RoomManager.Rooms.Last().Status.Value is JoinedRoomStatus);
}
[Test]
public void TestClickDeselection()
{
AddRooms(1);
AddAssert("no selection", () => checkRoomSelected(null));
press(Key.Down);
AddAssert("first room selected", () => checkRoomSelected(RoomManager.Rooms.First()));
AddStep("click away", () => InputManager.Click(MouseButton.Left));
AddAssert("no selection", () => checkRoomSelected(null));
}
private void press(Key down)
{
AddStep($"press {down}", () => InputManager.Key(down));

View File

@ -22,7 +22,7 @@ namespace osu.Game.Online.API.Requests.Responses
public double? PP { get; set; }
[JsonProperty(@"room_id")]
public int RoomID { get; set; }
public long RoomID { get; set; }
[JsonProperty("total_score")]
public long TotalScore { get; set; }

View File

@ -0,0 +1,19 @@
// 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 Newtonsoft.Json;
namespace osu.Game.Online.Rooms
{
/// <summary>
/// Represents attempts on a specific playlist item.
/// </summary>
public class ItemAttemptsCount
{
[JsonProperty("id")]
public int PlaylistItemID { get; set; }
[JsonProperty("attempts")]
public int Attempts { get; set; }
}
}

View File

@ -0,0 +1,16 @@
// 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 Newtonsoft.Json;
namespace osu.Game.Online.Rooms
{
/// <summary>
/// Represents aggregated score for the local user for a playlist.
/// </summary>
public class PlaylistAggregateScore
{
[JsonProperty("playlist_item_attempts")]
public ItemAttemptsCount[] PlaylistItemAttempts { get; set; }
}
}

View File

@ -72,6 +72,10 @@ namespace osu.Game.Online.Rooms
[JsonIgnore]
public readonly Bindable<int?> MaxParticipants = new Bindable<int?>();
[Cached]
[JsonProperty("current_user_score")]
public readonly Bindable<PlaylistAggregateScore> UserScore = new Bindable<PlaylistAggregateScore>();
[Cached]
[JsonProperty("recent_participants")]
public readonly BindableList<User> RecentParticipants = new BindableList<User>();
@ -144,6 +148,7 @@ namespace osu.Game.Online.Rooms
MaxParticipants.Value = other.MaxParticipants.Value;
ParticipantCount.Value = other.ParticipantCount.Value;
EndDate.Value = other.EndDate.Value;
UserScore.Value = other.UserScore.Value;
if (EndDate.Value != null && DateTimeOffset.Now >= EndDate.Value)
Status.Value = new RoomStatusEnded();

View File

@ -9,7 +9,6 @@ using osuTK;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Users.Drawables;
using osu.Game.Graphics.Containers;
using osu.Game.Utils;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Bindables;
using System.Linq;
@ -245,11 +244,32 @@ namespace osu.Game.Overlays.Comments
if (Comment.EditedAt.HasValue)
{
info.Add(new OsuSpriteText
var font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular);
var colour = colourProvider.Foreground1;
info.Add(new FillFlowContainer
{
Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular),
Text = $@"edited {HumanizerUtils.Humanize(Comment.EditedAt.Value)} by {Comment.EditedUser.Username}",
Colour = colourProvider.Foreground1
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new OsuSpriteText
{
Font = font,
Text = "edited ",
Colour = colour
},
new DrawableDate(Comment.EditedAt.Value)
{
Font = font,
Colour = colour
},
new OsuSpriteText
{
Font = font,
Text = $@" by {Comment.EditedUser.Username}",
Colour = colour
},
}
});
}

View File

@ -1,6 +1,7 @@
// 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.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@ -39,12 +40,26 @@ namespace osu.Game.Screens.OnlinePlay.Components
{
base.LoadComplete();
MaxAttempts.BindValueChanged(attempts =>
MaxAttempts.BindValueChanged(_ => updateAttempts());
UserScore.BindValueChanged(_ => updateAttempts(), true);
}
private void updateAttempts()
{
attemptDisplay.Text = attempts.NewValue == null
? string.Empty
: $"Maximum attempts: {attempts.NewValue:N0}";
}, true);
if (MaxAttempts.Value != null)
{
attemptDisplay.Text = $"Maximum attempts: {MaxAttempts.Value:N0}";
if (UserScore.Value != null)
{
int remaining = MaxAttempts.Value.Value - UserScore.Value.PlaylistItemAttempts.Sum(a => a.Attempts);
attemptDisplay.Text += $" ({remaining} remaining)";
}
}
else
{
attemptDisplay.Text = string.Empty;
}
}
}
}

View File

@ -11,6 +11,7 @@ using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Framework.Threading;
using osu.Game.Extensions;
using osu.Game.Graphics.Cursor;
@ -42,6 +43,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
[Resolved(CanBeNull = true)]
private LoungeSubScreen loungeSubScreen { get; set; }
// handle deselection
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
public RoomsContainer()
{
RelativeSizeAxes = Axes.X;
@ -69,8 +73,16 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
rooms.BindTo(roomManager.Rooms);
filter?.BindValueChanged(criteria => Filter(criteria.NewValue));
selectedRoom.BindValueChanged(selection =>
{
updateSelection();
}, true);
}
private void updateSelection() =>
roomFlow.Children.ForEach(r => r.State = r.Room == selectedRoom.Value ? SelectionState.Selected : SelectionState.NotSelected);
public void Filter(FilterCriteria criteria)
{
roomFlow.Children.ForEach(r =>
@ -125,6 +137,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
}
Filter(filter?.Value);
updateSelection();
}
private void removeRooms(IEnumerable<Room> rooms)
@ -146,11 +160,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
roomFlow.SetLayoutPosition(room, room.Room.Position.Value);
}
private void selectRoom(Room room)
{
roomFlow.Children.ForEach(r => r.State = r.Room == room ? SelectionState.Selected : SelectionState.NotSelected);
selectedRoom.Value = room;
}
private void selectRoom(Room room) => selectedRoom.Value = room;
private void joinSelected()
{
@ -159,6 +169,12 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
JoinRequested?.Invoke(selectedRoom.Value);
}
protected override bool OnClick(ClickEvent e)
{
selectRoom(null);
return base.OnClick(e);
}
#region Key selection logic (shared with BeatmapCarousel)
public bool OnPressed(GlobalAction action)

View File

@ -75,7 +75,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
managerUpdated = beatmapManager.ItemUpdated.GetBoundCopy();
managerUpdated.BindValueChanged(beatmapUpdated);
UserMods.BindValueChanged(_ => updateMods());
UserMods.BindValueChanged(_ => Scheduler.AddOnce(UpdateMods));
}
public override void OnEntering(IScreen last)
@ -94,7 +94,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
{
base.OnResuming(last);
beginHandlingTrack();
updateMods();
Scheduler.AddOnce(UpdateMods);
}
public override bool OnExiting(IScreen next)
@ -125,7 +125,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
.Where(m => SelectedItem.Value.AllowedMods.Any(a => m.GetType() == a.GetType()))
.ToList();
updateMods();
UpdateMods();
Ruleset.Value = SelectedItem.Value.Ruleset.Value;
}
@ -142,7 +142,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap);
}
private void updateMods()
protected virtual void UpdateMods()
{
if (SelectedItem.Value == null)
return;

View File

@ -275,6 +275,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
UserMods.BindValueChanged(onUserModsChanged);
client.LoadRequested += onLoadRequested;
client.RoomUpdated += onRoomUpdated;
isConnected = client.IsConnected.GetBoundCopy();
isConnected.BindValueChanged(connected =>
@ -284,6 +285,17 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
}, true);
}
protected override void UpdateMods()
{
if (SelectedItem.Value == null || client.LocalUser == null)
return;
// update local mods based on room's reported status for the local user (omitting the base call implementation).
// this makes the server authoritative, and avoids the local user potentially setting mods that the server is not aware of (ie. if the match was started during the selection being changed).
var ruleset = Ruleset.Value.CreateInstance();
Mods.Value = client.LocalUser.Mods.Select(m => m.ToMod(ruleset)).Concat(SelectedItem.Value.RequiredMods).ToList();
}
public override bool OnBackButton()
{
if (client.Room != null && settingsOverlay.State.Value == Visibility.Visible)
@ -390,6 +402,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
}
}
private void onRoomUpdated()
{
// user mods may have changed.
Scheduler.AddOnce(UpdateMods);
}
private void onLoadRequested()
{
Debug.Assert(client.Room != null);
@ -407,7 +425,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
base.Dispose(isDisposing);
if (client != null)
{
client.RoomUpdated -= onRoomUpdated;
client.LoadRequested -= onLoadRequested;
}
modSettingChangeTracker?.Dispose();
}

View File

@ -44,6 +44,9 @@ namespace osu.Game.Screens.OnlinePlay
[Resolved(typeof(Room))]
protected Bindable<int?> MaxAttempts { get; private set; }
[Resolved(typeof(Room))]
public Bindable<PlaylistAggregateScore> UserScore { get; private set; }
[Resolved(typeof(Room))]
protected Bindable<DateTimeOffset?> EndDate { get; private set; }