mirror of
https://github.com/ppy/osu.git
synced 2024-12-13 07:43:00 +08:00
Add new methods to ruleset for quicker mod lookups
This commit is contained in:
parent
e66d76d26e
commit
4d0530ca9d
@ -39,5 +39,11 @@ namespace osu.Game.Benchmarks
|
||||
{
|
||||
ruleset.GetAllMods().Consume(new Consumer());
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void BenchmarkGetAllModsForReference()
|
||||
{
|
||||
ruleset.GetAllModsForReference().Consume(new Consumer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ namespace osu.Game.Tournament.Components
|
||||
}
|
||||
|
||||
var ruleset = rulesets.GetRuleset(ladderInfo.Ruleset.Value?.ID ?? 0);
|
||||
var modIcon = ruleset?.CreateInstance().GetAllMods().FirstOrDefault(mod => mod.Acronym == modAcronym);
|
||||
var modIcon = ruleset?.CreateInstance().GetModForAcronym(modAcronym);
|
||||
|
||||
if (modIcon == null)
|
||||
return;
|
||||
|
@ -48,7 +48,7 @@ namespace osu.Game.Online.API
|
||||
|
||||
public Mod ToMod(Ruleset ruleset)
|
||||
{
|
||||
Mod resultMod = ruleset.GetAllMods().FirstOrDefault(m => m.Acronym == Acronym);
|
||||
Mod resultMod = ruleset.GetModForAcronym(Acronym);
|
||||
|
||||
if (resultMod == null)
|
||||
throw new InvalidOperationException($"There is no mod in the ruleset ({ruleset.ShortName}) matching the acronym {Acronym}.");
|
||||
|
@ -23,7 +23,7 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
|
||||
var rulesetInstance = ruleset.CreateInstance();
|
||||
|
||||
var mods = Mods != null ? rulesetInstance.GetAllMods().Where(mod => Mods.Contains(mod.Acronym)).ToArray() : Array.Empty<Mod>();
|
||||
var mods = Mods != null ? Mods.Select(acronym => rulesetInstance.GetModForAcronym(acronym)).Where(m => m != null).ToArray() : Array.Empty<Mod>();
|
||||
|
||||
// all API scores provided by this class are considered to be legacy.
|
||||
mods = mods.Append(rulesetInstance.GetAllMods().OfType<ModClassic>().Single()).ToArray();
|
||||
|
@ -54,7 +54,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
return;
|
||||
|
||||
modsContainer.Add(new ModButton(new ModNoMod()));
|
||||
modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllMods().Where(m => m.UserPlayable).Select(m => new ModButton(m)));
|
||||
modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllModsForReference().Where(m => m.UserPlayable).Select(m => new ModButton(m)));
|
||||
|
||||
modsContainer.ForEach(button =>
|
||||
{
|
||||
|
@ -107,7 +107,7 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
var incompatibleTypes = mod.IncompatibleMods;
|
||||
|
||||
var allMods = ruleset.Value.CreateInstance().GetAllMods();
|
||||
var allMods = ruleset.Value.CreateInstance().GetAllModsForReference();
|
||||
|
||||
incompatibleMods.Value = allMods.Where(m => m.GetType() != mod.GetType() && incompatibleTypes.Any(t => t.IsInstanceOfType(m))).ToList();
|
||||
incompatibleText.Text = incompatibleMods.Value.Any() ? "Incompatible with:" : "Compatible with all mods";
|
||||
|
@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
@ -23,6 +24,7 @@ using osu.Game.Scoring;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Users;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.EnumExtensions;
|
||||
using osu.Framework.Testing;
|
||||
@ -38,6 +40,13 @@ namespace osu.Game.Rulesets
|
||||
{
|
||||
public RulesetInfo RulesetInfo { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns fresh instances of all mods.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This comes with considerable allocation overhead. If only accessing for reference purposes (ie. not changing bindables / settings)
|
||||
/// use <see cref="GetAllModsForReference"/> instead.
|
||||
/// </remarks>
|
||||
public IEnumerable<Mod> GetAllMods() => Enum.GetValues(typeof(ModType)).Cast<ModType>()
|
||||
// Confine all mods of each mod type into a single IEnumerable<Mod>
|
||||
.SelectMany(GetModsFor)
|
||||
@ -46,6 +55,37 @@ namespace osu.Game.Rulesets
|
||||
// Resolve MultiMods as their .Mods property
|
||||
.SelectMany(mod => (mod as MultiMod)?.Mods ?? new[] { mod });
|
||||
|
||||
private static readonly ConcurrentDictionary<int, Mod[]> mod_reference_cache = new ConcurrentDictionary<int, Mod[]>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns all mods for a query-only purpose.
|
||||
/// Bindables should not be considered usable when retrieving via this method (use <see cref="GetAllMods"/> instead).
|
||||
/// </summary>
|
||||
public IEnumerable<Mod> GetAllModsForReference()
|
||||
{
|
||||
if (!(RulesetInfo.ID is int id))
|
||||
return GetAllMods();
|
||||
|
||||
if (!mod_reference_cache.TryGetValue(id, out var mods))
|
||||
mod_reference_cache[id] = mods = GetAllMods().ToArray();
|
||||
|
||||
return mods;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a fresh instance of the mod matching the specified acronym.
|
||||
/// </summary>
|
||||
/// <param name="acronym">The acronym to query for .</param>
|
||||
public Mod GetModForAcronym(string acronym)
|
||||
{
|
||||
var type = GetAllModsForReference().FirstOrDefault(m => m.Acronym == acronym)?.GetType();
|
||||
|
||||
if (type != null)
|
||||
return (Mod)Activator.CreateInstance(type);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract IEnumerable<Mod> GetModsFor(ModType type);
|
||||
|
||||
/// <summary>
|
||||
|
Loading…
Reference in New Issue
Block a user