mirror of
https://github.com/ppy/osu.git
synced 2024-12-16 07:42:54 +08:00
Merge pull request #29914 from peppy/fix-judgement-counter-sync
Fix judgement counter not showing correct counts when spectating user mid-play
This commit is contained in:
commit
a00ed8dd77
@ -19,6 +19,7 @@ using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.HUD.JudgementCounter;
|
||||
using osu.Game.Tests.Beatmaps.IO;
|
||||
using osu.Game.Tests.Gameplay;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
@ -167,14 +168,16 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
public void TestSpectatingDuringGameplay()
|
||||
{
|
||||
start();
|
||||
sendFrames(300);
|
||||
sendFrames(300, initialResultCount: 100);
|
||||
|
||||
loadSpectatingScreen();
|
||||
waitForPlayerCurrent();
|
||||
|
||||
sendFrames(300);
|
||||
sendFrames(300, initialResultCount: 100);
|
||||
|
||||
AddUntilStep("playing from correct point in time", () => player.ChildrenOfType<DrawableRuleset>().First().FrameStableClock.CurrentTime, () => Is.GreaterThan(30000));
|
||||
AddAssert("check judgement counts are correct", () => player.ChildrenOfType<JudgementCountController>().Single().Counters.Sum(c => c.ResultCount.Value),
|
||||
() => Is.GreaterThanOrEqualTo(100));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -405,9 +408,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
private void checkPaused(bool state) =>
|
||||
AddUntilStep($"game is {(state ? "paused" : "playing")}", () => player.ChildrenOfType<DrawableRuleset>().First().IsPaused.Value == state);
|
||||
|
||||
private void sendFrames(int count = 10, double startTime = 0)
|
||||
private void sendFrames(int count = 10, double startTime = 0, int initialResultCount = 0)
|
||||
{
|
||||
AddStep("send frames", () => spectatorClient.SendFramesFromUser(streamingUser.Id, count, startTime));
|
||||
AddStep("send frames", () => spectatorClient.SendFramesFromUser(streamingUser.Id, count, startTime, initialResultCount));
|
||||
}
|
||||
|
||||
private void loadSpectatingScreen()
|
||||
|
@ -181,6 +181,8 @@ namespace osu.Game.Rulesets.Scoring
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<HitResult, int> Statistics => ScoreResultCounts;
|
||||
|
||||
private bool beatmapApplied;
|
||||
|
||||
protected readonly Dictionary<HitResult, int> ScoreResultCounts = new Dictionary<HitResult, int>();
|
||||
|
18
osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCount.cs
Normal file
18
osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCount.cs
Normal file
@ -0,0 +1,18 @@
|
||||
// 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 osu.Framework.Bindables;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Screens.Play.HUD.JudgementCounter
|
||||
{
|
||||
public struct JudgementCount
|
||||
{
|
||||
public LocalisableString DisplayName { get; set; }
|
||||
|
||||
public HitResult[] Types { get; set; }
|
||||
|
||||
public BindableInt ResultCount { get; set; }
|
||||
}
|
||||
}
|
@ -6,7 +6,6 @@ using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
@ -53,10 +52,29 @@ namespace osu.Game.Screens.Play.HUD.JudgementCounter
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
scoreProcessor.OnResetFromReplayFrame += updateAllCountsFromReplayFrame;
|
||||
scoreProcessor.NewJudgement += judgement => updateCount(judgement, false);
|
||||
scoreProcessor.JudgementReverted += judgement => updateCount(judgement, true);
|
||||
}
|
||||
|
||||
private bool hasUpdatedCountsFromReplayFrame;
|
||||
|
||||
private void updateAllCountsFromReplayFrame()
|
||||
{
|
||||
if (hasUpdatedCountsFromReplayFrame)
|
||||
return;
|
||||
|
||||
foreach (var kvp in scoreProcessor.Statistics)
|
||||
{
|
||||
if (!results.TryGetValue(kvp.Key, out var count))
|
||||
continue;
|
||||
|
||||
count.ResultCount.Value = kvp.Value;
|
||||
}
|
||||
|
||||
hasUpdatedCountsFromReplayFrame = true;
|
||||
}
|
||||
|
||||
private void updateCount(JudgementResult judgement, bool revert)
|
||||
{
|
||||
if (!results.TryGetValue(judgement.Type, out var count))
|
||||
@ -67,14 +85,5 @@ namespace osu.Game.Screens.Play.HUD.JudgementCounter
|
||||
else
|
||||
count.ResultCount.Value++;
|
||||
}
|
||||
|
||||
public struct JudgementCount
|
||||
{
|
||||
public LocalisableString DisplayName { get; set; }
|
||||
|
||||
public HitResult[] Types { get; set; }
|
||||
|
||||
public BindableInt ResultCount { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Screens.Play.HUD.JudgementCounter
|
||||
@ -19,16 +18,16 @@ namespace osu.Game.Screens.Play.HUD.JudgementCounter
|
||||
public BindableBool ShowName = new BindableBool();
|
||||
public Bindable<FillDirection> Direction = new Bindable<FillDirection>();
|
||||
|
||||
public readonly JudgementCountController.JudgementCount Result;
|
||||
public readonly JudgementCount Result;
|
||||
|
||||
public JudgementCounter(JudgementCountController.JudgementCount result) => Result = result;
|
||||
public JudgementCounter(JudgementCount result) => Result = result;
|
||||
|
||||
public OsuSpriteText ResultName = null!;
|
||||
private FillFlowContainer flowContainer = null!;
|
||||
private JudgementRollingCounter counter = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours, IBindable<RulesetInfo> ruleset)
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
|
@ -126,7 +126,7 @@ namespace osu.Game.Screens.Play.HUD.JudgementCounter
|
||||
}
|
||||
}
|
||||
|
||||
private JudgementCounter createCounter(JudgementCountController.JudgementCount info) =>
|
||||
private JudgementCounter createCounter(JudgementCount info) =>
|
||||
new JudgementCounter(info)
|
||||
{
|
||||
State = { Value = Visibility.Hidden },
|
||||
|
@ -13,6 +13,8 @@ using osu.Game.Online.API;
|
||||
using osu.Game.Online.Spectator;
|
||||
using osu.Game.Replays.Legacy;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
@ -99,13 +101,24 @@ namespace osu.Game.Tests.Visual.Spectator
|
||||
/// <param name="userId">The user to send frames for.</param>
|
||||
/// <param name="count">The total number of frames to send.</param>
|
||||
/// <param name="startTime">The time to start gameplay frames from.</param>
|
||||
public void SendFramesFromUser(int userId, int count, double startTime = 0)
|
||||
/// <param name="initialResultCount">Add a number of misses to frame header data for testing purposes.</param>
|
||||
public void SendFramesFromUser(int userId, int count, double startTime = 0, int initialResultCount = 0)
|
||||
{
|
||||
var frames = new List<LegacyReplayFrame>();
|
||||
|
||||
int currentFrameIndex = userNextFrameDictionary[userId];
|
||||
int lastFrameIndex = currentFrameIndex + count - 1;
|
||||
|
||||
var scoreProcessor = new ScoreProcessor(rulesetStore.GetRuleset(0)!.CreateInstance());
|
||||
|
||||
for (int i = 0; i < initialResultCount; i++)
|
||||
{
|
||||
scoreProcessor.ApplyResult(new JudgementResult(new HitObject(), new Judgement())
|
||||
{
|
||||
Type = HitResult.Miss,
|
||||
});
|
||||
}
|
||||
|
||||
for (; currentFrameIndex <= lastFrameIndex; currentFrameIndex++)
|
||||
{
|
||||
// This is done in the next frame so that currentFrameIndex is updated to the correct value.
|
||||
@ -130,7 +143,16 @@ namespace osu.Game.Tests.Visual.Spectator
|
||||
Combo = currentFrameIndex,
|
||||
TotalScore = (long)(currentFrameIndex * 123478 * RNG.NextDouble(0.99, 1.01)),
|
||||
Accuracy = RNG.NextDouble(0.98, 1),
|
||||
}, new ScoreProcessor(rulesetStore.GetRuleset(0)!.CreateInstance()), frames.ToArray());
|
||||
Statistics = scoreProcessor.Statistics.ToDictionary(),
|
||||
}, scoreProcessor, frames.ToArray());
|
||||
|
||||
if (initialResultCount > 0)
|
||||
{
|
||||
foreach (var f in frames)
|
||||
f.Header = bundle.Header;
|
||||
}
|
||||
|
||||
scoreProcessor.ResetFromReplayFrame(frames.Last());
|
||||
((ISpectatorClient)this).UserSentFrames(userId, bundle);
|
||||
|
||||
frames.Clear();
|
||||
|
Loading…
Reference in New Issue
Block a user