mirror of
https://github.com/osukey/osukey.git
synced 2025-08-03 22:56:36 +09:00
Make a RulesetDatabase.
This commit is contained in:
@ -5,7 +5,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
@ -77,6 +76,8 @@ namespace osu.Game.Database
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Storage.DeleteDatabase(@"beatmaps");
|
||||
|
||||
foreach (var setInfo in Query<BeatmapSetInfo>())
|
||||
{
|
||||
if (Storage.Exists(setInfo.Path))
|
||||
@ -89,6 +90,13 @@ namespace osu.Game.Database
|
||||
Connection.DeleteAll<BeatmapInfo>();
|
||||
}
|
||||
|
||||
protected override Type[] ValidTypes => new[] {
|
||||
typeof(BeatmapSetInfo),
|
||||
typeof(BeatmapInfo),
|
||||
typeof(BeatmapMetadata),
|
||||
typeof(BeatmapDifficulty),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Import multiple <see cref="BeatmapSetInfo"/> from <paramref name="paths"/>.
|
||||
/// </summary>
|
||||
@ -275,47 +283,6 @@ namespace osu.Game.Database
|
||||
return working;
|
||||
}
|
||||
|
||||
public TableQuery<T> Query<T>() where T : class
|
||||
{
|
||||
return Connection.Table<T>();
|
||||
}
|
||||
|
||||
public T GetWithChildren<T>(object id) where T : class
|
||||
{
|
||||
return Connection.GetWithChildren<T>(id);
|
||||
}
|
||||
|
||||
public List<T> GetAllWithChildren<T>(Expression<Func<T, bool>> filter = null, bool recursive = true)
|
||||
where T : class
|
||||
{
|
||||
return Connection.GetAllWithChildren(filter, recursive);
|
||||
}
|
||||
|
||||
public T GetChildren<T>(T item, bool recursive = false)
|
||||
{
|
||||
if (item == null) return default(T);
|
||||
|
||||
Connection.GetChildren(item, recursive);
|
||||
return item;
|
||||
}
|
||||
|
||||
private readonly Type[] validTypes = {
|
||||
typeof(BeatmapSetInfo),
|
||||
typeof(BeatmapInfo),
|
||||
typeof(BeatmapMetadata),
|
||||
typeof(BeatmapDifficulty),
|
||||
};
|
||||
|
||||
public void Update<T>(T record, bool cascade = true) where T : class
|
||||
{
|
||||
if (validTypes.All(t => t != typeof(T)))
|
||||
throw new ArgumentException("Must be a type managed by BeatmapDatabase", nameof(T));
|
||||
if (cascade)
|
||||
Connection.UpdateWithChildren(record);
|
||||
else
|
||||
Connection.Update(record);
|
||||
}
|
||||
|
||||
public bool Exists(BeatmapSetInfo beatmapSet) => Storage.Exists(beatmapSet.Path);
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using osu.Game.IO.Serialization;
|
||||
using osu.Game.Modes;
|
||||
using SQLite.Net.Attributes;
|
||||
using SQLiteNetExtensions.Attributes;
|
||||
using System;
|
||||
@ -55,15 +54,12 @@ namespace osu.Game.Database
|
||||
public float StackLeniency { get; set; }
|
||||
public bool SpecialStyle { get; set; }
|
||||
|
||||
public int Mode { get; set; }
|
||||
[ForeignKey(typeof(RulesetInfo))]
|
||||
public int RulesetID { get; set; }
|
||||
|
||||
[OneToOne(CascadeOperations = CascadeOperation.All)]
|
||||
public RulesetInfo Ruleset { get; set; }
|
||||
|
||||
[Ignore]
|
||||
public Ruleset Ruleset
|
||||
{
|
||||
get { return RulesetCollection.GetRuleset(Mode); }
|
||||
set { Mode = RulesetCollection.GetId(value); }
|
||||
}
|
||||
|
||||
public bool LetterboxInBreaks { get; set; }
|
||||
public bool WidescreenStoryboard { get; set; }
|
||||
|
||||
|
@ -2,9 +2,13 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using SQLite.Net;
|
||||
using SQLiteNetExtensions.Extensions;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
@ -24,8 +28,7 @@ namespace osu.Game.Database
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error(e, @"Failed to initialise the beatmap database! Trying again with a clean database...");
|
||||
storage.DeleteDatabase(@"beatmaps");
|
||||
Logger.Error(e, $@"Failed to initialise the {GetType()}! Trying again with a clean database...");
|
||||
Reset();
|
||||
Prepare();
|
||||
}
|
||||
@ -40,5 +43,41 @@ namespace osu.Game.Database
|
||||
/// Reset this database to a default state. Undo all changes to database and storage backings.
|
||||
/// </summary>
|
||||
public abstract void Reset();
|
||||
|
||||
public TableQuery<T> Query<T>() where T : class
|
||||
{
|
||||
return Connection.Table<T>();
|
||||
}
|
||||
|
||||
public T GetWithChildren<T>(object id) where T : class
|
||||
{
|
||||
return Connection.GetWithChildren<T>(id);
|
||||
}
|
||||
|
||||
public List<T> GetAllWithChildren<T>(Expression<Func<T, bool>> filter = null, bool recursive = true)
|
||||
where T : class
|
||||
{
|
||||
return Connection.GetAllWithChildren(filter, recursive);
|
||||
}
|
||||
|
||||
public T GetChildren<T>(T item, bool recursive = false)
|
||||
{
|
||||
if (item == null) return default(T);
|
||||
|
||||
Connection.GetChildren(item, recursive);
|
||||
return item;
|
||||
}
|
||||
|
||||
protected abstract Type[] ValidTypes { get; }
|
||||
|
||||
public void Update<T>(T record, bool cascade = true) where T : class
|
||||
{
|
||||
if (ValidTypes.All(t => t != typeof(T)))
|
||||
throw new ArgumentException("Must be a type managed by BeatmapDatabase", nameof(T));
|
||||
if (cascade)
|
||||
Connection.UpdateWithChildren(record);
|
||||
else
|
||||
Connection.Update(record);
|
||||
}
|
||||
}
|
||||
}
|
107
osu.Game/Database/RulesetDatabase.cs
Normal file
107
osu.Game/Database/RulesetDatabase.cs
Normal file
@ -0,0 +1,107 @@
|
||||
// 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 System.Linq;
|
||||
using System.Reflection;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Modes;
|
||||
using SQLite.Net;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
/// <summary>
|
||||
/// Todo: All of this needs to be moved to a RulesetDatabase.
|
||||
/// </summary>
|
||||
public class RulesetDatabase : Database
|
||||
{
|
||||
public IEnumerable<RulesetInfo> AllRulesets => Query<RulesetInfo>().Where(r => r.Available);
|
||||
|
||||
public RulesetDatabase(Storage storage, SQLiteConnection connection)
|
||||
: base(storage, connection)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Prepare()
|
||||
{
|
||||
Connection.CreateTable<RulesetInfo>();
|
||||
|
||||
List<Ruleset> instances = new List<Ruleset>();
|
||||
|
||||
foreach (string file in Directory.GetFiles(Environment.CurrentDirectory, @"osu.Game.Modes.*.dll"))
|
||||
{
|
||||
try
|
||||
{
|
||||
var assembly = Assembly.LoadFile(file);
|
||||
var rulesets = assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(Ruleset)));
|
||||
|
||||
if (rulesets.Count() != 1)
|
||||
continue;
|
||||
|
||||
Assembly.LoadFile(file);
|
||||
|
||||
foreach (Type rulesetType in rulesets)
|
||||
instances.Add((Ruleset)Activator.CreateInstance(rulesetType));
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
Connection.BeginTransaction();
|
||||
|
||||
//add all legacy modes in correct order
|
||||
foreach (var r in instances.Where(r => r.LegacyID >= 0).OrderBy(r => r.LegacyID))
|
||||
{
|
||||
Connection.InsertOrReplace(createRulesetInfo(r));
|
||||
}
|
||||
|
||||
//add any other modes
|
||||
foreach (var r in instances.Where(r => r.LegacyID < 0))
|
||||
{
|
||||
var us = createRulesetInfo(r);
|
||||
|
||||
var existing = Query<RulesetInfo>().FirstOrDefault(ri => ri.InstantiationInfo == us.InstantiationInfo);
|
||||
|
||||
if (existing == null)
|
||||
Connection.Insert(us);
|
||||
}
|
||||
|
||||
//perform a consistency check
|
||||
foreach (var r in Query<RulesetInfo>())
|
||||
{
|
||||
try
|
||||
{
|
||||
r.CreateInstance();
|
||||
r.Available = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
r.Available = false;
|
||||
}
|
||||
|
||||
Connection.Update(r);
|
||||
}
|
||||
|
||||
Connection.Commit();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private RulesetInfo createRulesetInfo(Ruleset ruleset) => new RulesetInfo
|
||||
{
|
||||
Name = ruleset.Description,
|
||||
InstantiationInfo = ruleset.GetType().AssemblyQualifiedName,
|
||||
ID = ruleset.LegacyID
|
||||
};
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Connection.DeleteAll<RulesetInfo>();
|
||||
}
|
||||
|
||||
protected override Type[] ValidTypes => new[] { typeof(RulesetInfo) };
|
||||
|
||||
public RulesetInfo GetRuleset(int id) => Query<RulesetInfo>().First(r => r.ID == id);
|
||||
}
|
||||
}
|
24
osu.Game/Database/RulesetInfo.cs
Normal file
24
osu.Game/Database/RulesetInfo.cs
Normal file
@ -0,0 +1,24 @@
|
||||
// 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 osu.Game.Modes;
|
||||
using SQLite.Net.Attributes;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
public class RulesetInfo
|
||||
{
|
||||
[PrimaryKey, AutoIncrement]
|
||||
public int ID { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string InstantiationInfo { get; set; }
|
||||
|
||||
[Indexed]
|
||||
public bool Available { get; set; }
|
||||
|
||||
public Ruleset CreateInstance() => (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo));
|
||||
}
|
||||
}
|
@ -7,7 +7,6 @@ using System.Linq;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.IO.Legacy;
|
||||
using osu.Game.IPC;
|
||||
using osu.Game.Modes;
|
||||
using osu.Game.Modes.Scoring;
|
||||
using SharpCompress.Compressors.LZMA;
|
||||
using SQLite.Net;
|
||||
@ -17,17 +16,20 @@ namespace osu.Game.Database
|
||||
public class ScoreDatabase : Database
|
||||
{
|
||||
private readonly Storage storage;
|
||||
|
||||
private readonly BeatmapDatabase beatmaps;
|
||||
private readonly RulesetDatabase rulesets;
|
||||
|
||||
private const string replay_folder = @"replays";
|
||||
|
||||
// ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised)
|
||||
private ScoreIPCChannel ipc;
|
||||
|
||||
public ScoreDatabase(Storage storage, SQLiteConnection connection, IIpcHost importHost = null, BeatmapDatabase beatmaps = null) : base(storage, connection)
|
||||
public ScoreDatabase(Storage storage, SQLiteConnection connection, IIpcHost importHost = null, BeatmapDatabase beatmaps = null, RulesetDatabase rulesets = null) : base(storage, connection)
|
||||
{
|
||||
this.storage = storage;
|
||||
this.beatmaps = beatmaps;
|
||||
this.rulesets = rulesets;
|
||||
|
||||
if (importHost != null)
|
||||
ipc = new ScoreIPCChannel(importHost, this);
|
||||
@ -40,7 +42,7 @@ namespace osu.Game.Database
|
||||
using (Stream s = storage.GetStream(Path.Combine(replay_folder, replayFilename)))
|
||||
using (SerializationReader sr = new SerializationReader(s))
|
||||
{
|
||||
var ruleset = RulesetCollection.GetRuleset(sr.ReadByte());
|
||||
var ruleset = rulesets.GetRuleset(sr.ReadByte()).CreateInstance();
|
||||
score = ruleset.CreateScoreProcessor().CreateScore();
|
||||
|
||||
/* score.Pass = true;*/
|
||||
@ -116,5 +118,7 @@ namespace osu.Game.Database
|
||||
public override void Reset()
|
||||
{
|
||||
}
|
||||
|
||||
protected override Type[] ValidTypes => new[] { typeof(Score) };
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user