1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 17:32:54 +08:00

Split retrieving of beatmap and storyboard decoder

Storyboard works again. Not satisfied with the solution though.
This commit is contained in:
Aergwyn 2017-12-01 19:11:52 +01:00
parent db50ad794e
commit a49f3479a2
9 changed files with 151 additions and 104 deletions

View File

@ -50,7 +50,7 @@ namespace osu.Game.Tests.Beatmaps.IO
BeatmapMetadata meta; BeatmapMetadata meta;
using (var stream = new StreamReader(reader.GetStream("Soleily - Renatus (Deif) [Platter].osu"))) using (var stream = new StreamReader(reader.GetStream("Soleily - Renatus (Deif) [Platter].osu")))
meta = BeatmapDecoder.GetDecoder(stream).DecodeBeatmap(stream).Metadata; meta = Decoder.GetBeatmapDecoder(stream).DecodeBeatmap(stream).Metadata;
Assert.AreEqual(241526, meta.OnlineBeatmapSetID); Assert.AreEqual(241526, meta.OnlineBeatmapSetID);
Assert.AreEqual("Soleily", meta.Artist); Assert.AreEqual("Soleily", meta.Artist);

View File

@ -495,7 +495,7 @@ namespace osu.Game.Beatmaps
BeatmapMetadata metadata; BeatmapMetadata metadata;
using (var stream = new StreamReader(reader.GetStream(mapName))) using (var stream = new StreamReader(reader.GetStream(mapName)))
metadata = BeatmapDecoder.GetDecoder(stream).DecodeBeatmap(stream).Metadata; metadata = Decoder.GetBeatmapDecoder(stream).DecodeBeatmap(stream).Metadata;
// check if a set already exists with the same online id. // check if a set already exists with the same online id.
beatmapSet = beatmaps.BeatmapSets.FirstOrDefault(b => b.OnlineBeatmapSetID == metadata.OnlineBeatmapSetID) ?? new BeatmapSetInfo beatmapSet = beatmaps.BeatmapSets.FirstOrDefault(b => b.OnlineBeatmapSetID == metadata.OnlineBeatmapSetID) ?? new BeatmapSetInfo
@ -518,7 +518,7 @@ namespace osu.Game.Beatmaps
raw.CopyTo(ms); raw.CopyTo(ms);
ms.Position = 0; ms.Position = 0;
var decoder = BeatmapDecoder.GetDecoder(sr); var decoder = Decoder.GetBeatmapDecoder(sr);
Beatmap beatmap = decoder.DecodeBeatmap(sr); Beatmap beatmap = decoder.DecodeBeatmap(sr);
beatmap.BeatmapInfo.Path = name; beatmap.BeatmapInfo.Path = name;
@ -571,7 +571,7 @@ namespace osu.Game.Beatmaps
{ {
using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path)))) using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path))))
{ {
BeatmapDecoder decoder = BeatmapDecoder.GetDecoder(stream); Decoder decoder = Decoder.GetBeatmapDecoder(stream);
return decoder.DecodeBeatmap(stream); return decoder.DecodeBeatmap(stream);
} }
} }
@ -620,9 +620,9 @@ namespace osu.Game.Beatmaps
try try
{ {
BeatmapDecoder decoder; Decoder decoder;
using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path)))) using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path))))
decoder = BeatmapDecoder.GetDecoder(stream); decoder = Decoder.GetStoryboardDecoder(stream);
using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapSetInfo.StoryboardFile)))) using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapSetInfo.StoryboardFile))))
return decoder.DecodeStoryboard(stream); return decoder.DecodeStoryboard(stream);

View File

@ -1,67 +0,0 @@
// 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.Collections.Generic;
using System.IO;
using osu.Game.Storyboards;
namespace osu.Game.Beatmaps.Formats
{
public abstract class BeatmapDecoder
{
private static readonly Dictionary<string, Type> decoders = new Dictionary<string, Type>();
static BeatmapDecoder()
{
LegacyDecoder.Register();
}
public static BeatmapDecoder GetDecoder(StreamReader stream)
{
if (stream == null)
throw new ArgumentNullException(nameof(stream));
string line;
do { line = stream.ReadLine()?.Trim(); }
while (line != null && line.Length == 0);
if (line == null || !decoders.ContainsKey(line))
throw new IOException(@"Unknown file format");
return (BeatmapDecoder)Activator.CreateInstance(decoders[line], line);
}
protected static void AddDecoder<T>(string magic) where T : BeatmapDecoder
{
decoders[magic] = typeof(T);
}
public virtual Beatmap DecodeBeatmap(StreamReader stream) => ParseBeatmap(stream);
protected virtual Beatmap ParseBeatmap(StreamReader stream)
{
var beatmap = new Beatmap
{
BeatmapInfo = new BeatmapInfo
{
Metadata = new BeatmapMetadata(),
BaseDifficulty = new BeatmapDifficulty(),
},
};
ParseBeatmap(stream, beatmap);
return beatmap;
}
protected abstract void ParseBeatmap(StreamReader stream, Beatmap beatmap);
public virtual Storyboard DecodeStoryboard(StreamReader stream)
{
var storyboard = new Storyboard();
ParseStoryboard(stream, storyboard);
return storyboard;
}
protected abstract void ParseStoryboard(StreamReader stream, Storyboard storyboard);
}
}

