Merge branch 'master' into tooltips

This commit is contained in:
Jorolf
2017-04-19 13:51:39 +02:00
committed by GitHub
274 changed files with 2299 additions and 1609 deletions

View File

@ -4,8 +4,7 @@
using OpenTK.Graphics;
using osu.Game.Beatmaps.Timing;
using osu.Game.Database;
using osu.Game.Modes;
using osu.Game.Modes.Objects;
using osu.Game.Rulesets.Objects;
using System.Collections.Generic;
namespace osu.Game.Beatmaps
@ -50,12 +49,6 @@ namespace osu.Game.Beatmaps
/// </summary>
public class Beatmap : Beatmap<HitObject>
{
/// <summary>
/// Calculates the star difficulty for this Beatmap.
/// </summary>
/// <returns>The star difficulty.</returns>
public double CalculateStarDifficulty() => Ruleset.GetRuleset(BeatmapInfo.Mode).CreateDifficultyCalculator(this).Calculate();
/// <summary>
/// Constructs a new beatmap.
/// </summary>
@ -63,6 +56,7 @@ namespace osu.Game.Beatmaps
public Beatmap(Beatmap original = null)
: base(original)
{
HitObjects = original?.HitObjects;
}
}
}

View File

@ -1,7 +1,8 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects;
using osu.Game.Rulesets.Beatmaps;
using osu.Game.Rulesets.Objects;
using System.Collections.Generic;
namespace osu.Game.Beatmaps
@ -41,6 +42,6 @@ namespace osu.Game.Beatmaps
{
}
protected abstract IBeatmapConverter<T> CreateBeatmapConverter();
protected abstract BeatmapConverter<T> CreateBeatmapConverter();
}
}

View File

@ -6,7 +6,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Modes;
using OpenTK;
using OpenTK.Graphics;
@ -45,7 +44,7 @@ namespace osu.Game.Beatmaps.Drawables
Origin = Anchor.Centre,
TextSize = Size.X,
Colour = Color4.White,
Icon = Ruleset.GetRuleset(beatmap.Mode).Icon
Icon = beatmap.Ruleset.CreateInstance().Icon
}
};
}

View File

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using osu.Game.Modes.Objects;
using osu.Game.Rulesets.Objects;
using osu.Game.Database;
namespace osu.Game.Beatmaps.Formats

View File

