mirror of
https://github.com/ppy/osu.git
synced 2024-11-15 16:22:21 +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.Scoring;
|
||||||
using osu.Game.Screens;
|
using osu.Game.Screens;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
|
using osu.Game.Screens.Play.HUD.JudgementCounter;
|
||||||
using osu.Game.Tests.Beatmaps.IO;
|
using osu.Game.Tests.Beatmaps.IO;
|
||||||
using osu.Game.Tests.Gameplay;
|
using osu.Game.Tests.Gameplay;
|
||||||
using osu.Game.Tests.Visual.Multiplayer;
|
using osu.Game.Tests.Visual.Multiplayer;
|
||||||
@ -167,14 +168,16 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
public void TestSpectatingDuringGameplay()
|
public void TestSpectatingDuringGameplay()
|
||||||
{
|
{
|
||||||
start();
|
start();
|
||||||
sendFrames(300);
|
sendFrames(300, initialResultCount: 100);
|
||||||
|
|
||||||
loadSpectatingScreen();
|
loadSpectatingScreen();
|
||||||
waitForPlayerCurrent();
|
waitForPlayerCurrent();
|
||||||
|
|
||||||
sendFrames(300);
|
sendFrames(300, initialResultCount: 100);
|
||||||
|
|
||||||
AddUntilStep("playing from correct point in time", () => player.ChildrenOfType<DrawableRuleset>().First().FrameStableClock.CurrentTime, () => Is.GreaterThan(30000));
|
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]
|
[Test]
|
||||||
@ -405,9 +408,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
private void checkPaused(bool state) =>
|
private void checkPaused(bool state) =>
|
||||||
AddUntilStep($"game is {(state ? "paused" : "playing")}", () => player.ChildrenOfType<DrawableRuleset>().First().IsPaused.Value == 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()
|
private void loadSpectatingScreen()
|
||||||
|
@ -181,6 +181,8 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<HitResult, int> Statistics => ScoreResultCounts;
|
||||||
|
|
||||||
private bool beatmapApplied;
|
private bool beatmapApplied;
|
||||||
|
|
||||||
protected readonly Dictionary<HitResult, int> ScoreResultCounts = new Dictionary<HitResult, int>();
|
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.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Localisation;
|
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
@ -53,10 +52,29 @@ namespace osu.Game.Screens.Play.HUD.JudgementCounter
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
|
scoreProcessor.OnResetFromReplayFrame += updateAllCountsFromReplayFrame;
|
||||||
scoreProcessor.NewJudgement += judgement => updateCount(judgement, false);
|
scoreProcessor.NewJudgement += judgement => updateCount(judgement, false);
|
||||||
scoreProcessor.JudgementReverted += judgement => updateCount(judgement, true);
|
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)
|
private void updateCount(JudgementResult judgement, bool revert)
|
||||||
{
|
{
|
||||||
if (!results.TryGetValue(judgement.Type, out var count))
|
if (!results.TryGetValue(judgement.Type, out var count))
|
||||||
@ -67,14 +85,5 @@ namespace osu.Game.Screens.Play.HUD.JudgementCounter
|
|||||||
else
|
else
|
||||||
count.ResultCount.Value++;
|
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;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Rulesets;
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Play.HUD.JudgementCounter
|
namespace osu.Game.Screens.Play.HUD.JudgementCounter
|
||||||
@ -19,16 +18,16 @@ namespace osu.Game.Screens.Play.HUD.JudgementCounter
|
|||||||
public BindableBool ShowName = new BindableBool();
|
public BindableBool ShowName = new BindableBool();
|
||||||
public Bindable<FillDirection> Direction = new Bindable<FillDirection>();
|
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!;
|
public OsuSpriteText ResultName = null!;
|
||||||
private FillFlowContainer flowContainer = null!;
|
private FillFlowContainer flowContainer = null!;
|
||||||
private JudgementRollingCounter counter = null!;
|
private JudgementRollingCounter counter = null!;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours, IBindable<RulesetInfo> ruleset)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both;
|
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)
|
new JudgementCounter(info)
|
||||||
{
|
{
|
||||||
State = { Value = Visibility.Hidden },
|
State = { Value = Visibility.Hidden },
|
||||||
|
@ -13,6 +13,8 @@ using osu.Game.Online.API;
|
|||||||
using osu.Game.Online.Spectator;
|
using osu.Game.Online.Spectator;
|
||||||
using osu.Game.Replays.Legacy;
|
using osu.Game.Replays.Legacy;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Replays;
|
using osu.Game.Rulesets.Replays;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.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="userId">The user to send frames for.</param>
|
||||||
/// <param name="count">The total number of frames to send.</param>
|
/// <param name="count">The total number of frames to send.</param>
|
||||||
/// <param name="startTime">The time to start gameplay frames from.</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>();
|
var frames = new List<LegacyReplayFrame>();
|
||||||
|
|
||||||
int currentFrameIndex = userNextFrameDictionary[userId];
|
int currentFrameIndex = userNextFrameDictionary[userId];
|
||||||
int lastFrameIndex = currentFrameIndex + count - 1;
|
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++)
|
for (; currentFrameIndex <= lastFrameIndex; currentFrameIndex++)
|
||||||
{
|
{
|
||||||
// This is done in the next frame so that currentFrameIndex is updated to the correct value.
|
// 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,
|
Combo = currentFrameIndex,
|
||||||
TotalScore = (long)(currentFrameIndex * 123478 * RNG.NextDouble(0.99, 1.01)),
|
TotalScore = (long)(currentFrameIndex * 123478 * RNG.NextDouble(0.99, 1.01)),
|
||||||
Accuracy = RNG.NextDouble(0.98, 1),
|
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);
|
((ISpectatorClient)this).UserSentFrames(userId, bundle);
|
||||||
|
|
||||||
frames.Clear();
|
frames.Clear();
|
||||||
|
Loading…
Reference in New Issue
Block a user