mirror of
https://github.com/osukey/osukey.git
synced 2025-08-02 22:26:41 +09:00
Implement a conversion process for ReplayFrames
This commit is contained in:
151
osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs
Normal file
151
osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs
Normal file
@ -0,0 +1,151 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.IO;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.IO.Legacy;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
using osu.Game.Rulesets.Replays.Legacy;
|
||||
using osu.Game.Rulesets.Replays.Types;
|
||||
using osu.Game.Users;
|
||||
using SharpCompress.Compressors.LZMA;
|
||||
|
||||
namespace osu.Game.Rulesets.Scoring.Legacy
|
||||
{
|
||||
public class LegacyScoreParser : IScoreParser
|
||||
{
|
||||
private readonly RulesetStore rulesets;
|
||||
private readonly BeatmapManager beatmaps;
|
||||
|
||||
public LegacyScoreParser(RulesetStore rulesets, BeatmapManager beatmaps)
|
||||
{
|
||||
this.rulesets = rulesets;
|
||||
this.beatmaps = beatmaps;
|
||||
}
|
||||
|
||||
private Beatmap currentBeatmap;
|
||||
private Score currentScore;
|
||||
private Ruleset currentRuleset;
|
||||
|
||||
public Score Parse(Stream stream)
|
||||
{
|
||||
Score score;
|
||||
|
||||
using (SerializationReader sr = new SerializationReader(stream))
|
||||
{
|
||||
currentScore = score = new Score { Ruleset = rulesets.GetRuleset(sr.ReadByte()) };
|
||||
currentRuleset = score.Ruleset.CreateInstance();
|
||||
|
||||
/* score.Pass = true;*/
|
||||
var version = sr.ReadInt32();
|
||||
|
||||
/* score.FileChecksum = */
|
||||
var beatmapHash = sr.ReadString();
|
||||
score.Beatmap = beatmaps.QueryBeatmap(b => b.MD5Hash == beatmapHash);
|
||||
currentBeatmap = beatmaps.GetWorkingBeatmap(score.Beatmap).Beatmap;
|
||||
|
||||
/* score.PlayerName = */
|
||||
score.User = new User { Username = sr.ReadString() };
|
||||
/* var localScoreChecksum = */
|
||||
sr.ReadString();
|
||||
/* score.Count300 = */
|
||||
sr.ReadUInt16();
|
||||
/* score.Count100 = */
|
||||
sr.ReadUInt16();
|
||||
/* score.Count50 = */
|
||||
sr.ReadUInt16();
|
||||
/* score.CountGeki = */
|
||||
sr.ReadUInt16();
|
||||
/* score.CountKatu = */
|
||||
sr.ReadUInt16();
|
||||
/* score.CountMiss = */
|
||||
sr.ReadUInt16();
|
||||
score.TotalScore = sr.ReadInt32();
|
||||
score.MaxCombo = sr.ReadUInt16();
|
||||
/* score.Perfect = */
|
||||
sr.ReadBoolean();
|
||||
/* score.EnabledMods = (Mods)*/
|
||||
sr.ReadInt32();
|
||||
/* score.HpGraphString = */
|
||||
sr.ReadString();
|
||||
/* score.Date = */
|
||||
sr.ReadDateTime();
|
||||
|
||||
var compressedReplay = sr.ReadByteArray();
|
||||
|
||||
if (version >= 20140721)
|
||||
/*OnlineId =*/
|
||||
sr.ReadInt64();
|
||||
else if (version >= 20121008)
|
||||
/*OnlineId =*/
|
||||
sr.ReadInt32();
|
||||
|
||||
using (var replayInStream = new MemoryStream(compressedReplay))
|
||||
{
|
||||
byte[] properties = new byte[5];
|
||||
if (replayInStream.Read(properties, 0, 5) != 5)
|
||||
throw new IOException("input .lzma is too short");
|
||||
long outSize = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
int v = replayInStream.ReadByte();
|
||||
if (v < 0)
|
||||
throw new IOException("Can't Read 1");
|
||||
outSize |= (long)(byte)v << (8 * i);
|
||||
}
|
||||
|
||||
long compressedSize = replayInStream.Length - replayInStream.Position;
|
||||
|
||||
using (var lzma = new LzmaStream(properties, replayInStream, compressedSize, outSize))
|
||||
using (var reader = new StreamReader(lzma))
|
||||
{
|
||||
score.Replay = new Replay { User = score.User };
|
||||
readLegacyReplay(score.Replay, reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
private void readLegacyReplay(Replay replay, StreamReader reader)
|
||||
{
|
||||
float lastTime = 0;
|
||||
|
||||
foreach (var l in reader.ReadToEnd().Split(','))
|
||||
{
|
||||
var split = l.Split('|');
|
||||
|
||||
if (split.Length < 4)
|
||||
continue;
|
||||
|
||||
if (split[0] == "-12345")
|
||||
{
|
||||
// Todo: The seed is provided in split[3], which we'll need to use at some point
|
||||
continue;
|
||||
}
|
||||
|
||||
var diff = float.Parse(split[0]);
|
||||
lastTime += diff;
|
||||
|
||||
// Todo: At some point we probably want to rewind and play back the negative-time frames
|
||||
// but for now we'll achieve equal playback to stable by skipping negative frames
|
||||
if (diff < 0)
|
||||
continue;
|
||||
|
||||
replay.Frames.Add(convertFrame(new LegacyReplayFrame(lastTime, float.Parse(split[1]), float.Parse(split[2]), (ReplayButtonState)int.Parse(split[3]))));
|
||||
}
|
||||
}
|
||||
|
||||
private ReplayFrame convertFrame(LegacyReplayFrame legacyFrame)
|
||||
{
|
||||
var converted = currentRuleset.CreateReplayFrame();
|
||||
converted.Time = legacyFrame.Time;
|
||||
|
||||
if (converted is IConvertibleReplayFrame convertible)
|
||||
convertible.ConvertFrom(legacyFrame, currentScore, currentBeatmap);
|
||||
|
||||
return converted;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user