2017-03-04 10:02:36 +00:00
|
|
|
|
// Copyright (c) 2007-2017 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.Framework.Platform;
|
|
|
|
|
using osu.Game.IO.Legacy;
|
|
|
|
|
using osu.Game.IPC;
|
|
|
|
|
using osu.Game.Modes;
|
|
|
|
|
using SharpCompress.Compressors.LZMA;
|
|
|
|
|
|
|
|
|
|
namespace osu.Game.Database
|
|
|
|
|
{
|
|
|
|
|
public class ScoreDatabase
|
|
|
|
|
{
|
|
|
|
|
private readonly Storage storage;
|
|
|
|
|
private readonly BeatmapDatabase beatmaps;
|
|
|
|
|
|
|
|
|
|
private const string replay_folder = @"replays";
|
|
|
|
|
|
|
|
|
|
private ScoreIPCChannel ipc;
|
|
|
|
|
|
|
|
|
|
public ScoreDatabase(Storage storage, IIpcHost importHost = null, BeatmapDatabase beatmaps = null)
|
|
|
|
|
{
|
|
|
|
|
this.storage = storage;
|
|
|
|
|
this.beatmaps = beatmaps;
|
|
|
|
|
|
|
|
|
|
if (importHost != null)
|
|
|
|
|
ipc = new ScoreIPCChannel(importHost, this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Score ReadReplayFile(string replayFilename)
|
|
|
|
|
{
|
|
|
|
|
Score score;
|
|
|
|
|
|
|
|
|
|
using (Stream s = storage.GetStream(Path.Combine(replay_folder, replayFilename)))
|
|
|
|
|
using (SerializationReader sr = new SerializationReader(s))
|
|
|
|
|
{
|
|
|
|
|
var ruleset = Ruleset.GetRuleset((PlayMode)sr.ReadByte());
|
|
|
|
|
var processor = ruleset.CreateScoreProcessor();
|
|
|
|
|
|
|
|
|
|
score = processor.GetScore();
|
|
|
|
|
|
|
|
|
|
/* score.Pass = true;*/
|
|
|
|
|
var version = sr.ReadInt32();
|
|
|
|
|
/* score.FileChecksum = */
|
|
|
|
|
var beatmapHash = sr.ReadString();
|
|
|
|
|
score.Beatmap = beatmaps.Query<BeatmapInfo>().Where(b => b.Hash == beatmapHash).FirstOrDefault();
|
|
|
|
|
/* score.PlayerName = */
|
|
|
|
|
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)
|
2017-03-09 05:00:17 +00:00
|
|
|
|
throw new Exception("input .lzma is too short");
|
2017-03-04 10:02:36 +00:00
|
|
|
|
long outSize = 0;
|
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
|
|
|
{
|
|
|
|
|
int v = replayInStream.ReadByte();
|
|
|
|
|
if (v < 0)
|
2017-03-09 05:00:17 +00:00
|
|
|
|
throw new Exception("Can't Read 1");
|
|
|
|
|
outSize |= (long)(byte)v << (8 * i);
|
2017-03-04 10:02:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
long compressedSize = replayInStream.Length - replayInStream.Position;
|
|
|
|
|
|
|
|
|
|
using (var lzma = new LzmaStream(properties, replayInStream, compressedSize, outSize))
|
|
|
|
|
using (var reader = new StreamReader(lzma))
|
|
|
|
|
score.Replay = new LegacyReplay(reader);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return score;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|