mirror of
https://github.com/osukey/osukey.git
synced 2025-07-01 16:29:58 +09:00
Various updates to ruleset and primary key usages to move closer to realm support
This commit is contained in:
@ -505,7 +505,7 @@ namespace osu.Game.Tests.Database
|
|||||||
RunTestWithRealmAsync(async (realmFactory, storage) =>
|
RunTestWithRealmAsync(async (realmFactory, storage) =>
|
||||||
{
|
{
|
||||||
using var importer = new NonOptimisedBeatmapImporter(realmFactory, storage);
|
using var importer = new NonOptimisedBeatmapImporter(realmFactory, storage);
|
||||||
using var store = new RealmRulesetStore(realmFactory, storage);
|
using var store = new RulesetStore(realmFactory, storage);
|
||||||
|
|
||||||
var imported = await LoadOszIntoStore(importer, realmFactory.Context);
|
var imported = await LoadOszIntoStore(importer, realmFactory.Context);
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
InputManager.MoveMouseTo(item.ScreenSpaceDrawQuad.Centre);
|
InputManager.MoveMouseTo(item.ScreenSpaceDrawQuad.Centre);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddAssert("song 1 is 5th", () => beatmapSets[4] == first);
|
AddAssert("song 1 is 5th", () => beatmapSets[4].Equals(first));
|
||||||
|
|
||||||
AddStep("release handle", () => InputManager.ReleaseButton(MouseButton.Left));
|
AddStep("release handle", () => InputManager.ReleaseButton(MouseButton.Left));
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ namespace osu.Game.Beatmaps
|
|||||||
}
|
}
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public BeatmapMetadata Metadata => BeatmapInfo?.Metadata ?? BeatmapInfo?.BeatmapSet?.Metadata;
|
public BeatmapMetadata Metadata => BeatmapInfo.Metadata;
|
||||||
|
|
||||||
public ControlPointInfo ControlPointInfo { get; set; } = new ControlPointInfo();
|
public ControlPointInfo ControlPointInfo { get; set; } = new ControlPointInfo();
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// Handles general operations related to global beatmap management.
|
/// Handles general operations related to global beatmap management.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ExcludeFromDynamicCompile]
|
[ExcludeFromDynamicCompile]
|
||||||
public class BeatmapManager : IModelManager<BeatmapSetInfo>, IModelFileManager<BeatmapSetInfo, BeatmapSetFileInfo>, IModelImporter<BeatmapSetInfo>, IWorkingBeatmapCache, IDisposable
|
public class BeatmapManager : IModelManager<BeatmapSetInfo>, IModelFileManager<BeatmapSetInfo, RealmNamedFileUsage>, IModelImporter<BeatmapSetInfo>, IWorkingBeatmapCache, IDisposable
|
||||||
{
|
{
|
||||||
public ITrackStore BeatmapTrackStore { get; }
|
public ITrackStore BeatmapTrackStore { get; }
|
||||||
|
|
||||||
@ -294,12 +294,12 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
#region Implementation of IModelFileManager<in BeatmapSetInfo,in BeatmapSetFileInfo>
|
#region Implementation of IModelFileManager<in BeatmapSetInfo,in BeatmapSetFileInfo>
|
||||||
|
|
||||||
public void ReplaceFile(BeatmapSetInfo model, BeatmapSetFileInfo file, Stream contents)
|
public void ReplaceFile(BeatmapSetInfo model, RealmNamedFileUsage file, Stream contents)
|
||||||
{
|
{
|
||||||
beatmapModelManager.ReplaceFile(model, file, contents);
|
beatmapModelManager.ReplaceFile(model, file, contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteFile(BeatmapSetInfo model, BeatmapSetFileInfo file)
|
public void DeleteFile(BeatmapSetInfo model, RealmNamedFileUsage file)
|
||||||
{
|
{
|
||||||
beatmapModelManager.DeleteFile(model, file);
|
beatmapModelManager.DeleteFile(model, file);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -16,6 +17,7 @@ using osu.Framework.Threading;
|
|||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
|
using osu.Game.Stores;
|
||||||
using SharpCompress.Compressors;
|
using SharpCompress.Compressors;
|
||||||
using SharpCompress.Compressors.BZip2;
|
using SharpCompress.Compressors.BZip2;
|
||||||
|
|
||||||
@ -83,15 +85,14 @@ namespace osu.Game.Beatmaps
|
|||||||
if (res != null)
|
if (res != null)
|
||||||
{
|
{
|
||||||
beatmapInfo.Status = res.Status;
|
beatmapInfo.Status = res.Status;
|
||||||
|
|
||||||
|
Debug.Assert(beatmapInfo.BeatmapSet != null);
|
||||||
|
|
||||||
beatmapInfo.BeatmapSet.Status = res.BeatmapSet?.Status ?? BeatmapOnlineStatus.None;
|
beatmapInfo.BeatmapSet.Status = res.BeatmapSet?.Status ?? BeatmapOnlineStatus.None;
|
||||||
beatmapInfo.BeatmapSet.OnlineID = res.OnlineBeatmapSetID;
|
beatmapInfo.BeatmapSet.OnlineID = res.OnlineBeatmapSetID;
|
||||||
beatmapInfo.OnlineID = res.OnlineID;
|
beatmapInfo.OnlineID = res.OnlineID;
|
||||||
|
|
||||||
if (beatmapInfo.Metadata != null)
|
beatmapInfo.Metadata.Author.OnlineID = res.AuthorID;
|
||||||
beatmapInfo.Metadata.AuthorID = res.AuthorID;
|
|
||||||
|
|
||||||
if (beatmapInfo.BeatmapSet.Metadata != null)
|
|
||||||
beatmapInfo.BeatmapSet.Metadata.AuthorID = res.AuthorID;
|
|
||||||
|
|
||||||
logForModel(set, $"Online retrieval mapped {beatmapInfo} to {res.OnlineBeatmapSetID} / {res.OnlineID}.");
|
logForModel(set, $"Online retrieval mapped {beatmapInfo} to {res.OnlineBeatmapSetID} / {res.OnlineID}.");
|
||||||
}
|
}
|
||||||
@ -185,15 +186,14 @@ namespace osu.Game.Beatmaps
|
|||||||
var status = (BeatmapOnlineStatus)reader.GetByte(2);
|
var status = (BeatmapOnlineStatus)reader.GetByte(2);
|
||||||
|
|
||||||
beatmapInfo.Status = status;
|
beatmapInfo.Status = status;
|
||||||
|
|
||||||
|
Debug.Assert(beatmapInfo.BeatmapSet != null);
|
||||||
|
|
||||||
beatmapInfo.BeatmapSet.Status = status;
|
beatmapInfo.BeatmapSet.Status = status;
|
||||||
beatmapInfo.BeatmapSet.OnlineID = reader.GetInt32(0);
|
beatmapInfo.BeatmapSet.OnlineID = reader.GetInt32(0);
|
||||||
beatmapInfo.OnlineID = reader.GetInt32(1);
|
beatmapInfo.OnlineID = reader.GetInt32(1);
|
||||||
|
|
||||||
if (beatmapInfo.Metadata != null)
|
beatmapInfo.Metadata.Author.OnlineID = reader.GetInt32(3);
|
||||||
beatmapInfo.Metadata.AuthorID = reader.GetInt32(3);
|
|
||||||
|
|
||||||
if (beatmapInfo.BeatmapSet.Metadata != null)
|
|
||||||
beatmapInfo.BeatmapSet.Metadata.AuthorID = reader.GetInt32(3);
|
|
||||||
|
|
||||||
logForModel(set, $"Cached local retrieval for {beatmapInfo}.");
|
logForModel(set, $"Cached local retrieval for {beatmapInfo}.");
|
||||||
return true;
|
return true;
|
||||||
@ -211,7 +211,7 @@ namespace osu.Game.Beatmaps
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void logForModel(BeatmapSetInfo set, string message) =>
|
private void logForModel(BeatmapSetInfo set, string message) =>
|
||||||
ArchiveModelManager<BeatmapSetInfo, BeatmapSetFileInfo>.LogForModel(set, $"[{nameof(BeatmapOnlineLookupQueue)}] {message}");
|
RealmArchiveModelImporter<BeatmapSetInfo>.LogForModel(set, $"[{nameof(BeatmapOnlineLookupQueue)}] {message}");
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
@ -79,7 +79,7 @@ namespace osu.Game.Beatmaps
|
|||||||
// if there are no files, presume the full beatmap info has not yet been fetched from the database.
|
// if there are no files, presume the full beatmap info has not yet been fetched from the database.
|
||||||
if (beatmapInfo?.BeatmapSet?.Files.Count == 0)
|
if (beatmapInfo?.BeatmapSet?.Files.Count == 0)
|
||||||
{
|
{
|
||||||
int lookupId = beatmapInfo.ID;
|
var lookupId = beatmapInfo.ID;
|
||||||
beatmapInfo = BeatmapManager.QueryBeatmap(b => b.ID == lookupId);
|
beatmapInfo = BeatmapManager.QueryBeatmap(b => b.ID == lookupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +93,8 @@ namespace osu.Game.Beatmaps
|
|||||||
if (working != null)
|
if (working != null)
|
||||||
return working;
|
return working;
|
||||||
|
|
||||||
beatmapInfo.Metadata ??= beatmapInfo.BeatmapSet.Metadata;
|
// TODO: is this still required..?
|
||||||
|
//beatmapInfo.Metadata ??= beatmapInfo.BeatmapSet.Metadata;
|
||||||
|
|
||||||
workingCache.Add(working = new BeatmapManagerWorkingBeatmap(beatmapInfo, this));
|
workingCache.Add(working = new BeatmapManagerWorkingBeatmap(beatmapInfo, this));
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ namespace osu.Game.Database
|
|||||||
{
|
{
|
||||||
protected readonly Storage Storage;
|
protected readonly Storage Storage;
|
||||||
|
|
||||||
protected readonly IDatabaseContextFactory ContextFactory;
|
protected readonly RealmContextFactory ContextFactory;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Refresh an instance potentially from a different thread with a local context-tracked instance.
|
/// Refresh an instance potentially from a different thread with a local context-tracked instance.
|
||||||
@ -36,7 +36,7 @@ namespace osu.Game.Database
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DatabaseBackedStore(IDatabaseContextFactory contextFactory, Storage storage = null)
|
protected DatabaseBackedStore(RealmContextFactory contextFactory, Storage storage = null)
|
||||||
{
|
{
|
||||||
ContextFactory = contextFactory;
|
ContextFactory = contextFactory;
|
||||||
Storage = storage;
|
Storage = storage;
|
||||||
|
@ -14,7 +14,7 @@ using osu.Game.Overlays.Notifications;
|
|||||||
namespace osu.Game.Database
|
namespace osu.Game.Database
|
||||||
{
|
{
|
||||||
public abstract class ModelDownloader<TModel, T> : IModelDownloader<T>
|
public abstract class ModelDownloader<TModel, T> : IModelDownloader<T>
|
||||||
where TModel : class, IHasPrimaryKey, ISoftDelete, IEquatable<TModel>, T
|
where TModel : class, IHasGuidPrimaryKey, ISoftDelete, IEquatable<TModel>, T
|
||||||
where T : class
|
where T : class
|
||||||
{
|
{
|
||||||
public Action<Notification> PostNotification { protected get; set; }
|
public Action<Notification> PostNotification { protected get; set; }
|
||||||
|
@ -78,7 +78,7 @@ namespace osu.Game.Input.Bindings
|
|||||||
{
|
{
|
||||||
var defaults = DefaultKeyBindings.ToList();
|
var defaults = DefaultKeyBindings.ToList();
|
||||||
|
|
||||||
if (ruleset != null && !ruleset.ID.HasValue)
|
if (ruleset != null && !ruleset.IsManaged)
|
||||||
// some tests instantiate a ruleset which is not present in the database.
|
// some tests instantiate a ruleset which is not present in the database.
|
||||||
// in these cases we still want key bindings to work, but matching to database instances would result in none being present,
|
// in these cases we still want key bindings to work, but matching to database instances would result in none being present,
|
||||||
// so let's populate the defaults directly.
|
// so let's populate the defaults directly.
|
||||||
|
@ -190,9 +190,6 @@ namespace osu.Game
|
|||||||
|
|
||||||
runMigrations();
|
runMigrations();
|
||||||
|
|
||||||
dependencies.Cache(RulesetStore = new RulesetStore(contextFactory, Storage));
|
|
||||||
dependencies.CacheAs<IRulesetStore>(RulesetStore);
|
|
||||||
|
|
||||||
dependencies.Cache(realmFactory = new RealmContextFactory(Storage, "client", contextFactory));
|
dependencies.Cache(realmFactory = new RealmContextFactory(Storage, "client", contextFactory));
|
||||||
|
|
||||||
new EFToRealmMigrator(contextFactory, realmFactory, LocalConfig).Run();
|
new EFToRealmMigrator(contextFactory, realmFactory, LocalConfig).Run();
|
||||||
@ -227,24 +224,12 @@ namespace osu.Game
|
|||||||
dependencies.Cache(RulesetStore = new RulesetStore(realmFactory, Storage));
|
dependencies.Cache(RulesetStore = new RulesetStore(realmFactory, Storage));
|
||||||
|
|
||||||
// ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup()
|
// ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup()
|
||||||
dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, contextFactory, Scheduler, Host, () => difficultyCache, LocalConfig));
|
dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, API, realmFactory, Scheduler, Host, () => difficultyCache, LocalConfig));
|
||||||
dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, contextFactory, RulesetStore, API, Audio, Resources, Host, defaultBeatmap, performOnlineLookups: true));
|
dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, realmFactory, RulesetStore, API, Audio, Resources, Host, defaultBeatmap, performOnlineLookups: true));
|
||||||
|
|
||||||
dependencies.Cache(BeatmapDownloader = new BeatmapModelDownloader(BeatmapManager, API));
|
dependencies.Cache(BeatmapDownloader = new BeatmapModelDownloader(BeatmapManager, API));
|
||||||
dependencies.Cache(ScoreDownloader = new ScoreModelDownloader(ScoreManager, API));
|
dependencies.Cache(ScoreDownloader = new ScoreModelDownloader(ScoreManager, API));
|
||||||
|
|
||||||
// this should likely be moved to ArchiveModelManager when another case appears where it is necessary
|
|
||||||
// to have inter-dependent model managers. this could be obtained with an IHasForeign<T> interface to
|
|
||||||
// allow lookups to be done on the child (ScoreManager in this case) to perform the cascading delete.
|
|
||||||
List<ScoreInfo> getBeatmapScores(BeatmapSetInfo set)
|
|
||||||
{
|
|
||||||
var beatmapIds = BeatmapManager.QueryBeatmaps(b => b.BeatmapSetInfoID == set.ID).Select(b => b.ID).ToList();
|
|
||||||
return ScoreManager.QueryScores(s => beatmapIds.Contains(s.BeatmapInfo.ID)).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
BeatmapManager.ItemRemoved += item => ScoreManager.Delete(getBeatmapScores(item), true);
|
|
||||||
BeatmapManager.ItemUpdated += item => ScoreManager.Undelete(getBeatmapScores(item), true);
|
|
||||||
|
|
||||||
dependencies.Cache(difficultyCache = new BeatmapDifficultyCache());
|
dependencies.Cache(difficultyCache = new BeatmapDifficultyCache());
|
||||||
AddInternal(difficultyCache);
|
AddInternal(difficultyCache);
|
||||||
|
|
||||||
@ -438,7 +423,9 @@ namespace osu.Game
|
|||||||
|
|
||||||
private void onRulesetChanged(ValueChangedEvent<RulesetInfo> r)
|
private void onRulesetChanged(ValueChangedEvent<RulesetInfo> r)
|
||||||
{
|
{
|
||||||
if (r.NewValue?.Available != true)
|
Ruleset instance;
|
||||||
|
|
||||||
|
if (r.NewValue?.Available != true || (instance = r.NewValue.CreateInstance()) == null)
|
||||||
{
|
{
|
||||||
// reject the change if the ruleset is not available.
|
// reject the change if the ruleset is not available.
|
||||||
Ruleset.Value = r.OldValue?.Available == true ? r.OldValue : RulesetStore.AvailableRulesets.First();
|
Ruleset.Value = r.OldValue?.Available == true ? r.OldValue : RulesetStore.AvailableRulesets.First();
|
||||||
@ -448,7 +435,9 @@ namespace osu.Game
|
|||||||
var dict = new Dictionary<ModType, IReadOnlyList<Mod>>();
|
var dict = new Dictionary<ModType, IReadOnlyList<Mod>>();
|
||||||
|
|
||||||
foreach (ModType type in Enum.GetValues(typeof(ModType)))
|
foreach (ModType type in Enum.GetValues(typeof(ModType)))
|
||||||
dict[type] = r.NewValue.CreateInstance().GetModsFor(type).ToList();
|
{
|
||||||
|
dict[type] = instance.GetModsFor(type).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
if (!SelectedMods.Disabled)
|
if (!SelectedMods.Disabled)
|
||||||
SelectedMods.Value = Array.Empty<Mod>();
|
SelectedMods.Value = Array.Empty<Mod>();
|
||||||
@ -489,7 +478,6 @@ namespace osu.Game
|
|||||||
|
|
||||||
contextFactory?.FlushConnections();
|
contextFactory?.FlushConnections();
|
||||||
|
|
||||||
realmRulesetStore?.Dispose();
|
|
||||||
realmFactory?.Dispose();
|
realmFactory?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ namespace osu.Game.Rulesets
|
|||||||
throw new RulesetLoadException(@"Instantiation failure");
|
throw new RulesetLoadException(@"Instantiation failure");
|
||||||
|
|
||||||
// overwrite the pre-populated RulesetInfo with a potentially database attached copy.
|
// overwrite the pre-populated RulesetInfo with a potentially database attached copy.
|
||||||
ruleset.RulesetInfo = this;
|
// ruleset.RulesetInfo = this;
|
||||||
|
|
||||||
return ruleset;
|
return ruleset;
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ namespace osu.Game.Screens.Edit.Verify
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
InterpretedDifficulty.Default = EditorBeatmap.BeatmapInfo.DifficultyRating;
|
InterpretedDifficulty.Default = BeatmapDifficultyCache.GetDifficultyRating(EditorBeatmap.BeatmapInfo.StarRating);
|
||||||
InterpretedDifficulty.SetDefault();
|
InterpretedDifficulty.SetDefault();
|
||||||
|
|
||||||
IssueList = new IssueList();
|
IssueList = new IssueList();
|
||||||
|
@ -226,8 +226,8 @@ namespace osu.Game.Screens.Play
|
|||||||
// ensure the score is in a consistent state with the current player.
|
// ensure the score is in a consistent state with the current player.
|
||||||
Score.ScoreInfo.BeatmapInfo = Beatmap.Value.BeatmapInfo;
|
Score.ScoreInfo.BeatmapInfo = Beatmap.Value.BeatmapInfo;
|
||||||
Score.ScoreInfo.Ruleset = ruleset.RulesetInfo;
|
Score.ScoreInfo.Ruleset = ruleset.RulesetInfo;
|
||||||
if (ruleset.RulesetInfo.ID != null)
|
if (ruleset.RulesetInfo.OnlineID >= 0)
|
||||||
Score.ScoreInfo.RulesetID = ruleset.RulesetInfo.ID.Value;
|
Score.ScoreInfo.RulesetID = ruleset.RulesetInfo.OnlineID;
|
||||||
Score.ScoreInfo.Mods = gameplayMods;
|
Score.ScoreInfo.Mods = gameplayMods;
|
||||||
|
|
||||||
dependencies.CacheAs(GameplayState = new GameplayState(playableBeatmap, ruleset, gameplayMods, Score));
|
dependencies.CacheAs(GameplayState = new GameplayState(playableBeatmap, ruleset, gameplayMods, Score));
|
||||||
@ -488,6 +488,9 @@ namespace osu.Game.Screens.Play
|
|||||||
var rulesetInfo = Ruleset.Value ?? Beatmap.Value.BeatmapInfo.Ruleset;
|
var rulesetInfo = Ruleset.Value ?? Beatmap.Value.BeatmapInfo.Ruleset;
|
||||||
ruleset = rulesetInfo.CreateInstance();
|
ruleset = rulesetInfo.CreateInstance();
|
||||||
|
|
||||||
|
if (ruleset == null)
|
||||||
|
throw new RulesetLoadException("Instantiation failure");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
playable = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, gameplayMods);
|
playable = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, gameplayMods);
|
||||||
|
@ -26,7 +26,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
protected override APIRequest<APIScoreToken> CreateTokenRequest()
|
protected override APIRequest<APIScoreToken> CreateTokenRequest()
|
||||||
{
|
{
|
||||||
int beatmapId = Beatmap.Value.BeatmapInfo.OnlineID ?? -1;
|
int beatmapId = Beatmap.Value.BeatmapInfo.OnlineID;
|
||||||
int rulesetId = Ruleset.Value.OnlineID;
|
int rulesetId = Ruleset.Value.OnlineID;
|
||||||
|
|
||||||
if (beatmapId <= 0)
|
if (beatmapId <= 0)
|
||||||
|
@ -197,7 +197,8 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
public void UpdateBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() =>
|
public void UpdateBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() =>
|
||||||
{
|
{
|
||||||
int? previouslySelectedID = null;
|
Guid? previouslySelectedID = null;
|
||||||
|
|
||||||
CarouselBeatmapSet existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.Equals(beatmapSet));
|
CarouselBeatmapSet existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.Equals(beatmapSet));
|
||||||
|
|
||||||
// If the selected beatmap is about to be removed, store its ID so it can be re-selected if required
|
// If the selected beatmap is about to be removed, store its ID so it can be re-selected if required
|
||||||
@ -626,9 +627,9 @@ namespace osu.Game.Screens.Select
|
|||||||
if (beatmapSet.Beatmaps.All(b => b.Hidden))
|
if (beatmapSet.Beatmaps.All(b => b.Hidden))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// todo: remove the need for this.
|
// todo: probably not required any more.
|
||||||
foreach (var b in beatmapSet.Beatmaps)
|
// foreach (var b in beatmapSet.Beatmaps)
|
||||||
b.Metadata ??= beatmapSet.Metadata;
|
// b.Metadata ??= beatmapSet.Metadata;
|
||||||
|
|
||||||
var set = new CarouselBeatmapSet(beatmapSet)
|
var set = new CarouselBeatmapSet(beatmapSet)
|
||||||
{
|
{
|
||||||
|
@ -48,7 +48,7 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
if (LastSelected == null || LastSelected.Filtered.Value)
|
if (LastSelected == null || LastSelected.Filtered.Value)
|
||||||
{
|
{
|
||||||
if (GetRecommendedBeatmap?.Invoke(Children.OfType<CarouselBeatmap>().Where(b => !b.Filtered.Value).Select(b => b.BeatmapInfo)) is BeatmapInfo recommended)
|
if (GetRecommendedBeatmap?.Invoke(Children.OfType<CarouselBeatmap>().Where(b => !b.Filtered.Value).Select(b => b.BeatmapInfo)) is BeatmapInfo recommended)
|
||||||
return Children.OfType<CarouselBeatmap>().First(b => b.BeatmapInfo == recommended);
|
return Children.OfType<CarouselBeatmap>().First(b => b.BeatmapInfo.Equals(recommended));
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.GetNextToSelect();
|
return base.GetNextToSelect();
|
||||||
@ -63,16 +63,16 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
case SortMode.Artist:
|
case SortMode.Artist:
|
||||||
return string.Compare(BeatmapSet.Metadata.Artist, otherSet.BeatmapSet.Metadata.Artist, StringComparison.OrdinalIgnoreCase);
|
return string.Compare(BeatmapSet.Metadata?.Artist, otherSet.BeatmapSet.Metadata?.Artist, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
case SortMode.Title:
|
case SortMode.Title:
|
||||||
return string.Compare(BeatmapSet.Metadata.Title, otherSet.BeatmapSet.Metadata.Title, StringComparison.OrdinalIgnoreCase);
|
return string.Compare(BeatmapSet.Metadata?.Title, otherSet.BeatmapSet.Metadata?.Title, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
case SortMode.Author:
|
case SortMode.Author:
|
||||||
return string.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username, StringComparison.OrdinalIgnoreCase);
|
return string.Compare(BeatmapSet.Metadata?.Author.Username, otherSet.BeatmapSet.Metadata?.Author.Username, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
case SortMode.Source:
|
case SortMode.Source:
|
||||||
return string.Compare(BeatmapSet.Metadata.Source, otherSet.BeatmapSet.Metadata.Source, StringComparison.OrdinalIgnoreCase);
|
return string.Compare(BeatmapSet.Metadata?.Source, otherSet.BeatmapSet.Metadata?.Source, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
case SortMode.DateAdded:
|
case SortMode.DateAdded:
|
||||||
return otherSet.BeatmapSet.DateAdded.CompareTo(BeatmapSet.DateAdded);
|
return otherSet.BeatmapSet.DateAdded.CompareTo(BeatmapSet.DateAdded);
|
||||||
|
@ -41,13 +41,13 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
{
|
{
|
||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
{
|
{
|
||||||
Text = new RomanisableString(beatmapSet.Metadata.TitleUnicode, beatmapSet.Metadata.Title),
|
Text = new RomanisableString(beatmapSet.Metadata?.TitleUnicode, beatmapSet.Metadata?.Title),
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 22, italics: true),
|
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 22, italics: true),
|
||||||
Shadow = true,
|
Shadow = true,
|
||||||
},
|
},
|
||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
{
|
{
|
||||||
Text = new RomanisableString(beatmapSet.Metadata.ArtistUnicode, beatmapSet.Metadata.Artist),
|
Text = new RomanisableString(beatmapSet.Metadata?.ArtistUnicode, beatmapSet.Metadata?.Artist),
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 17, italics: true),
|
Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 17, italics: true),
|
||||||
Shadow = true,
|
Shadow = true,
|
||||||
},
|
},
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -37,8 +36,6 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
public FilterCriteria CreateCriteria()
|
public FilterCriteria CreateCriteria()
|
||||||
{
|
{
|
||||||
Debug.Assert(ruleset.Value.ID != null);
|
|
||||||
|
|
||||||
string query = searchTextBox.Text;
|
string query = searchTextBox.Text;
|
||||||
|
|
||||||
var criteria = new FilterCriteria
|
var criteria = new FilterCriteria
|
||||||
@ -56,7 +53,7 @@ namespace osu.Game.Screens.Select
|
|||||||
if (!maximumStars.IsDefault)
|
if (!maximumStars.IsDefault)
|
||||||
criteria.UserStarDifficulty.Max = maximumStars.Value;
|
criteria.UserStarDifficulty.Max = maximumStars.Value;
|
||||||
|
|
||||||
criteria.RulesetCriteria = ruleset.Value.CreateInstance().CreateRulesetFilterCriteria();
|
criteria.RulesetCriteria = ruleset.Value.CreateInstance()?.CreateRulesetFilterCriteria();
|
||||||
|
|
||||||
FilterQueryParser.ApplyQueries(criteria, query);
|
FilterQueryParser.ApplyQueries(criteria, query);
|
||||||
return criteria;
|
return criteria;
|
||||||
|
@ -33,7 +33,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
get => beatmapInfo;
|
get => beatmapInfo;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (beatmapInfo == value)
|
if (beatmapInfo.Equals(value))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
beatmapInfo = value;
|
beatmapInfo = value;
|
||||||
@ -154,7 +154,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fetchBeatmapInfo.OnlineID == null || fetchBeatmapInfo.Status <= BeatmapOnlineStatus.Pending)
|
if (fetchBeatmapInfo.OnlineID <= 0 || fetchBeatmapInfo.Status <= BeatmapOnlineStatus.Pending)
|
||||||
{
|
{
|
||||||
PlaceholderState = PlaceholderState.Unavailable;
|
PlaceholderState = PlaceholderState.Unavailable;
|
||||||
return null;
|
return null;
|
||||||
|
@ -482,7 +482,7 @@ namespace osu.Game.Screens.Select
|
|||||||
else
|
else
|
||||||
selectionChangedDebounce = Scheduler.AddDelayed(run, 200);
|
selectionChangedDebounce = Scheduler.AddDelayed(run, 200);
|
||||||
|
|
||||||
if (beatmap != beatmapInfoPrevious)
|
if (!beatmap.Equals(beatmapInfoPrevious))
|
||||||
{
|
{
|
||||||
if (beatmap != null && beatmapInfoPrevious != null && Time.Current - audioFeedbackLastPlaybackTime >= 50)
|
if (beatmap != null && beatmapInfoPrevious != null && Time.Current - audioFeedbackLastPlaybackTime >= 50)
|
||||||
{
|
{
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -78,7 +79,11 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
currentTestBeatmap = Decoder.GetDecoder<Beatmap>(reader).Decode(reader);
|
currentTestBeatmap = Decoder.GetDecoder<Beatmap>(reader).Decode(reader);
|
||||||
|
|
||||||
// populate ruleset for beatmap converters that require it to be present.
|
// populate ruleset for beatmap converters that require it to be present.
|
||||||
currentTestBeatmap.BeatmapInfo.Ruleset = rulesetStore.GetRuleset(currentTestBeatmap.BeatmapInfo.RulesetID);
|
var ruleset = rulesetStore.GetRuleset(currentTestBeatmap.BeatmapInfo.RulesetID);
|
||||||
|
|
||||||
|
Debug.Assert(ruleset != null);
|
||||||
|
|
||||||
|
currentTestBeatmap.BeatmapInfo.Ruleset = ruleset;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -94,11 +99,7 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
userSkinInfo.Files.Add(new RealmNamedFileUsage(new RealmFile { Hash = userFile }, userFile));
|
userSkinInfo.Files.Add(new RealmNamedFileUsage(new RealmFile { Hash = userFile }, userFile));
|
||||||
|
|
||||||
beatmapInfo.BeatmapSet.Files.Clear();
|
beatmapInfo.BeatmapSet.Files.Clear();
|
||||||
beatmapInfo.BeatmapSet.Files.Add(new BeatmapSetFileInfo
|
beatmapInfo.BeatmapSet.Files.Add(new RealmNamedFileUsage(new RealmFile { Hash = beatmapFile }, beatmapFile));
|
||||||
{
|
|
||||||
Filename = beatmapFile,
|
|
||||||
FileInfo = new IO.FileInfo { Hash = beatmapFile }
|
|
||||||
});
|
|
||||||
|
|
||||||
// Need to refresh the cached skin source to refresh the skin resource store.
|
// Need to refresh the cached skin source to refresh the skin resource store.
|
||||||
dependencies.SkinSource = new SkinProvidingContainer(Skin = new LegacySkin(userSkinInfo, this));
|
dependencies.SkinSource = new SkinProvidingContainer(Skin = new LegacySkin(userSkinInfo, this));
|
||||||
|
@ -116,7 +116,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
private readonly WorkingBeatmap testBeatmap;
|
private readonly WorkingBeatmap testBeatmap;
|
||||||
|
|
||||||
public TestBeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore<byte[]> resources, GameHost host, WorkingBeatmap defaultBeatmap, WorkingBeatmap testBeatmap)
|
public TestBeatmapManager(Storage storage, RealmContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore<byte[]> resources, GameHost host, WorkingBeatmap defaultBeatmap, WorkingBeatmap testBeatmap)
|
||||||
: base(storage, contextFactory, rulesets, api, audioManager, resources, host, defaultBeatmap)
|
: base(storage, contextFactory, rulesets, api, audioManager, resources, host, defaultBeatmap)
|
||||||
{
|
{
|
||||||
this.testBeatmap = testBeatmap;
|
this.testBeatmap = testBeatmap;
|
||||||
|
Reference in New Issue
Block a user