Merge branch 'master' into mania-difficulty

This commit is contained in:
Dean Herbert
2018-03-12 13:31:48 +09:00
committed by GitHub
259 changed files with 5722 additions and 1366 deletions

View File

@ -0,0 +1,152 @@
// 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;
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.Users;
using SharpCompress.Compressors.LZMA;
namespace osu.Game.Rulesets.Scoring.Legacy
{
public class LegacyScoreParser
{
private readonly RulesetStore rulesets;
private readonly BeatmapManager beatmaps;
public LegacyScoreParser(RulesetStore rulesets, BeatmapManager beatmaps)
{
this.rulesets = rulesets;
this.beatmaps = beatmaps;
}
private Beatmap currentBeatmap;
private Ruleset currentRuleset;
public Score Parse(Stream stream)
{
Score score;
using (SerializationReader sr = new SerializationReader(stream))
{
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 convertible = currentRuleset.CreateConvertibleReplayFrame();
if (convertible == null)
throw new InvalidOperationException($"Legacy replay cannot be converted for the ruleset: {currentRuleset.Description}");
convertible.ConvertFrom(legacyFrame, currentBeatmap);
var frame = (ReplayFrame)convertible;
frame.Time = legacyFrame.Time;
return frame;
}
}
}

View File

@ -2,16 +2,12 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using System.IO;
using osu.Framework.Platform;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.IO.Legacy;
using osu.Game.IPC;
using osu.Game.Rulesets.Replays;
using osu.Game.Users;
using SharpCompress.Compressors.LZMA;
using osu.Game.Rulesets.Scoring.Legacy;
namespace osu.Game.Rulesets.Scoring
{
@ -53,127 +49,8 @@ namespace osu.Game.Rulesets.Scoring
public Score ReadReplayFile(string replayFilename)
{
Score score;
using (Stream s = storage.GetStream(Path.Combine(replay_folder, replayFilename)))
using (SerializationReader sr = new SerializationReader(s))
{
score = new Score
{
Ruleset = rulesets.GetRuleset(sr.ReadByte())
};
/* score.Pass = true;*/
var version = sr.ReadInt32();
/* score.FileChecksum = */
var beatmapHash = sr.ReadString();
score.Beatmap = beatmaps.QueryBeatmap(b => b.MD5Hash == beatmapHash);
/* 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 = createLegacyReplay(reader);
score.Replay.User = score.User;
}
}
}
return score;
return new LegacyScoreParser(rulesets, beatmaps).Parse(s);
}
/// <summary>
/// Creates a legacy replay which is read from a stream.
/// </summary>
/// <param name="reader">The stream reader.</param>
/// <returns>The legacy replay.</returns>
private Replay createLegacyReplay(StreamReader reader)
{
var frames = new List<ReplayFrame>();
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;
frames.Add(new ReplayFrame(
lastTime,
float.Parse(split[1]),
float.Parse(split[2]),
(ReplayButtonState)int.Parse(split[3])
));
}
return new Replay { Frames = frames };
}
}
}