@ -7,9 +7,8 @@ using System.IO;
using OpenTK.Graphics;
using osu.Game.Beatmaps.Events;
using osu.Game.Beatmaps.Timing;
using osu.Game.Modes;
using osu.Game.Modes.Objects;
using osu.Game.Beatmaps.Legacy;
using osu.Game.Rulesets.Objects.Legacy;
namespace osu.Game.Beatmaps.Formats
{
@ -30,6 +29,8 @@ namespace osu.Game.Beatmaps.Formats
// TODO: Not sure how far back to go, or differences between versions
}
private HitObjectParser parser;
private LegacySampleBank defaultSampleBank;
private int defaultSampleVolume = 100;
@ -84,7 +85,23 @@ namespace osu.Game.Beatmaps.Formats
beatmap.BeatmapInfo.StackLeniency = float.Parse(val, NumberFormatInfo.InvariantInfo);
break;
case @"Mode":
beatmap.BeatmapInfo.Mode = (PlayMode)int.Parse(val);
beatmap.BeatmapInfo.RulesetID = int.Parse(val);
switch (beatmap.BeatmapInfo.RulesetID)
{
case 0:
parser = new Rulesets.Objects.Legacy.Osu.HitObjectParser();
break;
case 1:
parser = new Rulesets.Objects.Legacy.Taiko.HitObjectParser();
break;
case 2:
parser = new Rulesets.Objects.Legacy.Catch.HitObjectParser();
break;
case 3:
parser = new Rulesets.Objects.Legacy.Mania.HitObjectParser();
break;
}
break;
case @"LetterboxInBreaks":
beatmap.BeatmapInfo.LetterboxInBreaks = int.Parse(val) == 1;
@ -304,8 +321,6 @@ namespace osu.Game.Beatmaps.Formats
{
beatmap.BeatmapInfo.BeatmapVersion = beatmapVersion;
HitObjectParser parser = new LegacyHitObjectParser();
Section section = Section.None;
bool hasCustomColours = false;

View File

@ -1,21 +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 osu.Game.Modes.Objects;
namespace osu.Game.Beatmaps
{
/// <summary>
/// Converts a Beatmap for another mode.
/// </summary>
/// <typeparam name="T">The type of HitObject stored in the Beatmap.</typeparam>
public interface IBeatmapConverter<T> where T : HitObject
{
/// <summary>
/// Converts a Beatmap to another mode.
/// </summary>
/// <param name="original">The original Beatmap.</param>
/// <returns>The converted Beatmap.</returns>
Beatmap<T> Convert(Beatmap original);
}
}

View File

@ -5,8 +5,7 @@ using osu.Framework.Audio.Track;
using osu.Framework.Configuration;
using osu.Framework.Graphics.Textures;
using osu.Game.Database;
using osu.Game.Modes;
using osu.Game.Modes.Mods;
using osu.Game.Rulesets.Mods;
using System;
using System.Collections.Generic;
@ -18,14 +17,6 @@ namespace osu.Game.Beatmaps
public readonly BeatmapSetInfo BeatmapSetInfo;
/// <summary>
/// A play mode that is preferred for this beatmap. PlayMode will become this mode where conversion is feasible,
/// or otherwise to the beatmap's default.
/// </summary>
public PlayMode? PreferredPlayMode;
public PlayMode PlayMode => Beatmap?.BeatmapInfo?.Mode > PlayMode.Osu ? Beatmap.BeatmapInfo.Mode : PreferredPlayMode ?? PlayMode.Osu;
public readonly Bindable<IEnumerable<Mod>> Mods = new Bindable<IEnumerable<Mod>>();
public readonly bool WithStoryboard;

View File

@ -4,7 +4,6 @@
using System;
using osu.Framework.Configuration;
using osu.Framework.Platform;
using osu.Game.Modes;
namespace osu.Game.Configuration
{
@ -17,7 +16,7 @@ namespace osu.Game.Configuration
Set(OsuConfig.Username, string.Empty);
Set(OsuConfig.Token, string.Empty);
Set(OsuConfig.PlayMode, PlayMode.Osu);
Set(OsuConfig.Ruleset, 0, 0, int.MaxValue);
Set(OsuConfig.AudioDevice, string.Empty);
Set(OsuConfig.SavePassword, false);
@ -196,7 +195,7 @@ namespace osu.Game.Configuration
public enum OsuConfig
{
// New osu:
PlayMode,
Ruleset,
Token,
// Imported from old osu:
BeatmapDirectory,

View File

@ -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;
@ -18,37 +17,21 @@ using SQLiteNetExtensions.Extensions;
namespace osu.Game.Database
{
public class BeatmapDatabase
public class BeatmapDatabase : Database
{
private SQLiteConnection connection { get; }
private readonly Storage storage;
private readonly RulesetDatabase rulesets;
public event Action<BeatmapSetInfo> BeatmapSetAdded;
public event Action<BeatmapSetInfo> BeatmapSetRemoved;
// ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised)
private BeatmapIPCChannel ipc;
public BeatmapDatabase(Storage storage, IIpcHost importHost = null)
public BeatmapDatabase(Storage storage, SQLiteConnection connection, RulesetDatabase rulesets, IIpcHost importHost = null) : base(storage, connection)
{
this.storage = storage;
this.rulesets = rulesets;
if (importHost != null)
ipc = new BeatmapIPCChannel(importHost, this);
if (connection == null)
{
try
{
connection = prepareConnection();
deletePending();
}
catch (Exception e)
{
Logger.Error(e, @"Failed to initialise the beatmap database! Trying again with a clean database...");
storage.DeleteDatabase(@"beatmaps");
connection = prepareConnection();
}
}
}
private void deletePending()
@ -57,20 +40,20 @@ namespace osu.Game.Database
{
try
{
storage.Delete(b.Path);
Storage.Delete(b.Path);
GetChildren(b, true);
foreach (var i in b.Beatmaps)
{
if (i.Metadata != null) connection.Delete(i.Metadata);
if (i.Difficulty != null) connection.Delete(i.Difficulty);
if (i.Metadata != null) Connection.Delete(i.Metadata);
if (i.Difficulty != null) Connection.Delete(i.Difficulty);
connection.Delete(i);
Connection.Delete(i);
}
if (b.Metadata != null) connection.Delete(b.Metadata);
connection.Delete(b);
if (b.Metadata != null) Connection.Delete(b.Metadata);
Connection.Delete(b);
}
catch (Exception e)
{
@ -80,42 +63,41 @@ namespace osu.Game.Database
//this is required because sqlite migrations don't work, initially inserting nulls into this field.
//see https://github.com/praeclarum/sqlite-net/issues/326
connection.Query<BeatmapSetInfo>("UPDATE BeatmapSetInfo SET DeletePending = 0 WHERE DeletePending IS NULL");
Connection.Query<BeatmapSetInfo>("UPDATE BeatmapSetInfo SET DeletePending = 0 WHERE DeletePending IS NULL");
}
private SQLiteConnection prepareConnection()
protected override void Prepare(bool reset = false)
{
var conn = storage.GetDatabase(@"beatmaps");
Connection.CreateTable<BeatmapMetadata>();
Connection.CreateTable<BeatmapDifficulty>();
Connection.CreateTable<BeatmapSetInfo>();
Connection.CreateTable<BeatmapInfo>();
try
if (reset)
{
conn.CreateTable<BeatmapMetadata>();
conn.CreateTable<BeatmapDifficulty>();
conn.CreateTable<BeatmapSetInfo>();
conn.CreateTable<BeatmapInfo>();
}
catch
{
conn.Close();
throw;
Storage.DeleteDatabase(@"beatmaps");
foreach (var setInfo in Query<BeatmapSetInfo>())
{
if (Storage.Exists(setInfo.Path))
Storage.Delete(setInfo.Path);
}
Connection.DeleteAll<BeatmapMetadata>();
Connection.DeleteAll<BeatmapDifficulty>();
Connection.DeleteAll<BeatmapSetInfo>();
Connection.DeleteAll<BeatmapInfo>();
}
return conn;
deletePending();
}
public void Reset()
{
foreach (var setInfo in Query<BeatmapSetInfo>())
{
if (storage.Exists(setInfo.Path))
storage.Delete(setInfo.Path);
}
connection.DeleteAll<BeatmapMetadata>();
connection.DeleteAll<BeatmapDifficulty>();
connection.DeleteAll<BeatmapSetInfo>();
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"/>.
@ -174,7 +156,7 @@ namespace osu.Game.Database
BeatmapMetadata metadata;
using (var reader = ArchiveReader.GetReader(storage, path))
using (var reader = ArchiveReader.GetReader(Storage, path))
{
using (var stream = new StreamReader(reader.GetStream(reader.BeatmapFilenames[0])))
metadata = BeatmapDecoder.GetDecoder(stream).Decode(stream).Metadata;
@ -182,18 +164,18 @@ namespace osu.Game.Database
if (File.Exists(path)) // Not always the case, i.e. for LegacyFilesystemReader
{
using (var input = storage.GetStream(path))
using (var input = Storage.GetStream(path))
{
hash = input.GetMd5Hash();
input.Seek(0, SeekOrigin.Begin);
path = Path.Combine(@"beatmaps", hash.Remove(1), hash.Remove(2), hash);
if (!storage.Exists(path))
using (var output = storage.GetStream(path, FileAccess.Write))
if (!Storage.Exists(path))
using (var output = Storage.GetStream(path, FileAccess.Write))
input.CopyTo(output);
}
}
var existing = connection.Table<BeatmapSetInfo>().FirstOrDefault(b => b.Hash == hash);
var existing = Connection.Table<BeatmapSetInfo>().FirstOrDefault(b => b.Hash == hash);
if (existing != null)
{
@ -216,7 +198,7 @@ namespace osu.Game.Database
Metadata = metadata
};
using (var archive = ArchiveReader.GetReader(storage, path))
using (var archive = ArchiveReader.GetReader(Storage, path))
{
string[] mapNames = archive.BeatmapFilenames;
foreach (var name in mapNames)
@ -236,7 +218,9 @@ namespace osu.Game.Database
// TODO: Diff beatmap metadata with set metadata and leave it here if necessary
beatmap.BeatmapInfo.Metadata = null;
beatmap.BeatmapInfo.StarDifficulty = beatmap.CalculateStarDifficulty();
// TODO: this should be done in a better place once we actually need to dynamically update it.
beatmap.BeatmapInfo.Ruleset = rulesets.Query<RulesetInfo>().FirstOrDefault(r => r.ID == beatmap.BeatmapInfo.RulesetID);
beatmap.BeatmapInfo.StarDifficulty = rulesets.Query<RulesetInfo>().FirstOrDefault(r => r.ID == beatmap.BeatmapInfo.RulesetID)?.CreateInstance()?.CreateDifficultyCalculator(beatmap).Calculate() ?? 0;
beatmapSet.Beatmaps.Add(beatmap.BeatmapInfo);
}
@ -248,17 +232,17 @@ namespace osu.Game.Database
public void Import(IEnumerable<BeatmapSetInfo> beatmapSets)
{
lock (connection)
lock (Connection)
{
connection.BeginTransaction();
Connection.BeginTransaction();
foreach (var s in beatmapSets)
{
connection.InsertWithChildren(s, true);
Connection.InsertOrReplaceWithChildren(s, true);
BeatmapSetAdded?.Invoke(s);
}
connection.Commit();
Connection.Commit();
}
}
@ -275,7 +259,7 @@ namespace osu.Game.Database
if (string.IsNullOrEmpty(beatmapSet.Path))
return null;
return ArchiveReader.GetReader(storage, beatmapSet.Path);
return ArchiveReader.GetReader(Storage, beatmapSet.Path);
}
public BeatmapSetInfo GetBeatmapSet(int id)
@ -287,12 +271,14 @@ namespace osu.Game.Database
{
var beatmapSetInfo = Query<BeatmapSetInfo>().FirstOrDefault(s => s.ID == beatmapInfo.BeatmapSetInfoID);
//we need metadata
GetChildren(beatmapSetInfo);
if (beatmapSetInfo == null)
throw new InvalidOperationException($@"Beatmap set {beatmapInfo.BeatmapSetInfoID} is not in the local database.");
//we need metadata
GetChildren(beatmapSetInfo);
//we also need a ruleset
GetChildren(beatmapInfo);
if (beatmapInfo.Metadata == null)
beatmapInfo.Metadata = beatmapSetInfo.Metadata;
@ -303,47 +289,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);
public bool Exists(BeatmapSetInfo beatmapSet) => Storage.Exists(beatmapSet.Path);
}
}

View File

@ -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;
@ -54,7 +53,13 @@ namespace osu.Game.Database
public bool Countdown { get; set; }
public float StackLeniency { get; set; }
public bool SpecialStyle { get; set; }
public PlayMode Mode { get; set; }
[ForeignKey(typeof(RulesetInfo))]
public int RulesetID { get; set; }
[OneToOne(CascadeOperations = CascadeOperation.All)]
public RulesetInfo Ruleset { get; set; }
public bool LetterboxInBreaks { get; set; }
public bool WidescreenStoryboard { get; set; }

View File

@ -26,6 +26,7 @@ namespace osu.Game.Database
public double MaxStarDifficulty => Beatmaps.Max(b => b.StarDifficulty);
[Indexed]
public bool DeletePending { get; set; }
public string Hash { get; set; }

View File

@ -0,0 +1,82 @@
// 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.Linq;
using System.Linq.Expressions;
using osu.Framework.Logging;
using osu.Framework.Platform;
using SQLite.Net;
using SQLiteNetExtensions.Extensions;
namespace osu.Game.Database
{
public abstract class Database
{
protected SQLiteConnection Connection { get; }
protected Storage Storage { get; }
protected Database(Storage storage, SQLiteConnection connection)
{
Storage = storage;
Connection = connection;
try
{
Prepare();
}
catch (Exception e)
{
Logger.Error(e, $@"Failed to initialise the {GetType()}! Trying again with a clean database...");
Prepare(true);
}
}
/// <summary>
/// Prepare this database for use.
/// </summary>
protected abstract void Prepare(bool reset = false);
/// <summary>
/// Reset this database to a default state. Undo all changes to database and storage backings.
/// </summary>
public void Reset() => Prepare(true);
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);
}
}
}

View File

@ -0,0 +1,103 @@
// 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.Rulesets;
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(bool reset = false)
{
Connection.CreateTable<RulesetInfo>();
if (reset)
{
Connection.DeleteAll<RulesetInfo>();
}
List<Ruleset> instances = new List<Ruleset>();
foreach (string file in Directory.GetFiles(Environment.CurrentDirectory, @"osu.Game.Rulesets.*.dll"))
{
try
{
var assembly = Assembly.LoadFile(file);
var rulesets = assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(Ruleset)));
if (rulesets.Count() != 1)
continue;
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
};
protected override Type[] ValidTypes => new[] { typeof(RulesetInfo) };
public RulesetInfo GetRuleset(int id) => Query<RulesetInfo>().First(r => r.ID == id);
}
}

View File

@ -0,0 +1,26 @@
// 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.Rulesets;
using SQLite.Net.Attributes;
namespace osu.Game.Database
{
public class RulesetInfo
{
[PrimaryKey, AutoIncrement]
public int? ID { get; set; }
[Indexed(Unique = true)]
public string Name { get; set; }
[Indexed(Unique = true)]
public string InstantiationInfo { get; set; }
[Indexed]
public bool Available { get; set; }
public Ruleset CreateInstance() => (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo));
}
}

