mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 21:02:55 +08:00
Merge branch 'refs/heads/db-refactor' into general-fixes
This commit is contained in:
commit
0e9a155be5
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -5,7 +5,7 @@
|
||||
"name": "Launch",
|
||||
"type": "mono",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/osu.Desktop.VisualTests/bin/Debug/osu!.exe",
|
||||
"program": "${workspaceRoot}/osu.Desktop/bin/Debug/osu!.exe",
|
||||
"args": [],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "",
|
||||
|
@ -5,6 +5,7 @@ using System.Linq;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using osu.Game.Beatmaps.IO;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Desktop.Beatmaps.IO
|
||||
{
|
||||
@ -31,8 +32,7 @@ namespace osu.Desktop.Beatmaps.IO
|
||||
using (var stream = new StreamReader(ReadFile(beatmaps[0])))
|
||||
{
|
||||
var decoder = BeatmapDecoder.GetDecoder(stream);
|
||||
firstMap = new Beatmap();
|
||||
decoder.Decode(stream, firstMap);
|
||||
firstMap = decoder.Decode(stream);
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,11 +48,12 @@ namespace osu.Desktop.Beatmaps.IO
|
||||
|
||||
public override BeatmapMetadata ReadMetadata()
|
||||
{
|
||||
return firstMap.Metadata;
|
||||
return firstMap.BeatmapInfo.Metadata;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
// no-op
|
||||
}
}
|
||||
}
|
||||
}
|
||||
}
|
@ -26,9 +26,8 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
var decoder = new OsuLegacyDecoder();
|
||||
using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||
{
|
||||
Beatmap beatmap = new Beatmap();
|
||||
decoder.Decode(new StreamReader(stream), beatmap);
|
||||
var meta = beatmap.Metadata;
|
||||
var beatmap = decoder.Decode(new StreamReader(stream));
|
||||
var meta = beatmap.BeatmapInfo.Metadata;
|
||||
Assert.AreEqual(241526, meta.BeatmapSetID);
|
||||
Assert.AreEqual("Soleily", meta.Artist);
|
||||
Assert.AreEqual("Soleily", meta.ArtistUnicode);
|
||||
@ -49,16 +48,15 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
var decoder = new OsuLegacyDecoder();
|
||||
using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||
{
|
||||
Beatmap beatmap = new Beatmap();
|
||||
decoder.Decode(new StreamReader(stream), beatmap);
|
||||
Assert.AreEqual(0, beatmap.AudioLeadIn);
|
||||
Assert.AreEqual(false, beatmap.Countdown);
|
||||
Assert.AreEqual(SampleSet.Soft, beatmap.SampleSet);
|
||||
Assert.AreEqual(0.7f, beatmap.StackLeniency);
|
||||
Assert.AreEqual(false, beatmap.SpecialStyle);
|
||||
Assert.AreEqual(PlayMode.Osu, beatmap.Mode);
|
||||
Assert.AreEqual(false, beatmap.LetterboxInBreaks);
|
||||
Assert.AreEqual(false, beatmap.WidescreenStoryboard);
|
||||
var beatmapInfo = decoder.Decode(new StreamReader(stream)).BeatmapInfo;
|
||||
Assert.AreEqual(0, beatmapInfo.AudioLeadIn);
|
||||
Assert.AreEqual(false, beatmapInfo.Countdown);
|
||||
Assert.AreEqual(SampleSet.Soft, beatmapInfo.SampleSet);
|
||||
Assert.AreEqual(0.7f, beatmapInfo.StackLeniency);
|
||||
Assert.AreEqual(false, beatmapInfo.SpecialStyle);
|
||||
Assert.AreEqual(PlayMode.Osu, beatmapInfo.Mode);
|
||||
Assert.AreEqual(false, beatmapInfo.LetterboxInBreaks);
|
||||
Assert.AreEqual(false, beatmapInfo.WidescreenStoryboard);
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,8 +66,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
var decoder = new OsuLegacyDecoder();
|
||||
using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||
{
|
||||
Beatmap beatmap = new Beatmap();
|
||||
decoder.Decode(new StreamReader(stream), beatmap);
|
||||
var beatmap = decoder.Decode(new StreamReader(stream)).BeatmapInfo;
|
||||
int[] expectedBookmarks =
|
||||
{
|
||||
11505, 22054, 32604, 43153, 53703, 64252, 74802, 85351,
|
||||
@ -92,9 +89,8 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
var decoder = new OsuLegacyDecoder();
|
||||
using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||
{
|
||||
Beatmap beatmap = new Beatmap();
|
||||
decoder.Decode(new StreamReader(stream), beatmap);
|
||||
var difficulty = beatmap.BaseDifficulty;
|
||||
var beatmap = decoder.Decode(new StreamReader(stream));
|
||||
var difficulty = beatmap.BeatmapInfo.BaseDifficulty;
|
||||
Assert.AreEqual(6.5f, difficulty.DrainRate);
|
||||
Assert.AreEqual(4, difficulty.CircleSize);
|
||||
Assert.AreEqual(8, difficulty.OverallDifficulty);
|
||||
@ -110,8 +106,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
var decoder = new OsuLegacyDecoder();
|
||||
using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||
{
|
||||
Beatmap beatmap = new Beatmap();
|
||||
decoder.Decode(new StreamReader(stream), beatmap);
|
||||
var beatmap = decoder.Decode(new StreamReader(stream));
|
||||
Color4[] expected =
|
||||
{
|
||||
new Color4(142, 199, 255, 255),
|
||||
@ -132,8 +127,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
var decoder = new OsuLegacyDecoder();
|
||||
using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||
{
|
||||
Beatmap beatmap = new Beatmap();
|
||||
decoder.Decode(new StreamReader(stream), beatmap);
|
||||
var beatmap = decoder.Decode(new StreamReader(stream));
|
||||
var slider = beatmap.HitObjects[0] as Slider;
|
||||
Assert.IsNotNull(slider);
|
||||
Assert.AreEqual(new Vector2(192, 168), slider.Position);
|
||||
|
@ -1,69 +1,20 @@
|
||||
//Copyright (c) 2007-2016 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.Linq;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Beatmaps.Objects;
|
||||
using osu.Game.Beatmaps.Samples;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using osu.Game.GameModes.Play;
|
||||
using osu.Game.Users;
|
||||
using SQLite;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
{
|
||||
public class Beatmap
|
||||
{
|
||||
[PrimaryKey]
|
||||
public int BeatmapID { get; set; }
|
||||
[NotNull, Indexed]
|
||||
public int BeatmapSetID { get; set; }
|
||||
[Indexed]
|
||||
public int BeatmapMetadataID { get; set; }
|
||||
public int BaseDifficultyID { get; set; }
|
||||
[Ignore]
|
||||
public BeatmapInfo BeatmapInfo { get; set; }
|
||||
public List<HitObject> HitObjects { get; set; }
|
||||
[Ignore]
|
||||
public List<ControlPoint> ControlPoints { get; set; }
|
||||
[Ignore]
|
||||
public BeatmapMetadata Metadata { get; set; }
|
||||
[Ignore]
|
||||
public BaseDifficulty BaseDifficulty { get; set; }
|
||||
[Ignore]
|
||||
public List<Color4> ComboColors { 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; }
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Users;
|
||||
using SQLite;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
{
|
||||
/// <summary>
|
||||
/// A beatmap set contains multiple beatmap (difficulties).
|
||||
/// </summary>
|
||||
public class BeatmapSet
|
||||
{
|
||||
[PrimaryKey]
|
||||
public int BeatmapSetID { get; set; }
|
||||
[NotNull, Indexed]
|
||||
public int BeatmapMetadataID { get; set; }
|
||||
[Ignore]
|
||||
public List<Beatmap> Beatmaps { get; protected set; } = new List<Beatmap>();
|
||||
[Ignore]
|
||||
public BeatmapMetadata Metadata { get; set; }
|
||||
[Ignore]
|
||||
public User Creator { get; set; }
|
||||
public string Hash { get; set; }
|
||||
public string Path { get; set; }
|
||||
}
|
||||
}
|
@ -15,11 +15,12 @@ namespace osu.Game.Beatmaps.Formats
|
||||
throw new IOException(@"Unknown file format");
|
||||
return (BeatmapDecoder)Activator.CreateInstance(decoders[line]);
|
||||
}
|
||||
protected static void AddDecoder<T>(string magic) where T : BeatmapDecoder
|
||||
|
||||
protected static void AddDecoder<T>(string magic) where T : BeatmapDecoder
|
||||
{
|
||||
decoders[magic] = typeof(T);
|
||||
}
|
||||
|
||||
public abstract void Decode(TextReader stream, Beatmap beatmap);
|
||||
public abstract Beatmap Decode(TextReader stream);
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Beatmaps.Events;
|
||||
using osu.Game.Beatmaps.Objects;
|
||||
using osu.Game.Beatmaps.Samples;
|
||||
@ -38,37 +39,38 @@ namespace osu.Game.Beatmaps.Formats
|
||||
|
||||
private void handleGeneral(Beatmap beatmap, string key, string val)
|
||||
{
|
||||
var metadata = beatmap.BeatmapInfo.Metadata;
|
||||
switch (key)
|
||||
{
|
||||
case @"AudioFilename":
|
||||
beatmap.Metadata.AudioFile = val;
|
||||
metadata.AudioFile = val;
|
||||
break;
|
||||
case @"AudioLeadIn":
|
||||
beatmap.AudioLeadIn = int.Parse(val);
|
||||
beatmap.BeatmapInfo.AudioLeadIn = int.Parse(val);
|
||||
break;
|
||||
case @"PreviewTime":
|
||||
beatmap.Metadata.PreviewTime = int.Parse(val);
|
||||
metadata.PreviewTime = int.Parse(val);
|
||||
break;
|
||||
case @"Countdown":
|
||||
beatmap.Countdown = int.Parse(val) == 1;
|
||||
beatmap.BeatmapInfo.Countdown = int.Parse(val) == 1;
|
||||
break;
|
||||
case @"SampleSet":
|
||||
beatmap.SampleSet = (SampleSet)Enum.Parse(typeof(SampleSet), val);
|
||||
beatmap.BeatmapInfo.SampleSet = (SampleSet)Enum.Parse(typeof(SampleSet), val);
|
||||
break;
|
||||
case @"StackLeniency":
|
||||
beatmap.StackLeniency = float.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
beatmap.BeatmapInfo.StackLeniency = float.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case @"Mode":
|
||||
beatmap.Mode = (PlayMode)int.Parse(val);
|
||||
beatmap.BeatmapInfo.Mode = (PlayMode)int.Parse(val);
|
||||
break;
|
||||
case @"LetterboxInBreaks":
|
||||
beatmap.LetterboxInBreaks = int.Parse(val) == 1;
|
||||
beatmap.BeatmapInfo.LetterboxInBreaks = int.Parse(val) == 1;
|
||||
break;
|
||||
case @"SpecialStyle":
|
||||
beatmap.SpecialStyle = int.Parse(val) == 1;
|
||||
beatmap.BeatmapInfo.SpecialStyle = int.Parse(val) == 1;
|
||||
break;
|
||||
case @"WidescreenStoryboard":
|
||||
beatmap.WidescreenStoryboard = int.Parse(val) == 1;
|
||||
beatmap.BeatmapInfo.WidescreenStoryboard = int.Parse(val) == 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -78,82 +80,84 @@ namespace osu.Game.Beatmaps.Formats
|
||||
switch (key)
|
||||
{
|
||||
case @"Bookmarks":
|
||||
beatmap.StoredBookmarks = val;
|
||||
beatmap.BeatmapInfo.StoredBookmarks = val;
|
||||
break;
|
||||
case @"DistanceSpacing":
|
||||
beatmap.DistanceSpacing = double.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
beatmap.BeatmapInfo.DistanceSpacing = double.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case @"BeatDivisor":
|
||||
beatmap.BeatDivisor = int.Parse(val);
|
||||
beatmap.BeatmapInfo.BeatDivisor = int.Parse(val);
|
||||
break;
|
||||
case @"GridSize":
|
||||
beatmap.GridSize = int.Parse(val);
|
||||
beatmap.BeatmapInfo.GridSize = int.Parse(val);
|
||||
break;
|
||||
case @"TimelineZoom":
|
||||
beatmap.TimelineZoom = double.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
beatmap.BeatmapInfo.TimelineZoom = double.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMetadata(Beatmap beatmap, string key, string val)
|
||||
{
|
||||
var metadata = beatmap.BeatmapInfo.Metadata;
|
||||
switch (key)
|
||||
{
|
||||
case @"Title":
|
||||
beatmap.Metadata.Title = val;
|
||||
metadata.Title = val;
|
||||
break;
|
||||
case @"TitleUnicode":
|
||||
beatmap.Metadata.TitleUnicode = val;
|
||||
metadata.TitleUnicode = val;
|
||||
break;
|
||||
case @"Artist":
|
||||
beatmap.Metadata.Artist = val;
|
||||
metadata.Artist = val;
|
||||
break;
|
||||
case @"ArtistUnicode":
|
||||
beatmap.Metadata.ArtistUnicode = val;
|
||||
metadata.ArtistUnicode = val;
|
||||
break;
|
||||
case @"Creator":
|
||||
beatmap.Metadata.Author = val;
|
||||
metadata.Author = val;
|
||||
break;
|
||||
case @"Version":
|
||||
beatmap.Version = val;
|
||||
beatmap.BeatmapInfo.Version = val;
|
||||
break;
|
||||
case @"Source":
|
||||
beatmap.Metadata.Source = val;
|
||||
beatmap.BeatmapInfo.Metadata.Source = val;
|
||||
break;
|
||||
case @"Tags":
|
||||
beatmap.Metadata.Tags = val;
|
||||
beatmap.BeatmapInfo.Metadata.Tags = val;
|
||||
break;
|
||||
case @"BeatmapID":
|
||||
beatmap.BeatmapID = int.Parse(val);
|
||||
beatmap.BeatmapInfo.BeatmapID = int.Parse(val);
|
||||
break;
|
||||
case @"BeatmapSetID":
|
||||
beatmap.BeatmapSetID = int.Parse(val);
|
||||
beatmap.Metadata.BeatmapSetID = int.Parse(val);
|
||||
beatmap.BeatmapInfo.BeatmapSetID = int.Parse(val);
|
||||
metadata.BeatmapSetID = int.Parse(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDifficulty(Beatmap beatmap, string key, string val)
|
||||
{
|
||||
var difficulty = beatmap.BeatmapInfo.BaseDifficulty;
|
||||
switch (key)
|
||||
{
|
||||
case @"HPDrainRate":
|
||||
beatmap.BaseDifficulty.DrainRate = float.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
difficulty.DrainRate = float.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case @"CircleSize":
|
||||
beatmap.BaseDifficulty.CircleSize = float.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
difficulty.CircleSize = float.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case @"OverallDifficulty":
|
||||
beatmap.BaseDifficulty.OverallDifficulty = float.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
difficulty.OverallDifficulty = float.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case @"ApproachRate":
|
||||
beatmap.BaseDifficulty.ApproachRate = float.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
difficulty.ApproachRate = float.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case @"SliderMultiplier":
|
||||
beatmap.BaseDifficulty.SliderMultiplier = float.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
difficulty.SliderMultiplier = float.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case @"SliderTickRate":
|
||||
beatmap.BaseDifficulty.SliderTickRate = float.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
difficulty.SliderTickRate = float.Parse(val, NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -176,7 +180,7 @@ namespace osu.Game.Beatmaps.Formats
|
||||
type = (EventType)_type;
|
||||
// TODO: Parse and store the rest of the event
|
||||
if (type == EventType.Background)
|
||||
beatmap.Metadata.BackgroundFile = split[2].Trim('"');
|
||||
beatmap.BeatmapInfo.Metadata.BackgroundFile = split[2].Trim('"');
|
||||
}
|
||||
|
||||
private void handleTimingPoints(Beatmap beatmap, string val)
|
||||
@ -202,15 +206,15 @@ namespace osu.Game.Beatmaps.Formats
|
||||
});
|
||||
}
|
||||
|
||||
public override void Decode(TextReader stream, Beatmap beatmap)
|
||||
public override Beatmap Decode(TextReader stream)
|
||||
{
|
||||
// We don't overwrite these two because they're DB bound
|
||||
if (beatmap.Metadata == null) beatmap.Metadata = new BeatmapMetadata();
|
||||
if (beatmap.BaseDifficulty == null) beatmap.BaseDifficulty = new BaseDifficulty();
|
||||
// These are fine though
|
||||
beatmap.HitObjects = new List<HitObject>();
|
||||
beatmap.ControlPoints = new List<ControlPoint>();
|
||||
beatmap.ComboColors = new List<Color4>();
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject>(),
|
||||
ControlPoints = new List<ControlPoint>(),
|
||||
ComboColors = new List<Color4>(),
|
||||
BeatmapInfo = new BeatmapInfo(),
|
||||
};
|
||||
|
||||
var section = Section.None;
|
||||
string line;
|
||||
@ -262,10 +266,12 @@ namespace osu.Game.Beatmaps.Formats
|
||||
handleColours(beatmap, key, val);
|
||||
break;
|
||||
case Section.HitObjects:
|
||||
beatmap.HitObjects.Add(HitObject.Parse(beatmap.Mode, val));
|
||||
beatmap.HitObjects.Add(HitObject.Parse(beatmap.BeatmapInfo.Mode, val));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return beatmap;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Game.Beatmaps.IO
|
||||
{
|
||||
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using Ionic.Zip;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Game.Beatmaps.IO
|
||||
{
|
||||
@ -33,8 +34,7 @@ namespace osu.Game.Beatmaps.IO
|
||||
using (var stream = new StreamReader(ReadFile(beatmaps[0])))
|
||||
{
|
||||
var decoder = BeatmapDecoder.GetDecoder(stream);
|
||||
firstMap = new Beatmap();
|
||||
decoder.Decode(stream, firstMap);
|
||||
firstMap = decoder.Decode(stream);
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,9 +53,10 @@ namespace osu.Game.Beatmaps.IO
|
||||
|
||||
public override BeatmapMetadata ReadMetadata()
|
||||
{
|
||||
return firstMap.Metadata;
|
||||
return firstMap.BeatmapInfo.Metadata;
|
||||
}
|
||||
public override void Dispose()
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
archive.Dispose();
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using SQLite;
|
||||
using SQLite.Net.Attributes;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
public class BaseDifficulty
|
||||
{
|
@ -1,12 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using osu.Game.Beatmaps.IO;
|
||||
using SQLite;
|
||||
using SQLite.Net;
|
||||
using SQLiteNetExtensions.Extensions;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
@ -23,14 +25,18 @@ namespace osu.Game.Database
|
||||
connection = storage.GetDatabase(@"beatmaps");
|
||||
connection.CreateTable<BeatmapMetadata>();
|
||||
connection.CreateTable<BaseDifficulty>();
|
||||
connection.CreateTable<BeatmapSet>();
|
||||
connection.CreateTable<Beatmap>();
|
||||
connection.CreateTable<BeatmapSetInfo>();
|
||||
connection.CreateTable<BeatmapInfo>();
|
||||
}
|
||||
}
|
||||
public void AddBeatmap(string path)
|
||||
|
||||
public void ImportBeatmap(string path)
|
||||
{
|
||||
string hash = null;
|
||||
ArchiveReader reader;
|
||||
var reader = ArchiveReader.GetReader(storage, path);
|
||||
var metadata = reader.ReadMetadata();
|
||||
if (connection.Table<BeatmapSetInfo>().Count(b => b.BeatmapSetID == metadata.BeatmapSetID) != 0)
|
||||
return; // TODO: Update this beatmap instead
|
||||
if (File.Exists(path)) // Not always the case, i.e. for LegacyFilesystemReader
|
||||
{
|
||||
using (var md5 = MD5.Create())
|
||||
@ -41,60 +47,82 @@ namespace osu.Game.Database
|
||||
var outputPath = Path.Combine(@"beatmaps", hash.Remove(1), hash.Remove(2), hash);
|
||||
using (var output = storage.GetStream(outputPath, FileAccess.Write))
|
||||
input.CopyTo(output);
|
||||
reader = ArchiveReader.GetReader(storage, path = outputPath);
|
||||
}
|
||||
}
|
||||
else
|
||||
reader = ArchiveReader.GetReader(storage, path);
|
||||
var metadata = reader.ReadMetadata();
|
||||
if (connection.Table<BeatmapSet>().Count(b => b.BeatmapSetID == metadata.BeatmapSetID) != 0)
|
||||
return; // TODO: Update this beatmap instead
|
||||
string[] mapNames = reader.ReadBeatmaps();
|
||||
var beatmapSet = new BeatmapSet
|
||||
var beatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
BeatmapSetID = metadata.BeatmapSetID,
|
||||
Path = path,
|
||||
Hash = hash,
|
||||
};
|
||||
var maps = new List<Beatmap>();
|
||||
var maps = new List<BeatmapInfo>();
|
||||
foreach (var name in mapNames)
|
||||
{
|
||||
using (var stream = new StreamReader(reader.ReadFile(name)))
|
||||
{
|
||||
var decoder = BeatmapDecoder.GetDecoder(stream);
|
||||
Beatmap beatmap = new Beatmap();
|
||||
decoder.Decode(stream, beatmap);
|
||||
maps.Add(beatmap);
|
||||
beatmap.BaseDifficultyID = connection.Insert(beatmap.BaseDifficulty);
|
||||
Beatmap beatmap = decoder.Decode(stream);
|
||||
beatmap.BeatmapInfo.Path = name;
|
||||
// TODO: Diff beatmap metadata with set metadata and insert if necessary
|
||||
beatmap.BeatmapInfo.Metadata = null;
|
||||
maps.Add(beatmap.BeatmapInfo);
|
||||
connection.Insert(beatmap.BeatmapInfo.BaseDifficulty);
|
||||
connection.Insert(beatmap.BeatmapInfo);
|
||||
connection.UpdateWithChildren(beatmap.BeatmapInfo);
|
||||
}
|
||||
}
|
||||
beatmapSet.BeatmapMetadataID = connection.Insert(metadata);
|
||||
connection.Insert(beatmapSet);
|
||||
connection.InsertAll(maps);
|
||||
beatmapSet.BeatmapMetadataID = connection.Insert(metadata);
|
||||
connection.UpdateWithChildren(beatmapSet);
|
||||
}
|
||||
public ArchiveReader GetReader(BeatmapSet beatmapSet)
|
||||
|
||||
public ArchiveReader GetReader(BeatmapSetInfo beatmapSet)
|
||||
{
|
||||
return ArchiveReader.GetReader(storage, beatmapSet.Path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a BeatmapSet pulled from the database, loads the rest of its data from disk.
|
||||
/// </summary>
public void PopulateBeatmap(BeatmapSet beatmapSet)
|
||||
|
||||
public BeatmapSetInfo GetBeatmapSet(int id)
|
||||
{
|
||||
return Query<BeatmapSetInfo>().Where(s => s.BeatmapSetID == id).FirstOrDefault();
|
||||
}
|
||||
|
||||
public Beatmap GetBeatmap(BeatmapInfo beatmapInfo)
|
||||
{
|
||||
var beatmapSet = Query<BeatmapSetInfo>()
|
||||
.Where(s => s.BeatmapSetID == beatmapInfo.BeatmapSetID).FirstOrDefault();
|
||||
if (beatmapSet == null)
|
||||
throw new InvalidOperationException(
|
||||
$@"Beatmap set {beatmapInfo.BeatmapSetID} is not in the local database.");
|
||||
using (var reader = GetReader(beatmapSet))
|
||||
using (var stream = new StreamReader(reader.ReadFile(beatmapInfo.Path)))
|
||||
{
|
||||
string[] mapNames = reader.ReadBeatmaps();
|
||||
foreach (var name in mapNames)
|
||||
{
|
||||
using (var stream = new StreamReader(reader.ReadFile(name)))
|
||||
{
|
||||
var decoder = BeatmapDecoder.GetDecoder(stream);
|
||||
Beatmap beatmap = new Beatmap();
|
||||
decoder.Decode(stream, beatmap);
|
||||
beatmapSet.Beatmaps.Add(beatmap);
|
||||
}
|
||||
}
|
||||
var decoder = BeatmapDecoder.GetDecoder(stream);
|
||||
return decoder.Decode(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public TableQuery<T> Query<T>() where T : class
|
||||
{
|
||||
return connection.Table<T>();
|
||||
}
|
||||
|
||||
readonly Type[] validTypes = new[]
|
||||
{
|
||||
typeof(BeatmapSetInfo),
|
||||
typeof(BeatmapInfo),
|
||||
typeof(BeatmapMetadata),
|
||||
typeof(BaseDifficulty),
|
||||
};
|
||||
|
||||
public void Update<T>(T record, bool cascade = true) where T : class
|
||||
{
|
||||
if (!validTypes.Any(t => t == typeof(T)))
|
||||
throw new ArgumentException(nameof(T), "Must be a type managed by BeatmapDatabase");
|
||||
if (cascade)
|
||||
connection.UpdateWithChildren(record);
|
||||
else
|
||||
connection.Update(record);
|
||||
}
|
||||
}
|
||||
}
|
65
osu.Game/Database/BeatmapInfo.cs
Normal file
65
osu.Game/Database/BeatmapInfo.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps.Samples;
|
||||
using osu.Game.GameModes.Play;
|
||||
using SQLite.Net.Attributes;
|
||||
using SQLiteNetExtensions.Attributes;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
public class BeatmapInfo
|
||||
{
|
||||
public BeatmapInfo()
|
||||
{
|
||||
BaseDifficulty = new BaseDifficulty();
|
||||
}
|
||||
|
||||
[PrimaryKey]
|
||||
public int BeatmapID { get; set; }
|
||||
[NotNull, Indexed]
|
||||
public int BeatmapSetID { get; set; }
|
||||
[ForeignKey(typeof(BeatmapMetadata))]
|
||||
public int BeatmapMetadataID { get; set; }
|
||||
[ForeignKey(typeof(BaseDifficulty)), NotNull]
|
||||
public int BaseDifficultyID { get; set; }
|
||||
[OneToOne]
|
||||
public BeatmapMetadata Metadata { get; set; }
|
||||
[OneToOne]
|
||||
public BaseDifficulty BaseDifficulty { get; set; }
|
||||
|
||||
public string Path { 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; }
|
||||
}
|
||||
}
|
@ -2,9 +2,9 @@
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.GameModes.Play;
|
||||
using SQLite;
|
||||
using SQLite.Net.Attributes;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
public class BeatmapMetadata
|
||||
{
|
19
osu.Game/Database/BeatmapSetInfo.cs
Normal file
19
osu.Game/Database/BeatmapSetInfo.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using SQLite.Net.Attributes;
|
||||
using SQLiteNetExtensions.Attributes;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
public class BeatmapSetInfo
|
||||
{
|
||||
[PrimaryKey]
|
||||
public int BeatmapSetID { get; set; }
|
||||
[OneToOne]
|
||||
public BeatmapMetadata Metadata { get; set; }
|
||||
[NotNull, ForeignKey(typeof(BeatmapMetadata))]
|
||||
public int BeatmapMetadataID { get; set; }
|
||||
public string Hash { get; set; }
|
||||
public string Path { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ namespace osu.Game
|
||||
{
|
||||
try
|
||||
{
|
||||
Beatmaps.AddBeatmap(message.Path);
|
||||
Beatmaps.ImportBeatmap(message.Path);
|
||||
// TODO: Switch to beatmap list and select the new song
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -43,26 +43,24 @@
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="SQLitePCLRaw.core">
|
||||
<HintPath>$(SolutionDir)\packages\SQLitePCLRaw.core.1.0.1\lib\net45\SQLitePCLRaw.core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SQLitePCLRaw.provider.e_sqlite3">
|
||||
<HintPath>$(SolutionDir)\packages\SQLitePCLRaw.provider.e_sqlite3.net45.1.0.1\lib\net45\SQLitePCLRaw.provider.e_sqlite3.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SQLitePCLRaw.batteries_green">
|
||||
<HintPath>$(SolutionDir)\packages\SQLitePCLRaw.bundle_green.1.0.1\lib\net45\SQLitePCLRaw.batteries_green.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SQLite-net">
|
||||
<HintPath>$(SolutionDir)\packages\sqlite-net-pcl.1.2.0\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLite-net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DotNetZip">
|
||||
<HintPath>$(SolutionDir)\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SQLite.Net.Platform.Win32">
|
||||
<HintPath>$(SolutionDir)\packages\SQLite.Net-PCL.3.0.5\lib\net4\SQLite.Net.Platform.Win32.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SQLite.Net">
|
||||
<HintPath>$(SolutionDir)\packages\SQLite.Net-PCL.3.0.5\lib\net40\SQLite.Net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SQLite.Net.Platform.Generic">
|
||||
<HintPath>$(SolutionDir)\packages\SQLite.Net-PCL.3.0.5\lib\net40\SQLite.Net.Platform.Generic.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SQLiteNetExtensions">
|
||||
<HintPath>$(SolutionDir)\packages\SQLiteNetExtensions.1.3.0\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\SQLiteNetExtensions.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Beatmaps\Beatmap.cs" />
|
||||
<Compile Include="Beatmaps\BeatmapSet.cs" />
|
||||
<Compile Include="Beatmaps\BeatmapMetadata.cs" />
|
||||
<Compile Include="Beatmaps\Objects\Catch\CatchConverter.cs" />
|
||||
<Compile Include="Beatmaps\Objects\Catch\Drawable\DrawableFruit.cs" />
|
||||
<Compile Include="Beatmaps\Objects\HitObject.cs" />
|
||||
@ -168,9 +166,12 @@
|
||||
<Compile Include="Beatmaps\Formats\BeatmapDecoder.cs" />
|
||||
<Compile Include="Beatmaps\Formats\OsuLegacyDecoder.cs" />
|
||||
<Compile Include="Beatmaps\IO\OszArchiveReader.cs" />
|
||||
<Compile Include="Beatmaps\BaseDifficulty.cs" />
|
||||
<Compile Include="Beatmaps\Events\EventType.cs" />
|
||||
<Compile Include="VolumeMeter.cs" />
|
||||
<Compile Include="Database\BeatmapSetInfo.cs" />
|
||||
<Compile Include="Database\BeatmapMetadata.cs" />
|
||||
<Compile Include="Database\BeatmapInfo.cs" />
|
||||
<Compile Include="Database\BaseDifficulty.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(SolutionDir)\osu-framework\osu.Framework\osu.Framework.csproj">
|
||||
@ -198,7 +199,4 @@
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<Import Project="$(SolutionDir)\packages\SQLitePCLRaw.lib.e_sqlite3.v110_xp.1.0.1\build\SQLitePCLRaw.lib.e_sqlite3.v110_xp.targets" Condition="Exists('..\packages\SQLitePCLRaw.lib.e_sqlite3.v110_xp.1.0.1\build\SQLitePCLRaw.lib.e_sqlite3.v110_xp.targets')" />
|
||||
<Import Project="$(SolutionDir)\packages\SQLitePCLRaw.lib.e_sqlite3.osx.1.0.1\build\SQLitePCLRaw.lib.e_sqlite3.osx.targets" Condition="Exists('..\packages\SQLitePCLRaw.lib.e_sqlite3.osx.1.0.1\build\SQLitePCLRaw.lib.e_sqlite3.osx.targets')" />
|
||||
<Import Project="$(SolutionDir)\packages\SQLitePCLRaw.lib.e_sqlite3.linux.1.0.1\build\SQLitePCLRaw.lib.e_sqlite3.linux.targets" Condition="Exists('..\packages\SQLitePCLRaw.lib.e_sqlite3.linux.1.0.1\build\SQLitePCLRaw.lib.e_sqlite3.linux.targets')" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -7,11 +7,6 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
|
||||
<package id="DotNetZip" version="1.10.1" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
|
||||
<package id="ppy.OpenTK" version="1.1.2225.3" targetFramework="net45" />
|
||||
<package id="sqlite-net-pcl" version="1.2.0" targetFramework="net45" />
|
||||
<package id="SQLitePCLRaw.bundle_green" version="1.0.1" targetFramework="net45" />
|
||||
<package id="SQLitePCLRaw.core" version="1.0.1" targetFramework="net45" />
|
||||
<package id="SQLitePCLRaw.lib.e_sqlite3.linux" version="1.0.1" targetFramework="net45" />
|
||||
<package id="SQLitePCLRaw.lib.e_sqlite3.osx" version="1.0.1" targetFramework="net45" />
|
||||
<package id="SQLitePCLRaw.lib.e_sqlite3.v110_xp" version="1.0.1" targetFramework="net45" />
|
||||
<package id="SQLitePCLRaw.provider.e_sqlite3.net45" version="1.0.1" targetFramework="net45" />
|
||||
<package id="SQLite.Net-PCL" version="3.0.5" targetFramework="net45" />
|
||||
<package id="SQLiteNetExtensions" version="1.3.0" targetFramework="net45" />
|
||||
</packages>
|
||||
|
Loading…
Reference in New Issue
Block a user