View File

@ -0,0 +1,120 @@
// 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.Collections.Generic;
using System.IO;
using osu.Game.Storyboards;
namespace osu.Game.Beatmaps.Formats
{
public abstract class Decoder
{
private static readonly Dictionary<string, Type> beatmapDecoders = new Dictionary<string, Type>();
private static readonly Dictionary<string, Type> storyboardDecoders = new Dictionary<string, Type>();
static Decoder()
{
LegacyDecoder.Register();
}
/// <summary>
/// Retrieves a <see cref="Decoder"/> to parse <see cref="Beatmap"/>s.
/// </summary>
/// <param name="stream">A stream pointing to the <see cref="Beatmap"/> to retrieve the version from.</param>
public static Decoder GetBeatmapDecoder(StreamReader stream)
{
string line = readFirstLine(stream);
if (line == null || !beatmapDecoders.ContainsKey(line))
throw new IOException(@"Unknown file format");
return (Decoder)Activator.CreateInstance(beatmapDecoders[line], line);
}
/// <summary>
/// Retrieves a <see cref="Decoder"/> to parse <see cref="Storyboard"/>s.
/// </summary>
/// <param name="stream">A stream pointing to the <see cref="Beatmap"/> to retrieve the version from.</param>
public static Decoder GetStoryboardDecoder(StreamReader stream)
{
string line = readFirstLine(stream);
if (line == null || !storyboardDecoders.ContainsKey(line))
throw new IOException(@"Unknown file format");
return (Decoder)Activator.CreateInstance(storyboardDecoders[line], line);
}
private static string readFirstLine(StreamReader stream)
{
if (stream == null)
throw new ArgumentNullException(nameof(stream));
string line;
do
{ line = stream.ReadLine()?.Trim(); }
while (line != null && line.Length == 0);
return line;
}
/// <summary>
/// Adds the <see cref="Decoder"/> to the list of <see cref="Beatmap"/> and <see cref="Storyboard"/> decoder.
/// </summary>
/// <typeparam name="A">Type to decode a <see cref="Beatmap"/> with.</typeparam>
/// /// <typeparam name="B">Type to decode a <see cref="Storyboard"/> with.</typeparam>
/// <param name="version">A string representation of the version.</param>
protected static void AddDecoder<A, B>(string version) where A : Decoder where B : Decoder
{
beatmapDecoders[version] = typeof(A);
storyboardDecoders[version] = typeof(B);
}
/// <summary>
/// Adds the <see cref="Decoder"/> to the list of <see cref="Beatmap"/> decoder.
/// </summary>
/// <typeparam name="T">Type to decode a <see cref="Beatmap"/> with.</typeparam>
/// <param name="version">A string representation of the version.</param>
protected static void AddBeatmapDecoder<T>(string version) where T : Decoder
{
beatmapDecoders[version] = typeof(T);
}
/// <summary>
/// Adds the <see cref="Decoder"/> to the list of <see cref="Storyboard"/> decoder.
/// </summary>
/// <typeparam name="T">Type to decode a <see cref="Storyboard"/> with.</typeparam>
/// <param name="version">A string representation of the version.</param>
protected static void AddStoryboardDecoder<T>(string version) where T : Decoder
{
storyboardDecoders[version] = typeof(T);
}
public virtual Beatmap DecodeBeatmap(StreamReader stream) => ParseBeatmap(stream);
protected virtual Beatmap ParseBeatmap(StreamReader stream)
{
var beatmap = new Beatmap
{
BeatmapInfo = new BeatmapInfo
{
Metadata = new BeatmapMetadata(),
BaseDifficulty = new BeatmapDifficulty(),
},
};
ParseBeatmap(stream, beatmap);
return beatmap;
}
protected abstract void ParseBeatmap(StreamReader stream, Beatmap beatmap);
public virtual Storyboard DecodeStoryboard(StreamReader stream)
{
var storyboard = new Storyboard();
ParseStoryboard(stream, storyboard);
return storyboard;
}
protected abstract void ParseStoryboard(StreamReader stream, Storyboard storyboard);
}
}

