mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 12:33:01 +08:00
Merge pull request #14917 from peppy/new-interfaces
Add new read-only interfaces for all remaining model types
This commit is contained in:
commit
13bea7833e
@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
return new CatchDifficultyAttributes { Mods = mods, Skills = skills };
|
return new CatchDifficultyAttributes { Mods = mods, Skills = skills };
|
||||||
|
|
||||||
// this is the same as osu!, so there's potential to share the implementation... maybe
|
// this is the same as osu!, so there's potential to share the implementation... maybe
|
||||||
double preempt = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate;
|
double preempt = IBeatmapDifficultyInfo.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate;
|
||||||
|
|
||||||
return new CatchDifficultyAttributes
|
return new CatchDifficultyAttributes
|
||||||
{
|
{
|
||||||
|
@ -132,7 +132,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
{
|
{
|
||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
|
|
||||||
TimePreempt = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450);
|
TimePreempt = (float)IBeatmapDifficultyInfo.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450);
|
||||||
|
|
||||||
Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2;
|
Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
: base(ruleset, beatmap, mods)
|
: base(ruleset, beatmap, mods)
|
||||||
{
|
{
|
||||||
Direction.Value = ScrollingDirection.Down;
|
Direction.Value = ScrollingDirection.Down;
|
||||||
TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450);
|
TimeRange.Value = IBeatmapDifficultyInfo.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay);
|
protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay);
|
||||||
|
@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
|
|
||||||
double starRating = basePerformance > 0.00001 ? Math.Cbrt(1.12) * 0.027 * (Math.Cbrt(100000 / Math.Pow(2, 1 / 1.1) * basePerformance) + 4) : 0;
|
double starRating = basePerformance > 0.00001 ? Math.Cbrt(1.12) * 0.027 * (Math.Cbrt(100000 / Math.Pow(2, 1 / 1.1) * basePerformance) + 4) : 0;
|
||||||
|
|
||||||
double preempt = (int)BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate;
|
double preempt = (int)IBeatmapDifficultyInfo.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate;
|
||||||
|
|
||||||
int maxCombo = beatmap.HitObjects.Count;
|
int maxCombo = beatmap.HitObjects.Count;
|
||||||
// Add the ticks + tail of the slider. 1 is subtracted because the head circle would be counted twice (once for the slider itself in the line above)
|
// Add the ticks + tail of the slider. 1 is subtracted because the head circle would be counted twice (once for the slider itself in the line above)
|
||||||
|
@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
{
|
{
|
||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
|
|
||||||
TimePreempt = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1800, 1200, PREEMPT_MIN);
|
TimePreempt = (float)IBeatmapDifficultyInfo.DifficultyRange(difficulty.ApproachRate, 1800, 1200, PREEMPT_MIN);
|
||||||
|
|
||||||
// Preempt time can go below 450ms. Normally, this is achieved via the DT mod which uniformly speeds up all animations game wide regardless of AR.
|
// Preempt time can go below 450ms. Normally, this is achieved via the DT mod which uniformly speeds up all animations game wide regardless of AR.
|
||||||
// This uniform speedup is hard to match 1:1, however we can at least make AR>10 (via mods) feel good by extending the upper linear function above.
|
// This uniform speedup is hard to match 1:1, however we can at least make AR>10 (via mods) feel good by extending the upper linear function above.
|
||||||
|
@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
|
|
||||||
double secondsDuration = Duration / 1000;
|
double secondsDuration = Duration / 1000;
|
||||||
|
|
||||||
double minimumRotationsPerSecond = stable_matching_fudge * BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 3, 5, 7.5);
|
double minimumRotationsPerSecond = stable_matching_fudge * IBeatmapDifficultyInfo.DifficultyRange(difficulty.OverallDifficulty, 3, 5, 7.5);
|
||||||
|
|
||||||
SpinsRequired = (int)(secondsDuration * minimumRotationsPerSecond);
|
SpinsRequired = (int)(secondsDuration * minimumRotationsPerSecond);
|
||||||
MaximumBonusSpins = (int)((maximum_rotations_per_second - minimumRotationsPerSecond) * secondsDuration);
|
MaximumBonusSpins = (int)((maximum_rotations_per_second - minimumRotationsPerSecond) * secondsDuration);
|
||||||
|
@ -117,7 +117,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
|
|
||||||
case IHasDuration endTimeData:
|
case IHasDuration endTimeData:
|
||||||
{
|
{
|
||||||
double hitMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty, 3, 5, 7.5) * swell_hit_multiplier;
|
double hitMultiplier = IBeatmapDifficultyInfo.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty, 3, 5, 7.5) * swell_hit_multiplier;
|
||||||
|
|
||||||
yield return new Swell
|
yield return new Swell
|
||||||
{
|
{
|
||||||
|
@ -40,8 +40,8 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
|||||||
{
|
{
|
||||||
base.ApplyBeatmap(beatmap);
|
base.ApplyBeatmap(beatmap);
|
||||||
|
|
||||||
hpMultiplier = 1 / (object_count_factor * Math.Max(1, beatmap.HitObjects.OfType<Hit>().Count()) * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98));
|
hpMultiplier = 1 / (object_count_factor * Math.Max(1, beatmap.HitObjects.OfType<Hit>().Count()) * IBeatmapDifficultyInfo.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98));
|
||||||
hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120);
|
hpMissMultiplier = IBeatmapDifficultyInfo.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override double GetHealthIncreaseFor(JudgementResult result)
|
protected override double GetHealthIncreaseFor(JudgementResult result)
|
||||||
|
@ -19,7 +19,7 @@ namespace osu.Game.Tests.Localisation
|
|||||||
Title = "Romanised title",
|
Title = "Romanised title",
|
||||||
TitleUnicode = "Unicode Title"
|
TitleUnicode = "Unicode Title"
|
||||||
};
|
};
|
||||||
var romanisableString = metadata.ToRomanisableString();
|
var romanisableString = metadata.GetDisplayTitleRomanisable();
|
||||||
|
|
||||||
Assert.AreEqual(metadata.ToString(), romanisableString.Romanised);
|
Assert.AreEqual(metadata.ToString(), romanisableString.Romanised);
|
||||||
Assert.AreEqual($"{metadata.ArtistUnicode} - {metadata.TitleUnicode}", romanisableString.Original);
|
Assert.AreEqual($"{metadata.ArtistUnicode} - {metadata.TitleUnicode}", romanisableString.Original);
|
||||||
@ -33,7 +33,7 @@ namespace osu.Game.Tests.Localisation
|
|||||||
Artist = "Romanised Artist",
|
Artist = "Romanised Artist",
|
||||||
Title = "Romanised title"
|
Title = "Romanised title"
|
||||||
};
|
};
|
||||||
var romanisableString = metadata.ToRomanisableString();
|
var romanisableString = metadata.GetDisplayTitleRomanisable();
|
||||||
|
|
||||||
Assert.AreEqual(romanisableString.Romanised, romanisableString.Original);
|
Assert.AreEqual(romanisableString.Romanised, romanisableString.Original);
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ namespace osu.Game.Tournament.Components
|
|||||||
if ((mods & LegacyMods.DoubleTime) > 0)
|
if ((mods & LegacyMods.DoubleTime) > 0)
|
||||||
{
|
{
|
||||||
// temporary local calculation (taken from OsuDifficultyCalculator)
|
// temporary local calculation (taken from OsuDifficultyCalculator)
|
||||||
double preempt = (int)BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450) / 1.5;
|
double preempt = (int)IBeatmapDifficultyInfo.DifficultyRange(ar, 1800, 1200, 450) / 1.5;
|
||||||
ar = (float)(preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5);
|
ar = (float)(preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5);
|
||||||
|
|
||||||
bpm *= 1.5f;
|
bpm *= 1.5f;
|
||||||
|
@ -5,7 +5,7 @@ using osu.Game.Database;
|
|||||||
|
|
||||||
namespace osu.Game.Beatmaps
|
namespace osu.Game.Beatmaps
|
||||||
{
|
{
|
||||||
public class BeatmapDifficulty : IHasPrimaryKey
|
public class BeatmapDifficulty : IHasPrimaryKey, IBeatmapDifficultyInfo
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The default value used for all difficulty settings except <see cref="SliderMultiplier"/> and <see cref="SliderTickRate"/>.
|
/// The default value used for all difficulty settings except <see cref="SliderMultiplier"/> and <see cref="SliderTickRate"/>.
|
||||||
@ -49,47 +49,5 @@ namespace osu.Game.Beatmaps
|
|||||||
difficulty.SliderMultiplier = SliderMultiplier;
|
difficulty.SliderMultiplier = SliderMultiplier;
|
||||||
difficulty.SliderTickRate = SliderTickRate;
|
difficulty.SliderTickRate = SliderTickRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Maps a difficulty value [0, 10] to a two-piece linear range of values.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="difficulty">The difficulty value to be mapped.</param>
|
|
||||||
/// <param name="min">Minimum of the resulting range which will be achieved by a difficulty value of 0.</param>
|
|
||||||
/// <param name="mid">Midpoint of the resulting range which will be achieved by a difficulty value of 5.</param>
|
|
||||||
/// <param name="max">Maximum of the resulting range which will be achieved by a difficulty value of 10.</param>
|
|
||||||
/// <returns>Value to which the difficulty value maps in the specified range.</returns>
|
|
||||||
public static double DifficultyRange(double difficulty, double min, double mid, double max)
|
|
||||||
{
|
|
||||||
if (difficulty > 5)
|
|
||||||
return mid + (max - mid) * (difficulty - 5) / 5;
|
|
||||||
if (difficulty < 5)
|
|
||||||
return mid - (mid - min) * (5 - difficulty) / 5;
|
|
||||||
|
|
||||||
return mid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Maps a difficulty value [0, 10] to a two-piece linear range of values.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="difficulty">The difficulty value to be mapped.</param>
|
|
||||||
/// <param name="range">The values that define the two linear ranges.
|
|
||||||
/// <list type="table">
|
|
||||||
/// <item>
|
|
||||||
/// <term>od0</term>
|
|
||||||
/// <description>Minimum of the resulting range which will be achieved by a difficulty value of 0.</description>
|
|
||||||
/// </item>
|
|
||||||
/// <item>
|
|
||||||
/// <term>od5</term>
|
|
||||||
/// <description>Midpoint of the resulting range which will be achieved by a difficulty value of 5.</description>
|
|
||||||
/// </item>
|
|
||||||
/// <item>
|
|
||||||
/// <term>od10</term>
|
|
||||||
/// <description>Maximum of the resulting range which will be achieved by a difficulty value of 10.</description>
|
|
||||||
/// </item>
|
|
||||||
/// </list>
|
|
||||||
/// </param>
|
|
||||||
/// <returns>Value to which the difficulty value maps in the specified range.</returns>
|
|
||||||
public static double DifficultyRange(double difficulty, (double od0, double od5, double od10) range)
|
|
||||||
=> DifficultyRange(difficulty, range.od0, range.od5, range.od10);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ using System.ComponentModel.DataAnnotations;
|
|||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using osu.Framework.Localisation;
|
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
@ -17,7 +16,7 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
[ExcludeFromDynamicCompile]
|
[ExcludeFromDynamicCompile]
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class BeatmapInfo : IEquatable<BeatmapInfo>, IHasPrimaryKey
|
public class BeatmapInfo : IEquatable<BeatmapInfo>, IHasPrimaryKey, IBeatmapInfo
|
||||||
{
|
{
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
@ -152,18 +151,7 @@ namespace osu.Game.Beatmaps
|
|||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public DifficultyRating DifficultyRating => BeatmapDifficultyCache.GetDifficultyRating(StarDifficulty);
|
public DifficultyRating DifficultyRating => BeatmapDifficultyCache.GetDifficultyRating(StarDifficulty);
|
||||||
|
|
||||||
public string[] SearchableTerms => new[]
|
public override string ToString() => this.GetDisplayTitle();
|
||||||
{
|
|
||||||
Version
|
|
||||||
}.Concat(Metadata?.SearchableTerms ?? Enumerable.Empty<string>()).Where(s => !string.IsNullOrEmpty(s)).ToArray();
|
|
||||||
|
|
||||||
public override string ToString() => $"{Metadata ?? BeatmapSet?.Metadata} {versionString}".Trim();
|
|
||||||
|
|
||||||
public RomanisableString ToRomanisableString()
|
|
||||||
{
|
|
||||||
var metadata = (Metadata ?? BeatmapSet?.Metadata)?.ToRomanisableString() ?? new RomanisableString(null, null);
|
|
||||||
return new RomanisableString($"{metadata.GetPreferred(true)} {versionString}".Trim(), $"{metadata.GetPreferred(false)} {versionString}".Trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(BeatmapInfo other)
|
public bool Equals(BeatmapInfo other)
|
||||||
{
|
{
|
||||||
@ -187,5 +175,22 @@ namespace osu.Game.Beatmaps
|
|||||||
/// Returns a shallow-clone of this <see cref="BeatmapInfo"/>.
|
/// Returns a shallow-clone of this <see cref="BeatmapInfo"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BeatmapInfo Clone() => (BeatmapInfo)MemberwiseClone();
|
public BeatmapInfo Clone() => (BeatmapInfo)MemberwiseClone();
|
||||||
|
|
||||||
|
#region Implementation of IHasOnlineID
|
||||||
|
|
||||||
|
public int? OnlineID => OnlineBeatmapID;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Implementation of IBeatmapInfo
|
||||||
|
|
||||||
|
string IBeatmapInfo.DifficultyName => Version;
|
||||||
|
IBeatmapMetadataInfo IBeatmapInfo.Metadata => Metadata;
|
||||||
|
IBeatmapDifficultyInfo IBeatmapInfo.Difficulty => BaseDifficulty;
|
||||||
|
IBeatmapSetInfo IBeatmapInfo.BeatmapSet => BeatmapSet;
|
||||||
|
IRulesetInfo IBeatmapInfo.Ruleset => Ruleset;
|
||||||
|
double IBeatmapInfo.StarRating => StarDifficulty;
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
38
osu.Game/Beatmaps/BeatmapInfoExtensions.cs
Normal file
38
osu.Game/Beatmaps/BeatmapInfoExtensions.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
|
||||||
|
namespace osu.Game.Beatmaps
|
||||||
|
{
|
||||||
|
public static class BeatmapInfoExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A user-presentable display title representing this beatmap.
|
||||||
|
/// </summary>
|
||||||
|
public static string GetDisplayTitle(this IBeatmapInfo beatmapInfo) => $"{getClosestMetadata(beatmapInfo)} {getVersionString(beatmapInfo)}".Trim();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A user-presentable display title representing this beatmap, with localisation handling for potentially romanisable fields.
|
||||||
|
/// </summary>
|
||||||
|
public static RomanisableString GetDisplayTitleRomanisable(this IBeatmapInfo beatmapInfo)
|
||||||
|
{
|
||||||
|
var metadata = getClosestMetadata(beatmapInfo).GetDisplayTitleRomanisable();
|
||||||
|
var versionString = getVersionString(beatmapInfo);
|
||||||
|
|
||||||
|
return new RomanisableString($"{metadata.GetPreferred(true)} {versionString}".Trim(), $"{metadata.GetPreferred(false)} {versionString}".Trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string[] GetSearchableTerms(this IBeatmapInfo beatmapInfo) => new[]
|
||||||
|
{
|
||||||
|
beatmapInfo.DifficultyName
|
||||||
|
}.Concat(getClosestMetadata(beatmapInfo).GetSearchableTerms()).Where(s => !string.IsNullOrEmpty(s)).ToArray();
|
||||||
|
|
||||||
|
private static string getVersionString(IBeatmapInfo beatmapInfo) => string.IsNullOrEmpty(beatmapInfo.DifficultyName) ? string.Empty : $"[{beatmapInfo.DifficultyName}]";
|
||||||
|
|
||||||
|
// temporary helper methods until we figure which metadata should be where.
|
||||||
|
private static IBeatmapMetadataInfo getClosestMetadata(IBeatmapInfo beatmapInfo) =>
|
||||||
|
beatmapInfo.Metadata ?? beatmapInfo.BeatmapSet?.Metadata ?? new BeatmapMetadata();
|
||||||
|
}
|
||||||
|
}
|
@ -4,9 +4,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.Linq;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using osu.Framework.Localisation;
|
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
@ -15,7 +13,7 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
[ExcludeFromDynamicCompile]
|
[ExcludeFromDynamicCompile]
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class BeatmapMetadata : IEquatable<BeatmapMetadata>, IHasPrimaryKey
|
public class BeatmapMetadata : IEquatable<BeatmapMetadata>, IHasPrimaryKey, IBeatmapMetadataInfo
|
||||||
{
|
{
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
@ -83,50 +81,13 @@ namespace osu.Game.Beatmaps
|
|||||||
public int PreviewTime { get; set; }
|
public int PreviewTime { get; set; }
|
||||||
|
|
||||||
public string AudioFile { get; set; }
|
public string AudioFile { get; set; }
|
||||||
|
|
||||||
public string BackgroundFile { get; set; }
|
public string BackgroundFile { get; set; }
|
||||||
|
|
||||||
public override string ToString()
|
public bool Equals(BeatmapMetadata other) => ((IBeatmapMetadataInfo)this).Equals(other);
|
||||||
{
|
|
||||||
string author = Author == null ? string.Empty : $"({Author})";
|
|
||||||
return $"{Artist} - {Title} {author}".Trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
public RomanisableString ToRomanisableString()
|
public override string ToString() => this.GetDisplayTitle();
|
||||||
{
|
|
||||||
string author = Author == null ? string.Empty : $"({Author})";
|
|
||||||
var artistUnicode = string.IsNullOrEmpty(ArtistUnicode) ? Artist : ArtistUnicode;
|
|
||||||
var titleUnicode = string.IsNullOrEmpty(TitleUnicode) ? Title : TitleUnicode;
|
|
||||||
|
|
||||||
return new RomanisableString($"{artistUnicode} - {titleUnicode} {author}".Trim(), $"{Artist} - {Title} {author}".Trim());
|
string IBeatmapMetadataInfo.Author => AuthorString;
|
||||||
}
|
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public string[] SearchableTerms => new[]
|
|
||||||
{
|
|
||||||
Author?.Username,
|
|
||||||
Artist,
|
|
||||||
ArtistUnicode,
|
|
||||||
Title,
|
|
||||||
TitleUnicode,
|
|
||||||
Source,
|
|
||||||
Tags
|
|
||||||
}.Where(s => !string.IsNullOrEmpty(s)).ToArray();
|
|
||||||
|
|
||||||
public bool Equals(BeatmapMetadata other)
|
|
||||||
{
|
|
||||||
if (other == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return Title == other.Title
|
|
||||||
&& TitleUnicode == other.TitleUnicode
|
|
||||||
&& Artist == other.Artist
|
|
||||||
&& ArtistUnicode == other.ArtistUnicode
|
|
||||||
&& AuthorString == other.AuthorString
|
|
||||||
&& Source == other.Source
|
|
||||||
&& Tags == other.Tags
|
|
||||||
&& PreviewTime == other.PreviewTime
|
|
||||||
&& AudioFile == other.AudioFile
|
|
||||||
&& BackgroundFile == other.BackgroundFile;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
46
osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs
Normal file
46
osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
|
||||||
|
namespace osu.Game.Beatmaps
|
||||||
|
{
|
||||||
|
public static class BeatmapMetadataInfoExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An array of all searchable terms provided in contained metadata.
|
||||||
|
/// </summary>
|
||||||
|
public static string[] GetSearchableTerms(this IBeatmapMetadataInfo metadataInfo) => new[]
|
||||||
|
{
|
||||||
|
metadataInfo.Author,
|
||||||
|
metadataInfo.Artist,
|
||||||
|
metadataInfo.ArtistUnicode,
|
||||||
|
metadataInfo.Title,
|
||||||
|
metadataInfo.TitleUnicode,
|
||||||
|
metadataInfo.Source,
|
||||||
|
metadataInfo.Tags
|
||||||
|
}.Where(s => !string.IsNullOrEmpty(s)).ToArray();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A user-presentable display title representing this metadata.
|
||||||
|
/// </summary>
|
||||||
|
public static string GetDisplayTitle(this IBeatmapMetadataInfo metadataInfo)
|
||||||
|
{
|
||||||
|
string author = string.IsNullOrEmpty(metadataInfo.Author) ? string.Empty : $"({metadataInfo.Author})";
|
||||||
|
return $"{metadataInfo.Artist} - {metadataInfo.Title} {author}".Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A user-presentable display title representing this beatmap, with localisation handling for potentially romanisable fields.
|
||||||
|
/// </summary>
|
||||||
|
public static RomanisableString GetDisplayTitleRomanisable(this IBeatmapMetadataInfo metadataInfo)
|
||||||
|
{
|
||||||
|
string author = string.IsNullOrEmpty(metadataInfo.Author) ? string.Empty : $"({metadataInfo.Author})";
|
||||||
|
var artistUnicode = string.IsNullOrEmpty(metadataInfo.ArtistUnicode) ? metadataInfo.Artist : metadataInfo.ArtistUnicode;
|
||||||
|
var titleUnicode = string.IsNullOrEmpty(metadataInfo.TitleUnicode) ? metadataInfo.Title : metadataInfo.TitleUnicode;
|
||||||
|
|
||||||
|
return new RomanisableString($"{artistUnicode} - {titleUnicode} {author}".Trim(), $"{metadataInfo.Artist} - {metadataInfo.Title} {author}".Trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,7 @@ using osu.Game.IO;
|
|||||||
|
|
||||||
namespace osu.Game.Beatmaps
|
namespace osu.Game.Beatmaps
|
||||||
{
|
{
|
||||||
public class BeatmapSetFileInfo : INamedFileInfo, IHasPrimaryKey
|
public class BeatmapSetFileInfo : INamedFileInfo, IHasPrimaryKey, INamedFileUsage
|
||||||
{
|
{
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
@ -19,5 +19,7 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
[Required]
|
[Required]
|
||||||
public string Filename { get; set; }
|
public string Filename { get; set; }
|
||||||
|
|
||||||
|
public IFileInfo File => FileInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ using osu.Game.Database;
|
|||||||
namespace osu.Game.Beatmaps
|
namespace osu.Game.Beatmaps
|
||||||
{
|
{
|
||||||
[ExcludeFromDynamicCompile]
|
[ExcludeFromDynamicCompile]
|
||||||
public class BeatmapSetInfo : IHasPrimaryKey, IHasFiles<BeatmapSetFileInfo>, ISoftDelete, IEquatable<BeatmapSetInfo>
|
public class BeatmapSetInfo : IHasPrimaryKey, IHasFiles<BeatmapSetFileInfo>, ISoftDelete, IEquatable<BeatmapSetInfo>, IBeatmapSetInfo
|
||||||
{
|
{
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
@ -61,8 +61,6 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public string Hash { get; set; }
|
public string Hash { get; set; }
|
||||||
|
|
||||||
public string StoryboardFile => Files.Find(f => f.Filename.EndsWith(".osb", StringComparison.OrdinalIgnoreCase))?.Filename;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the storage path for the file in this beatmapset with the given filename, if any exists, otherwise null.
|
/// Returns the storage path for the file in this beatmapset with the given filename, if any exists, otherwise null.
|
||||||
/// The path returned is relative to the user file storage.
|
/// The path returned is relative to the user file storage.
|
||||||
@ -90,5 +88,19 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
return ReferenceEquals(this, other);
|
return ReferenceEquals(this, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Implementation of IHasOnlineID
|
||||||
|
|
||||||
|
public int? OnlineID => OnlineBeatmapSetID;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Implementation of IBeatmapSetInfo
|
||||||
|
|
||||||
|
IBeatmapMetadataInfo IBeatmapSetInfo.Metadata => Metadata;
|
||||||
|
IEnumerable<IBeatmapInfo> IBeatmapSetInfo.Beatmaps => Beatmaps;
|
||||||
|
IEnumerable<INamedFileUsage> IBeatmapSetInfo.Files => Files;
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
90
osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs
Normal file
90
osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace osu.Game.Beatmaps
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A representation of all top-level difficulty settings for a beatmap.
|
||||||
|
/// </summary>
|
||||||
|
public interface IBeatmapDifficultyInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The default value used for all difficulty settings except <see cref="SliderMultiplier"/> and <see cref="SliderTickRate"/>.
|
||||||
|
/// </summary>
|
||||||
|
const float DEFAULT_DIFFICULTY = 5;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The drain rate of the associated beatmap.
|
||||||
|
/// </summary>
|
||||||
|
float DrainRate { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The circle size of the associated beatmap.
|
||||||
|
/// </summary>
|
||||||
|
float CircleSize { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The overall difficulty of the associated beatmap.
|
||||||
|
/// </summary>
|
||||||
|
float OverallDifficulty { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The approach rate of the associated beatmap.
|
||||||
|
/// </summary>
|
||||||
|
float ApproachRate { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The slider multiplier of the associated beatmap.
|
||||||
|
/// </summary>
|
||||||
|
double SliderMultiplier { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The slider tick rate of the associated beatmap.
|
||||||
|
/// </summary>
|
||||||
|
double SliderTickRate { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maps a difficulty value [0, 10] to a two-piece linear range of values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="difficulty">The difficulty value to be mapped.</param>
|
||||||
|
/// <param name="min">Minimum of the resulting range which will be achieved by a difficulty value of 0.</param>
|
||||||
|
/// <param name="mid">Midpoint of the resulting range which will be achieved by a difficulty value of 5.</param>
|
||||||
|
/// <param name="max">Maximum of the resulting range which will be achieved by a difficulty value of 10.</param>
|
||||||
|
/// <returns>Value to which the difficulty value maps in the specified range.</returns>
|
||||||
|
static double DifficultyRange(double difficulty, double min, double mid, double max)
|
||||||
|
{
|
||||||
|
if (difficulty > 5)
|
||||||
|
return mid + (max - mid) * (difficulty - 5) / 5;
|
||||||
|
if (difficulty < 5)
|
||||||
|
return mid - (mid - min) * (5 - difficulty) / 5;
|
||||||
|
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maps a difficulty value [0, 10] to a two-piece linear range of values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="difficulty">The difficulty value to be mapped.</param>
|
||||||
|
/// <param name="range">The values that define the two linear ranges.
|
||||||
|
/// <list type="table">
|
||||||
|
/// <item>
|
||||||
|
/// <term>od0</term>
|
||||||
|
/// <description>Minimum of the resulting range which will be achieved by a difficulty value of 0.</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>od5</term>
|
||||||
|
/// <description>Midpoint of the resulting range which will be achieved by a difficulty value of 5.</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>od10</term>
|
||||||
|
/// <description>Maximum of the resulting range which will be achieved by a difficulty value of 10.</description>
|
||||||
|
/// </item>
|
||||||
|
/// </list>
|
||||||
|
/// </param>
|
||||||
|
/// <returns>Value to which the difficulty value maps in the specified range.</returns>
|
||||||
|
static double DifficultyRange(double difficulty, (double od0, double od5, double od10) range)
|
||||||
|
=> DifficultyRange(difficulty, range.od0, range.od5, range.od10);
|
||||||
|
}
|
||||||
|
}
|
66
osu.Game/Beatmaps/IBeatmapInfo.cs
Normal file
66
osu.Game/Beatmaps/IBeatmapInfo.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Game.Database;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace osu.Game.Beatmaps
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A single beatmap difficulty.
|
||||||
|
/// </summary>
|
||||||
|
public interface IBeatmapInfo : IHasOnlineID
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The user-specified name given to this beatmap.
|
||||||
|
/// </summary>
|
||||||
|
string DifficultyName { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The metadata representing this beatmap. May be shared between multiple beatmaps.
|
||||||
|
/// </summary>
|
||||||
|
IBeatmapMetadataInfo? Metadata { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The difficulty settings for this beatmap.
|
||||||
|
/// </summary>
|
||||||
|
IBeatmapDifficultyInfo Difficulty { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The beatmap set this beatmap is part of.
|
||||||
|
/// </summary>
|
||||||
|
IBeatmapSetInfo? BeatmapSet { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The playable length in milliseconds of this beatmap.
|
||||||
|
/// </summary>
|
||||||
|
double Length { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The most common BPM of this beatmap.
|
||||||
|
/// </summary>
|
||||||
|
double BPM { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The SHA-256 hash representing this beatmap's contents.
|
||||||
|
/// </summary>
|
||||||
|
string Hash { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MD5 is kept for legacy support (matching against replays etc.).
|
||||||
|
/// </summary>
|
||||||
|
string MD5Hash { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ruleset this beatmap was made for.
|
||||||
|
/// </summary>
|
||||||
|
IRulesetInfo Ruleset { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The basic star rating for this beatmap (with no mods applied).
|
||||||
|
/// </summary>
|
||||||
|
double StarRating { get; }
|
||||||
|
}
|
||||||
|
}
|
83
osu.Game/Beatmaps/IBeatmapMetadataInfo.cs
Normal file
83
osu.Game/Beatmaps/IBeatmapMetadataInfo.cs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace osu.Game.Beatmaps
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Metadata representing a beatmap. May be shared between multiple beatmap difficulties.
|
||||||
|
/// </summary>
|
||||||
|
public interface IBeatmapMetadataInfo : IEquatable<IBeatmapMetadataInfo>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The romanised title of this beatmap.
|
||||||
|
/// </summary>
|
||||||
|
string Title { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The unicode title of this beatmap.
|
||||||
|
/// </summary>
|
||||||
|
string TitleUnicode { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The romanised artist of this beatmap.
|
||||||
|
/// </summary>
|
||||||
|
string Artist { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The unicode artist of this beatmap.
|
||||||
|
/// </summary>
|
||||||
|
string ArtistUnicode { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The author of this beatmap.
|
||||||
|
/// </summary>
|
||||||
|
string Author { get; } // eventually should be linked to a persisted User.
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The source of this beatmap.
|
||||||
|
/// </summary>
|
||||||
|
string Source { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The tags of this beatmap.
|
||||||
|
/// </summary>
|
||||||
|
string Tags { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time in milliseconds to begin playing the track for preview purposes.
|
||||||
|
/// If -1, the track should begin playing at 40% of its length.
|
||||||
|
/// </summary>
|
||||||
|
int PreviewTime { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The filename of the audio file consumed by this beatmap.
|
||||||
|
/// </summary>
|
||||||
|
string AudioFile { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The filename of the background image file consumed by this beatmap.
|
||||||
|
/// </summary>
|
||||||
|
string BackgroundFile { get; }
|
||||||
|
|
||||||
|
bool IEquatable<IBeatmapMetadataInfo>.Equals(IBeatmapMetadataInfo? other)
|
||||||
|
{
|
||||||
|
if (other == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return Title == other.Title
|
||||||
|
&& TitleUnicode == other.TitleUnicode
|
||||||
|
&& Artist == other.Artist
|
||||||
|
&& ArtistUnicode == other.ArtistUnicode
|
||||||
|
&& Author == other.Author
|
||||||
|
&& Source == other.Source
|
||||||
|
&& Tags == other.Tags
|
||||||
|
&& PreviewTime == other.PreviewTime
|
||||||
|
&& AudioFile == other.AudioFile
|
||||||
|
&& BackgroundFile == other.BackgroundFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
osu.Game/Beatmaps/IBeatmapSetInfo.cs
Normal file
52
osu.Game/Beatmaps/IBeatmapSetInfo.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Game.Database;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace osu.Game.Beatmaps
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A representation of a collection of beatmap difficulties, generally packaged as an ".osz" archive.
|
||||||
|
/// </summary>
|
||||||
|
public interface IBeatmapSetInfo : IHasOnlineID
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The date when this beatmap was imported.
|
||||||
|
/// </summary>
|
||||||
|
DateTimeOffset DateAdded { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The best-effort metadata representing this set. In the case metadata differs between contained beatmaps, one is arbitrarily chosen.
|
||||||
|
/// </summary>
|
||||||
|
IBeatmapMetadataInfo? Metadata { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// All beatmaps contained in this set.
|
||||||
|
/// </summary>
|
||||||
|
IEnumerable<IBeatmapInfo> Beatmaps { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// All files used by this set.
|
||||||
|
/// </summary>
|
||||||
|
IEnumerable<INamedFileUsage> Files { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum star difficulty of all beatmaps in this set.
|
||||||
|
/// </summary>
|
||||||
|
double MaxStarDifficulty { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum playable length in milliseconds of all beatmaps in this set.
|
||||||
|
/// </summary>
|
||||||
|
double MaxLength { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum BPM of all beatmaps in this set.
|
||||||
|
/// </summary>
|
||||||
|
double MaxBPM { get; }
|
||||||
|
}
|
||||||
|
}
|
@ -201,12 +201,14 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
var decoder = Decoder.GetDecoder<Storyboard>(stream);
|
var decoder = Decoder.GetDecoder<Storyboard>(stream);
|
||||||
|
|
||||||
|
var storyboardFilename = BeatmapSetInfo?.Files.FirstOrDefault(f => f.Filename.EndsWith(".osb", StringComparison.OrdinalIgnoreCase))?.Filename;
|
||||||
|
|
||||||
// todo: support loading from both set-wide storyboard *and* beatmap specific.
|
// todo: support loading from both set-wide storyboard *and* beatmap specific.
|
||||||
if (BeatmapSetInfo?.StoryboardFile == null)
|
if (string.IsNullOrEmpty(storyboardFilename))
|
||||||
storyboard = decoder.Decode(stream);
|
storyboard = decoder.Decode(stream);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
using (var secondaryStream = new LineBufferedReader(GetStream(BeatmapSetInfo.GetPathForFile(BeatmapSetInfo.StoryboardFile))))
|
using (var secondaryStream = new LineBufferedReader(GetStream(BeatmapSetInfo.GetPathForFile(storyboardFilename))))
|
||||||
storyboard = decoder.Decode(stream, secondaryStream);
|
storyboard = decoder.Decode(stream, secondaryStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
osu.Game/Database/IHasOnlineID.cs
Normal file
15
osu.Game/Database/IHasOnlineID.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace osu.Game.Database
|
||||||
|
{
|
||||||
|
public interface IHasOnlineID
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The server-side ID representing this instance, if one exists.
|
||||||
|
/// </summary>
|
||||||
|
int? OnlineID { get; }
|
||||||
|
}
|
||||||
|
}
|
25
osu.Game/Database/INamedFileUsage.cs
Normal file
25
osu.Game/Database/INamedFileUsage.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Game.IO;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace osu.Game.Database
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A usage of a file, with a local filename attached.
|
||||||
|
/// </summary>
|
||||||
|
public interface INamedFileUsage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The underlying file on disk.
|
||||||
|
/// </summary>
|
||||||
|
IFileInfo File { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The filename for this usage.
|
||||||
|
/// </summary>
|
||||||
|
string Filename { get; }
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@ using osu.Game.Database;
|
|||||||
|
|
||||||
namespace osu.Game.IO
|
namespace osu.Game.IO
|
||||||
{
|
{
|
||||||
public class FileInfo : IHasPrimaryKey
|
public class FileInfo : IHasPrimaryKey, IFileInfo
|
||||||
{
|
{
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
|
18
osu.Game/IO/IFileInfo.cs
Normal file
18
osu.Game/IO/IFileInfo.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace osu.Game.IO
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A representation of a tracked file.
|
||||||
|
/// </summary>
|
||||||
|
public interface IFileInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// SHA-256 hash of the file content.
|
||||||
|
/// </summary>
|
||||||
|
string Hash { get; }
|
||||||
|
}
|
||||||
|
}
|
@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Music
|
|||||||
{
|
{
|
||||||
Padding = new MarginPadding { Left = 5 };
|
Padding = new MarginPadding { Left = 5 };
|
||||||
|
|
||||||
FilterTerms = item.Metadata.SearchableTerms;
|
FilterTerms = item.Metadata.GetSearchableTerms();
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
|
47
osu.Game/Rulesets/IRulesetInfo.cs
Normal file
47
osu.Game/Rulesets/IRulesetInfo.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Game.Database;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A representation of a ruleset's metadata.
|
||||||
|
/// </summary>
|
||||||
|
public interface IRulesetInfo : IHasOnlineID
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The user-exposed name of this ruleset.
|
||||||
|
/// </summary>
|
||||||
|
string Name { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An acronym defined by the ruleset that can be used as a permanent identifier.
|
||||||
|
/// </summary>
|
||||||
|
string ShortName { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A string representation of this ruleset, to be used with reflection to instantiate the ruleset represented by this metadata.
|
||||||
|
/// </summary>
|
||||||
|
string InstantiationInfo { get; }
|
||||||
|
|
||||||
|
Ruleset? CreateInstance()
|
||||||
|
{
|
||||||
|
var type = Type.GetType(InstantiationInfo);
|
||||||
|
|
||||||
|
if (type == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var ruleset = Activator.CreateInstance(type) as Ruleset;
|
||||||
|
|
||||||
|
// overwrite the pre-populated RulesetInfo with a potentially database attached copy.
|
||||||
|
// TODO: figure if we still want/need this after switching to realm.
|
||||||
|
// ruleset.RulesetInfo = this;
|
||||||
|
|
||||||
|
return ruleset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@ using osu.Framework.Testing;
|
|||||||
namespace osu.Game.Rulesets
|
namespace osu.Game.Rulesets
|
||||||
{
|
{
|
||||||
[ExcludeFromDynamicCompile]
|
[ExcludeFromDynamicCompile]
|
||||||
public class RulesetInfo : IEquatable<RulesetInfo>
|
public class RulesetInfo : IEquatable<RulesetInfo>, IRulesetInfo
|
||||||
{
|
{
|
||||||
public int? ID { get; set; }
|
public int? ID { get; set; }
|
||||||
|
|
||||||
@ -54,5 +54,11 @@ namespace osu.Game.Rulesets
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() => Name ?? $"{Name} ({ShortName}) ID: {ID}";
|
public override string ToString() => Name ?? $"{Name} ({ShortName}) ID: {ID}";
|
||||||
|
|
||||||
|
#region Implementation of IHasOnlineID
|
||||||
|
|
||||||
|
public int? OnlineID => ID;
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
.First()
|
.First()
|
||||||
)));
|
)));
|
||||||
|
|
||||||
targetMinimumHealth = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, min_health_target, mid_health_target, max_health_target);
|
targetMinimumHealth = IBeatmapDifficultyInfo.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, min_health_target, mid_health_target, max_health_target);
|
||||||
|
|
||||||
// Add back a portion of the amount of HP to be drained, depending on the lenience requested.
|
// Add back a portion of the amount of HP to be drained, depending on the lenience requested.
|
||||||
targetMinimumHealth += drainLenience * (1 - targetMinimumHealth);
|
targetMinimumHealth += drainLenience * (1 - targetMinimumHealth);
|
||||||
|
@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
{
|
{
|
||||||
foreach (var range in GetRanges())
|
foreach (var range in GetRanges())
|
||||||
{
|
{
|
||||||
var value = BeatmapDifficulty.DifficultyRange(difficulty, (range.Min, range.Average, range.Max));
|
var value = IBeatmapDifficultyInfo.DifficultyRange(difficulty, (range.Min, range.Average, range.Max));
|
||||||
|
|
||||||
switch (range.Result)
|
switch (range.Result)
|
||||||
{
|
{
|
||||||
|
@ -108,7 +108,7 @@ namespace osu.Game.Screens.OnlinePlay
|
|||||||
difficultyIconContainer.Child = new DifficultyIcon(beatmap.Value, ruleset.Value, requiredMods) { Size = new Vector2(32) };
|
difficultyIconContainer.Child = new DifficultyIcon(beatmap.Value, ruleset.Value, requiredMods) { Size = new Vector2(32) };
|
||||||
|
|
||||||
beatmapText.Clear();
|
beatmapText.Clear();
|
||||||
beatmapText.AddLink(Item.Beatmap.Value.ToRomanisableString(), LinkAction.OpenBeatmap, Item.Beatmap.Value.OnlineBeatmapID.ToString(), null, text =>
|
beatmapText.AddLink(Item.Beatmap.Value.GetDisplayTitleRomanisable(), LinkAction.OpenBeatmap, Item.Beatmap.Value.OnlineBeatmapID.ToString(), null, text =>
|
||||||
{
|
{
|
||||||
text.Truncate = true;
|
text.Truncate = true;
|
||||||
text.RelativeSizeAxes = Axes.X;
|
text.RelativeSizeAxes = Axes.X;
|
||||||
|
@ -379,7 +379,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
|||||||
if (item.NewValue?.Beatmap.Value != null)
|
if (item.NewValue?.Beatmap.Value != null)
|
||||||
{
|
{
|
||||||
statusText.Text = "Currently playing ";
|
statusText.Text = "Currently playing ";
|
||||||
beatmapText.AddLink(item.NewValue.Beatmap.Value.ToRomanisableString(),
|
beatmapText.AddLink(item.NewValue.Beatmap.Value.GetDisplayTitleRomanisable(),
|
||||||
LinkAction.OpenBeatmap,
|
LinkAction.OpenBeatmap,
|
||||||
item.NewValue.Beatmap.Value.OnlineBeatmapID.ToString(),
|
item.NewValue.Beatmap.Value.OnlineBeatmapID.ToString(),
|
||||||
creationParameters: s =>
|
creationParameters: s =>
|
||||||
|
@ -57,7 +57,7 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
|
|
||||||
if (match)
|
if (match)
|
||||||
{
|
{
|
||||||
var terms = BeatmapInfo.SearchableTerms;
|
var terms = BeatmapInfo.GetSearchableTerms();
|
||||||
|
|
||||||
foreach (var criteriaTerm in criteria.SearchTerms)
|
foreach (var criteriaTerm in criteria.SearchTerms)
|
||||||
match &= terms.Any(term => term.Contains(criteriaTerm, StringComparison.InvariantCultureIgnoreCase));
|
match &= terms.Any(term => term.Contains(criteriaTerm, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
Loading…
Reference in New Issue
Block a user