View File

@ -7,26 +7,29 @@ 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 osu.Game.Rulesets.Scoring;
using SharpCompress.Compressors.LZMA;
using SQLite.Net;
namespace osu.Game.Database
{
public class ScoreDatabase
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, IIpcHost importHost = null, BeatmapDatabase beatmaps = null)
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);
@ -39,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 = Ruleset.GetRuleset((PlayMode)sr.ReadByte());
var ruleset = rulesets.GetRuleset(sr.ReadByte()).CreateInstance();
score = ruleset.CreateScoreProcessor().CreateScore();
/* score.Pass = true;*/
@ -107,5 +110,11 @@ namespace osu.Game.Database
return score;
}
protected override void Prepare(bool reset = false)
{
}
protected override Type[] ValidTypes => new[] { typeof(Score) };
}
}

View File

@ -817,13 +817,13 @@ namespace osu.Game.Graphics
fa_youtube_play = 0xf16a,
fa_youtube_square = 0xf166,
// gamemode icons in circles
// ruleset icons in circles
fa_osu_osu_o = 0xe000,
fa_osu_mania_o = 0xe001,
fa_osu_fruits_o = 0xe002,
fa_osu_taiko_o = 0xe003,
// gamemode icons without circles
// ruleset icons without circles
fa_osu_filled_circle = 0xe004,
fa_osu_cross_o = 0xe005,
fa_osu_logo = 0xe006,

View File

@ -1,18 +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 osu.Game.Modes.Objects.Types;
using OpenTK;
namespace osu.Game.Modes.Objects.Legacy
{
/// <summary>
/// Legacy Hit-type, used for parsing Beatmaps.
/// </summary>
public sealed class LegacyHit : HitObject, IHasPosition, IHasCombo
{
public Vector2 Position { get; set; }
public bool NewCombo { get; set; }
}
}

View File

@ -1,13 +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
namespace osu.Game.Modes
{
public enum PlayMode
{
Osu = 0,
Taiko = 1,
Catch = 2,
Mania = 3
}
}

View File

@ -1,60 +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 osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Modes.Mods;
using osu.Game.Modes.UI;
using osu.Game.Screens.Play;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using osu.Game.Modes.Scoring;
namespace osu.Game.Modes
{
public class BeatmapStatistic
{
public FontAwesome Icon;
public string Content;
public string Name;
}
public abstract class Ruleset
{
private static readonly ConcurrentDictionary<PlayMode, Type> available_rulesets = new ConcurrentDictionary<PlayMode, Type>();
public static IEnumerable<PlayMode> PlayModes => available_rulesets.Keys;
public virtual IEnumerable<BeatmapStatistic> GetBeatmapStatistics(WorkingBeatmap beatmap) => new BeatmapStatistic[] { };
public abstract IEnumerable<Mod> GetModsFor(ModType type);
public abstract HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap);
public abstract DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap);
public abstract ScoreProcessor CreateScoreProcessor();
public static void Register(Ruleset ruleset) => available_rulesets.TryAdd(ruleset.PlayMode, ruleset.GetType());
protected abstract PlayMode PlayMode { get; }
public virtual FontAwesome Icon => FontAwesome.fa_question_circle;
public abstract string Description { get; }
public abstract IEnumerable<KeyCounter> CreateGameplayKeys();
public static Ruleset GetRuleset(PlayMode mode)
{
Type type;
if (!available_rulesets.TryGetValue(mode, out type))
return null;
return Activator.CreateInstance(type) as Ruleset;
}
}
}

View File

@ -5,7 +5,7 @@ using System.Collections.Generic;
using Newtonsoft.Json;
using osu.Framework.IO.Network;
using osu.Game.Database;
using osu.Game.Modes.Scoring;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Online.API.Requests
{
@ -21,19 +21,16 @@ namespace osu.Game.Online.API.Requests
protected override WebRequest CreateWebRequest()
{
var req = base.CreateWebRequest();
req.AddParameter(@"c", beatmap.Hash);
req.AddParameter(@"f", beatmap.Path);
//req.AddParameter(@"c", beatmap.Hash);
//req.AddParameter(@"f", beatmap.Path);
return req;
}
protected override string Target => @"beatmaps/scores";
protected override string Target => $@"beatmaps/{beatmap.OnlineBeatmapID}/scores";
}
public class GetScoresResponse
{
[JsonProperty(@"beatmap")]
public BeatmapInfo Beatmap;
[JsonProperty(@"scores")]
public IEnumerable<Score> Scores;
}

View File