View File

@ -20,6 +20,15 @@ namespace osu.Game.Beatmaps.Formats
private LegacySampleBank defaultSampleBank; private LegacySampleBank defaultSampleBank;
private int defaultSampleVolume = 100; private int defaultSampleVolume = 100;
public LegacyBeatmapDecoder()
{
}
public LegacyBeatmapDecoder(string header)
{
BeatmapVersion = int.Parse(header.Substring(17));
}
protected override void ProcessSection(Section section, string line) protected override void ProcessSection(Section section, string line)
{ {
switch (section) switch (section)

View File

@ -9,34 +9,25 @@ using osu.Game.Storyboards;
namespace osu.Game.Beatmaps.Formats namespace osu.Game.Beatmaps.Formats
{ {
public class LegacyDecoder : BeatmapDecoder public abstract class LegacyDecoder : Decoder
{ {
public static void Register() public static void Register()
{ {
AddDecoder<LegacyBeatmapDecoder>(@"osu file format v14"); AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v14");
AddDecoder<LegacyBeatmapDecoder>(@"osu file format v13"); AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v13");
AddDecoder<LegacyBeatmapDecoder>(@"osu file format v12"); AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v12");
AddDecoder<LegacyBeatmapDecoder>(@"osu file format v11"); AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v11");
AddDecoder<LegacyBeatmapDecoder>(@"osu file format v10"); AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v10");
AddDecoder<LegacyBeatmapDecoder>(@"osu file format v9"); AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v9");
AddDecoder<LegacyBeatmapDecoder>(@"osu file format v8"); AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v8");
AddDecoder<LegacyBeatmapDecoder>(@"osu file format v7"); AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v7");
AddDecoder<LegacyBeatmapDecoder>(@"osu file format v6"); AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v6");
AddDecoder<LegacyBeatmapDecoder>(@"osu file format v5"); AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v5");
AddDecoder<LegacyBeatmapDecoder>(@"osu file format v4"); AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v4");
AddDecoder<LegacyBeatmapDecoder>(@"osu file format v3"); AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v3");
// TODO: differences between versions // TODO: differences between versions
} }
public LegacyDecoder()
{
}
public LegacyDecoder(string header)
{
BeatmapVersion = int.Parse(header.Substring(17));
}
protected Beatmap Beatmap; protected Beatmap Beatmap;
protected Storyboard Storyboard; protected Storyboard Storyboard;
@ -105,10 +96,7 @@ namespace osu.Game.Beatmaps.Formats
} }
} }
protected virtual void ProcessSection(Section section, string line) protected abstract void ProcessSection(Section section, string line);
{
}
/// <summary> /// <summary>
/// Decodes any beatmap variables present in a line into their real values. /// Decodes any beatmap variables present in a line into their real values.

View File

@ -4,9 +4,6 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Framework.Graphics; using osu.Framework.Graphics;

View File

@ -63,7 +63,7 @@ namespace osu.Game.Tests.Visual
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(test_beatmap_data))) using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(test_beatmap_data)))
using (var reader = new StreamReader(stream)) using (var reader = new StreamReader(stream))
beatmap = BeatmapDecoder.GetDecoder(reader).DecodeBeatmap(reader); beatmap = Game.Beatmaps.Formats.Decoder.GetBeatmapDecoder(reader).DecodeBeatmap(reader);
return beatmap; return beatmap;
} }

View File

@ -313,7 +313,7 @@
<Compile Include="Beatmaps\Drawables\DifficultyIcon.cs" /> <Compile Include="Beatmaps\Drawables\DifficultyIcon.cs" />
<Compile Include="Beatmaps\Drawables\Panel.cs" /> <Compile Include="Beatmaps\Drawables\Panel.cs" />
<Compile Include="Beatmaps\DummyWorkingBeatmap.cs" /> <Compile Include="Beatmaps\DummyWorkingBeatmap.cs" />
<Compile Include="Beatmaps\Formats\BeatmapDecoder.cs" /> <Compile Include="Beatmaps\Formats\Decoder.cs" />
<Compile Include="Beatmaps\Formats\LegacyBeatmapDecoder.cs" /> <Compile Include="Beatmaps\Formats\LegacyBeatmapDecoder.cs" />
<Compile Include="Beatmaps\IO\ArchiveReader.cs" /> <Compile Include="Beatmaps\IO\ArchiveReader.cs" />
<Compile Include="Beatmaps\IO\LegacyFilesystemReader.cs" /> <Compile Include="Beatmaps\IO\LegacyFilesystemReader.cs" />