diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs index 5d25287e45..e89350de1a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs @@ -26,6 +26,8 @@ namespace osu.Game.Tests.Visual.Gameplay [TestFixture] public class TestSceneReplayDownloadButton : OsuManualInputManagerTestScene { + private const long online_score_id = 2553163309; + [Resolved] private RulesetStore rulesets { get; set; } @@ -43,6 +45,15 @@ namespace osu.Game.Tests.Visual.Gameplay beatmapManager.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely(); } + [SetUpSteps] + public void SetUpSteps() + { + AddStep("delete previous imports", () => + { + scoreManager.Delete(s => s.OnlineID == online_score_id); + }); + } + [Test] public void TestDisplayStates() { @@ -180,7 +191,7 @@ namespace osu.Game.Tests.Visual.Gameplay { return new APIScore { - OnlineID = 2553163309, + OnlineID = online_score_id, RulesetID = 0, Beatmap = CreateAPIBeatmapSet(new OsuRuleset().RulesetInfo).Beatmaps.First(), HasReplay = replayAvailable, diff --git a/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs index 98e6cd514b..4e6342868a 100644 --- a/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs +++ b/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs @@ -27,6 +27,8 @@ namespace osu.Game.Tests.Visual.Multiplayer { public abstract class MultiplayerGameplayLeaderboardTestScene : OsuTestScene { + private const int total_users = 16; + protected readonly BindableList MultiplayerUsers = new BindableList(); protected MultiplayerGameplayLeaderboard Leaderboard { get; private set; } @@ -84,7 +86,11 @@ namespace osu.Game.Tests.Visual.Multiplayer [SetUpSteps] public virtual void SetUpSteps() { - AddStep("reset counts", () => spectatorClient.Invocations.Clear()); + AddStep("reset counts", () => + { + spectatorClient.Invocations.Clear(); + lastHeaders.Clear(); + }); AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = new APIUser { @@ -94,7 +100,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("populate users", () => { MultiplayerUsers.Clear(); - for (int i = 0; i < 16; i++) + for (int i = 0; i < total_users; i++) MultiplayerUsers.Add(CreateUser(i)); }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index 5cd3bb2f0f..5caab9487e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -3,7 +3,6 @@ using System.Linq; using osu.Framework.Graphics; -using osu.Framework.Utils; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Rulesets.Osu.Scoring; @@ -14,12 +13,14 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMultiplayerGameplayLeaderboardTeams : MultiplayerGameplayLeaderboardTestScene { + private int team; + protected override MultiplayerRoomUser CreateUser(int userId) { var user = base.CreateUser(userId); user.MatchState = new TeamVersusUserState { - TeamID = RNG.Next(0, 2) + TeamID = team++ % 2 }; return user; } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs index bdc348b043..bcb36a585f 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs @@ -26,10 +26,10 @@ namespace osu.Game.Tests.Visual.Multiplayer var beatmapInfo = CreateBeatmap(rulesetInfo).BeatmapInfo; var score = TestResources.CreateTestScoreInfo(beatmapInfo); - SortedDictionary teamScores = new SortedDictionary + SortedDictionary teamScores = new SortedDictionary { - { 0, new BindableInt(team1Score) }, - { 1, new BindableInt(team2Score) } + { 0, new BindableLong(team1Score) }, + { 1, new BindableLong(team2Score) } }; Stack.Push(screen = new MultiplayerTeamResultsScreen(score, 1, new PlaylistItem(beatmapInfo), teamScores)); diff --git a/osu.Game/Online/ScoreDownloadTracker.cs b/osu.Game/Online/ScoreDownloadTracker.cs index d7e31c8a59..ed1c566dbe 100644 --- a/osu.Game/Online/ScoreDownloadTracker.cs +++ b/osu.Game/Online/ScoreDownloadTracker.cs @@ -47,7 +47,10 @@ namespace osu.Game.Online Downloader.DownloadBegan += downloadBegan; Downloader.DownloadFailed += downloadFailed; - realmSubscription = realm.RegisterForNotifications(r => r.All().Where(s => ((s.OnlineID > 0 && s.OnlineID == TrackedItem.OnlineID) || s.Hash == TrackedItem.Hash) && !s.DeletePending), (items, changes, ___) => + realmSubscription = realm.RegisterForNotifications(r => r.All().Where(s => + ((s.OnlineID > 0 && s.OnlineID == TrackedItem.OnlineID) + || (!string.IsNullOrEmpty(s.Hash) && s.Hash == TrackedItem.Hash)) + && !s.DeletePending), (items, changes, ___) => { if (items.Any()) Schedule(() => UpdateState(DownloadState.LocallyAvailable)); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs index 14a779dedf..3f0f3e043c 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs @@ -24,12 +24,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { public class MultiplayerTeamResultsScreen : MultiplayerResultsScreen { - private readonly SortedDictionary teamScores; + private readonly SortedDictionary teamScores; private Container winnerBackground; private Drawable winnerText; - public MultiplayerTeamResultsScreen(ScoreInfo score, long roomId, PlaylistItem playlistItem, SortedDictionary teamScores) + public MultiplayerTeamResultsScreen(ScoreInfo score, long roomId, PlaylistItem playlistItem, SortedDictionary teamScores) : base(score, roomId, playlistItem) { if (teamScores.Count != 2) diff --git a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs index 88cf9529bf..2129000268 100644 --- a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs +++ b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs @@ -19,8 +19,8 @@ namespace osu.Game.Screens.Play.HUD private const float bar_height = 18; private const float font_size = 50; - public BindableInt Team1Score = new BindableInt(); - public BindableInt Team2Score = new BindableInt(); + public BindableLong Team1Score = new BindableLong(); + public BindableLong Team2Score = new BindableLong(); protected MatchScoreCounter Score1Text; protected MatchScoreCounter Score2Text; @@ -133,7 +133,7 @@ namespace osu.Game.Screens.Play.HUD var winningBar = Team1Score.Value > Team2Score.Value ? score1Bar : score2Bar; var losingBar = Team1Score.Value <= Team2Score.Value ? score1Bar : score2Bar; - int diff = Math.Max(Team1Score.Value, Team2Score.Value) - Math.Min(Team1Score.Value, Team2Score.Value); + long diff = Math.Max(Team1Score.Value, Team2Score.Value) - Math.Min(Team1Score.Value, Team2Score.Value); losingBar.ResizeWidthTo(0, 400, Easing.OutQuint); winningBar.ResizeWidthTo(Math.Min(0.4f, MathF.Pow(diff / 1500000f, 0.5f) / 2), 400, Easing.OutQuint); diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 4f5edab526..41b40e9a91 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Play.HUD { protected readonly Dictionary UserScores = new Dictionary(); - public readonly SortedDictionary TeamScores = new SortedDictionary(); + public readonly SortedDictionary TeamScores = new SortedDictionary(); [Resolved] private OsuColour colours { get; set; } @@ -75,21 +75,27 @@ namespace osu.Game.Screens.Play.HUD foreach (var user in playingUsers) { var trackedUser = CreateUserData(user, ruleset, scoreProcessor); + trackedUser.ScoringMode.BindTo(scoringMode); + trackedUser.Score.BindValueChanged(_ => Scheduler.AddOnce(updateTotals)); + UserScores[user.UserID] = trackedUser; if (trackedUser.Team is int team && !TeamScores.ContainsKey(team)) - TeamScores.Add(team, new BindableInt()); + TeamScores.Add(team, new BindableLong()); } userLookupCache.GetUsersAsync(playingUsers.Select(u => u.UserID).ToArray()).ContinueWith(task => Schedule(() => { var users = task.GetResultSafely(); - foreach (var user in users) + for (int i = 0; i < users.Length; i++) { - if (user == null) - continue; + var user = users[i] ?? new APIUser + { + Id = playingUsers[i].UserID, + Username = "Unknown user", + }; var trackedUser = UserScores[user.Id]; @@ -175,8 +181,6 @@ namespace osu.Game.Screens.Play.HUD trackedData.Frames.Add(new TimedFrame(bundle.Frames.First().Time, bundle.Header)); trackedData.UpdateScore(); - - updateTotals(); }); private void updateTotals() diff --git a/osu.Game/Stores/RealmArchiveModelImporter.cs b/osu.Game/Stores/RealmArchiveModelImporter.cs index 1d0e16d549..6d1449a4b4 100644 --- a/osu.Game/Stores/RealmArchiveModelImporter.cs +++ b/osu.Game/Stores/RealmArchiveModelImporter.cs @@ -351,8 +351,7 @@ namespace osu.Game.Stores using (var transaction = realm.BeginWrite()) { - if (existing.DeletePending) - UndeleteForReuse(existing); + UndeleteForReuse(existing); transaction.Commit(); } @@ -388,9 +387,7 @@ namespace osu.Game.Stores { LogForModel(item, @$"Found existing {HumanisedModelName} for {item} (ID {existing.ID}) – skipping import."); - if (existing.DeletePending) - UndeleteForReuse(existing); - + UndeleteForReuse(existing); transaction.Commit(); return existing.ToLive(Realm); @@ -536,6 +533,10 @@ namespace osu.Game.Stores /// The existing model. protected virtual void UndeleteForReuse(TModel existing) { + if (!existing.DeletePending) + return; + + LogForModel(existing, $@"Existing {HumanisedModelName}'s deletion flag has been removed to allow for reuse."); existing.DeletePending = false; }