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:
commit
8930ff4465
@ -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));
|
||||
|
@ -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; }
|
||||
|
19
osu.Game/Online/Rooms/ItemAttemptsCount.cs
Normal file
19
osu.Game/Online/Rooms/ItemAttemptsCount.cs
Normal 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; }
|
||||
}
|
||||
}
|
16
osu.Game/Online/Rooms/PlaylistAggregateScore.cs
Normal file
16
osu.Game/Online/Rooms/PlaylistAggregateScore.cs
Normal 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; }
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
@ -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
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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; }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user