From 9b4bc3e36de15b43b7bf5c82f1a1f4b17101d769 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 7 Oct 2016 16:19:24 -0400 Subject: [PATCH] Implement most of the legacy beatmap decoder Missing timing points, events, and hit object decoders remain to be written --- .../Beatmaps/IO/OszArchiveReaderTest.cs | 13 ++++ osu.Game/Beatmaps/Beatmap.cs | 33 ++++++++ osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 75 ++++++++++++++++--- osu.Game/Beatmaps/Objects/HitObject.cs | 13 ++++ osu.Game/Beatmaps/Objects/Osu/OsuBaseHit.cs | 5 ++ 5 files changed, 128 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs index 502f410951..779fbff6ba 100644 --- a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs @@ -62,6 +62,19 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.AreEqual("Renatus", meta.Title); Assert.AreEqual("Renatus", meta.TitleUnicode); } + } + [Test] + public void TestReadFile() + { + using (var osz = File.OpenRead(Resource.GetPath("241526 Soleily - Renatus.osz"))) + { + var reader = new OszArchiveReader(osz); + using (var stream = new StreamReader( + reader.ReadFile("Soleily - Renatus (Deif) [Platter].osu"))) + { + Assert.AreEqual("osu file format v13", stream.ReadLine().Trim()); + } + } } } } diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 2c96f62988..c1f3d7f744 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -2,7 +2,9 @@ //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using System.Linq; using osu.Game.Beatmaps.Objects; +using osu.Game.Beatmaps.Samples; using osu.Game.Beatmaps.Timing; using osu.Game.GameModes.Play; using osu.Game.Users; @@ -27,7 +29,38 @@ namespace osu.Game.Beatmaps public BeatmapMetadata Metadata { get; set; } [Ignore] public BaseDifficulty BaseDifficulty { get; set; } + + // General + public int AudioLeadIn { get; set; } + public bool Countdown { get; set; } + public SampleSet SampleSet { get; set; } + public float StackLeniency { get; set; } + public bool SpecialStyle { get; set; } public PlayMode Mode { get; set; } + public bool LetterboxInBreaks { get; set; } + public bool WidescreenStoryboard { get; set; } + + // Editor + // This bookmarks stuff is necessary because DB doesn't know how to store int[] + public string StoredBookmarks { get; internal set; } + [Ignore] + public int[] Bookmarks + { + get + { + return StoredBookmarks.Split(',').Select(b => int.Parse(b)).ToArray(); + } + set + { + StoredBookmarks = string.Join(",", value); + } + } + public double DistanceSpacing { get; set; } + public int BeatDivisor { get; set; } + public int GridSize { get; set; } + public double TimelineZoom { get; set; } + + // Metadata public string Version { get; set; } } } \ No newline at end of file diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index cf01b751a9..f027c404e4 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using osu.Game.Beatmaps.Events; using osu.Game.Beatmaps.Objects; +using osu.Game.Beatmaps.Samples; using osu.Game.Beatmaps.Timing; using osu.Game.GameModes.Play; @@ -41,31 +42,53 @@ namespace osu.Game.Beatmaps.Formats beatmap.Metadata.AudioFile = val; break; case "AudioLeadIn": - // TODO + beatmap.AudioLeadIn = int.Parse(val); break; case "PreviewTime": beatmap.Metadata.PreviewTime = int.Parse(val); break; case "Countdown": - // TODO + beatmap.Countdown = int.Parse(val) == 1; break; case "SampleSet": - // TODO + beatmap.SampleSet = (SampleSet)Enum.Parse(typeof(SampleSet), val); break; case "StackLeniency": - // TODO + beatmap.StackLeniency = float.Parse(val); break; case "Mode": beatmap.Mode = (PlayMode)int.Parse(val); break; case "LetterboxInBreaks": - // TODO + beatmap.LetterboxInBreaks = int.Parse(val) == 1; break; case "SpecialStyle": - // TODO + beatmap.SpecialStyle = int.Parse(val) == 1; break; case "WidescreenStoryboard": - // TODO + beatmap.WidescreenStoryboard = int.Parse(val) == 1; + break; + } + } + + private void HandleEditor(Beatmap beatmap, string key, string val) + { + switch (key) + { + case "Bookmarks": + beatmap.StoredBookmarks = val; + break; + case "DistanceSpacing": + beatmap.DistanceSpacing = double.Parse(val); + break; + case "BeatDivisor": + beatmap.BeatDivisor = int.Parse(val); + break; + case "GridSize": + beatmap.GridSize = int.Parse(val); + break; + case "TimelineZoom": + beatmap.TimelineZoom = double.Parse(val); break; } } @@ -108,6 +131,31 @@ namespace osu.Game.Beatmaps.Formats } } + private void HandleDifficulty(Beatmap beatmap, string key, string val) + { + switch (key) + { + case "HPDrainRate": + beatmap.BaseDifficulty.DrainRate = float.Parse(val); + break; + case "CircleSize": + beatmap.BaseDifficulty.CircleSize = float.Parse(val); + break; + case "OverallDifficulty": + beatmap.BaseDifficulty.OverallDifficulty = float.Parse(val); + break; + case "ApproachRate": + beatmap.BaseDifficulty.ApproachRate = float.Parse(val); + break; + case "SliderMultiplier": + beatmap.BaseDifficulty.SliderMultiplier = float.Parse(val); + break; + case "SliderTickRate": + beatmap.BaseDifficulty.SliderTickRate = float.Parse(val); + break; + } + } + private void HandleEvents(Beatmap beatmap, string val) { if (val.StartsWith("//")) @@ -127,6 +175,11 @@ namespace osu.Game.Beatmaps.Formats beatmap.Metadata.BackgroundFile = split[2].Trim('"'); } + private void HandleTimingPoints(Beatmap beatmap, string val) + { + // TODO + } + public override Beatmap Decode(TextReader stream) { var beatmap = new Beatmap @@ -167,22 +220,22 @@ namespace osu.Game.Beatmaps.Formats HandleGeneral(beatmap, key, val); break; case Section.Editor: - // TODO + HandleEditor(beatmap, key, val); break; case Section.Metadata: HandleMetadata(beatmap, key, val); break; case Section.Difficulty: - // TODO + HandleDifficulty(beatmap, key, val); break; case Section.Events: HandleEvents(beatmap, val); break; case Section.TimingPoints: - // TODO + HandleTimingPoints(beatmap, val); break; case Section.HitObjects: - // TODO + beatmap.HitObjects.Add(HitObject.Parse(beatmap.Mode, val)); break; } } diff --git a/osu.Game/Beatmaps/Objects/HitObject.cs b/osu.Game/Beatmaps/Objects/HitObject.cs index 74636d0a6f..ffa5e8e6ff 100644 --- a/osu.Game/Beatmaps/Objects/HitObject.cs +++ b/osu.Game/Beatmaps/Objects/HitObject.cs @@ -1,7 +1,9 @@ //Copyright (c) 2007-2016 ppy Pty Ltd . //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Beatmaps.Objects.Osu; using osu.Game.Beatmaps.Samples; +using osu.Game.GameModes.Play; namespace osu.Game.Beatmaps.Objects { @@ -16,5 +18,16 @@ namespace osu.Game.Beatmaps.Objects public double Duration => (EndTime ?? StartTime) - StartTime; public HitSampleInfo Sample; + + public static HitObject Parse(PlayMode mode, string val) + { + switch (mode) + { + case PlayMode.Osu: + return OsuBaseHit.Parse(val); + default: + return null; + } + } } } diff --git a/osu.Game/Beatmaps/Objects/Osu/OsuBaseHit.cs b/osu.Game/Beatmaps/Objects/Osu/OsuBaseHit.cs index 8224bb7dc9..0edf3909d4 100644 --- a/osu.Game/Beatmaps/Objects/Osu/OsuBaseHit.cs +++ b/osu.Game/Beatmaps/Objects/Osu/OsuBaseHit.cs @@ -8,5 +8,10 @@ namespace osu.Game.Beatmaps.Objects.Osu public abstract class OsuBaseHit : HitObject { public Vector2 Position; + + public static OsuBaseHit Parse(string val) + { + return null; + } } }