@ -15,7 +15,6 @@ using osu.Framework.Logging;
using osu.Game.Graphics.UserInterface.Volume;
using osu.Framework.Allocation;
using osu.Framework.Timing;
using osu.Game.Modes;
using osu.Game.Overlays.Toolbar;
using osu.Game.Screens;
using osu.Game.Screens.Menu;
@ -24,8 +23,9 @@ using System.Linq;
using osu.Framework.Graphics.Primitives;
using System.Threading.Tasks;
using osu.Framework.Threading;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Modes.Scoring;
using osu.Game.Rulesets.Scoring;
using osu.Game.Overlays.Notifications;
using osu.Game.Screens.Play;
@ -58,7 +58,8 @@ namespace osu.Game
private VolumeControl volume;
public Bindable<PlayMode> PlayMode;
private Bindable<int> configRuleset;
public Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
private readonly string[] args;
@ -88,7 +89,9 @@ namespace osu.Game
Dependencies.Cache(this);
PlayMode = LocalConfig.GetBindable<PlayMode>(OsuConfig.PlayMode);
configRuleset = LocalConfig.GetBindable<int>(OsuConfig.Ruleset);
Ruleset.Value = RulesetDatabase.GetRuleset(configRuleset.Value);
Ruleset.ValueChanged += r => configRuleset.Value = r.ID ?? 0;
}
private ScheduledDelegate scoreLoad;
@ -199,11 +202,11 @@ namespace osu.Game
{
Depth = -3,
OnHome = delegate { intro?.ChildScreen?.MakeCurrent(); },
OnPlayModeChange = m => PlayMode.Value = m,
OnRulesetChange = r => Ruleset.Value = r,
}, t =>
{
PlayMode.ValueChanged += delegate { Toolbar.SetGameMode(PlayMode.Value); };
PlayMode.TriggerChange();
Ruleset.ValueChanged += delegate { Toolbar.SetRuleset(Ruleset.Value); };
Ruleset.TriggerChange();
overlayContent.Add(Toolbar);
});
@ -276,7 +279,7 @@ namespace osu.Game
return;
}
//central game mode change logic.
//central game screen change logic.
if (!currentScreen.ShowOverlays)
{
options.State = Visibility.Hidden;

View File

@ -18,6 +18,7 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Cursor;
using osu.Game.Graphics.Processing;
using osu.Game.Online.API;
using SQLite.Net;
namespace osu.Game
{
@ -27,6 +28,8 @@ namespace osu.Game
protected BeatmapDatabase BeatmapDatabase;
protected RulesetDatabase RulesetDatabase;
protected ScoreDatabase ScoreDatabase;
protected override string MainResourceFile => @"osu.Game.Resources.dll";
@ -80,8 +83,12 @@ namespace osu.Game
{
Dependencies.Cache(this);
Dependencies.Cache(LocalConfig);
Dependencies.Cache(BeatmapDatabase = new BeatmapDatabase(Host.Storage, Host));
Dependencies.Cache(ScoreDatabase = new ScoreDatabase(Host.Storage, Host, BeatmapDatabase));
SQLiteConnection connection = Host.Storage.GetDatabase(@"client");
Dependencies.Cache(RulesetDatabase = new RulesetDatabase(Host.Storage, connection));
Dependencies.Cache(BeatmapDatabase = new BeatmapDatabase(Host.Storage, connection, RulesetDatabase, Host));
Dependencies.Cache(ScoreDatabase = new ScoreDatabase(Host.Storage, connection, Host, BeatmapDatabase));
Dependencies.Cache(new OsuColour());
//this completely overrides the framework default. will need to change once we make a proper FontStore.

View File

@ -4,7 +4,7 @@
using OpenTK.Input;
using osu.Framework.Allocation;
using osu.Game.Graphics;
using osu.Game.Modes.Mods;
using osu.Game.Rulesets.Mods;
namespace osu.Game.Overlays.Mods
{

View File

@ -4,7 +4,7 @@
using OpenTK.Input;
using osu.Framework.Allocation;
using osu.Game.Graphics;
using osu.Game.Modes.Mods;
using osu.Game.Rulesets.Mods;
namespace osu.Game.Overlays.Mods
{

View File

@ -4,7 +4,7 @@
using OpenTK.Input;
using osu.Framework.Allocation;
using osu.Game.Graphics;
using osu.Game.Modes.Mods;
using osu.Game.Rulesets.Mods;
namespace osu.Game.Overlays.Mods
{

View File

@ -12,8 +12,8 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input;
using osu.Game.Graphics.Sprites;
using osu.Game.Modes.Mods;
using osu.Game.Modes.UI;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.UI;
using System;
using System.Linq;

View File

@ -9,7 +9,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Input;
using osu.Game.Graphics.Sprites;
using osu.Game.Modes.Mods;
using osu.Game.Rulesets.Mods;
using System;
namespace osu.Game.Overlays.Mods

View File

@ -13,11 +13,11 @@ using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds;
using osu.Game.Graphics.Sprites;
using osu.Game.Modes;
using osu.Game.Modes.Mods;
using osu.Game.Rulesets.Mods;
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Game.Database;
namespace osu.Game.Overlays.Mods
{
@ -37,26 +37,30 @@ namespace osu.Game.Overlays.Mods
public readonly Bindable<IEnumerable<Mod>> SelectedMods = new Bindable<IEnumerable<Mod>>();
public readonly Bindable<PlayMode> PlayMode = new Bindable<PlayMode>();
public readonly Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
private void modeChanged(PlayMode newMode)
private void rulesetChanged(RulesetInfo newRuleset)
{
var ruleset = Ruleset.GetRuleset(newMode);
var instance = newRuleset.CreateInstance();
foreach (ModSection section in modSectionsContainer.Children)
section.Buttons = ruleset.GetModsFor(section.ModType).Select(m => new ModButton(m)).ToArray();
section.Buttons = instance.GetModsFor(section.ModType).Select(m => new ModButton(m)).ToArray();
refreshSelectedMods();
}
[BackgroundDependencyLoader(permitNulls: true)]
private void load(OsuColour colours, OsuGame osu)
private void load(OsuColour colours, OsuGame osu, RulesetDatabase rulesets)
{
lowMultiplierColour = colours.Red;
highMultiplierColour = colours.Green;
if (osu != null)
PlayMode.BindTo(osu.PlayMode);
PlayMode.ValueChanged += modeChanged;
PlayMode.TriggerChange();
Ruleset.BindTo(osu.Ruleset);
else
Ruleset.Value = rulesets.AllRulesets.First();
Ruleset.ValueChanged += rulesetChanged;
Ruleset.TriggerChange();
}
protected override void PopOut()

View File

@ -1,15 +1,14 @@
// 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 osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Modes;
using OpenTK;
using OpenTK.Graphics;
@ -18,7 +17,7 @@ namespace osu.Game.Overlays.Options
public class OptionsFooter : FillFlowContainer
{
[BackgroundDependencyLoader]
private void load(OsuGameBase game, OsuColour colours)
private void load(OsuGameBase game, OsuColour colours, RulesetDatabase rulesets)
{
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
@ -27,13 +26,15 @@ namespace osu.Game.Overlays.Options
var modes = new List<Drawable>();
foreach (PlayMode m in Enum.GetValues(typeof(PlayMode)))
foreach (var ruleset in rulesets.AllRulesets)
{
modes.Add(new TextAwesome
{
Icon = Ruleset.GetRuleset(m).Icon,
Icon = ruleset.CreateInstance().Icon,
Colour = Color4.Gray,
TextSize = 20
});
}
Children = new Drawable[]
{

View File

@ -8,8 +8,8 @@ using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Modes;
using OpenTK;
namespace osu.Game.Overlays.Toolbar
@ -20,14 +20,14 @@ namespace osu.Game.Overlays.Toolbar
public const float TOOLTIP_HEIGHT = 30;
public Action OnHome;
public Action<PlayMode> OnPlayModeChange;
public Action<RulesetInfo> OnRulesetChange;
private readonly ToolbarModeSelector modeSelector;
private readonly ToolbarUserArea userArea;
protected override bool HideOnEscape => false;
protected override bool BlockPassThroughInput => false;
protected override bool BlockPassThroughMouse => false;
private const double transition_time = 500;
@ -55,9 +55,9 @@ namespace osu.Game.Overlays.Toolbar
},
modeSelector = new ToolbarModeSelector
{
OnPlayModeChange = mode =>
OnRulesetChange = mode =>
{
OnPlayModeChange?.Invoke(mode);
OnRulesetChange?.Invoke(mode);
}
}
}
@ -129,7 +129,7 @@ namespace osu.Game.Overlays.Toolbar
}
}
public void SetGameMode(PlayMode mode) => modeSelector.SetGameMode(mode);
public void SetRuleset(RulesetInfo ruleset) => modeSelector.SetRuleset(ruleset);
protected override void PopIn()
{

View File

@ -2,23 +2,26 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics.Containers;
using osu.Game.Modes;
using osu.Game.Database;
using OpenTK.Graphics;
namespace osu.Game.Overlays.Toolbar
{
public class ToolbarModeButton : ToolbarButton
{
private PlayMode mode;
public PlayMode Mode
private RulesetInfo ruleset;
public RulesetInfo Ruleset
{
get { return mode; }
get { return ruleset; }
set
{
mode = value;
TooltipMain = Ruleset.GetRuleset(mode).Description;
TooltipSub = $"Play some {Ruleset.GetRuleset(mode).Description}";
Icon = Ruleset.GetRuleset(mode).Icon;
ruleset = value;
var rInstance = ruleset.CreateInstance();
TooltipMain = rInstance.Description;
TooltipSub = $"Play some {rInstance.Description}";
Icon = rInstance.Icon;
}
}

View File

@ -3,12 +3,13 @@
using System;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Caching;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Sprites;
using osu.Game.Modes;
using osu.Game.Database;
using OpenTK;
using OpenTK.Graphics;
@ -22,7 +23,7 @@ namespace osu.Game.Overlays.Toolbar
private readonly Drawable modeButtonLine;
private ToolbarModeButton activeButton;
public Action<PlayMode> OnPlayModeChange;
public Action<RulesetInfo> OnRulesetChange;
public ToolbarModeSelector()
{
@ -62,16 +63,20 @@ namespace osu.Game.Overlays.Toolbar
}
}
};
}
foreach (PlayMode m in Ruleset.PlayModes)
[BackgroundDependencyLoader]
private void load(RulesetDatabase rulesets)
{
foreach (var ruleset in rulesets.AllRulesets)
{
modeButtons.Add(new ToolbarModeButton
{
Mode = m,
Ruleset = ruleset,
Action = delegate
{
SetGameMode(m);
OnPlayModeChange?.Invoke(m);
SetRuleset(ruleset);
OnRulesetChange?.Invoke(ruleset);
}
});
}
@ -84,11 +89,11 @@ namespace osu.Game.Overlays.Toolbar
Size = new Vector2(modeButtons.DrawSize.X, 1);
}
public void SetGameMode(PlayMode mode)
public void SetRuleset(RulesetInfo ruleset)
{
foreach (ToolbarModeButton m in modeButtons.Children.Cast<ToolbarModeButton>())
{
bool isActive = m.Mode == mode;
bool isActive = m.Ruleset.ID == ruleset.ID;
m.Active = isActive;
if (isActive)
activeButton = m;

View File

@ -0,0 +1,14 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Graphics;
namespace osu.Game.Rulesets
{
public class BeatmapStatistic
{
public FontAwesome Icon;
public string Content;
public string Name;
}
}

View File

@ -0,0 +1,90 @@
// 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.Linq;
using osu.Game.Rulesets.Objects;
using osu.Game.Beatmaps;
namespace osu.Game.Rulesets.Beatmaps
{
/// <summary>
/// Converts a Beatmap for another mode.
/// </summary>
/// <typeparam name="T">The type of HitObject stored in the Beatmap.</typeparam>
public abstract class BeatmapConverter<T> where T : HitObject
{
/// <summary>
/// Checks if a Beatmap can be converted using this Beatmap Converter.
/// </summary>
/// <param name="beatmap">The Beatmap to check.</param>
/// <returns>Whether the Beatmap can be converted using this Beatmap Converter.</returns>
public bool CanConvert(Beatmap beatmap) => ValidConversionTypes.All(t => beatmap.HitObjects.Any(t.IsInstanceOfType));
/// <summary>
/// Converts a Beatmap using this Beatmap Converter.
/// </summary>
/// <param name="original">The un-converted Beatmap.</param>
/// <returns>The converted Beatmap.</returns>
public Beatmap<T> Convert(Beatmap original)
{
// We always operate on a clone of the original beatmap, to not modify it game-wide
return ConvertBeatmap(new Beatmap(original));
}
/// <summary>
/// Performs the conversion of a Beatmap using this Beatmap Converter.
/// </summary>
/// <param name="original">The un-converted Beatmap.</param>
/// <returns>The converted Beatmap.</returns>
protected virtual Beatmap<T> ConvertBeatmap(Beatmap original)
{
return new Beatmap<T>
{
BeatmapInfo = original.BeatmapInfo,
TimingInfo = original.TimingInfo,
HitObjects = original.HitObjects.SelectMany(h => convert(h, original)).ToList()
};
}
/// <summary>
/// Converts a hit object.
/// </summary>
/// <param name="original">The hit object to convert.</param>
/// <param name="beatmap">The un-converted Beatmap.</param>
/// <returns>The converted hit object.</returns>
private IEnumerable<T> convert(HitObject original, Beatmap beatmap)
{
// Check if the hitobject is already the converted type
T tObject = original as T;
if (tObject != null)
{
yield return tObject;
yield break;
}
// Convert the hit object
foreach (var obj in ConvertHitObject(original, beatmap))
{
if (obj == null)
continue;
yield return obj;
}
}
/// <summary>
/// The types of HitObjects that can be converted to be used for this Beatmap.
/// </summary>
protected abstract IEnumerable<Type> ValidConversionTypes { get; }
/// <summary>
/// Performs the conversion of a hit object.
/// </summary>
/// <param name="original">The hit object to convert.</param>
/// <param name="beatmap">The un-converted Beatmap.</param>
/// <returns>The converted hit object.</returns>
protected abstract IEnumerable<T> ConvertHitObject(HitObject original, Beatmap beatmap);
}
}

View File

@ -1,15 +1,16 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects;
namespace osu.Game.Beatmaps
namespace osu.Game.Rulesets.Beatmaps
{
/// <summary>
/// Processes a post-converted Beatmap.
/// </summary>
/// <typeparam name="TObject">The type of HitObject contained in the Beatmap.</typeparam>
public interface IBeatmapProcessor<TObject>
public class BeatmapProcessor<TObject>
where TObject : HitObject
{
/// <summary>
@ -19,6 +20,6 @@ namespace osu.Game.Beatmaps
/// </para>
/// </summary>
/// <param name="beatmap">The Beatmap to process.</param>
void PostProcess(Beatmap<TObject> beatmap);
public virtual void PostProcess(Beatmap<TObject> beatmap) { }
}
}

View File

@ -9,9 +9,9 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Modes.Judgements
namespace osu.Game.Rulesets.Judgements
{
/// <summary>
/// A drawable object which visualises the hit result of a <see cref="Judgements.Judgement"/>.

View File

@ -1,10 +1,10 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Scoring;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Modes.Judgements
namespace osu.Game.Rulesets.Judgements
{
/// <summary>
/// Inidicates that the judgement this is attached to is a partial judgement and the scoring value may change.

View File

@ -1,9 +1,9 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Modes.Judgements
namespace osu.Game.Rulesets.Judgements
{
public abstract class Judgement
{

View File

@ -1,10 +1,10 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects;
using osu.Game.Modes.UI;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI;
namespace osu.Game.Modes.Mods
namespace osu.Game.Rulesets.Mods
{
/// <summary>
/// An interface for mods that are applied to a HitRenderer.

View File

@ -3,12 +3,12 @@
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Modes.Objects;
using osu.Game.Modes.UI;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI;
using System;
using osu.Game.Modes.Scoring;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Modes.Mods
namespace osu.Game.Rulesets.Mods
{
/// <summary>
/// The base class for gameplay modifiers.

View File

@ -1,7 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Mods
namespace osu.Game.Rulesets.Mods
{
public enum ModType
{

View File

@ -4,7 +4,7 @@
using System.Collections.Generic;
using OpenTK;
namespace osu.Game.Modes.Objects
namespace osu.Game.Rulesets.Objects
{
public class BezierApproximator
{

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
using osu.Framework.MathUtils;
using OpenTK;
namespace osu.Game.Modes.Objects
namespace osu.Game.Rulesets.Objects
{
public class CircularArcApproximator
{

View File

@ -2,10 +2,10 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Modes.Objects.Types;
using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic;
namespace osu.Game.Modes.Objects
namespace osu.Game.Rulesets.Objects
{
public class CurvedHitObject : HitObject, IHasCurve
{

View File

@ -1,7 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Objects.Drawables
namespace osu.Game.Rulesets.Objects.Drawables
{
public enum ArmedState
{

View File

@ -7,13 +7,13 @@ using osu.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Game.Modes.Judgements;
using osu.Game.Rulesets.Judgements;
using Container = osu.Framework.Graphics.Containers.Container;
using osu.Game.Modes.Objects.Types;
using osu.Game.Rulesets.Objects.Types;
using OpenTK.Graphics;
using osu.Game.Audio;
namespace osu.Game.Modes.Objects.Drawables
namespace osu.Game.Rulesets.Objects.Drawables
{
public abstract class DrawableHitObject<TJudgement> : Container, IStateful<ArmedState>
where TJudgement : Judgement

View File

@ -3,7 +3,7 @@
using System.ComponentModel;
namespace osu.Game.Modes.Objects.Drawables
namespace osu.Game.Rulesets.Objects.Drawables
{
public enum HitResult
{

View File

@ -3,7 +3,7 @@
using osu.Framework.Graphics;
namespace osu.Game.Modes.Objects.Drawables
namespace osu.Game.Rulesets.Objects.Drawables
{
public interface IDrawableHitObjectWithProxiedApproach
{

View File

@ -6,7 +6,7 @@ using osu.Game.Beatmaps.Timing;
using osu.Game.Database;
using System.Collections.Generic;
namespace osu.Game.Modes.Objects
namespace osu.Game.Rulesets.Objects
{
/// <summary>
/// A HitObject describes an object in a Beatmap.

View File

@ -1,7 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Objects
namespace osu.Game.Rulesets.Objects
{
public abstract class HitObjectParser
{

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Objects.Legacy.Catch
{
/// <summary>
/// Legacy osu!catch Hit-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Hit : HitObject, IHasCombo, IHasXPosition
{
public float X { get; set; }
public bool NewCombo { get; set; }
}
}

View File

@ -0,0 +1,45 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic;
namespace osu.Game.Rulesets.Objects.Legacy.Catch
{
/// <summary>
/// A HitObjectParser to parse legacy osu!catch Beatmaps.
/// </summary>
internal class HitObjectParser : Legacy.HitObjectParser
{
protected override HitObject CreateHit(Vector2 position, bool newCombo)
{
return new Hit
{
X = position.X,
NewCombo = newCombo,
};
}
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount)
{
return new Slider
{
X = position.X,
NewCombo = newCombo,
ControlPoints = controlPoints,
Distance = length,
CurveType = curveType,
RepeatCount = repeatCount
};
}
protected override HitObject CreateSpinner(Vector2 position, double endTime)
{
return new Spinner
{
EndTime = endTime
};
}
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Objects.Legacy.Catch
{
/// <summary>
/// Legacy osu!catch Slider-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Slider : CurvedHitObject, IHasXPosition, IHasCombo
{
public float X { get; set; }
public bool NewCombo { get; set; }
}
}

View File

@ -1,14 +1,14 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects.Types;
using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Modes.Objects.Legacy
namespace osu.Game.Rulesets.Objects.Legacy.Catch
{
/// <summary>
/// Legacy Spinner-type, used for parsing Beatmaps.
/// Legacy osu!catch Spinner-type, used for parsing Beatmaps.
/// </summary>
internal class LegacySpinner : HitObject, IHasEndTime
internal sealed class Spinner : HitObject, IHasEndTime
{
public double EndTime { get; set; }

View File

@ -2,24 +2,26 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Modes.Objects.Types;
using osu.Game.Rulesets.Objects.Types;
using System;
using System.Collections.Generic;
using System.Globalization;
using osu.Game.Modes.Objects.Legacy;
using osu.Game.Beatmaps.Formats;
using osu.Game.Audio;
namespace osu.Game.Modes.Objects
namespace osu.Game.Rulesets.Objects.Legacy
{
internal class LegacyHitObjectParser : HitObjectParser
/// <summary>
/// A HitObjectParser to parse legacy Beatmaps.
/// </summary>
internal abstract class HitObjectParser : Objects.HitObjectParser
{
public override HitObject Parse(string text)
{
string[] split = text.Split(',');
var type = (LegacyHitObjectType)int.Parse(split[3]) & ~LegacyHitObjectType.ColourHax;
bool combo = type.HasFlag(LegacyHitObjectType.NewCombo);
type &= ~LegacyHitObjectType.NewCombo;
var type = (HitObjectType)int.Parse(split[3]) & ~HitObjectType.ColourHax;
bool combo = type.HasFlag(HitObjectType.NewCombo);
type &= ~HitObjectType.NewCombo;
int sampleVolume = 0;
string normalSampleBank = null;
@ -27,22 +29,18 @@ namespace osu.Game.Modes.Objects
HitObject result;
if ((type & LegacyHitObjectType.Circle) > 0)
if ((type & HitObjectType.Circle) > 0)
{
result = new LegacyHit
{
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])),
NewCombo = combo
};
result = CreateHit(new Vector2(int.Parse(split[0]), int.Parse(split[1])), combo);
if (split.Length > 5)
readCustomSampleBanks(split[5], ref normalSampleBank, ref addSampleBank, ref sampleVolume);
}
else if ((type & LegacyHitObjectType.Slider) > 0)
else if ((type & HitObjectType.Slider) > 0)
{
CurveType curveType = CurveType.Catmull;
double length = 0;
List<Vector2> points = new List<Vector2> { new Vector2(int.Parse(split[0]), int.Parse(split[1])) };
var points = new List<Vector2> { new Vector2(int.Parse(split[0]), int.Parse(split[1])) };
string[] pointsplit = split[5].Split('|');
foreach (string t in pointsplit)
@ -68,11 +66,7 @@ namespace osu.Game.Modes.Objects
}
string[] temp = t.Split(':');
Vector2 v = new Vector2(
(int)Convert.ToDouble(temp[0], CultureInfo.InvariantCulture),
(int)Convert.ToDouble(temp[1], CultureInfo.InvariantCulture)
);
points.Add(v);
points.Add(new Vector2((int)Convert.ToDouble(temp[0], CultureInfo.InvariantCulture), (int)Convert.ToDouble(temp[1], CultureInfo.InvariantCulture)));
}
int repeatCount = Convert.ToInt32(split[6], CultureInfo.InvariantCulture);
@ -83,37 +77,26 @@ namespace osu.Game.Modes.Objects
if (split.Length > 7)
length = Convert.ToDouble(split[7], CultureInfo.InvariantCulture);
result = new LegacySlider
{
ControlPoints = points,
Distance = length,
CurveType = curveType,
RepeatCount = repeatCount,
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])),
NewCombo = combo
};
result = CreateSlider(new Vector2(int.Parse(split[0]), int.Parse(split[1])), combo, points, length, curveType, repeatCount);
if (split.Length > 10)
readCustomSampleBanks(split[10], ref normalSampleBank, ref addSampleBank, ref sampleVolume);
}
else if ((type & LegacyHitObjectType.Spinner) > 0)
else if ((type & HitObjectType.Spinner) > 0)
{
result = new LegacySpinner
{
EndTime = Convert.ToDouble(split[5], CultureInfo.InvariantCulture)
};
result = CreateSpinner(new Vector2(512, 384) / 2, Convert.ToDouble(split[5], CultureInfo.InvariantCulture));
if (split.Length > 6)
readCustomSampleBanks(split[6], ref normalSampleBank, ref addSampleBank, ref sampleVolume);
}
else if ((type & LegacyHitObjectType.Hold) > 0)
else if ((type & HitObjectType.Hold) > 0)
{
// Note: Hold is generated by BMS converts
// Todo: Apparently end time is determined by samples??
// Shouldn't need implementation until mania
result = new LegacyHold
result = new Hold
{
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])),
NewCombo = combo
@ -191,6 +174,34 @@ namespace osu.Game.Modes.Objects
sampleVolume = split.Length > 3 ? int.Parse(split[3]) : 0;
}
/// <summary>
/// Creates a legacy Hit-type hit object.
/// </summary>
/// <param name="position">The position of the hit object.</param>
/// <param name="newCombo">Whether the hit object creates a new combo.</param>
/// <returns>The hit object.</returns>
protected abstract HitObject CreateHit(Vector2 position, bool newCombo);
/// <summary>
/// Creats a legacy Slider-type hit object.
/// </summary>
/// <param name="position">The position of the hit object.</param>
/// <param name="newCombo">Whether the hit object creates a new combo.</param>
/// <param name="controlPoints">The slider control points.</param>
/// <param name="length">The slider length.</param>
/// <param name="curveType">The slider curve type.</param>
/// <param name="repeatCount">The slider repeat count.</param>
/// <returns>The hit object.</returns>
protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount);
/// <summary>
/// Creates a legacy Spinner-type hit object.
/// </summary>
/// <param name="position">The position of the hit object.</param>
/// <param name="endTime">The spinner end time.</param>
/// <returns>The hit object.</returns>
protected abstract HitObject CreateSpinner(Vector2 position, double endTime);
[Flags]
private enum LegacySoundType
{

View File

@ -3,10 +3,10 @@
using System;
namespace osu.Game.Modes.Objects.Legacy
namespace osu.Game.Rulesets.Objects.Legacy
{
[Flags]
public enum LegacyHitObjectType
public enum HitObjectType
{
Circle = 1 << 0,
Slider = 1 << 1,

View File

@ -2,17 +2,21 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Modes.Objects.Types;
using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Modes.Objects.Legacy
namespace osu.Game.Rulesets.Objects.Legacy
{
/// <summary>
/// Legacy Hold-type, used for parsing "specials" in beatmaps.
/// </summary>
public sealed class LegacyHold : HitObject, IHasPosition, IHasCombo, IHasHold
internal sealed class Hold : HitObject, IHasPosition, IHasCombo, IHasHold
{
public Vector2 Position { get; set; }
public float X => Position.X;
public float Y => Position.Y;
public bool NewCombo { get; set; }
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Objects.Legacy.Mania
{
/// <summary>
/// Legacy osu!mania Hit-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Hit : HitObject, IHasXPosition, IHasCombo
{
public float X { get; set; }
public bool NewCombo { get; set; }
}
}

View File

@ -0,0 +1,46 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic;
namespace osu.Game.Rulesets.Objects.Legacy.Mania
{
/// <summary>
/// A HitObjectParser to parse legacy osu!mania Beatmaps.
/// </summary>
internal class HitObjectParser : Legacy.HitObjectParser
{
protected override HitObject CreateHit(Vector2 position, bool newCombo)
{
return new Hit
{
X = position.X,
NewCombo = newCombo,
};
}
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount)
{
return new Slider
{
X = position.X,
NewCombo = newCombo,
ControlPoints = controlPoints,
Distance = length,
CurveType = curveType,
RepeatCount = repeatCount
};
}
protected override HitObject CreateSpinner(Vector2 position, double endTime)
{
return new Spinner
{
X = position.X,
EndTime = endTime
};
}
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Objects.Legacy.Mania
{
/// <summary>
/// Legacy osu!mania Slider-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Slider : CurvedHitObject, IHasXPosition, IHasCombo
{
public float X { get; set; }
public bool NewCombo { get; set; }
}
}

View File

@ -0,0 +1,19 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Objects.Legacy.Mania
{
/// <summary>
/// Legacy osu!mania Spinner-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Spinner : HitObject, IHasEndTime, IHasXPosition
{
public double EndTime { get; set; }
public double Duration => EndTime - StartTime;
public float X { get; set; }
}
}

View File

@ -1,18 +1,22 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects.Types;
using osu.Game.Rulesets.Objects.Types;
using OpenTK;
namespace osu.Game.Modes.Objects.Legacy
namespace osu.Game.Rulesets.Objects.Legacy.Osu
{
/// <summary>
/// Legacy Slider-type, used for parsing Beatmaps.
/// Legacy osu! Hit-type, used for parsing Beatmaps.
/// </summary>
public sealed class LegacySlider : CurvedHitObject, IHasPosition, IHasCombo
internal sealed class Hit : HitObject, IHasPosition, IHasCombo
{
public Vector2 Position { get; set; }
public float X => Position.X;
public float Y => Position.Y;
public bool NewCombo { get; set; }
}
}

View File

@ -0,0 +1,46 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic;
namespace osu.Game.Rulesets.Objects.Legacy.Osu
{
/// <summary>
/// A HitObjectParser to parse legacy osu! Beatmaps.
/// </summary>
internal class HitObjectParser : Legacy.HitObjectParser
{
protected override HitObject CreateHit(Vector2 position, bool newCombo)
{
return new Hit
{
Position = position,
NewCombo = newCombo,
};
}
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount)
{
return new Slider
{
Position = position,
NewCombo = newCombo,
ControlPoints = controlPoints,
Distance = length,
CurveType = curveType,
RepeatCount = repeatCount
};
}
protected override HitObject CreateSpinner(Vector2 position, double endTime)
{
return new Spinner
{
Position = position,
EndTime = endTime
};
}
}
}

View File

@ -0,0 +1,22 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects.Types;
using OpenTK;
namespace osu.Game.Rulesets.Objects.Legacy.Osu
{
/// <summary>
/// Legacy osu! Slider-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Slider : CurvedHitObject, IHasPosition, IHasCombo
{
public Vector2 Position { get; set; }
public float X => Position.X;
public float Y => Position.Y;
public bool NewCombo { get; set; }
}
}

View 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 osu.Game.Rulesets.Objects.Types;
using OpenTK;
namespace osu.Game.Rulesets.Objects.Legacy.Osu
{
/// <summary>
/// Legacy osu! Spinner-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Spinner : HitObject, IHasEndTime, IHasPosition
{
public double EndTime { get; set; }
public double Duration => EndTime - StartTime;
public Vector2 Position { get; set; }
public float X => Position.X;
public float Y => Position.Y;
}
}

View File

@ -0,0 +1,15 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Objects.Legacy.Taiko
{
/// <summary>
/// Legacy osu!taiko Hit-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Hit : HitObject, IHasCombo
{
public bool NewCombo { get; set; }
}
}

View File

@ -0,0 +1,43 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic;
namespace osu.Game.Rulesets.Objects.Legacy.Taiko
{
/// <summary>
/// A HitObjectParser to parse legacy osu!taiko Beatmaps.
/// </summary>
internal class HitObjectParser : Legacy.HitObjectParser
{
protected override HitObject CreateHit(Vector2 position, bool newCombo)
{
return new Hit
{
NewCombo = newCombo,
};
}
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount)
{
return new Slider
{
NewCombo = newCombo,
ControlPoints = controlPoints,
Distance = length,
CurveType = curveType,
RepeatCount = repeatCount
};
}
protected override HitObject CreateSpinner(Vector2 position, double endTime)
{
return new Spinner
{
EndTime = endTime
};
}
}
}

View File

@ -0,0 +1,15 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Objects.Legacy.Taiko
{
/// <summary>
/// Legacy osu!taiko Slider-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Slider : CurvedHitObject, IHasCombo
{
public bool NewCombo { get; set; }
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Objects.Legacy.Taiko
{
/// <summary>
/// Legacy osu!taiko Spinner-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Spinner : HitObject, IHasEndTime
{
public double EndTime { get; set; }
public double Duration => EndTime - StartTime;
}
}

View File

@ -4,10 +4,10 @@
using System.Collections.Generic;
using System.Linq;
using osu.Framework.MathUtils;
using osu.Game.Modes.Objects.Types;
using osu.Game.Rulesets.Objects.Types;
using OpenTK;
namespace osu.Game.Modes.Objects
namespace osu.Game.Rulesets.Objects
{
public class SliderCurve
{

View File

@ -1,7 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Objects.Types
namespace osu.Game.Rulesets.Objects.Types
{
public enum CurveType
{

View File

@ -1,7 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Objects.Types
namespace osu.Game.Rulesets.Objects.Types
{
/// <summary>
/// A HitObject that is part of a combo.

View File

@ -4,7 +4,7 @@
using System.Collections.Generic;
using OpenTK;
namespace osu.Game.Modes.Objects.Types
namespace osu.Game.Rulesets.Objects.Types
{
/// <summary>
/// A HitObject that has a curve.

View File

@ -1,7 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Objects.Types
namespace osu.Game.Rulesets.Objects.Types
{
/// <summary>
/// A HitObject that has a positional length.

View File

@ -1,7 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Objects.Types
namespace osu.Game.Rulesets.Objects.Types
{
/// <summary>
/// A HitObject that ends at a different time than its start time.

View File

@ -1,7 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Objects.Types
namespace osu.Game.Rulesets.Objects.Types
{
/// <summary>
/// A special type of HitObject, mostly used for legacy conversion of "holds".

View File

@ -3,12 +3,12 @@
using OpenTK;
namespace osu.Game.Modes.Objects.Types
namespace osu.Game.Rulesets.Objects.Types
{
/// <summary>
/// A HitObject that has a starting position.
/// </summary>
public interface IHasPosition
public interface IHasPosition : IHasXPosition, IHasYPosition
{
/// <summary>
/// The starting position of the HitObject.

View File

@ -1,7 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Objects.Types
namespace osu.Game.Rulesets.Objects.Types
{
/// <summary>
/// A HitObject that spans some length.

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Rulesets.Objects.Types
{
/// <summary>
/// A HitObject that has a starting X-position.
/// </summary>
public interface IHasXPosition
{
/// <summary>
/// The starting X-position of this HitObject.
/// </summary>
float X { get; }
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Rulesets.Objects.Types
{
/// <summary>
/// A HitObject that has a starting Y-position.
/// </summary>
public interface IHasYPosition
{
/// <summary>
/// The starting Y-position of this HitObject.
/// </summary>
float Y { get; }
}
}

View File

@ -12,7 +12,7 @@ using OpenTK.Input;
using KeyboardState = osu.Framework.Input.KeyboardState;
using MouseState = osu.Framework.Input.MouseState;
namespace osu.Game.Modes.Replays
namespace osu.Game.Rulesets.Replays
{
/// <summary>
/// The ReplayHandler will take a replay and handle the propagation of updates to the input stack.

View File

@ -3,10 +3,12 @@
using System.Collections.Generic;
namespace osu.Game.Modes.Replays
namespace osu.Game.Rulesets.Replays
{
public class Replay
{
protected const double KEY_UP_DELAY = 50;
public List<ReplayFrame> Frames = new List<ReplayFrame>();
}
}
}

View File

@ -3,7 +3,7 @@
using System;
namespace osu.Game.Modes.Replays
namespace osu.Game.Rulesets.Replays
{
[Flags]
public enum ReplayButtonState

View File

@ -3,7 +3,7 @@
using OpenTK;
namespace osu.Game.Modes.Replays
namespace osu.Game.Rulesets.Replays
{
public class ReplayFrame
{

View File

@ -0,0 +1,37 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Play;
using System.Collections.Generic;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets
{
public abstract class Ruleset
{
public virtual IEnumerable<BeatmapStatistic> GetBeatmapStatistics(WorkingBeatmap beatmap) => new BeatmapStatistic[] { };
public abstract IEnumerable<Mod> GetModsFor(ModType type);
public abstract HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap);
public abstract DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap);
public abstract ScoreProcessor CreateScoreProcessor();
public virtual FontAwesome Icon => FontAwesome.fa_question_circle;
public abstract string Description { get; }
public abstract IEnumerable<KeyCounter> CreateGameplayKeys();
/// <summary>
/// Do not override this unless you are a legacy mode.
/// </summary>
public virtual int LegacyID => -1;
}
}

View File

@ -5,12 +5,12 @@ using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using osu.Game.Database;
using osu.Game.Modes.Mods;
using osu.Game.Rulesets.Mods;
using osu.Game.Users;
using System.IO;
using osu.Game.Modes.Replays;
using osu.Game.Rulesets.Replays;
namespace osu.Game.Modes.Scoring
namespace osu.Game.Rulesets.Scoring
{
public class Score
{
@ -19,32 +19,24 @@ namespace osu.Game.Modes.Scoring
[JsonProperty(@"score")]
public double TotalScore { get; set; }
public double Accuracy { get; set; }
public double Health { get; set; }
[JsonProperty(@"maxcombo")]
[JsonProperty(@"accuracy")]
public double Accuracy { get; set; }
public double Health { get; set; } = 1;
[JsonProperty(@"combo")]
public int MaxCombo { get; set; }
public int Combo { get; set; }
[JsonProperty(@"mods")]
protected string[] ModStrings { get; set; } //todo: parse to Mod objects
public Mod[] Mods { get; set; }
private User user;
public User User
{
get
{
return user ?? new User
{
Username = LegacyUsername,
Id = LegacyUserID
};
}
set
{
user = value;
}
}
[JsonProperty(@"user")]
public User User;
[JsonProperty(@"replay_data")]
public Replay Replay;
@ -54,13 +46,7 @@ namespace osu.Game.Modes.Scoring
[JsonProperty(@"score_id")]
public long OnlineScoreID;
[JsonProperty(@"username")]
public string LegacyUsername;
[JsonProperty(@"user_id")]
public long LegacyUserID;
[JsonProperty(@"date")]
[JsonProperty(@"created_at")]
public DateTime Date;
/// <summary>

View File

@ -5,12 +5,12 @@ using System;
using System.Collections.Generic;
using osu.Framework.Configuration;
using osu.Game.Beatmaps;
using osu.Game.Modes.Judgements;
using osu.Game.Modes.Objects;
using osu.Game.Modes.UI;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Modes.Scoring
namespace osu.Game.Rulesets.Scoring
{
public abstract class ScoreProcessor
{
@ -62,7 +62,7 @@ namespace osu.Game.Modes.Scoring
}
/// <summary>
/// Creates a Score applicable to the game mode in which this ScoreProcessor resides.
/// Creates a Score applicable to the ruleset in which this ScoreProcessor resides.
/// </summary>
/// <returns>The Score.</returns>
public virtual Score CreateScore() => new Score
@ -193,4 +193,4 @@ namespace osu.Game.Modes.Scoring
/// <param name="judgement">The judgement that triggered this calculation.</param>
protected virtual void OnJudgementChanged(TJudgement judgement) { }
}
}
}

View File

@ -3,7 +3,7 @@
using System.ComponentModel;
namespace osu.Game.Modes.Scoring
namespace osu.Game.Rulesets.Scoring
{
public enum ScoreRank
{

View File

@ -10,7 +10,7 @@ using osu.Framework.Graphics.Transforms;
using osu.Framework.MathUtils;
using osu.Game.Graphics.Sprites;
namespace osu.Game.Modes.UI
namespace osu.Game.Rulesets.UI
{
public abstract class ComboCounter : Container
{

View File

@ -7,7 +7,7 @@ using osu.Framework.MathUtils;
using osu.Game.Graphics.UserInterface;
using System;
namespace osu.Game.Modes.UI
namespace osu.Game.Rulesets.UI
{
/// <summary>
/// Used to display combo with a roll-up animation in results screen.

View File

@ -4,7 +4,7 @@
using osu.Framework.Configuration;
using osu.Framework.Graphics.Containers;
namespace osu.Game.Modes.UI
namespace osu.Game.Rulesets.UI
{
public abstract class HealthDisplay : Container
{

View File

@ -5,20 +5,21 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Modes.Judgements;
using osu.Game.Modes.Mods;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Screens.Play;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using osu.Game.Modes.Replays;
using osu.Game.Modes.Scoring;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring;
using OpenTK;
using osu.Game.Rulesets.Beatmaps;
namespace osu.Game.Modes.UI
namespace osu.Game.Rulesets.UI
{
/// <summary>
/// Base HitRenderer. Doesn't hold objects.
@ -119,8 +120,12 @@ namespace osu.Game.Modes.UI
RelativeSizeAxes = Axes.Both;
IBeatmapConverter<TObject> converter = CreateBeatmapConverter();
IBeatmapProcessor<TObject> processor = CreateBeatmapProcessor();
BeatmapConverter<TObject> converter = CreateBeatmapConverter();
BeatmapProcessor<TObject> processor = CreateBeatmapProcessor();
// Check if the beatmap can be converted
if (!converter.CanConvert(beatmap.Beatmap))
throw new BeatmapInvalidForModeException($"{nameof(Beatmap)} can't be converted for the current ruleset.");
// Convert the beatmap
Beatmap = converter.Convert(beatmap.Beatmap);
@ -136,7 +141,6 @@ namespace osu.Game.Modes.UI
applyMods(beatmap.Mods.Value);
}
/// <summary>
/// Applies the active mods to this HitRenderer.
/// </summary>
@ -150,18 +154,18 @@ namespace osu.Game.Modes.UI
mod.Apply(this);
}
/// <summary>
/// Creates a converter to convert Beatmap to a specific mode.
/// </summary>
/// <returns>The Beatmap converter.</returns>
protected abstract IBeatmapConverter<TObject> CreateBeatmapConverter();
/// <summary>
/// Creates a processor to perform post-processing operations
/// on HitObjects in converted Beatmaps.
/// </summary>
/// <returns>The Beatmap processor.</returns>
protected abstract IBeatmapProcessor<TObject> CreateBeatmapProcessor();
protected virtual BeatmapProcessor<TObject> CreateBeatmapProcessor() => new BeatmapProcessor<TObject>();
/// <summary>
/// Creates a converter to convert Beatmap to a specific mode.
/// </summary>
/// <returns>The Beatmap converter.</returns>
protected abstract BeatmapConverter<TObject> CreateBeatmapConverter();
}
/// <summary>
@ -268,4 +272,12 @@ namespace osu.Game.Modes.UI
/// <returns>The Playfield.</returns>
protected abstract Playfield<TObject, TJudgement> CreatePlayfield();
}
public class BeatmapInvalidForModeException : Exception
{
public BeatmapInvalidForModeException(string text)
: base(text)
{
}
}
}

View File

@ -8,13 +8,13 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Configuration;
using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Play;
using osu.Game.Modes.Scoring;
using osu.Game.Rulesets.Scoring;
using osu.Framework.Input;
using OpenTK.Input;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
namespace osu.Game.Modes.UI
namespace osu.Game.Rulesets.UI
{
public abstract class HudOverlay : Container
{

View File

@ -6,7 +6,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
namespace osu.Game.Modes.UI
namespace osu.Game.Rulesets.UI
{
public class ModIcon : Container
{

View File

@ -4,13 +4,13 @@
using System;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using OpenTK;
using osu.Game.Modes.Judgements;
using osu.Game.Rulesets.Judgements;
using osu.Framework.Allocation;
namespace osu.Game.Modes.UI
namespace osu.Game.Rulesets.UI
{
public abstract class Playfield<TObject, TJudgement> : Container
where TObject : HitObject

View File

@ -3,7 +3,7 @@
using OpenTK;
namespace osu.Game.Modes.UI
namespace osu.Game.Rulesets.UI
{
/// <summary>
/// Uses the 'x' symbol and has a pop-out effect while rolling over.

View File

@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
namespace osu.Game.Modes.UI
namespace osu.Game.Rulesets.UI
{
public class StandardHealthDisplay : HealthDisplay, IHasAccentColour
{

View File

@ -10,7 +10,7 @@ using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Play;
namespace osu.Game.Modes.UI
namespace osu.Game.Rulesets.UI
{
public class StandardHudOverlay : HudOverlay
{
@ -57,7 +57,7 @@ namespace osu.Game.Modes.UI
Position = new Vector2(0, 30),
};
protected override SongProgress CreateProgress() => new SongProgress()
protected override SongProgress CreateProgress() => new SongProgress
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,

View File

@ -28,7 +28,7 @@ namespace osu.Game.Screens
public override bool Push(Screen screen)
{
// When trying to push a non-loaded GameMode, load it asynchronously and re-invoke Push
// When trying to push a non-loaded screen, load it asynchronously and re-invoke Push
// once it's done.
if (screen.LoadState == LoadState.NotLoaded)
{
@ -36,7 +36,7 @@ namespace osu.Game.Screens
return true;
}
// Make sure the in-progress loading is complete before pushing the GameMode.
// Make sure the in-progress loading is complete before pushing the screen.
while (screen.LoadState < LoadState.Loaded)
Thread.Sleep(1);

View File

@ -14,7 +14,7 @@ namespace osu.Game.Screens
internal BackgroundScreen Background { get; private set; }
/// <summary>
/// Override to create a BackgroundMode for the current GameMode.
/// Override to create a BackgroundMode for the current screen.
/// Note that the instance created may not be the used instance if it matches the BackgroundMode equality clause.
/// </summary>
protected virtual BackgroundScreen CreateBackground() => null;
@ -99,7 +99,7 @@ namespace osu.Game.Screens
if (Background != null && !Background.Equals(nextOsu?.Background))
{
if (nextOsu != null)
//We need to use MakeCurrent in case we are jumping up multiple game modes.
//We need to use MakeCurrent in case we are jumping up multiple game screens.
nextOsu.Background?.MakeCurrent();
else
Background.Exit();

Some files were not shown because too many files have changed in this diff Show More