1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 08:33:21 +08:00

Merge pull request #19678 from peppy/fix-file-comparisons-many-places

Fix audio track not correctly advancing when changing between certain beatmaps
This commit is contained in:
Dan Balasescu 2022-08-10 20:38:14 +09:00 committed by GitHub
commit f9c6dc314b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 84 additions and 39 deletions

View File

@ -36,6 +36,23 @@ namespace osu.Game.Tests.NonVisual
Assert.IsTrue(beatmapSetA.Beatmaps.Single().AudioEquals(beatmapSetB.Beatmaps.Single()));
}
[Test]
public void TestAudioEqualityCaseSensitivity()
{
var beatmapSetA = TestResources.CreateTestBeatmapSetInfo(1);
var beatmapSetB = TestResources.CreateTestBeatmapSetInfo(1);
// empty by default so let's set it..
beatmapSetA.Beatmaps.First().Metadata.AudioFile = "audio.mp3";
beatmapSetB.Beatmaps.First().Metadata.AudioFile = "audio.mp3";
addAudioFile(beatmapSetA, "abc", "AuDiO.mP3");
addAudioFile(beatmapSetB, "abc", "audio.mp3");
Assert.AreNotEqual(beatmapSetA, beatmapSetB);
Assert.IsTrue(beatmapSetA.Beatmaps.Single().AudioEquals(beatmapSetB.Beatmaps.Single()));
}
[Test]
public void TestAudioEqualitySameHash()
{

View File

@ -199,8 +199,8 @@ namespace osu.Game.Beatmaps
Debug.Assert(x.BeatmapSet != null);
Debug.Assert(y.BeatmapSet != null);
string? fileHashX = x.BeatmapSet.Files.FirstOrDefault(f => f.Filename == getFilename(x.Metadata))?.File.Hash;
string? fileHashY = y.BeatmapSet.Files.FirstOrDefault(f => f.Filename == getFilename(y.Metadata))?.File.Hash;
string? fileHashX = x.BeatmapSet.GetFile(getFilename(x.Metadata))?.File.Hash;
string? fileHashY = y.BeatmapSet.GetFile(getFilename(y.Metadata))?.File.Hash;
return fileHashX == fileHashY;
}

View File

@ -1,8 +1,6 @@
// 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 disable
using System.Linq;
using osu.Framework.Localisation;

View File

@ -300,7 +300,7 @@ namespace osu.Game.Beatmaps
stream.Seek(0, SeekOrigin.Begin);
// AddFile generally handles updating/replacing files, but this is a case where the filename may have also changed so let's delete for simplicity.
var existingFileInfo = setInfo.Files.SingleOrDefault(f => string.Equals(f.Filename, beatmapInfo.Path, StringComparison.OrdinalIgnoreCase));
var existingFileInfo = beatmapInfo.Path != null ? setInfo.GetFile(beatmapInfo.Path) : null;
string targetFilename = createBeatmapFilenameFromMetadata(beatmapInfo);
// ensure that two difficulties from the set don't point at the same beatmap file.

View File

@ -84,13 +84,6 @@ namespace osu.Game.Beatmaps
{
}
/// <summary>
/// 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.
/// </summary>
/// <param name="filename">The name of the file to get the storage path of.</param>
public string? GetPathForFile(string filename) => Files.SingleOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase))?.File.GetStoragePath();
public bool Equals(BeatmapSetInfo? other)
{
if (ReferenceEquals(this, other)) return true;

View File

@ -0,0 +1,33 @@
// 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.Linq;
using osu.Game.Database;
using osu.Game.Extensions;
using osu.Game.Models;
namespace osu.Game.Beatmaps
{
public static class BeatmapSetInfoExtensions
{
/// <summary>
/// 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 lookup is case insensitive.
/// </summary>
/// <param name="model">The model to operate on.</param>
/// <param name="filename">The name of the file to get the storage path of.</param>
public static string? GetPathForFile(this IHasRealmFiles model, string filename) => model.GetFile(filename)?.File.GetStoragePath();
/// <summary>
/// Returns the file usage 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 lookup is case insensitive.
/// </summary>
/// <param name="model">The model to operate on.</param>
/// <param name="filename">The name of the file to get the storage path of.</param>
public static RealmNamedFileUsage? GetFile(this IHasRealmFiles model, string filename) =>
model.Files.SingleOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase));
}
}

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using osu.Game.Beatmaps;
using osu.Game.Models;
namespace osu.Game.Database
@ -11,8 +12,16 @@ namespace osu.Game.Database
/// </summary>
public interface IHasRealmFiles
{
/// <summary>
/// Available files in this model, with locally filenames.
/// When performing lookups, consider using <see cref="BeatmapSetInfoExtensions.GetFile"/> or <see cref="BeatmapSetInfoExtensions.GetPathForFile"/> to do case-insensitive lookups.
/// </summary>
IList<RealmNamedFileUsage> Files { get; }
/// <summary>
/// A combined hash representing the model, based on the files it contains.
/// Implementation specific.
/// </summary>
string Hash { get; set; }
}
}

View File

