Merge pull request #9993 from bdach/mania-replay-crashes

Fix some mania replays failing to import
This commit is contained in:
Dan Balasescu 2020-08-28 13:58:42 +09:00 committed by GitHub
commit 9c0450b108
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 5 deletions

View File

@ -0,0 +1,66 @@
// 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.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Catch;
using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko;
using osu.Game.Scoring.Legacy;
using osu.Game.Tests.Resources;
namespace osu.Game.Tests.Beatmaps.Formats
{
[TestFixture]
public class LegacyScoreDecoderTest
{
[Test]
public void TestDecodeManiaReplay()
{
var decoder = new TestLegacyScoreDecoder();
using (var resourceStream = TestResources.OpenResource("Replays/mania-replay.osr"))
{
var score = decoder.Parse(resourceStream);
Assert.AreEqual(3, score.ScoreInfo.Ruleset.ID);
Assert.AreEqual(2, score.ScoreInfo.Statistics[HitResult.Great]);
Assert.AreEqual(1, score.ScoreInfo.Statistics[HitResult.Good]);
Assert.AreEqual(829_931, score.ScoreInfo.TotalScore);
Assert.AreEqual(3, score.ScoreInfo.MaxCombo);
Assert.That(score.Replay.Frames, Is.Not.Empty);
}
}
private class TestLegacyScoreDecoder : LegacyScoreDecoder
{
private static readonly Dictionary<int, Ruleset> rulesets = new Ruleset[]
{
new OsuRuleset(),
new TaikoRuleset(),
new CatchRuleset(),
new ManiaRuleset()
}.ToDictionary(ruleset => ((ILegacyRuleset)ruleset).LegacyID);
protected override Ruleset GetRuleset(int rulesetId) => rulesets[rulesetId];
protected override WorkingBeatmap GetBeatmap(string md5Hash) => new TestWorkingBeatmap(new Beatmap
{
BeatmapInfo = new BeatmapInfo
{
MD5Hash = md5Hash,
Ruleset = new OsuRuleset().RulesetInfo,
BaseDifficulty = new BeatmapDifficulty()
}
});
}
}
}

Binary file not shown.

View File

@ -241,12 +241,15 @@ namespace osu.Game.Scoring.Legacy
} }
var diff = Parsing.ParseFloat(split[0]); var diff = Parsing.ParseFloat(split[0]);
var mouseX = Parsing.ParseFloat(split[1], Parsing.MAX_COORDINATE_VALUE);
var mouseY = Parsing.ParseFloat(split[2], Parsing.MAX_COORDINATE_VALUE);
lastTime += diff; lastTime += diff;
if (i == 0 && diff == 0) if (i < 2 && mouseX == 256 && mouseY == -500)
// osu-stable adds a zero-time frame before potentially valid negative user frames. // at the start of the replay, stable places two replay frames, at time 0 and SkipBoundary - 1, respectively.
// we need to ignore this. // both frames use a position of (256, -500).
// ignore these frames as they serve no real purpose (and can even mislead ruleset-specific handlers - see mania)
continue; continue;
// Todo: At some point we probably want to rewind and play back the negative-time frames // Todo: At some point we probably want to rewind and play back the negative-time frames
@ -255,8 +258,8 @@ namespace osu.Game.Scoring.Legacy
continue; continue;
currentFrame = convertFrame(new LegacyReplayFrame(lastTime, currentFrame = convertFrame(new LegacyReplayFrame(lastTime,
Parsing.ParseFloat(split[1], Parsing.MAX_COORDINATE_VALUE), mouseX,
Parsing.ParseFloat(split[2], Parsing.MAX_COORDINATE_VALUE), mouseY,
(ReplayButtonState)Parsing.ParseInt(split[3])), currentFrame); (ReplayButtonState)Parsing.ParseInt(split[3])), currentFrame);
replay.Frames.Add(currentFrame); replay.Frames.Add(currentFrame);