@ -7,6 +7,7 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using osu.Framework.Platform;
using osu.Game.Beatmaps;
using osu.Game.Extensions;
using osu.Game.Models;
using osu.Game.Overlays.Notifications;
@ -79,7 +80,7 @@ namespace osu.Game.Database
/// </summary>
public void AddFile(TModel item, Stream contents, string filename, Realm realm)
{
var existing = item.Files.FirstOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase));
var existing = item.GetFile(filename);
if (existing != null)
{

View File

@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.IO;
using osu.Game.Beatmaps;
using osu.Game.IO.FileAbstraction;
using osu.Game.Rulesets.Edit.Checks.Components;
using osu.Game.Storyboards;

View File

@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.IO;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Edit.Checks.Components;
namespace osu.Game.Rulesets.Edit.Checks

View File

@ -4,7 +4,6 @@
#nullable disable
using System.IO;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
@ -78,7 +77,7 @@ namespace osu.Game.Screens.Edit.Setup
// remove the previous background for now.
// in the future we probably want to check if this is being used elsewhere (other difficulties?)
var oldFile = set.Files.FirstOrDefault(f => f.Filename == working.Value.Metadata.BackgroundFile);
var oldFile = set.GetFile(working.Value.Metadata.BackgroundFile);
using (var stream = source.OpenRead())
{
@ -107,7 +106,7 @@ namespace osu.Game.Screens.Edit.Setup
// remove the previous audio track for now.
// in the future we probably want to check if this is being used elsewhere (other difficulties?)
var oldFile = set.Files.FirstOrDefault(f => f.Filename == working.Value.Metadata.AudioFile);
var oldFile = set.GetFile(working.Value.Metadata.AudioFile);
using (var stream = source.OpenRead())
{

View File

@ -10,6 +10,7 @@ using System.Threading;
using Newtonsoft.Json;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Extensions;
using osu.Game.IO;
@ -49,7 +50,7 @@ namespace osu.Game.Skinning
protected override void Populate(SkinInfo model, ArchiveReader? archive, Realm realm, CancellationToken cancellationToken = default)
{
var skinInfoFile = model.Files.SingleOrDefault(f => f.Filename == skin_info_file);
var skinInfoFile = model.GetFile(skin_info_file);
if (skinInfoFile != null)
{
@ -129,7 +130,7 @@ namespace osu.Game.Skinning
authorLine,
};
var existingFile = item.Files.SingleOrDefault(f => f.Filename.Equals(@"skin.ini", StringComparison.OrdinalIgnoreCase));
var existingFile = item.GetFile(@"skin.ini");
if (existingFile == null)
{
@ -163,7 +164,7 @@ namespace osu.Game.Skinning
{
Logger.Log($"Skin {item}'s skin.ini had issues and has been removed. Please report this and provide the problematic skin.", LoggingTarget.Database, LogLevel.Important);
var existingIni = item.Files.SingleOrDefault(f => f.Filename.Equals(@"skin.ini", StringComparison.OrdinalIgnoreCase));
var existingIni = item.GetFile(@"skin.ini");
if (existingIni != null)
item.Files.Remove(existingIni);
@ -248,7 +249,7 @@ namespace osu.Game.Skinning
{
string filename = @$"{drawableInfo.Key}.json";
var oldFile = s.Files.FirstOrDefault(f => f.Filename == filename);
var oldFile = s.GetFile(filename);
if (oldFile != null)
modelManager.ReplaceFile(oldFile, streamContent, s.Realm);

View File

@ -1,10 +1,6 @@
// 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 disable
using System;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
@ -12,14 +8,14 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Textures;
using osu.Framework.Graphics.Video;
using osu.Game.Beatmaps;
using osu.Game.Extensions;
namespace osu.Game.Storyboards.Drawables
{
public class DrawableStoryboardVideo : CompositeDrawable
{
public readonly StoryboardVideo Video;
private Video video;
private Video? drawableVideo;
public override bool RemoveWhenNotAlive => false;
@ -33,7 +29,7 @@ namespace osu.Game.Storyboards.Drawables
[BackgroundDependencyLoader(true)]
private void load(IBindable<WorkingBeatmap> beatmap, TextureStore textureStore)
{
string path = beatmap.Value.BeatmapSetInfo?.Files.FirstOrDefault(f => f.Filename.Equals(Video.Path, StringComparison.OrdinalIgnoreCase))?.File.GetStoragePath();
string? path = beatmap.Value.BeatmapSetInfo?.GetPathForFile(Video.Path);
if (path == null)
return;
@ -43,7 +39,7 @@ namespace osu.Game.Storyboards.Drawables
if (stream == null)
return;
InternalChild = video = new Video(stream, false)
InternalChild = drawableVideo = new Video(stream, false)
{
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fill,
@ -57,12 +53,12 @@ namespace osu.Game.Storyboards.Drawables
{
base.LoadComplete();
if (video == null) return;
if (drawableVideo == null) return;
using (video.BeginAbsoluteSequence(Video.StartTime))
using (drawableVideo.BeginAbsoluteSequence(Video.StartTime))
{
Schedule(() => video.PlaybackPosition = Time.Current - Video.StartTime);
video.FadeIn(500);
Schedule(() => drawableVideo.PlaybackPosition = Time.Current - Video.StartTime);
drawableVideo.FadeIn(500);
}
}
}

View File

@ -1,14 +1,10 @@
// 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 disable
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps;
using osu.Game.Extensions;
using osu.Game.Rulesets.Mods;
using osu.Game.Storyboards.Drawables;
@ -90,12 +86,12 @@ namespace osu.Game.Storyboards
}
}
public DrawableStoryboard CreateDrawable(IReadOnlyList<Mod> mods = null) =>
public DrawableStoryboard CreateDrawable(IReadOnlyList<Mod>? mods = null) =>
new DrawableStoryboard(this, mods);
public Texture GetTextureFromPath(string path, TextureStore textureStore)
public Texture? GetTextureFromPath(string path, TextureStore textureStore)
{
string storyboardPath = BeatmapInfo.BeatmapSet?.Files.FirstOrDefault(f => f.Filename.Equals(path, StringComparison.OrdinalIgnoreCase))?.File.GetStoragePath();
string? storyboardPath = BeatmapInfo.BeatmapSet?.GetPathForFile(path);
if (!string.IsNullOrEmpty(storyboardPath))
return textureStore.Get(storyboardPath);