From ce864011f20366179cee5281fbf46f0f2b29c234 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 10 Oct 2021 12:19:56 -0700 Subject: [PATCH 001/129] Add ability to change ui scaling via keyboard --- osu.Game/OsuGame.cs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 8a018f17d9..e604e91471 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -986,6 +986,31 @@ namespace osu.Game return false; } + public override bool OnPressed(KeyBindingPressEvent e) + { + switch (e.Action) + { + case PlatformAction.ZoomIn: + adjustUIScaling(1); + return true; + + case PlatformAction.ZoomOut: + adjustUIScaling(-1); + return true; + + case PlatformAction.ZoomDefault: + LocalConfig.GetBindable(OsuSetting.UIScale).SetDefault(); + return true; + } + + void adjustUIScaling(int amount) + { + LocalConfig.SetValue(OsuSetting.UIScale, LocalConfig.Get(OsuSetting.UIScale) + (0.05f * amount)); + } + + return base.OnPressed(e); + } + #region Inactive audio dimming private readonly BindableDouble inactiveVolumeFade = new BindableDouble(); From 25f172fae8ba1c06771948afa0a9d0f73807a8a0 Mon Sep 17 00:00:00 2001 From: Susko3 <16479013+Susko3@users.noreply.github.com> Date: Sun, 17 Oct 2021 12:17:38 +0200 Subject: [PATCH 002/129] Update usages of OpenInNativeExplorer to use ShowFileInNativeExplorer Also updates WrappedStorage to override ShowFileInNativeExplorer. --- osu.Game/Database/ArchiveModelManager.cs | 6 ++++-- osu.Game/Graphics/ScreenshotManager.cs | 2 +- osu.Game/IO/WrappedStorage.cs | 2 ++ osu.Game/OsuGame.cs | 4 +++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 84e33e3f36..0c6b229413 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -462,10 +462,12 @@ namespace osu.Game.Database if (retrievedItem == null) throw new ArgumentException(@"Specified model could not be found", nameof(item)); - using (var outputStream = exportStorage.GetStream($"{getValidFilename(item.ToString())}{HandledExtensions.First()}", FileAccess.Write, FileMode.Create)) + var filename = $"{getValidFilename(item.ToString())}{HandledExtensions.First()}"; + + using (var outputStream = exportStorage.GetStream(filename, FileAccess.Write, FileMode.Create)) ExportModelTo(retrievedItem, outputStream); - exportStorage.OpenInNativeExplorer(); + exportStorage.ShowFileInNativeExplorer(filename); } /// diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 9cd403f409..27e6e2bb1c 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -135,7 +135,7 @@ namespace osu.Game.Graphics Text = $"{fileName} saved!", Activated = () => { - storage.OpenInNativeExplorer(); + storage.ShowFileInNativeExplorer(fileName); return true; } }); diff --git a/osu.Game/IO/WrappedStorage.cs b/osu.Game/IO/WrappedStorage.cs index b9ccc907d9..1e2d53d6fb 100644 --- a/osu.Game/IO/WrappedStorage.cs +++ b/osu.Game/IO/WrappedStorage.cs @@ -72,6 +72,8 @@ namespace osu.Game.IO public override void OpenPathInNativeExplorer(string path) => UnderlyingStorage.OpenPathInNativeExplorer(MutatePath(path)); + public override void ShowFileInNativeExplorer(string filename) => UnderlyingStorage.ShowFileInNativeExplorer(MutatePath(filename)); + public override Storage GetStorageForDirectory(string path) { if (string.IsNullOrEmpty(path)) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 820597488b..a36c1e18e0 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -913,13 +913,15 @@ namespace osu.Game } else if (recentLogCount == short_term_display_limit) { + var logFile = $@"{entry.Target.ToString().ToLowerInvariant()}.log"; + Schedule(() => Notifications.Post(new SimpleNotification { Icon = FontAwesome.Solid.EllipsisH, Text = "Subsequent messages have been logged. Click to view log files.", Activated = () => { - Storage.GetStorageForDirectory("logs").OpenInNativeExplorer(); + Storage.GetStorageForDirectory(@"logs").ShowFileInNativeExplorer(logFile); return true; } })); From 789c715f136254e68cdccce5d986bbfd9a05e1d6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Oct 2021 15:22:47 +0900 Subject: [PATCH 003/129] Add `skin.ini` write support to allow for more correct hashing --- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 33 +++++- osu.Game/Database/ArchiveModelManager.cs | 43 +++++-- osu.Game/Skinning/SkinManager.cs | 132 +++++++++++++++++----- 3 files changed, 162 insertions(+), 46 deletions(-) diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index b2600bb887..67c94413ca 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -38,7 +38,32 @@ namespace osu.Game.Tests.Skins.IO } [Test] - public async Task TestImportTwiceWithSameMetadata() + public async Task TestImportTwiceWithSameMetadataAndFilename() + { + using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportSkinTest))) + { + try + { + var osu = LoadOsuIntoHost(host); + + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk")); + + Assert.That(imported2.ID, Is.EqualTo(imported.ID)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Count, Is.EqualTo(1)); + + // the first should be overwritten by the second import. + Assert.That(imported.Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); + } + finally + { + host.Exit(); + } + } + } + + [Test] + public async Task TestImportTwiceWithSameMetadataButDifferentFilename() { using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportSkinTest))) { @@ -50,10 +75,10 @@ namespace osu.Game.Tests.Skins.IO var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin2.osk")); Assert.That(imported2.ID, Is.Not.EqualTo(imported.ID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Count, Is.EqualTo(1)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Count, Is.EqualTo(2)); - // the first should be overwritten by the second import. - Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).First().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); + // skin.ini will be rewritten and therefore not match. + Assert.That(imported.Files.First().FileInfoID, Is.Not.EqualTo(imported2.Files.First().FileInfoID)); } finally { diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 9c777d324b..e52e5bdfe7 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -507,18 +507,26 @@ namespace osu.Game.Database /// The existing file to be deleted. public void DeleteFile(TModel model, TFileModel file) { - using (var usage = ContextFactory.GetForWrite()) + if (model.ID > 0) { - // Dereference the existing file info, since the file model will be removed. - if (file.FileInfo != null) + using (var usage = ContextFactory.GetForWrite()) { - Files.Dereference(file.FileInfo); + // Dereference the existing file info, since the file model will be removed. + if (file.FileInfo != null) + { + Files.Dereference(file.FileInfo); - // This shouldn't be required, but here for safety in case the provided TModel is not being change tracked - // Definitely can be removed once we rework the database backend. - usage.Context.Set().Remove(file); + // This shouldn't be required, but here for safety in case the provided TModel is not being change tracked + // Definitely can be removed once we rework the database backend. + usage.Context.Set().Remove(file); + } + + model.Files.Remove(file); } - + } + else + { + Files.Dereference(file.FileInfo); model.Files.Remove(file); } } @@ -531,15 +539,28 @@ namespace osu.Game.Database /// The filename for the new file. public void AddFile(TModel model, Stream contents, string filename) { - using (ContextFactory.GetForWrite()) + if (model.ID > 0) { + using (ContextFactory.GetForWrite()) + { + model.Files.Add(new TFileModel + { + Filename = filename, + FileInfo = Files.Add(contents) + }); + + Update(model); + } + } + else + { + // This function may be called during the import process. + // Should not exist like this once we have switched to realm. model.Files.Add(new TFileModel { Filename = filename, FileInfo = Files.Add(contents) }); - - Update(model); } } diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 3842acab74..724ca3bc62 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -14,7 +14,6 @@ using Newtonsoft.Json; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; -using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.Textures; @@ -138,52 +137,123 @@ namespace osu.Game.Skinning { var instance = GetSkin(item); - // in the case the skin has a skin.ini file, we are going to create a hash based on that. - // we don't want to do this in the case we don't have a skin.ini, as it would match only on the filename portion, - // causing potentially unique skin imports to be considered as a duplicate. - if (!string.IsNullOrEmpty(instance.Configuration.SkinInfo.Name)) - { - // we need to populate early to create a hash based off skin.ini contents - populateMetadata(item, instance, reader?.Name); + // This function can be run on fresh import or save. The logic here ensures a skin.ini file is in a good state for both operations. - return item.ToString().ComputeSHA2Hash(); + // LegacySkin will parse the skin.ini and populate `Skin.Configuration` during construction above. + bool hasSkinIni = string.IsNullOrEmpty(instance.Configuration.SkinInfo.Name); + + if (hasSkinIni) + { + item.Name = instance.Configuration.SkinInfo.Name; + item.Creator = instance.Configuration.SkinInfo.Creator; } + item.Creator ??= unknown_creator_string; + + bool isImport = reader != null; + + if (isImport) + { + // For imports, we want to use the archive or folder name as part of the metadata, in addition to any existing skin.ini metadata. + // In an ideal world, skin.ini would be the only source of metadata, but a lot of skin creators and users don't update it when making modifications. + // In both of these cases, the expectation from the user is that the filename or folder name is displayed somewhere to identify the skin. + + string archiveName = item.Name.Replace(".osk", "", StringComparison.OrdinalIgnoreCase); + + if (archiveName != item.Name) + item.Name = $"{item.Name} [{archiveName}]"; + } + + // By this point, the metadata in SkinInfo will be correct. + // Regardless of whether this is an import or not, let's write the skin.ini if non-existing or non-matching. + // This is (weirdly) done inside ComputeHash to avoid adding a new method to handle this case. After switching to realm it can be moved into another place. + if (instance.Configuration.SkinInfo.Name != item.Name) + updateSkinIniMetadata(item, hasSkinIni); + return base.ComputeHash(item, reader); } + private void updateSkinIniMetadata(SkinInfo item, bool hasSkinIni) + { + string nameLine = $"Name: {item.Name}"; + string authorLine = $"Author: {item.Name}"; + + if (hasSkinIni) + { + List outputLines = new List(); + + bool addedName = false; + bool addedAuthor = false; + + var existingFile = item.Files.First(f => f.Filename == "skin.ini"); + + using (var stream = Files.Storage.GetStream(existingFile.FileInfo.StoragePath)) + using (var sr = new StreamReader(stream)) + { + string line; + + while ((line = sr.ReadLine()) != null) + { + if (line.StartsWith("Name:", StringComparison.Ordinal)) + { + outputLines.Add(nameLine); + addedName = true; + } + else if (line.StartsWith("Author:", StringComparison.Ordinal)) + { + outputLines.Add(authorLine); + addedAuthor = true; + } + else + outputLines.Add(line); + } + } + + if (!addedName || !addedAuthor) + { + outputLines.AddRange(new[] + { + "[General]", + nameLine, + authorLine, + }); + } + + using (Stream stream = new MemoryStream()) + using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) + { + foreach (string line in outputLines) + sw.WriteLine(line); + + ReplaceFile(item, existingFile, stream); + } + } + else + { + using (Stream stream = new MemoryStream()) + using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) + { + sw.WriteLine("[General]"); + sw.WriteLine(nameLine); + sw.WriteLine(authorLine); + + AddFile(item, stream, "skin.ini"); + } + } + } + protected override Task Populate(SkinInfo model, ArchiveReader archive, CancellationToken cancellationToken = default) { var instance = GetSkin(model); model.InstantiationInfo ??= instance.GetType().GetInvariantInstantiationInfo(); - populateMetadata(model, instance, archive?.Name); + model.Name = instance.Configuration.SkinInfo.Name; + model.Creator = instance.Configuration.SkinInfo.Creator; return Task.CompletedTask; } - private void populateMetadata(SkinInfo item, Skin instance, string archiveName) - { - if (!string.IsNullOrEmpty(instance.Configuration.SkinInfo.Name)) - { - item.Name = instance.Configuration.SkinInfo.Name; - item.Creator = instance.Configuration.SkinInfo.Creator; - } - else - { - item.Name = item.Name.Replace(".osk", "", StringComparison.OrdinalIgnoreCase); - item.Creator ??= unknown_creator_string; - } - - // generally when importing from a folder, the ".osk" extension will not be present. - // if we ever need a more reliable method of determining this, the type of `ArchiveReader` can be checked. - bool isArchiveImport = archiveName?.Contains(".osk", StringComparison.OrdinalIgnoreCase) == true; - - if (archiveName != null && !isArchiveImport && archiveName != item.Name) - item.Name = $"{item.Name} [{archiveName}]"; - } - /// /// Retrieve a instance for the provided /// From fa542f254778747c2dfb8e8c0d17fe5f2e995de9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Oct 2021 14:05:32 +0900 Subject: [PATCH 004/129] Include `json` files in skin hashing This covers the new layout storage we are doing. --- osu.Game/Skinning/SkinManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 724ca3bc62..9c7ea28cc4 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -50,7 +50,7 @@ namespace osu.Game.Skinning public override IEnumerable HandledExtensions => new[] { ".osk" }; - protected override string[] HashableFileTypes => new[] { ".ini" }; + protected override string[] HashableFileTypes => new[] { ".ini", ".json" }; protected override string ImportFromStablePath => "Skins"; @@ -140,7 +140,7 @@ namespace osu.Game.Skinning // This function can be run on fresh import or save. The logic here ensures a skin.ini file is in a good state for both operations. // LegacySkin will parse the skin.ini and populate `Skin.Configuration` during construction above. - bool hasSkinIni = string.IsNullOrEmpty(instance.Configuration.SkinInfo.Name); + bool hasSkinIni = !string.IsNullOrEmpty(instance.Configuration.SkinInfo.Name); if (hasSkinIni) { From 439e90fce3d3c804fceb80e928af0ed2f87836bb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Oct 2021 15:51:14 +0900 Subject: [PATCH 005/129] Disallow archive imports with no hashable files --- osu.Game/Database/ArchiveModelManager.cs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index e52e5bdfe7..5b07bfe9a5 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -317,14 +317,18 @@ namespace osu.Game.Database /// protected virtual string ComputeHash(TModel item, ArchiveReader reader = null) { - if (reader != null) - // fast hashing for cases where the item's files may not be populated. - return computeHashFast(reader); + var hashableFiles = item.Files + .Where(f => HashableFileTypes.Any(ext => f.Filename.EndsWith(ext, StringComparison.OrdinalIgnoreCase))) + .OrderBy(f => f.Filename) + .ToArray(); + + if (hashableFiles.Length == 0) + throw new InvalidOperationException("Attempted to hash an archive with no files"); // for now, concatenate all hashable files in the set to create a unique hash. MemoryStream hashable = new MemoryStream(); - foreach (TFileModel file in item.Files.Where(f => HashableFileTypes.Any(ext => f.Filename.EndsWith(ext, StringComparison.OrdinalIgnoreCase))).OrderBy(f => f.Filename)) + foreach (TFileModel file in hashableFiles) { using (Stream s = Files.Store.GetStream(file.FileInfo.StoragePath)) s.CopyTo(hashable); @@ -700,10 +704,10 @@ namespace osu.Game.Database s.CopyTo(hashable); } - if (hashable.Length > 0) - return hashable.ComputeSHA2Hash(); + if (hashable.Length == 0) + throw new InvalidOperationException("Attempted to hash an archive with no files"); - return reader.Name.ComputeSHA2Hash(); + return hashable.ComputeSHA2Hash(); } /// From 19f30177eacb10e733216d3534ec997b1dc9a5a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Oct 2021 16:48:32 +0900 Subject: [PATCH 006/129] Rewrite tests completely --- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 249 ++++++++++------------ 1 file changed, 108 insertions(+), 141 deletions(-) diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index 67c94413ca..8449b0bbd3 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -4,6 +4,7 @@ using System; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Allocation; @@ -16,180 +17,130 @@ namespace osu.Game.Tests.Skins.IO { public class ImportSkinTest : ImportTest { - [Test] - public async Task TestBasicImport() - { - using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportSkinTest))) - { - try - { - var osu = LoadOsuIntoHost(host); - - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk")); - - Assert.That(imported.Name, Is.EqualTo("test skin")); - Assert.That(imported.Creator, Is.EqualTo("skinner")); - } - finally - { - host.Exit(); - } - } - } + #region Testing filename metadata inclusion [Test] - public async Task TestImportTwiceWithSameMetadataAndFilename() + public Task TestSingleImportDifferentFilename() => runSkinTest(async osu => { - using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportSkinTest))) - { - try - { - var osu = LoadOsuIntoHost(host); + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk")); - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk")); - - Assert.That(imported2.ID, Is.EqualTo(imported.ID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Count, Is.EqualTo(1)); - - // the first should be overwritten by the second import. - Assert.That(imported.Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); - } - finally - { - host.Exit(); - } - } - } + // When the import filename doesn't match, it should be appended (and update the skin.ini). + Assert.That(imported.Name, Is.EqualTo("test skin [skin]")); + Assert.That(imported.Creator, Is.EqualTo("skinner")); + }); [Test] - public async Task TestImportTwiceWithSameMetadataButDifferentFilename() + public Task TestSingleImportMatchingFilename() => runSkinTest(async osu => { - using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportSkinTest))) - { - try - { - var osu = LoadOsuIntoHost(host); + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "test skin.osk")); - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin2.osk")); + // When the import filename matches it shouldn't be appended. + Assert.That(imported.Name, Is.EqualTo("test skin")); + Assert.That(imported.Creator, Is.EqualTo("skinner")); + }); - Assert.That(imported2.ID, Is.Not.EqualTo(imported.ID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Count, Is.EqualTo(2)); + #endregion - // skin.ini will be rewritten and therefore not match. - Assert.That(imported.Files.First().FileInfoID, Is.Not.EqualTo(imported2.Files.First().FileInfoID)); - } - finally - { - host.Exit(); - } - } - } + #region Cases where imports should match existing [Test] - public async Task TestImportTwiceWithNoMetadata() + public Task TestImportTwiceWithSameMetadataAndFilename() => runSkinTest(async osu => { - using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportSkinTest))) - { - try - { - var osu = LoadOsuIntoHost(host); + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk")); - // if a user downloads two skins that do have skin.ini files but don't have any creator metadata in the skin.ini, they should both import separately just for safety. - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk(string.Empty, string.Empty), "download.osk")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk(string.Empty, string.Empty), "download.osk")); - - Assert.That(imported2.ID, Is.Not.EqualTo(imported.ID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Count, Is.EqualTo(2)); - - Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).First().Files.First().FileInfoID, Is.EqualTo(imported.Files.First().FileInfoID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Last().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); - } - finally - { - host.Exit(); - } - } - } + assertImportedOnce(imported, imported2); + }); [Test] - public async Task TestImportTwiceWithDifferentMetadata() + public Task TestImportTwiceWithNoMetadataSameDownloadFilename() => runSkinTest(async osu => { - using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportSkinTest))) - { - try - { - var osu = LoadOsuIntoHost(host); + // if a user downloads two skins that do have skin.ini files but don't have any creator metadata in the skin.ini, they should both import separately just for safety. + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk(string.Empty, string.Empty), "download.osk")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk(string.Empty, string.Empty), "download.osk")); - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin v2", "skinner"), "skin.osk")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin v2.1", "skinner"), "skin2.osk")); - - Assert.That(imported2.ID, Is.Not.EqualTo(imported.ID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Count, Is.EqualTo(2)); - - Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).First().Files.First().FileInfoID, Is.EqualTo(imported.Files.First().FileInfoID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Last().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); - } - finally - { - host.Exit(); - } - } - } + assertImportedOnce(imported, imported2); + }); [Test] - public async Task TestImportUpperCasedOskArchive() + public Task TestImportUpperCasedOskArchive() => runSkinTest(async osu => { - using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportSkinTest))) - { - try - { - var osu = LoadOsuIntoHost(host); + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1"), "name 1.OsK")); + assertCorrectMetadata(imported, "name 1", "author 1"); - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1"), "skin1.OsK")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1"), "name 1.oSK")); - Assert.That(imported.Name, Is.EqualTo("name 1")); - Assert.That(imported.Creator, Is.EqualTo("author 1")); + assertImportedOnce(imported, imported2); + }); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1"), "skin1.oSK")); + #endregion - Assert.That(imported2.Hash, Is.EqualTo(imported.Hash)); - } - finally - { - host.Exit(); - } - } - } + #region Cases where imports should be uniquely imported [Test] - public async Task TestSameMetadataNameDifferentFolderName() + public Task TestImportTwiceWithSameMetadataButDifferentFilename() => runSkinTest(async osu => { - using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportSkinTest))) - { - try - { - var osu = LoadOsuIntoHost(host); + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin2.osk")); - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1", false), "my custom skin 1")); - Assert.That(imported.Name, Is.EqualTo("name 1 [my custom skin 1]")); - Assert.That(imported.Creator, Is.EqualTo("author 1")); + assertImportedBoth(imported, imported2); + }); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1", false), "my custom skin 2")); - Assert.That(imported2.Name, Is.EqualTo("name 1 [my custom skin 2]")); - Assert.That(imported2.Creator, Is.EqualTo("author 1")); + [Test] + public Task TestImportTwiceWithNoMetadataDifferentDownloadFilename() => runSkinTest(async osu => + { + // if a user downloads two skins that do have skin.ini files but don't have any creator metadata in the skin.ini, they should both import separately just for safety. + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk(string.Empty, string.Empty), "download.osk")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk(string.Empty, string.Empty), "download2.osk")); - Assert.That(imported2.Hash, Is.Not.EqualTo(imported.Hash)); - } - finally - { - host.Exit(); - } - } + assertImportedBoth(imported, imported2); + }); + + [Test] + public Task TestImportTwiceWithSameFilenameDifferentMetadata() => runSkinTest(async osu => + { + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin v2", "skinner"), "skin.osk")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin v2.1", "skinner"), "skin.osk")); + + assertImportedBoth(imported, imported2); + assertCorrectMetadata(imported, "test skin v2 [skin]", "skinner"); + assertCorrectMetadata(imported2, "test skin v2.1 [skin]", "skinner"); + }); + + [Test] + public Task TestSameMetadataNameDifferentFolderName() => runSkinTest(async osu => + { + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1"), "my custom skin 1")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1"), "my custom skin 2")); + + assertImportedBoth(imported, imported2); + assertCorrectMetadata(imported, "name 1 [my custom skin 2]", "author 1"); + assertCorrectMetadata(imported, "name 1 [my custom skin 2]", "author 1"); + }); + + #endregion + + private void assertCorrectMetadata(SkinInfo imported, string name, string creator) + { + Assert.That(imported.Name, Is.EqualTo(name)); + Assert.That(imported.Creator, Is.EqualTo(creator)); } - private MemoryStream createOsk(string name, string author, bool makeUnique = true) + private void assertImportedBoth(SkinInfo imported, SkinInfo imported2) + { + Assert.That(imported2.ID, Is.Not.EqualTo(imported.ID)); + Assert.That(imported2.Hash, Is.Not.EqualTo(imported.Hash)); + Assert.That(imported2.Files.Select(f => f.FileInfoID), Is.Not.EquivalentTo(imported.Files.Select(f => f.FileInfoID))); + } + + private void assertImportedOnce(SkinInfo imported, SkinInfo imported2) + { + Assert.That(imported2.ID, Is.EqualTo(imported.ID)); + Assert.That(imported2.Hash, Is.EqualTo(imported.Hash)); + Assert.That(imported2.Files.Select(f => f.FileInfoID), Is.EquivalentTo(imported.Files.Select(f => f.FileInfoID))); + } + + private MemoryStream createOsk(string name, string author, bool makeUnique = false) { var zipStream = new MemoryStream(); using var zip = ZipArchive.Create(); @@ -218,6 +169,22 @@ namespace osu.Game.Tests.Skins.IO return stream; } + private async Task runSkinTest(Func action, [CallerMemberName] string callingMethodName = @"") + { + using (HeadlessGameHost host = new CleanRunHeadlessGameHost(callingMethodName)) + { + try + { + var osu = LoadOsuIntoHost(host); + await action(osu); + } + finally + { + host.Exit(); + } + } + } + private async Task loadSkinIntoOsu(OsuGameBase osu, ArchiveReader archive = null) { var skinManager = osu.Dependencies.Get(); From a95c754fd3d0e867d7910fe3f2a746a10261329b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Oct 2021 16:49:58 +0900 Subject: [PATCH 007/129] Fix multiple issues and make metadata fallback process more logical --- osu.Game/Skinning/SkinManager.cs | 49 +++++++++++++++----------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 9c7ea28cc4..452c081a41 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -140,26 +140,19 @@ namespace osu.Game.Skinning // This function can be run on fresh import or save. The logic here ensures a skin.ini file is in a good state for both operations. // LegacySkin will parse the skin.ini and populate `Skin.Configuration` during construction above. - bool hasSkinIni = !string.IsNullOrEmpty(instance.Configuration.SkinInfo.Name); - - if (hasSkinIni) - { - item.Name = instance.Configuration.SkinInfo.Name; - item.Creator = instance.Configuration.SkinInfo.Creator; - } - - item.Creator ??= unknown_creator_string; + string skinIniSourcedName = instance.Configuration.SkinInfo.Name; + string archiveName = item.Name.Replace(".osk", "", StringComparison.OrdinalIgnoreCase); bool isImport = reader != null; if (isImport) { + item.Name = !string.IsNullOrEmpty(skinIniSourcedName) ? skinIniSourcedName : archiveName; + item.Creator = instance.Configuration.SkinInfo.Creator ?? unknown_creator_string; + // For imports, we want to use the archive or folder name as part of the metadata, in addition to any existing skin.ini metadata. // In an ideal world, skin.ini would be the only source of metadata, but a lot of skin creators and users don't update it when making modifications. // In both of these cases, the expectation from the user is that the filename or folder name is displayed somewhere to identify the skin. - - string archiveName = item.Name.Replace(".osk", "", StringComparison.OrdinalIgnoreCase); - if (archiveName != item.Name) item.Name = $"{item.Name} [{archiveName}]"; } @@ -167,26 +160,26 @@ namespace osu.Game.Skinning // By this point, the metadata in SkinInfo will be correct. // Regardless of whether this is an import or not, let's write the skin.ini if non-existing or non-matching. // This is (weirdly) done inside ComputeHash to avoid adding a new method to handle this case. After switching to realm it can be moved into another place. - if (instance.Configuration.SkinInfo.Name != item.Name) - updateSkinIniMetadata(item, hasSkinIni); + if (skinIniSourcedName != item.Name) + updateSkinIniMetadata(item); return base.ComputeHash(item, reader); } - private void updateSkinIniMetadata(SkinInfo item, bool hasSkinIni) + private void updateSkinIniMetadata(SkinInfo item) { string nameLine = $"Name: {item.Name}"; - string authorLine = $"Author: {item.Name}"; + string authorLine = $"Author: {item.Creator}"; - if (hasSkinIni) + var existingFile = item.Files.SingleOrDefault(f => f.Filename == "skin.ini"); + + if (existingFile != null) { List outputLines = new List(); bool addedName = false; bool addedAuthor = false; - var existingFile = item.Files.First(f => f.Filename == "skin.ini"); - using (var stream = Files.Storage.GetStream(existingFile.FileInfo.StoragePath)) using (var sr = new StreamReader(stream)) { @@ -220,10 +213,12 @@ namespace osu.Game.Skinning } using (Stream stream = new MemoryStream()) - using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) { - foreach (string line in outputLines) - sw.WriteLine(line); + using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) + { + foreach (string line in outputLines) + sw.WriteLine(line); + } ReplaceFile(item, existingFile, stream); } @@ -231,11 +226,13 @@ namespace osu.Game.Skinning else { using (Stream stream = new MemoryStream()) - using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) { - sw.WriteLine("[General]"); - sw.WriteLine(nameLine); - sw.WriteLine(authorLine); + using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) + { + sw.WriteLine("[General]"); + sw.WriteLine(nameLine); + sw.WriteLine(authorLine); + } AddFile(item, stream, "skin.ini"); } From 602303e9470225f1a57f647fb648331a1150a10e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Oct 2021 17:03:30 +0900 Subject: [PATCH 008/129] Add test coverage for `skin.ini` contents --- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 103 ++++++++++++++++------ osu.Game/Skinning/SkinManager.cs | 4 + 2 files changed, 80 insertions(+), 27 deletions(-) diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index 8449b0bbd3..67c5be0c2a 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Platform; +using osu.Game.IO; using osu.Game.IO.Archives; using osu.Game.Skinning; using SharpCompress.Archives.Zip; @@ -22,21 +23,36 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestSingleImportDifferentFilename() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk")); + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); // When the import filename doesn't match, it should be appended (and update the skin.ini). - Assert.That(imported.Name, Is.EqualTo("test skin [skin]")); - Assert.That(imported.Creator, Is.EqualTo("skinner")); + assertCorrectMetadata(imported, "test skin [skin]", "skinner", osu); }); [Test] public Task TestSingleImportMatchingFilename() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "test skin.osk")); + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "test skin.osk")); // When the import filename matches it shouldn't be appended. - Assert.That(imported.Name, Is.EqualTo("test skin")); - Assert.That(imported.Creator, Is.EqualTo("skinner")); + assertCorrectMetadata(imported, "test skin", "skinner", osu); + }); + + [Test] + public Task TestSingleImportNoIniFile() => runSkinTest(async osu => + { + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithNonIniFile(), "test skin.osk")); + + // When the import filename matches it shouldn't be appended. + assertCorrectMetadata(imported, "test skin", "Unknown", osu); + }); + + [Test] + public Task TestEmptyImportFails() => runSkinTest(osu => + { + Assert.ThrowsAsync(() => loadSkinIntoOsu(osu, new ZipArchiveReader(createEmptyOsk(), "test skin.osk"))); + + return Task.CompletedTask; }); #endregion @@ -46,8 +62,8 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestImportTwiceWithSameMetadataAndFilename() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk")); + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); assertImportedOnce(imported, imported2); }); @@ -56,8 +72,8 @@ namespace osu.Game.Tests.Skins.IO public Task TestImportTwiceWithNoMetadataSameDownloadFilename() => runSkinTest(async osu => { // if a user downloads two skins that do have skin.ini files but don't have any creator metadata in the skin.ini, they should both import separately just for safety. - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk(string.Empty, string.Empty), "download.osk")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk(string.Empty, string.Empty), "download.osk")); + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk")); assertImportedOnce(imported, imported2); }); @@ -65,14 +81,24 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestImportUpperCasedOskArchive() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1"), "name 1.OsK")); - assertCorrectMetadata(imported, "name 1", "author 1"); + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "name 1.OsK")); + assertCorrectMetadata(imported, "name 1", "author 1", osu); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1"), "name 1.oSK")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "name 1.oSK")); assertImportedOnce(imported, imported2); }); + [Test] + public Task TestSameMetadataNameSameFolderName() => runSkinTest(async osu => + { + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1")); + + assertImportedOnce(imported, imported2); + assertCorrectMetadata(imported, "name 1 [my custom skin 1]", "author 1", osu); + }); + #endregion #region Cases where imports should be uniquely imported @@ -80,8 +106,8 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestImportTwiceWithSameMetadataButDifferentFilename() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin2.osk")); + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin2.osk")); assertImportedBoth(imported, imported2); }); @@ -90,8 +116,8 @@ namespace osu.Game.Tests.Skins.IO public Task TestImportTwiceWithNoMetadataDifferentDownloadFilename() => runSkinTest(async osu => { // if a user downloads two skins that do have skin.ini files but don't have any creator metadata in the skin.ini, they should both import separately just for safety. - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk(string.Empty, string.Empty), "download.osk")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk(string.Empty, string.Empty), "download2.osk")); + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download2.osk")); assertImportedBoth(imported, imported2); }); @@ -99,31 +125,37 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestImportTwiceWithSameFilenameDifferentMetadata() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin v2", "skinner"), "skin.osk")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin v2.1", "skinner"), "skin.osk")); + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin v2", "skinner"), "skin.osk")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin v2.1", "skinner"), "skin.osk")); assertImportedBoth(imported, imported2); - assertCorrectMetadata(imported, "test skin v2 [skin]", "skinner"); - assertCorrectMetadata(imported2, "test skin v2.1 [skin]", "skinner"); + assertCorrectMetadata(imported, "test skin v2 [skin]", "skinner", osu); + assertCorrectMetadata(imported2, "test skin v2.1 [skin]", "skinner", osu); }); [Test] public Task TestSameMetadataNameDifferentFolderName() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1"), "my custom skin 1")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1"), "my custom skin 2")); + var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1")); + var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 2")); assertImportedBoth(imported, imported2); - assertCorrectMetadata(imported, "name 1 [my custom skin 2]", "author 1"); - assertCorrectMetadata(imported, "name 1 [my custom skin 2]", "author 1"); + assertCorrectMetadata(imported, "name 1 [my custom skin 1]", "author 1", osu); + assertCorrectMetadata(imported2, "name 1 [my custom skin 2]", "author 1", osu); }); #endregion - private void assertCorrectMetadata(SkinInfo imported, string name, string creator) + private void assertCorrectMetadata(SkinInfo imported, string name, string creator, OsuGameBase osu) { Assert.That(imported.Name, Is.EqualTo(name)); Assert.That(imported.Creator, Is.EqualTo(creator)); + + // for extra safety let's reconstruct the skin, reading from the skin.ini. + var instance = imported.CreateInstance((IStorageResourceProvider)osu.Dependencies.Get(typeof(SkinManager))); + + Assert.That(instance.Configuration.SkinInfo.Name, Is.EqualTo(name)); + Assert.That(instance.Configuration.SkinInfo.Creator, Is.EqualTo(creator)); } private void assertImportedBoth(SkinInfo imported, SkinInfo imported2) @@ -140,7 +172,24 @@ namespace osu.Game.Tests.Skins.IO Assert.That(imported2.Files.Select(f => f.FileInfoID), Is.EquivalentTo(imported.Files.Select(f => f.FileInfoID))); } - private MemoryStream createOsk(string name, string author, bool makeUnique = false) + private MemoryStream createEmptyOsk() + { + var zipStream = new MemoryStream(); + using var zip = ZipArchive.Create(); + zip.SaveTo(zipStream); + return zipStream; + } + + private MemoryStream createOskWithNonIniFile() + { + var zipStream = new MemoryStream(); + using var zip = ZipArchive.Create(); + zip.AddEntry("hitcircle.png", new MemoryStream(new byte[] { 0, 1, 2, 3 })); + zip.SaveTo(zipStream); + return zipStream; + } + + private MemoryStream createOskWithIni(string name, string author, bool makeUnique = false) { var zipStream = new MemoryStream(); using var zip = ZipArchive.Create(); diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 452c081a41..213c92c103 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -135,6 +135,10 @@ namespace osu.Game.Skinning protected override string ComputeHash(SkinInfo item, ArchiveReader reader = null) { + // we will be adding a hashable file below, but this is only useful if there are any other files in the skin. + if (item.Files.Count == 0) + throw new InvalidOperationException("Attempted to hash an archive with no files"); + var instance = GetSkin(item); // This function can be run on fresh import or save. The logic here ensures a skin.ini file is in a good state for both operations. From 5f53dd80213c50eccb324c668109429584f94ec6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Oct 2021 17:12:44 +0900 Subject: [PATCH 009/129] Rename test variable for legibility --- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 98 +++++++++++------------ 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index 67c5be0c2a..21e4948972 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -23,28 +23,28 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestSingleImportDifferentFilename() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); + var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); // When the import filename doesn't match, it should be appended (and update the skin.ini). - assertCorrectMetadata(imported, "test skin [skin]", "skinner", osu); + assertCorrectMetadata(import1, "test skin [skin]", "skinner", osu); }); [Test] public Task TestSingleImportMatchingFilename() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "test skin.osk")); + var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "test skin.osk")); // When the import filename matches it shouldn't be appended. - assertCorrectMetadata(imported, "test skin", "skinner", osu); + assertCorrectMetadata(import1, "test skin", "skinner", osu); }); [Test] public Task TestSingleImportNoIniFile() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithNonIniFile(), "test skin.osk")); + var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithNonIniFile(), "test skin.osk")); // When the import filename matches it shouldn't be appended. - assertCorrectMetadata(imported, "test skin", "Unknown", osu); + assertCorrectMetadata(import1, "test skin", "Unknown", osu); }); [Test] @@ -62,114 +62,114 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestImportTwiceWithSameMetadataAndFilename() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); + var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); + var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); - assertImportedOnce(imported, imported2); + assertImportedOnce(import1, import2); }); [Test] public Task TestImportTwiceWithNoMetadataSameDownloadFilename() => runSkinTest(async osu => { // if a user downloads two skins that do have skin.ini files but don't have any creator metadata in the skin.ini, they should both import separately just for safety. - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk")); + var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk")); + var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk")); - assertImportedOnce(imported, imported2); + assertImportedOnce(import1, import2); }); [Test] public Task TestImportUpperCasedOskArchive() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "name 1.OsK")); - assertCorrectMetadata(imported, "name 1", "author 1", osu); + var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "name 1.OsK")); + assertCorrectMetadata(import1, "name 1", "author 1", osu); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "name 1.oSK")); + var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "name 1.oSK")); - assertImportedOnce(imported, imported2); + assertImportedOnce(import1, import2); }); [Test] public Task TestSameMetadataNameSameFolderName() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1")); + var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1")); + var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1")); - assertImportedOnce(imported, imported2); - assertCorrectMetadata(imported, "name 1 [my custom skin 1]", "author 1", osu); + assertImportedOnce(import1, import2); + assertCorrectMetadata(import1, "name 1 [my custom skin 1]", "author 1", osu); }); #endregion - #region Cases where imports should be uniquely imported + #region Cases where imports should be uniquely import1 [Test] public Task TestImportTwiceWithSameMetadataButDifferentFilename() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin2.osk")); + var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); + var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin2.osk")); - assertImportedBoth(imported, imported2); + assertImportedBoth(import1, import2); }); [Test] public Task TestImportTwiceWithNoMetadataDifferentDownloadFilename() => runSkinTest(async osu => { // if a user downloads two skins that do have skin.ini files but don't have any creator metadata in the skin.ini, they should both import separately just for safety. - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download2.osk")); + var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk")); + var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download2.osk")); - assertImportedBoth(imported, imported2); + assertImportedBoth(import1, import2); }); [Test] public Task TestImportTwiceWithSameFilenameDifferentMetadata() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin v2", "skinner"), "skin.osk")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin v2.1", "skinner"), "skin.osk")); + var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin v2", "skinner"), "skin.osk")); + var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin v2.1", "skinner"), "skin.osk")); - assertImportedBoth(imported, imported2); - assertCorrectMetadata(imported, "test skin v2 [skin]", "skinner", osu); - assertCorrectMetadata(imported2, "test skin v2.1 [skin]", "skinner", osu); + assertImportedBoth(import1, import2); + assertCorrectMetadata(import1, "test skin v2 [skin]", "skinner", osu); + assertCorrectMetadata(import2, "test skin v2.1 [skin]", "skinner", osu); }); [Test] public Task TestSameMetadataNameDifferentFolderName() => runSkinTest(async osu => { - var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1")); - var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 2")); + var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1")); + var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 2")); - assertImportedBoth(imported, imported2); - assertCorrectMetadata(imported, "name 1 [my custom skin 1]", "author 1", osu); - assertCorrectMetadata(imported2, "name 1 [my custom skin 2]", "author 1", osu); + assertImportedBoth(import1, import2); + assertCorrectMetadata(import1, "name 1 [my custom skin 1]", "author 1", osu); + assertCorrectMetadata(import2, "name 1 [my custom skin 2]", "author 1", osu); }); #endregion - private void assertCorrectMetadata(SkinInfo imported, string name, string creator, OsuGameBase osu) + private void assertCorrectMetadata(SkinInfo import1, string name, string creator, OsuGameBase osu) { - Assert.That(imported.Name, Is.EqualTo(name)); - Assert.That(imported.Creator, Is.EqualTo(creator)); + Assert.That(import1.Name, Is.EqualTo(name)); + Assert.That(import1.Creator, Is.EqualTo(creator)); // for extra safety let's reconstruct the skin, reading from the skin.ini. - var instance = imported.CreateInstance((IStorageResourceProvider)osu.Dependencies.Get(typeof(SkinManager))); + var instance = import1.CreateInstance((IStorageResourceProvider)osu.Dependencies.Get(typeof(SkinManager))); Assert.That(instance.Configuration.SkinInfo.Name, Is.EqualTo(name)); Assert.That(instance.Configuration.SkinInfo.Creator, Is.EqualTo(creator)); } - private void assertImportedBoth(SkinInfo imported, SkinInfo imported2) + private void assertImportedBoth(SkinInfo import1, SkinInfo import2) { - Assert.That(imported2.ID, Is.Not.EqualTo(imported.ID)); - Assert.That(imported2.Hash, Is.Not.EqualTo(imported.Hash)); - Assert.That(imported2.Files.Select(f => f.FileInfoID), Is.Not.EquivalentTo(imported.Files.Select(f => f.FileInfoID))); + Assert.That(import2.ID, Is.Not.EqualTo(import1.ID)); + Assert.That(import2.Hash, Is.Not.EqualTo(import1.Hash)); + Assert.That(import2.Files.Select(f => f.FileInfoID), Is.Not.EquivalentTo(import1.Files.Select(f => f.FileInfoID))); } - private void assertImportedOnce(SkinInfo imported, SkinInfo imported2) + private void assertImportedOnce(SkinInfo import1, SkinInfo import2) { - Assert.That(imported2.ID, Is.EqualTo(imported.ID)); - Assert.That(imported2.Hash, Is.EqualTo(imported.Hash)); - Assert.That(imported2.Files.Select(f => f.FileInfoID), Is.EquivalentTo(imported.Files.Select(f => f.FileInfoID))); + Assert.That(import2.ID, Is.EqualTo(import1.ID)); + Assert.That(import2.Hash, Is.EqualTo(import1.Hash)); + Assert.That(import2.Files.Select(f => f.FileInfoID), Is.EquivalentTo(import1.Files.Select(f => f.FileInfoID))); } private MemoryStream createEmptyOsk() From 9e6e41d7c06c09e671c3274ef7f56a75cfd09f1e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Oct 2021 17:33:36 +0900 Subject: [PATCH 010/129] Add migration to reset and repopulate existing skin hashes --- osu.Game/Database/ArchiveModelManager.cs | 11 +++++---- .../20211020081609_ResetSkinHashes.cs | 23 +++++++++++++++++++ osu.Game/Skinning/SkinManager.cs | 22 ++++++++++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Migrations/20211020081609_ResetSkinHashes.cs diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 5b07bfe9a5..63a5da79a7 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -32,7 +32,7 @@ namespace osu.Game.Database /// The associated file join type. public abstract class ArchiveModelManager : IModelManager, IModelFileManager where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete - where TFileModel : class, INamedFileInfo, new() + where TFileModel : class, INamedFileInfo, IHasPrimaryKey, new() { private const int import_queue_request_concurrency = 1; @@ -520,9 +520,12 @@ namespace osu.Game.Database { Files.Dereference(file.FileInfo); - // This shouldn't be required, but here for safety in case the provided TModel is not being change tracked - // Definitely can be removed once we rework the database backend. - usage.Context.Set().Remove(file); + if (file.ID > 0) + { + // This shouldn't be required, but here for safety in case the provided TModel is not being change tracked + // Definitely can be removed once we rework the database backend. + usage.Context.Set().Remove(file); + } } model.Files.Remove(file); diff --git a/osu.Game/Migrations/20211020081609_ResetSkinHashes.cs b/osu.Game/Migrations/20211020081609_ResetSkinHashes.cs new file mode 100644 index 0000000000..6d53c019ec --- /dev/null +++ b/osu.Game/Migrations/20211020081609_ResetSkinHashes.cs @@ -0,0 +1,23 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using osu.Game.Database; + +namespace osu.Game.Migrations +{ + [DbContext(typeof(OsuDbContext))] + [Migration("20211020081609_ResetSkinHashes")] + public partial class ResetSkinHashes : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql($"UPDATE SkinInfo SET Hash = null"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + } + } +} diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 213c92c103..0b611bfe8f 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -18,6 +18,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; +using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Utils; @@ -84,6 +85,27 @@ namespace osu.Game.Skinning SourceChanged?.Invoke(); }; + + // can be removed 20220420. + populateMissingHashes(); + } + + private void populateMissingHashes() + { + var skinsWithoutHashes = ModelStore.ConsumableItems.Where(i => i.Hash == null).ToArray(); + + foreach (SkinInfo skin in skinsWithoutHashes) + { + try + { + Update(skin); + } + catch (Exception e) + { + Delete(skin); + Logger.Error(e, $"Existing skin {skin} has been deleted during hash recomputation due to being invalid"); + } + } } protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == ".osk"; From 68c01fc20442312cd09a27c29194c2fb3774be35 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Oct 2021 17:34:09 +0900 Subject: [PATCH 011/129] Fix infinite loop on default skin (it can't have a `skin.ini`) --- osu.Game/Skinning/SkinManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 0b611bfe8f..afa411a15b 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -186,7 +186,7 @@ namespace osu.Game.Skinning // By this point, the metadata in SkinInfo will be correct. // Regardless of whether this is an import or not, let's write the skin.ini if non-existing or non-matching. // This is (weirdly) done inside ComputeHash to avoid adding a new method to handle this case. After switching to realm it can be moved into another place. - if (skinIniSourcedName != item.Name) + if (instance is LegacySkin && skinIniSourcedName != item.Name) updateSkinIniMetadata(item); return base.ComputeHash(item, reader); From 59b7210efaaf976301deefc9fdbd3c2d756f675f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Oct 2021 13:35:26 +0900 Subject: [PATCH 012/129] Revert disallowing imports with no files While it is logical that we want this, from a testing perspective this is a bit of a nightmare to fix. Let's revisit at a later point in time. --- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 7 ++-- osu.Game/Database/ArchiveModelManager.cs | 40 ++++++++++++++--------- osu.Game/Skinning/SkinManager.cs | 4 --- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index 21e4948972..20bf42345f 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -48,11 +48,12 @@ namespace osu.Game.Tests.Skins.IO }); [Test] - public Task TestEmptyImportFails() => runSkinTest(osu => + public Task TestEmptyImportImportsWithFilename() => runSkinTest(async osu => { - Assert.ThrowsAsync(() => loadSkinIntoOsu(osu, new ZipArchiveReader(createEmptyOsk(), "test skin.osk"))); + var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createEmptyOsk(), "test skin.osk")); - return Task.CompletedTask; + // When the import filename matches it shouldn't be appended. + assertCorrectMetadata(import1, "test skin", "Unknown", osu); }); #endregion diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 63a5da79a7..0bc4c40459 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -322,22 +322,22 @@ namespace osu.Game.Database .OrderBy(f => f.Filename) .ToArray(); - if (hashableFiles.Length == 0) - throw new InvalidOperationException("Attempted to hash an archive with no files"); - - // for now, concatenate all hashable files in the set to create a unique hash. - MemoryStream hashable = new MemoryStream(); - - foreach (TFileModel file in hashableFiles) + if (hashableFiles.Length > 0) { - using (Stream s = Files.Store.GetStream(file.FileInfo.StoragePath)) - s.CopyTo(hashable); + // for now, concatenate all hashable files in the set to create a unique hash. + MemoryStream hashable = new MemoryStream(); + + foreach (TFileModel file in hashableFiles) + { + using (Stream s = Files.Store.GetStream(file.FileInfo.StoragePath)) + s.CopyTo(hashable); + } + + if (hashable.Length > 0) + return hashable.ComputeSHA2Hash(); } - if (hashable.Length > 0) - return hashable.ComputeSHA2Hash(); - - return item.Hash; + return generateFallbackHash(); } /// @@ -707,10 +707,10 @@ namespace osu.Game.Database s.CopyTo(hashable); } - if (hashable.Length == 0) - throw new InvalidOperationException("Attempted to hash an archive with no files"); + if (hashable.Length > 0) + return hashable.ComputeSHA2Hash(); - return hashable.ComputeSHA2Hash(); + return generateFallbackHash(); } /// @@ -923,6 +923,14 @@ namespace osu.Game.Database #endregion + private static string generateFallbackHash() + { + // if a hash could no be generated from file content, presume a unique / new import. + // therefore, let's use a guaranteed unique hash. + // this doesn't follow the SHA2 hashing schema intentionally, so such entries on the data store can be identified. + return Guid.NewGuid().ToString(); + } + private string getValidFilename(string filename) { foreach (char c in Path.GetInvalidFileNameChars()) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index afa411a15b..304e48e854 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -157,10 +157,6 @@ namespace osu.Game.Skinning protected override string ComputeHash(SkinInfo item, ArchiveReader reader = null) { - // we will be adding a hashable file below, but this is only useful if there are any other files in the skin. - if (item.Files.Count == 0) - throw new InvalidOperationException("Attempted to hash an archive with no files"); - var instance = GetSkin(item); // This function can be run on fresh import or save. The logic here ensures a skin.ini file is in a good state for both operations. From a5088cac27c2d6955165efd45a86b68ed7952128 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Oct 2021 13:36:04 +0900 Subject: [PATCH 013/129] Fix default metadata propagation when no files are present --- osu.Game/Skinning/SkinInfo.cs | 6 +++--- osu.Game/Skinning/SkinManager.cs | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Skinning/SkinInfo.cs b/osu.Game/Skinning/SkinInfo.cs index 2bf8668ec6..3b34e23d57 100644 --- a/osu.Game/Skinning/SkinInfo.cs +++ b/osu.Game/Skinning/SkinInfo.cs @@ -18,12 +18,12 @@ namespace osu.Game.Skinning public int ID { get; set; } - public string Name { get; set; } + public string Name { get; set; } = string.Empty; + + public string Creator { get; set; } = string.Empty; public string Hash { get; set; } - public string Creator { get; set; } - public string InstantiationInfo { get; set; } public virtual Skin CreateInstance(IStorageResourceProvider resources) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 304e48e854..fffdf19976 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -149,7 +149,7 @@ namespace osu.Game.Skinning CurrentSkinInfo.Value = ModelStore.ConsumableItems.Single(i => i.ID == chosen.ID); } - protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo { Name = archive.Name }; + protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo { Name = archive.Name ?? "No name" }; private const string unknown_creator_string = "Unknown"; @@ -163,6 +163,7 @@ namespace osu.Game.Skinning // LegacySkin will parse the skin.ini and populate `Skin.Configuration` during construction above. string skinIniSourcedName = instance.Configuration.SkinInfo.Name; + string skinIniSourcedCreator = instance.Configuration.SkinInfo.Creator; string archiveName = item.Name.Replace(".osk", "", StringComparison.OrdinalIgnoreCase); bool isImport = reader != null; @@ -170,7 +171,7 @@ namespace osu.Game.Skinning if (isImport) { item.Name = !string.IsNullOrEmpty(skinIniSourcedName) ? skinIniSourcedName : archiveName; - item.Creator = instance.Configuration.SkinInfo.Creator ?? unknown_creator_string; + item.Creator = !string.IsNullOrEmpty(skinIniSourcedCreator) ? skinIniSourcedCreator : unknown_creator_string; // For imports, we want to use the archive or folder name as part of the metadata, in addition to any existing skin.ini metadata. // In an ideal world, skin.ini would be the only source of metadata, but a lot of skin creators and users don't update it when making modifications. From 08971ff8f27e1489354f8ee596f89ce186bd6565 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Oct 2021 11:03:28 +0900 Subject: [PATCH 014/129] Fix typo in region spedc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index 20bf42345f..b62fb8bd87 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -102,7 +102,7 @@ namespace osu.Game.Tests.Skins.IO #endregion - #region Cases where imports should be uniquely import1 + #region Cases where imports should be uniquely imported [Test] public Task TestImportTwiceWithSameMetadataButDifferentFilename() => runSkinTest(async osu => From e5b73f25cd40cadf90884fb8f2dc160d6a764ad8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Oct 2021 12:56:05 +0900 Subject: [PATCH 015/129] Ensure newly created `skin.ini` files are set to latest version --- osu.Game/Skinning/SkinManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index fffdf19976..16ed25eeb1 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -255,6 +255,7 @@ namespace osu.Game.Skinning sw.WriteLine("[General]"); sw.WriteLine(nameLine); sw.WriteLine(authorLine); + sw.WriteLine("Version: latest"); } AddFile(item, stream, "skin.ini"); From 9cdc1ba59219ecd31df04c235def14567f4fbee4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Oct 2021 13:43:45 +0900 Subject: [PATCH 016/129] Fix default legacy skin not being able to read from stored `skin.ini` --- osu.Game/Skinning/DefaultLegacySkin.cs | 9 +++++- osu.Game/Skinning/LegacySkin.cs | 39 ++++++++++++++++---------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index 16ac17546d..cd6dbd9ddd 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -19,7 +19,14 @@ namespace osu.Game.Skinning [UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)] public DefaultLegacySkin(SkinInfo skin, IStorageResourceProvider resources) - : base(skin, new NamespacedResourceStore(resources.Resources, "Skins/Legacy"), resources, string.Empty) + : base( + skin, + new NamespacedResourceStore(resources.Resources, "Skins/Legacy"), + resources, + // A default legacy skin may still have a skin.ini if it is modified by the user. + // We must specify the stream directly as we are redirecting storage to the osu-resources location for other files. + new LegacySkinResourceStore(skin, resources.Files).GetStream("skin.ini") + ) { Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255); Configuration.CustomComboColours = new List diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index b09620411b..5ab3ef84db 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -69,28 +69,37 @@ namespace osu.Game.Skinning /// Access to raw game resources. /// The user-facing filename of the configuration file to be parsed. Can accept an .osu or skin.ini file. protected LegacySkin(SkinInfo skin, [CanBeNull] IResourceStore storage, [CanBeNull] IStorageResourceProvider resources, string configurationFilename) + : this(skin, storage, resources, storage?.GetStream(configurationFilename)) + { + } + + /// + /// Construct a new legacy skin instance. + /// + /// The model for this skin. + /// A storage for looking up files within this skin using user-facing filenames. + /// Access to raw game resources. + /// An optional stream containing the contents of a skin.ini file. + protected LegacySkin(SkinInfo skin, [CanBeNull] IResourceStore storage, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] Stream configurationStream) : base(skin, resources) { - using (var stream = storage?.GetStream(configurationFilename)) + if (configurationStream != null) { - if (stream != null) + using (LineBufferedReader reader = new LineBufferedReader(configurationStream, true)) + Configuration = new LegacySkinDecoder().Decode(reader); + + configurationStream.Seek(0, SeekOrigin.Begin); + + using (LineBufferedReader reader = new LineBufferedReader(configurationStream)) { - using (LineBufferedReader reader = new LineBufferedReader(stream, true)) - Configuration = new LegacySkinDecoder().Decode(reader); + var maniaList = new LegacyManiaSkinDecoder().Decode(reader); - stream.Seek(0, SeekOrigin.Begin); - - using (LineBufferedReader reader = new LineBufferedReader(stream)) - { - var maniaList = new LegacyManiaSkinDecoder().Decode(reader); - - foreach (var config in maniaList) - maniaConfigurations[config.Keys] = config; - } + foreach (var config in maniaList) + maniaConfigurations[config.Keys] = config; } - else - Configuration = new LegacySkinConfiguration(); } + else + Configuration = new LegacySkinConfiguration(); if (storage != null) { From 82d0a6515fbe39536dd86122aede7caec25badd8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Oct 2021 14:08:12 +0900 Subject: [PATCH 017/129] Fix incorrect conditional for checking whether import (would fail for default skin) --- osu.Game/Skinning/SkinManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 16ed25eeb1..707afade09 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -166,7 +166,7 @@ namespace osu.Game.Skinning string skinIniSourcedCreator = instance.Configuration.SkinInfo.Creator; string archiveName = item.Name.Replace(".osk", "", StringComparison.OrdinalIgnoreCase); - bool isImport = reader != null; + bool isImport = item.ID == 0; if (isImport) { From 93482414d6d69fff3e02a0083afb1fb55244db23 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Oct 2021 14:41:59 +0900 Subject: [PATCH 018/129] Remove `SkinConfiguration` subclasses and allow configuration parsing for all skin types --- .../Legacy/CatchLegacySkinTransformer.cs | 2 +- .../Skinning/Legacy/LegacyStageBackground.cs | 2 +- .../Legacy/ManiaLegacySkinTransformer.cs | 2 +- .../Skinning/Legacy/LegacyMainCirclePiece.cs | 3 +- .../Skinning/Legacy/LegacyInputDrum.cs | 2 +- .../Gameplay/TestSceneHitObjectSamples.cs | 2 +- osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 2 +- .../Skins/TestSceneSkinConfigurationLookup.cs | 8 +-- .../Objects/Legacy/ConvertHitObjectParser.cs | 2 +- osu.Game/Skinning/DefaultSkin.cs | 1 - osu.Game/Skinning/DefaultSkinConfiguration.cs | 12 ---- osu.Game/Skinning/LegacyBeatmapSkin.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 55 ++++++++----------- osu.Game/Skinning/LegacySkinConfiguration.cs | 28 ---------- osu.Game/Skinning/LegacySkinDecoder.cs | 8 +-- osu.Game/Skinning/LegacySkinExtensions.cs | 2 +- osu.Game/Skinning/LegacySkinTransformer.cs | 2 +- osu.Game/Skinning/Skin.cs | 31 ++++++++++- osu.Game/Skinning/SkinConfiguration.cs | 20 +++++++ osu.Game/Skinning/SkinManager.cs | 2 +- 20 files changed, 92 insertions(+), 96 deletions(-) delete mode 100644 osu.Game/Skinning/DefaultSkinConfiguration.cs delete mode 100644 osu.Game/Skinning/LegacySkinConfiguration.cs diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs index 10fc4e78b2..335d78388b 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy return null; case CatchSkinComponents.Catcher: - var version = GetConfig(LegacySkinConfiguration.LegacySetting.Version)?.Value ?? 1; + var version = GetConfig(SkinConfiguration.LegacySetting.Version)?.Value ?? 1; if (version < 2.3m) { diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs index fec3e9493e..952fc7ddd6 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy float rightLineWidth = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.RightLineWidth, columnIndex)?.Value ?? 1; bool hasLeftLine = leftLineWidth > 0; - bool hasRightLine = rightLineWidth > 0 && skin.GetConfig(LegacySkinConfiguration.LegacySetting.Version)?.Value >= 2.4m + bool hasRightLine = rightLineWidth > 0 && skin.GetConfig(SkinConfiguration.LegacySetting.Version)?.Value >= 2.4m || isLastColumn; Color4 lineColour = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.ColumnLineColour, columnIndex)?.Value ?? Color4.White; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs index 814a737034..0de9a098bc 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs @@ -63,7 +63,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy { this.beatmap = (ManiaBeatmap)beatmap; - isLegacySkin = new Lazy(() => GetConfig(LegacySkinConfiguration.LegacySetting.Version) != null); + isLegacySkin = new Lazy(() => GetConfig(SkinConfiguration.LegacySetting.Version) != null); hasKeyTexture = new Lazy(() => { var keyImage = this.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.KeyImage, 0)?.Value ?? "mania-key1"; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs index d1c9b1bf92..0e0f4f4291 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs @@ -14,7 +14,6 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Skinning; using osuTK; using osuTK.Graphics; -using static osu.Game.Skinning.LegacySkinConfiguration; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { @@ -158,7 +157,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy if (hasNumber) { - var legacyVersion = skin.GetConfig(LegacySetting.Version)?.Value; + var legacyVersion = skin.GetConfig(SkinConfiguration.LegacySetting.Version)?.Value; if (legacyVersion >= 2.0m) // legacy skins of version 2.0 and newer only apply very short fade out to the number piece. diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs index 86be40dea8..43c5c07f80 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy // because the right half is flipped, we need to position using width - position to get the true "topleft" origin position float negativeScaleAdjust = content.Width / ratio; - if (skin.GetConfig(LegacySkinConfiguration.LegacySetting.Version)?.Value >= 2.1m) + if (skin.GetConfig(SkinConfiguration.LegacySetting.Version)?.Value >= 2.1m) { left.Centre.Position = new Vector2(0, taiko_bar_y) * ratio; right.Centre.Position = new Vector2(negativeScaleAdjust - 56, taiko_bar_y) * ratio; diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs index fc420e22a1..153d5b8e36 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Resources; -using static osu.Game.Skinning.LegacySkinConfiguration; +using static osu.Game.Skinning.SkinConfiguration; namespace osu.Game.Tests.Gameplay { diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index dcb866c99f..cfc140ce39 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -106,7 +106,7 @@ namespace osu.Game.Tests.Skins var decoder = new LegacySkinDecoder(); using (var resStream = TestResources.OpenResource("skin-latest.ini")) using (var stream = new LineBufferedReader(resStream)) - Assert.AreEqual(LegacySkinConfiguration.LATEST_VERSION, decoder.Decode(stream).LegacyVersion); + Assert.AreEqual(SkinConfiguration.LATEST_VERSION, decoder.Decode(stream).LegacyVersion); } [Test] diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index aadabec100..870d6d8f57 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -151,7 +151,7 @@ namespace osu.Game.Tests.Skins { AddStep("Set user skin version 2.3", () => userSource.Configuration.LegacyVersion = 2.3m); AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = null); - AddAssert("Check legacy version lookup", () => requester.GetConfig(LegacySkinConfiguration.LegacySetting.Version)?.Value == 2.3m); + AddAssert("Check legacy version lookup", () => requester.GetConfig(SkinConfiguration.LegacySetting.Version)?.Value == 2.3m); } [Test] @@ -160,7 +160,7 @@ namespace osu.Game.Tests.Skins // completely ignoring beatmap versions for simplicity. AddStep("Set user skin version 2.3", () => userSource.Configuration.LegacyVersion = 2.3m); AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = 1.7m); - AddAssert("Check legacy version lookup", () => requester.GetConfig(LegacySkinConfiguration.LegacySetting.Version)?.Value == 2.3m); + AddAssert("Check legacy version lookup", () => requester.GetConfig(SkinConfiguration.LegacySetting.Version)?.Value == 2.3m); } [Test] @@ -169,14 +169,14 @@ namespace osu.Game.Tests.Skins AddStep("Set user skin version 2.3", () => userSource.Configuration.LegacyVersion = null); AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = null); AddAssert("Check legacy version lookup", - () => requester.GetConfig(LegacySkinConfiguration.LegacySetting.Version)?.Value == LegacySkinConfiguration.LATEST_VERSION); + () => requester.GetConfig(SkinConfiguration.LegacySetting.Version)?.Value == SkinConfiguration.LATEST_VERSION); } [Test] public void TestIniWithNoVersionFallsBackTo1() { AddStep("Parse skin with no version", () => userSource.Configuration = new LegacySkinDecoder().Decode(new LineBufferedReader(new MemoryStream()))); - AddAssert("Check legacy version lookup", () => requester.GetConfig(LegacySkinConfiguration.LegacySetting.Version)?.Value == 1.0m); + AddAssert("Check legacy version lookup", () => requester.GetConfig(SkinConfiguration.LegacySetting.Version)?.Value == 1.0m); } public enum LookupType diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 0942a7264d..d902918e83 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -481,7 +481,7 @@ namespace osu.Game.Rulesets.Objects.Legacy /// /// /// Layered hit samples are automatically added in all modes (except osu!mania), but can be disabled - /// using the skin config option. + /// using the skin config option. /// public readonly bool IsLayered; diff --git a/osu.Game/Skinning/DefaultSkin.cs b/osu.Game/Skinning/DefaultSkin.cs index 8e03bddb4d..d972ce3af6 100644 --- a/osu.Game/Skinning/DefaultSkin.cs +++ b/osu.Game/Skinning/DefaultSkin.cs @@ -35,7 +35,6 @@ namespace osu.Game.Skinning : base(skin, resources) { this.resources = resources; - Configuration = new DefaultSkinConfiguration(); } public override Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => null; diff --git a/osu.Game/Skinning/DefaultSkinConfiguration.cs b/osu.Game/Skinning/DefaultSkinConfiguration.cs deleted file mode 100644 index 5842ee82ee..0000000000 --- a/osu.Game/Skinning/DefaultSkinConfiguration.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Skinning -{ - /// - /// A skin configuration pre-populated with sane defaults. - /// - public class DefaultSkinConfiguration : SkinConfiguration - { - } -} diff --git a/osu.Game/Skinning/LegacyBeatmapSkin.cs b/osu.Game/Skinning/LegacyBeatmapSkin.cs index 2093182dcc..8720a55076 100644 --- a/osu.Game/Skinning/LegacyBeatmapSkin.cs +++ b/osu.Game/Skinning/LegacyBeatmapSkin.cs @@ -50,7 +50,7 @@ namespace osu.Game.Skinning { switch (lookup) { - case LegacySkinConfiguration.LegacySetting s when s == LegacySkinConfiguration.LegacySetting.Version: + case SkinConfiguration.LegacySetting s when s == SkinConfiguration.LegacySetting.Version: // For lookup simplicity, ignore beatmap-level versioning completely. // If it is decided that we need this due to beatmaps somehow using it, the default (1.0 specified in LegacySkinDecoder.CreateTemplateObject) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 5ab3ef84db..6facb6fafd 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -47,12 +47,6 @@ namespace osu.Game.Skinning /// protected virtual bool UseCustomSampleBanks => false; - public new LegacySkinConfiguration Configuration - { - get => base.Configuration as LegacySkinConfiguration; - set => base.Configuration = value; - } - private readonly Dictionary maniaConfigurations = new Dictionary(); [UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)] @@ -81,26 +75,8 @@ namespace osu.Game.Skinning /// Access to raw game resources. /// An optional stream containing the contents of a skin.ini file. protected LegacySkin(SkinInfo skin, [CanBeNull] IResourceStore storage, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] Stream configurationStream) - : base(skin, resources) + : base(skin, resources, configurationStream) { - if (configurationStream != null) - { - using (LineBufferedReader reader = new LineBufferedReader(configurationStream, true)) - Configuration = new LegacySkinDecoder().Decode(reader); - - configurationStream.Seek(0, SeekOrigin.Begin); - - using (LineBufferedReader reader = new LineBufferedReader(configurationStream)) - { - var maniaList = new LegacyManiaSkinDecoder().Decode(reader); - - foreach (var config in maniaList) - maniaConfigurations[config.Keys] = config; - } - } - else - Configuration = new LegacySkinConfiguration(); - if (storage != null) { var samples = resources?.AudioManager?.GetSampleStore(storage); @@ -119,6 +95,21 @@ namespace osu.Game.Skinning true) != null); } + protected override void ParseConfigurationStream(Stream stream) + { + base.ParseConfigurationStream(stream); + + stream.Seek(0, SeekOrigin.Begin); + + using (LineBufferedReader reader = new LineBufferedReader(stream)) + { + var maniaList = new LegacyManiaSkinDecoder().Decode(reader); + + foreach (var config in maniaList) + maniaConfigurations[config.Keys] = config; + } + } + public override IBindable GetConfig(TLookup lookup) { switch (lookup) @@ -155,7 +146,7 @@ namespace osu.Game.Skinning break; - case LegacySkinConfiguration.LegacySetting legacy: + case SkinConfiguration.LegacySetting legacy: return legacySettingLookup(legacy); default: @@ -198,7 +189,7 @@ namespace osu.Game.Skinning case LegacyManiaSkinConfigurationLookups.ExplosionScale: Debug.Assert(maniaLookup.TargetColumn != null); - if (GetConfig(LegacySkinConfiguration.LegacySetting.Version)?.Value < 2.5m) + if (GetConfig(SkinConfiguration.LegacySetting.Version)?.Value < 2.5m) return SkinUtils.As(new Bindable(1)); if (existing.ExplosionWidth[maniaLookup.TargetColumn.Value] != 0) @@ -245,7 +236,7 @@ namespace osu.Game.Skinning case LegacyManiaSkinConfigurationLookups.HoldNoteLightScale: Debug.Assert(maniaLookup.TargetColumn != null); - if (GetConfig(LegacySkinConfiguration.LegacySetting.Version)?.Value < 2.5m) + if (GetConfig(SkinConfiguration.LegacySetting.Version)?.Value < 2.5m) return SkinUtils.As(new Bindable(1)); if (existing.HoldNoteLightWidth[maniaLookup.TargetColumn.Value] != 0) @@ -318,15 +309,15 @@ namespace osu.Game.Skinning => source.ImageLookups.TryGetValue(lookup, out var image) ? new Bindable(image) : null; [CanBeNull] - private IBindable legacySettingLookup(LegacySkinConfiguration.LegacySetting legacySetting) + private IBindable legacySettingLookup(SkinConfiguration.LegacySetting legacySetting) { switch (legacySetting) { - case LegacySkinConfiguration.LegacySetting.Version: - return SkinUtils.As(new Bindable(Configuration.LegacyVersion ?? LegacySkinConfiguration.LATEST_VERSION)); + case SkinConfiguration.LegacySetting.Version: + return SkinUtils.As(new Bindable(Configuration.LegacyVersion ?? SkinConfiguration.LATEST_VERSION)); default: - return genericLookup(legacySetting); + return genericLookup(legacySetting); } } diff --git a/osu.Game/Skinning/LegacySkinConfiguration.cs b/osu.Game/Skinning/LegacySkinConfiguration.cs deleted file mode 100644 index 20d1da8aaa..0000000000 --- a/osu.Game/Skinning/LegacySkinConfiguration.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Skinning -{ - public class LegacySkinConfiguration : SkinConfiguration - { - public const decimal LATEST_VERSION = 2.7m; - - /// - /// Legacy version of this skin. - /// - public decimal? LegacyVersion { get; internal set; } - - public enum LegacySetting - { - Version, - ComboPrefix, - ComboOverlap, - ScorePrefix, - ScoreOverlap, - HitCirclePrefix, - HitCircleOverlap, - AnimationFramerate, - LayeredHitSounds - } - } -} diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 2700f84815..dd8a9dedb2 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -6,14 +6,14 @@ using osu.Game.Beatmaps.Formats; namespace osu.Game.Skinning { - public class LegacySkinDecoder : LegacyDecoder + public class LegacySkinDecoder : LegacyDecoder { public LegacySkinDecoder() : base(1) { } - protected override void ParseLine(LegacySkinConfiguration skin, Section section, string line) + protected override void ParseLine(SkinConfiguration skin, Section section, string line) { if (section != Section.Colours) { @@ -34,7 +34,7 @@ namespace osu.Game.Skinning case @"Version": if (pair.Value == "latest") - skin.LegacyVersion = LegacySkinConfiguration.LATEST_VERSION; + skin.LegacyVersion = SkinConfiguration.LATEST_VERSION; else if (decimal.TryParse(pair.Value, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var version)) skin.LegacyVersion = version; @@ -57,7 +57,7 @@ namespace osu.Game.Skinning base.ParseLine(skin, section, line); } - protected override LegacySkinConfiguration CreateTemplateObject() + protected override SkinConfiguration CreateTemplateObject() { var config = base.CreateTemplateObject(); config.LegacyVersion = 1.0m; diff --git a/osu.Game/Skinning/LegacySkinExtensions.cs b/osu.Game/Skinning/LegacySkinExtensions.cs index fd1f905868..479afabb00 100644 --- a/osu.Game/Skinning/LegacySkinExtensions.cs +++ b/osu.Game/Skinning/LegacySkinExtensions.cs @@ -12,7 +12,7 @@ using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using static osu.Game.Skinning.LegacySkinConfiguration; +using static osu.Game.Skinning.SkinConfiguration; namespace osu.Game.Skinning { diff --git a/osu.Game/Skinning/LegacySkinTransformer.cs b/osu.Game/Skinning/LegacySkinTransformer.cs index 92b7a04dee..97084f34e0 100644 --- a/osu.Game/Skinning/LegacySkinTransformer.cs +++ b/osu.Game/Skinning/LegacySkinTransformer.cs @@ -10,7 +10,7 @@ using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.Textures; using osu.Game.Audio; using osu.Game.Rulesets.Objects.Legacy; -using static osu.Game.Skinning.LegacySkinConfiguration; +using static osu.Game.Skinning.SkinConfiguration; namespace osu.Game.Skinning { diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 92441f40da..d5f41f01a4 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -3,8 +3,10 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; +using JetBrains.Annotations; using Newtonsoft.Json; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; @@ -21,8 +23,9 @@ namespace osu.Game.Skinning public abstract class Skin : IDisposable, ISkin { public readonly SkinInfo SkinInfo; + private readonly IStorageResourceProvider resources; - public SkinConfiguration Configuration { get; protected set; } + public SkinConfiguration Configuration { get; set; } public IDictionary DrawableComponentInfo => drawableComponentInfo; @@ -36,9 +39,17 @@ namespace osu.Game.Skinning public abstract IBindable GetConfig(TLookup lookup); - protected Skin(SkinInfo skin, IStorageResourceProvider resources) + protected Skin(SkinInfo skin, IStorageResourceProvider resources, [CanBeNull] Stream configurationStream = null) { SkinInfo = skin; + this.resources = resources; + + configurationStream ??= getConfigurationStream(); + + if (configurationStream != null) + ParseConfigurationStream(configurationStream); + else + Configuration = new SkinConfiguration(); // we may want to move this to some kind of async operation in the future. foreach (SkinnableTarget skinnableTarget in Enum.GetValues(typeof(SkinnableTarget))) @@ -73,6 +84,22 @@ namespace osu.Game.Skinning } } + protected virtual void ParseConfigurationStream(Stream stream) + { + using (LineBufferedReader reader = new LineBufferedReader(stream, true)) + Configuration = new LegacySkinDecoder().Decode(reader); + } + + private Stream getConfigurationStream() + { + var path = SkinInfo.Files.SingleOrDefault(f => f.Filename == "skin.ini")?.FileInfo.StoragePath; + + if (string.IsNullOrEmpty(path)) + return null; + + return resources?.Files.GetStream(path); + } + /// /// Remove all stored customisations for the provided target. /// diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index a18144246f..f71f6811e8 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -14,11 +14,31 @@ namespace osu.Game.Skinning { public readonly SkinInfo SkinInfo = new SkinInfo(); + public const decimal LATEST_VERSION = 2.7m; + /// /// Whether to allow as a fallback list for when no combo colours are provided. /// internal bool AllowDefaultComboColoursFallback = true; + /// + /// Legacy version of this skin. + /// + public decimal? LegacyVersion { get; internal set; } + + public enum LegacySetting + { + Version, + ComboPrefix, + ComboOverlap, + ScorePrefix, + ScoreOverlap, + HitCirclePrefix, + HitCircleOverlap, + AnimationFramerate, + LayeredHitSounds + } + public static List DefaultComboColours { get; } = new List { new Color4(255, 192, 0, 255), diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 707afade09..177dbaf28f 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -183,7 +183,7 @@ namespace osu.Game.Skinning // By this point, the metadata in SkinInfo will be correct. // Regardless of whether this is an import or not, let's write the skin.ini if non-existing or non-matching. // This is (weirdly) done inside ComputeHash to avoid adding a new method to handle this case. After switching to realm it can be moved into another place. - if (instance is LegacySkin && skinIniSourcedName != item.Name) + if (skinIniSourcedName != item.Name) updateSkinIniMetadata(item); return base.ComputeHash(item, reader); From eef9949a0a928f3d10df97375119ccc1fbdbbf90 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Oct 2021 14:48:20 +0900 Subject: [PATCH 019/129] Remove unnecessary branching around EF logic --- osu.Game/Database/ArchiveModelManager.cs | 48 +++++++----------------- 1 file changed, 14 insertions(+), 34 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 0bc4c40459..ad5bc6d420 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -511,29 +511,21 @@ namespace osu.Game.Database /// The existing file to be deleted. public void DeleteFile(TModel model, TFileModel file) { - if (model.ID > 0) + using (var usage = ContextFactory.GetForWrite()) { - using (var usage = ContextFactory.GetForWrite()) + // Dereference the existing file info, since the file model will be removed. + if (file.FileInfo != null) { - // Dereference the existing file info, since the file model will be removed. - if (file.FileInfo != null) + Files.Dereference(file.FileInfo); + + if (file.ID > 0) { - Files.Dereference(file.FileInfo); - - if (file.ID > 0) - { - // This shouldn't be required, but here for safety in case the provided TModel is not being change tracked - // Definitely can be removed once we rework the database backend. - usage.Context.Set().Remove(file); - } + // This shouldn't be required, but here for safety in case the provided TModel is not being change tracked + // Definitely can be removed once we rework the database backend. + usage.Context.Set().Remove(file); } - - model.Files.Remove(file); } - } - else - { - Files.Dereference(file.FileInfo); + model.Files.Remove(file); } } @@ -546,29 +538,17 @@ namespace osu.Game.Database /// The filename for the new file. public void AddFile(TModel model, Stream contents, string filename) { - if (model.ID > 0) + using (ContextFactory.GetForWrite()) { - using (ContextFactory.GetForWrite()) - { - model.Files.Add(new TFileModel - { - Filename = filename, - FileInfo = Files.Add(contents) - }); - - Update(model); - } - } - else - { - // This function may be called during the import process. - // Should not exist like this once we have switched to realm. model.Files.Add(new TFileModel { Filename = filename, FileInfo = Files.Add(contents) }); } + + if (model.ID > 0) + Update(model); } /// From 9fcb3d9dd1ca32f87fd2d4404fa5bdacf3d1e4aa Mon Sep 17 00:00:00 2001 From: Jason Won Date: Fri, 22 Oct 2021 17:10:53 -0400 Subject: [PATCH 020/129] NoScopeMod: show cursor during breaks + spinners --- osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs | 31 +++++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs b/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs index c48cbd9992..026bb6c1cb 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs @@ -2,22 +2,27 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Game.Rulesets.UI; -using osu.Game.Rulesets.Mods; +using System.Linq; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Framework.Bindables; using osu.Framework.Localisation; using osu.Framework.Utils; -using osu.Game.Graphics.UserInterface; +using osu.Game.Beatmaps; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; +using osu.Game.Screens.Play; +using osu.Game.Utils; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModNoScope : Mod, IUpdatableByPlayfield, IApplicableToScoreProcessor + public class OsuModNoScope : Mod, IUpdatableByPlayfield, IApplicableToScoreProcessor, IApplicableToPlayer, IApplicableToBeatmap { /// /// Slightly higher than the cutoff for . @@ -34,6 +39,8 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; private BindableNumber currentCombo; + private IBindable isBreakTime; + private PeriodTracker spinnerPeriods; private float targetAlpha; @@ -52,6 +59,16 @@ namespace osu.Game.Rulesets.Osu.Mods public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; + public void ApplyToPlayer(Player player) + { + isBreakTime = player.IsBreakTime.GetBoundCopy(); + } + + public void ApplyToBeatmap(IBeatmap beatmap) + { + spinnerPeriods = new PeriodTracker(beatmap.HitObjects.OfType().Select(b => new Period(b.StartTime - transition_duration, b.EndTime))); + } + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { if (HiddenComboCount.Value == 0) return; @@ -65,7 +82,9 @@ namespace osu.Game.Rulesets.Osu.Mods public virtual void Update(Playfield playfield) { - playfield.Cursor.Alpha = (float)Interpolation.Lerp(playfield.Cursor.Alpha, targetAlpha, Math.Clamp(playfield.Time.Elapsed / transition_duration, 0, 1)); + var overrideAlpha = isBreakTime.Value || spinnerPeriods.IsInAny(playfield.Clock.CurrentTime); + var targetOverriddenAlpha = overrideAlpha ? 1 : targetAlpha; + playfield.Cursor.Alpha = (float)Interpolation.Lerp(playfield.Cursor.Alpha, targetOverriddenAlpha, Math.Clamp(playfield.Time.Elapsed / transition_duration, 0, 1)); } } From 4440b9ca11b6c5e8add43c24a4546d0b8256bd01 Mon Sep 17 00:00:00 2001 From: goodtrailer Date: Sat, 23 Oct 2021 01:59:07 -0700 Subject: [PATCH 021/129] Change IHasRepeats.NodeSamples to IList from List --- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 2 +- .../ManiaBeatmapSampleConversionTest.cs | 2 +- .../Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs | 2 +- osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 2 +- .../Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs | 2 +- .../Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs | 3 ++- osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs | 2 +- .../Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs | 2 +- osu.Game/Rulesets/Objects/Types/IHasRepeats.cs | 2 +- 13 files changed, 14 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 6d5a960f06..282afb6343 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -145,7 +145,7 @@ namespace osu.Game.Rulesets.Catch.Objects public double Distance => Path.Distance; - public List> NodeSamples { get; set; } = new List>(); + public IList> NodeSamples { get; set; } = new List>(); public double? LegacyLastTickOffset { get; set; } } diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapSampleConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapSampleConversionTest.cs index c8feb4ae24..9c690f360a 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapSampleConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapSampleConversionTest.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Tests private IList getSampleNames(IList hitSampleInfo) => hitSampleInfo.Select(sample => sample.LookupNames.First()).ToList(); - private IList> getNodeSampleNames(List> hitSampleInfo) + private IList> getNodeSampleNames(IList> hitSampleInfo) => hitSampleInfo?.Select(getSampleNames) .ToList(); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 1ed045f7e0..8f18521063 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -488,7 +488,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// Retrieves the list of node samples that occur at time greater than or equal to . /// /// The time to retrieve node samples at. - private List> nodeSamplesAt(int time) + private IList> nodeSamplesAt(int time) { if (!(HitObject is IHasPathWithRepeats curveData)) return null; diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index c1937af7e4..db0d3e2c5a 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Mania.Objects } } - public List> NodeSamples { get; set; } + public IList> NodeSamples { get; set; } /// /// The head note of the hold. diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 07d03ee1eb..a0c503a0b0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Objects /// internal float LazyTravelDistance; - public List> NodeSamples { get; set; } = new List>(); + public IList> NodeSamples { get; set; } = new List>(); [JsonIgnore] public IList TailSamples { get; private set; } diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 32aad6c36a..0c5719f29c 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps { if (shouldConvertSliderToHits(obj, beatmap, distanceData, out var taikoDuration, out var tickSpacing)) { - List> allSamples = obj is IHasPathWithRepeats curveData ? curveData.NodeSamples : new List>(new[] { samples }); + IList> allSamples = obj is IHasPathWithRepeats curveData ? curveData.NodeSamples : new List>(new[] { samples }); int i = 0; diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index c29179f749..2beb6bdbf2 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch } protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, PathControlPoint[] controlPoints, double? length, int repeatCount, - List> nodeSamples) + IList> nodeSamples) { newCombo |= forceNewCombo; comboOffset += extraComboOffset; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 0942a7264d..24022b8588 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -408,7 +408,7 @@ namespace osu.Game.Rulesets.Objects.Legacy /// The samples to be played when the slider nodes are hit. This includes the head and tail of the slider. /// The hit object. protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, PathControlPoint[] controlPoints, double? length, int repeatCount, - List> nodeSamples); + IList> nodeSamples); /// /// Creates a legacy Spinner-type hit object. diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index ad191f7ff5..9ff92fcc75 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Objects.Legacy public double Distance => Path.Distance; - public List> NodeSamples { get; set; } + public IList> NodeSamples { get; set; } public int RepeatCount { get; set; } [JsonIgnore] diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index bc64518f40..0eb6caf8ee 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs @@ -4,6 +4,7 @@ using osuTK; using osu.Game.Audio; using System.Collections.Generic; +using osu.Framework.Bindables; namespace osu.Game.Rulesets.Objects.Legacy.Mania { @@ -26,7 +27,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania } protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, PathControlPoint[] controlPoints, double? length, int repeatCount, - List> nodeSamples) + IList> nodeSamples) { return new ConvertSlider { diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index 75ecab0b8f..cb98721be5 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu } protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, PathControlPoint[] controlPoints, double? length, int repeatCount, - List> nodeSamples) + IList> nodeSamples) { newCombo |= forceNewCombo; comboOffset += extraComboOffset; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs index 13e3e84c6a..1eafc4e68b 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko } protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, PathControlPoint[] controlPoints, double? length, int repeatCount, - List> nodeSamples) + IList> nodeSamples) { return new ConvertSlider { diff --git a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs index 674e2aee88..2a4215b960 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Objects.Types /// n-1: The last repeat.
/// n: The last node. ///
- List> NodeSamples { get; } + IList> NodeSamples { get; } } public static class HasRepeatsExtensions From 0affe7b79d338e808f001476af5b2ae5cee89293 Mon Sep 17 00:00:00 2001 From: goodtrailer Date: Sat, 23 Oct 2021 02:25:20 -0700 Subject: [PATCH 022/129] Remove unnecessary using --- osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index 0eb6caf8ee..386eb8d3ee 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs @@ -4,7 +4,6 @@ using osuTK; using osu.Game.Audio; using System.Collections.Generic; -using osu.Framework.Bindables; namespace osu.Game.Rulesets.Objects.Legacy.Mania { From 051cc2cd92972c20027e4ef4dd4973f23cc7ac69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 24 Oct 2021 12:47:17 +0200 Subject: [PATCH 023/129] Update reference to configuration population process in comment --- osu.Game/Skinning/SkinManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 177dbaf28f..860d09e011 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -161,7 +161,7 @@ namespace osu.Game.Skinning // This function can be run on fresh import or save. The logic here ensures a skin.ini file is in a good state for both operations. - // LegacySkin will parse the skin.ini and populate `Skin.Configuration` during construction above. + // `Skin` will parse the skin.ini and populate `Skin.Configuration` during construction above. string skinIniSourcedName = instance.Configuration.SkinInfo.Name; string skinIniSourcedCreator = instance.Configuration.SkinInfo.Creator; string archiveName = item.Name.Replace(".osk", "", StringComparison.OrdinalIgnoreCase); From 51c5d0aec7e1fc33606f6b74c3d4c524f8d3fd33 Mon Sep 17 00:00:00 2001 From: Susko3 <16479013+Susko3@users.noreply.github.com> Date: Sun, 24 Oct 2021 12:59:19 +0200 Subject: [PATCH 024/129] Update to be in line with framework changes --- osu.Game/Database/ArchiveModelManager.cs | 2 +- osu.Game/Graphics/ScreenshotManager.cs | 2 +- osu.Game/IO/WrappedStorage.cs | 4 ++-- osu.Game/OsuGame.cs | 2 +- osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index cc25f84ecb..a0ca23eaec 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -467,7 +467,7 @@ namespace osu.Game.Database using (var outputStream = exportStorage.GetStream(filename, FileAccess.Write, FileMode.Create)) ExportModelTo(retrievedItem, outputStream); - exportStorage.ShowFileInNativeExplorer(filename); + exportStorage.PresentFileExternally(filename); } /// diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 27e6e2bb1c..c21986f6c4 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -135,7 +135,7 @@ namespace osu.Game.Graphics Text = $"{fileName} saved!", Activated = () => { - storage.ShowFileInNativeExplorer(fileName); + storage.PresentFileExternally(fileName); return true; } }); diff --git a/osu.Game/IO/WrappedStorage.cs b/osu.Game/IO/WrappedStorage.cs index 1e2d53d6fb..aadc4e760b 100644 --- a/osu.Game/IO/WrappedStorage.cs +++ b/osu.Game/IO/WrappedStorage.cs @@ -70,9 +70,9 @@ namespace osu.Game.IO public override Stream GetStream(string path, FileAccess access = FileAccess.Read, FileMode mode = FileMode.OpenOrCreate) => UnderlyingStorage.GetStream(MutatePath(path), access, mode); - public override void OpenPathInNativeExplorer(string path) => UnderlyingStorage.OpenPathInNativeExplorer(MutatePath(path)); + public override void OpenFileExternally(string filename) => UnderlyingStorage.OpenFileExternally(MutatePath(filename)); - public override void ShowFileInNativeExplorer(string filename) => UnderlyingStorage.ShowFileInNativeExplorer(MutatePath(filename)); + public override void PresentFileExternally(string filename) => UnderlyingStorage.PresentFileExternally(MutatePath(filename)); public override Storage GetStorageForDirectory(string path) { diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 4b001f03ad..985451fd6f 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -921,7 +921,7 @@ namespace osu.Game Text = "Subsequent messages have been logged. Click to view log files.", Activated = () => { - Storage.GetStorageForDirectory(@"logs").ShowFileInNativeExplorer(logFile); + Storage.GetStorageForDirectory(@"logs").PresentFileExternally(logFile); return true; } })); diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs index aa37748653..6bcb5ef715 100644 --- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs @@ -67,7 +67,7 @@ namespace osu.Game.Overlays.Settings.Sections.General Add(new SettingsButton { Text = GeneralSettingsStrings.OpenOsuFolder, - Action = storage.OpenInNativeExplorer, + Action = storage.PresentExternally, }); Add(new SettingsButton From 5303cae0444064e8696a8db979273ca6730155ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 Oct 2021 23:43:37 +0900 Subject: [PATCH 025/129] Add mention of stream close logic --- osu.Game/Skinning/Skin.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index d5f41f01a4..823a5d5133 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -47,6 +47,7 @@ namespace osu.Game.Skinning configurationStream ??= getConfigurationStream(); if (configurationStream != null) + // stream will be closed after use by LineBufferedReader. ParseConfigurationStream(configurationStream); else Configuration = new SkinConfiguration(); From 26cf5370c35bf977388eaf651503d783746bb34b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 Oct 2021 23:48:46 +0900 Subject: [PATCH 026/129] Remove unused `reader` parameter --- osu.Game/Database/ArchiveModelManager.cs | 4 ++-- osu.Game/Skinning/SkinManager.cs | 4 ++-- osu.Game/Tests/Visual/EditorTestScene.cs | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index ad5bc6d420..00e1f03b92 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -315,7 +315,7 @@ namespace osu.Game.Database /// /// In the case of no matching files, a hash will be generated from the passed archive's . /// - protected virtual string ComputeHash(TModel item, ArchiveReader reader = null) + protected virtual string ComputeHash(TModel item) { var hashableFiles = item.Files .Where(f => HashableFileTypes.Any(ext => f.Filename.EndsWith(ext, StringComparison.OrdinalIgnoreCase))) @@ -397,7 +397,7 @@ namespace osu.Game.Database LogForModel(item, @"Beginning import..."); item.Files = archive != null ? createFileInfos(archive, Files) : new List(); - item.Hash = ComputeHash(item, archive); + item.Hash = ComputeHash(item); await Populate(item, archive, cancellationToken).ConfigureAwait(false); diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 860d09e011..2187d2d875 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -155,7 +155,7 @@ namespace osu.Game.Skinning protected override bool HasCustomHashFunction => true; - protected override string ComputeHash(SkinInfo item, ArchiveReader reader = null) + protected override string ComputeHash(SkinInfo item) { var instance = GetSkin(item); @@ -186,7 +186,7 @@ namespace osu.Game.Skinning if (skinIniSourcedName != item.Name) updateSkinIniMetadata(item); - return base.ComputeHash(item, reader); + return base.ComputeHash(item); } private void updateSkinIniMetadata(SkinInfo item) diff --git a/osu.Game/Tests/Visual/EditorTestScene.cs b/osu.Game/Tests/Visual/EditorTestScene.cs index 798b0d01ee..4b02306d33 100644 --- a/osu.Game/Tests/Visual/EditorTestScene.cs +++ b/osu.Game/Tests/Visual/EditorTestScene.cs @@ -10,7 +10,6 @@ using osu.Framework.Platform; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Database; -using osu.Game.IO.Archives; using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Edit; @@ -154,7 +153,7 @@ namespace osu.Game.Tests.Visual { } - protected override string ComputeHash(BeatmapSetInfo item, ArchiveReader reader = null) + protected override string ComputeHash(BeatmapSetInfo item) => string.Empty; } From 207ccc4756474cea1a57b056f5404593433089d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 17 Oct 2021 14:15:36 +0200 Subject: [PATCH 027/129] Add test scene for beatmapset online status pill display --- .../TestSceneBeatmapSetOnlineStatusPill.cs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs new file mode 100644 index 0000000000..7bbf3c629b --- /dev/null +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs @@ -0,0 +1,32 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; +using osu.Game.Tests.Visual.UserInterface; +using osuTK; + +namespace osu.Game.Tests.Visual.Beatmaps +{ + public class TestSceneBeatmapSetOnlineStatusPill : ThemeComparisonTestScene + { + protected override Drawable CreateContent() => new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 10), + ChildrenEnumerable = Enum.GetValues(typeof(BeatmapSetOnlineStatus)).Cast().Select(status => new BeatmapSetOnlineStatusPill + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Status = status + }) + }; + } +} From 5ab3337a105a104074e1b019ea93bae329021402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 17 Oct 2021 14:42:04 +0200 Subject: [PATCH 028/129] Update beatmap set status pill appearance --- .../Drawables/BeatmapSetOnlineStatusPill.cs | 46 ++++++++++++++----- osu.Game/Graphics/OsuColour.cs | 36 +++++++++++++++ .../BeatmapSet/BeatmapSetHeaderContent.cs | 1 - 3 files changed, 71 insertions(+), 12 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs index ffc010b3a3..bc8af90069 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs @@ -1,6 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable enable + +using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; @@ -8,15 +11,13 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables { public class BeatmapSetOnlineStatusPill : CircularContainer { - private readonly OsuSpriteText statusText; - private readonly Box background; - private BeatmapSetOnlineStatus status; public BeatmapSetOnlineStatus Status @@ -29,8 +30,8 @@ namespace osu.Game.Beatmaps.Drawables status = value; - Alpha = value == BeatmapSetOnlineStatus.None ? 0 : 1; - statusText.Text = value.GetLocalisableDescription().ToUpper(); + if (IsLoaded) + updateState(); } } @@ -46,11 +47,14 @@ namespace osu.Game.Beatmaps.Drawables set => statusText.Padding = value; } - public Color4 BackgroundColour - { - get => background.Colour; - set => background.Colour = value; - } + private readonly OsuSpriteText statusText; + private readonly Box background; + + [Resolved] + private OsuColour colours { get; set; } = null!; + + [Resolved(CanBeNull = true)] + private OverlayColourProvider? colourProvider { get; set; } public BeatmapSetOnlineStatusPill() { @@ -63,7 +67,6 @@ namespace osu.Game.Beatmaps.Drawables { RelativeSizeAxes = Axes.Both, Colour = Color4.Black, - Alpha = 0.5f, }, statusText = new OsuSpriteText { @@ -74,6 +77,27 @@ namespace osu.Game.Beatmaps.Drawables }; Status = BeatmapSetOnlineStatus.None; + TextPadding = new MarginPadding { Horizontal = 5, Bottom = 1 }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateState(); + } + + private void updateState() + { + Alpha = Status == BeatmapSetOnlineStatus.None ? 0 : 1; + + statusText.Text = Status.GetLocalisableDescription().ToUpper(); + + if (colourProvider != null) + statusText.Colour = status == BeatmapSetOnlineStatus.Graveyard ? colourProvider.Background1 : colourProvider.Background3; + else + statusText.Colour = status == BeatmapSetOnlineStatus.Graveyard ? colours.GreySeafoamLight : Color4.Black; + + background.Colour = OsuColour.ForBeatmapSetOnlineStatus(Status) ?? colourProvider?.Light1 ?? colours.GreySeafoamLighter; } } } diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 40d163635a..3aa4dbf1d8 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -118,6 +118,42 @@ namespace osu.Game.Graphics } } + /// + /// Retrieves a colour for the given . + /// A value indicates that a "background" shade from the local + /// (or another fallback colour) should be used. + /// + /// + /// Sourced from web: https://github.com/ppy/osu-web/blob/007eebb1916ed5cb6a7866d82d8011b1060a945e/resources/assets/less/layout.less#L36-L50 + /// + public static Color4? ForBeatmapSetOnlineStatus(BeatmapSetOnlineStatus status) + { + switch (status) + { + case BeatmapSetOnlineStatus.Ranked: + case BeatmapSetOnlineStatus.Approved: + return Color4Extensions.FromHex(@"b3ff66"); + + case BeatmapSetOnlineStatus.Loved: + return Color4Extensions.FromHex(@"ff66ab"); + + case BeatmapSetOnlineStatus.Qualified: + return Color4Extensions.FromHex(@"66ccff"); + + case BeatmapSetOnlineStatus.Pending: + return Color4Extensions.FromHex(@"ffd966"); + + case BeatmapSetOnlineStatus.WIP: + return Color4Extensions.FromHex(@"ff9966"); + + case BeatmapSetOnlineStatus.Graveyard: + return Color4.Black; + + default: + return null; + } + } + /// /// Returns a foreground text colour that is supposed to contrast well with /// the supplied . diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs index c1029923f7..df88b06879 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs @@ -220,7 +220,6 @@ namespace osu.Game.Overlays.BeatmapSet private void load(OverlayColourProvider colourProvider) { coverGradient.Colour = ColourInfo.GradientVertical(colourProvider.Background6.Opacity(0.3f), colourProvider.Background6.Opacity(0.8f)); - onlineStatusPill.BackgroundColour = colourProvider.Background6; State.BindValueChanged(_ => updateDownloadButtons()); From feedd53a53d86945fe0460b73abd135f16474e5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 17 Oct 2021 14:55:52 +0200 Subject: [PATCH 029/129] Add support for setting fixed size of status pill --- .../TestSceneBeatmapSetOnlineStatusPill.cs | 16 ++++++++++++ .../Drawables/BeatmapSetOnlineStatusPill.cs | 25 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs index 7bbf3c629b..2d61385269 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs @@ -2,11 +2,16 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Linq; +using NUnit.Framework; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; +using osu.Game.Overlays; using osu.Game.Tests.Visual.UserInterface; using osuTK; @@ -28,5 +33,16 @@ namespace osu.Game.Tests.Visual.Beatmaps Status = status }) }; + + private IEnumerable statusPills => this.ChildrenOfType(); + + [Test] + public void TestFixedWidth() + { + AddStep("create themed content", () => CreateThemedContent(OverlayColourScheme.Red)); + + AddStep("set fixed width", () => statusPills.ForEach(pill => pill.FixedWidth = 90)); + AddStep("unset fixed width", () => statusPills.ForEach(pill => pill.FixedWidth = null)); + } } } diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs index bc8af90069..848bab6394 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs @@ -47,6 +47,31 @@ namespace osu.Game.Beatmaps.Drawables set => statusText.Padding = value; } + private float? fixedWidth; + + /// + /// When set to a non- value, the pill will be forcibly sized to the given width. + /// When set to a value, the pill will autosize to its contents. + /// + public float? FixedWidth + { + get => fixedWidth; + set + { + fixedWidth = value; + + if (fixedWidth == null) + { + AutoSizeAxes = Axes.Both; + } + else + { + AutoSizeAxes = Axes.Y; + Width = fixedWidth.Value; + } + } + } + private readonly OsuSpriteText statusText; private readonly Box background; From 9f62d1d98c71d763d68ef3837c5e0052a4a68a41 Mon Sep 17 00:00:00 2001 From: Jason Won Date: Sun, 24 Oct 2021 11:41:35 -0400 Subject: [PATCH 030/129] add tests for NoScope --- .../Mods/TestSceneOsuModNoScope.cs | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModNoScope.cs diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModNoScope.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModNoScope.cs new file mode 100644 index 0000000000..0d0fefe0ff --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModNoScope.cs @@ -0,0 +1,150 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Utils; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Timing; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Tests.Mods +{ + public class TestSceneOsuModNoScope : OsuModTestScene + { + [Test] + public void TestVisibleDuringBreak() + { + CreateModTest(new ModTestData + { + Mod = new OsuModNoScope + { + HiddenComboCount = { Value = 0 }, + }, + Autoplay = true, + PassCondition = () => true, + Beatmap = new Beatmap + { + HitObjects = new List + { + new HitCircle + { + Position = new Vector2(300, 192), + StartTime = 1000, + }, + new HitCircle + { + Position = new Vector2(300, 192), + StartTime = 5000, + } + }, + Breaks = new List + { + new BreakPeriod(2000, 4000), + } + } + }); + + AddUntilStep("wait for cursor to hide", () => cursorAlphaAlmostEquals(0)); + AddUntilStep("wait for start of break", isBreak); + AddUntilStep("wait for cursor to show", () => cursorAlphaAlmostEquals(1)); + AddUntilStep("wait for end of break", () => !isBreak()); + AddUntilStep("wait for cursor to hide", () => cursorAlphaAlmostEquals(0)); + } + + [Test] + public void TestVisibleDuringSpinner() + { + CreateModTest(new ModTestData + { + Mod = new OsuModNoScope + { + HiddenComboCount = { Value = 0 }, + }, + Autoplay = true, + PassCondition = () => true, + Beatmap = new Beatmap + { + HitObjects = new List + { + new HitCircle + { + Position = new Vector2(300, 192), + StartTime = 1000, + }, + new Spinner + { + Position = new Vector2(256, 192), + StartTime = 2000, + Duration = 2000, + }, + new HitCircle + { + Position = new Vector2(300, 192), + StartTime = 5000, + } + } + } + }); + + AddUntilStep("wait for cursor to hide", () => cursorAlphaAlmostEquals(0)); + AddUntilStep("wait for start of spinner", isSpinning); + AddUntilStep("wait for cursor to show", () => cursorAlphaAlmostEquals(1)); + AddUntilStep("wait for end of spinner", () => !isSpinning()); + AddUntilStep("wait for cursor to hide", () => cursorAlphaAlmostEquals(0)); + } + + [Test] + public void TestVisibleAfterComboBreak() + { + CreateModTest(new ModTestData + { + Mod = new OsuModNoScope + { + HiddenComboCount = { Value = 2 }, + }, + Autoplay = true, + PassCondition = () => true, + Beatmap = new Beatmap + { + HitObjects = new List + { + new HitCircle + { + Position = new Vector2(100, 192), + StartTime = 1000, + }, + new HitCircle + { + Position = new Vector2(150, 192), + StartTime = 3000, + }, + new HitCircle + { + Position = new Vector2(200, 192), + StartTime = 5000, + }, + } + } + }); + + AddAssert("cursor must start visible", () => cursorAlphaAlmostEquals(1)); + AddUntilStep("wait for combo", () => Player.ScoreProcessor.Combo.Value >= 2); + AddAssert("cursor must dim after combo", () => !cursorAlphaAlmostEquals(1)); + AddStep("break combo", () => Player.ScoreProcessor.Combo.Set(0)); + AddUntilStep("wait for cursor to show", () => cursorAlphaAlmostEquals(1)); + } + + private bool isSpinning() => Player.ChildrenOfType().SingleOrDefault()?.Progress > 0; + + private bool isBreak() => Player.IsBreakTime.Value; + + private bool cursorAlphaAlmostEquals(float alpha) => Precision.AlmostEquals(Player.DrawableRuleset.Cursor.Alpha, alpha); + } +} From 6b9e8dbd2e4ab90c57c1bb16bd20d22d6c56e81a Mon Sep 17 00:00:00 2001 From: Roxie Wattz Date: Sun, 24 Oct 2021 21:34:40 -0700 Subject: [PATCH 031/129] Added the ouendan 2 style hidden Added as an option for nostalgia nerds like me --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 24 ++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 9c7784a00a..59d6769e2c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -5,6 +5,8 @@ using System; using System.Diagnostics; using System.Linq; using osu.Framework.Graphics; +using osu.Framework.Bindables; +using osu.Game.Configuration; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; @@ -13,10 +15,14 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Skinning; + namespace osu.Game.Rulesets.Osu.Mods { public class OsuModHidden : ModHidden, IHidesApproachCircles { + [SettingSource("Don't fade out hit circles", "This makes the hidden mod only remove approach circles.")] + public Bindable NoHitCircles { get; } = new BindableBool(false); + public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; @@ -65,14 +71,16 @@ namespace osu.Game.Rulesets.Osu.Mods { case DrawableSliderTail _: using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) - drawableObject.FadeOut(fadeDuration); + if (!NoHitCircles.Value) + drawableObject.FadeOut(fadeDuration); break; case DrawableSliderRepeat sliderRepeat: using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) // only apply to circle piece – reverse arrow is not affected by hidden. - sliderRepeat.CirclePiece.FadeOut(fadeDuration); + if (!NoHitCircles.Value) + sliderRepeat.CirclePiece.FadeOut(fadeDuration); break; @@ -82,7 +90,8 @@ namespace osu.Game.Rulesets.Osu.Mods if (increaseVisibility) { // only fade the circle piece (not the approach circle) for the increased visibility object. - fadeTarget = circle.CirclePiece; + if (!NoHitCircles.Value) + fadeTarget = circle.CirclePiece; } else { @@ -92,18 +101,21 @@ namespace osu.Game.Rulesets.Osu.Mods } using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) - fadeTarget.FadeOut(fadeDuration); + if (!NoHitCircles.Value) + fadeTarget.FadeOut(fadeDuration); break; case DrawableSlider slider: using (slider.BeginAbsoluteSequence(fadeStartTime)) - slider.Body.FadeOut(fadeDuration, Easing.Out); + if (!NoHitCircles.Value) + slider.Body.FadeOut(fadeDuration, Easing.Out); break; case DrawableSliderTick sliderTick: using (sliderTick.BeginAbsoluteSequence(fadeStartTime)) - sliderTick.FadeOut(fadeDuration); + if (!NoHitCircles.Value) + sliderTick.FadeOut(fadeDuration); break; From d1b720af167141c44566ceb1ce24b5eed04677fb Mon Sep 17 00:00:00 2001 From: Roxie Wattz Date: Sun, 24 Oct 2021 21:51:12 -0700 Subject: [PATCH 032/129] Add Ouendan 2 reference --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 59d6769e2c..a57b22451d 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Mods { public class OsuModHidden : ModHidden, IHidesApproachCircles { - [SettingSource("Don't fade out hit circles", "This makes the hidden mod only remove approach circles.")] + [SettingSource("Don't fade out hit circles", "This makes the hidden mod only remove approach circles, similar to Ouendan 2's Easy difficulties.")] public Bindable NoHitCircles { get; } = new BindableBool(false); public override string Description => @"Play with no approach circles and fading circles/sliders."; From 03896fd2ebf219489deb289942c6f0c99e568304 Mon Sep 17 00:00:00 2001 From: Roxie Wattz Date: Sun, 24 Oct 2021 22:17:55 -0700 Subject: [PATCH 033/129] Added test for Ouendan 2 style Hidden mod --- .../Mods/TestSceneOsuModHidden.cs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs index ed9da36b05..f25df90737 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs @@ -117,6 +117,42 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods PassCondition = checkSomeHit }); + [Test] + public void OuendanTwoHidden() => CreateModTest(new ModTestData + { + Mod = new OsuModHidden { NoHitCircles = { Value = true } }, + Autoplay = true, + Beatmap = new Beatmap + { + HitObjects = new List + { + new HitCircle + { + StartTime = 1000, + Position = new Vector2(206,142) + }, + new HitCircle + { + StartTime = 2000, + Position = new Vector2(306,142) + }, + new Slider + { + StartTime = 3000, + Position = new Vector2(156,242), + Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, new Vector2(200,0), }) + }, + new Spinner + { + Position = new Vector2(256,192), + StartTime = 7000, + EndTime = 9000 + } + } + }, + PassCondition = checkSomeHit + }); + private bool checkSomeHit() => Player.ScoreProcessor.JudgedHits >= 4; private bool objectWithIncreasedVisibilityHasIndex(int index) From 19312435d0b53de9e2619aedc75beef9005b5b8e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Oct 2021 13:47:12 +0900 Subject: [PATCH 034/129] Add ability to make test `APIBeatmaps` from test scenes Allow tests to create a sample `APIBeatmapSet` One step towards removing calls to `ToBeatmap` / `ToBeatmapSet`. --- .../Online/TestSceneBeatmapListingOverlay.cs | 26 +++------- .../API/Requests/Responses/APIBeatmapSet.cs | 6 +-- osu.Game/Tests/Visual/OsuTestScene.cs | 51 +++++++++++++++++++ 3 files changed, 60 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs index 963809ebe1..7042f1e4fe 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs @@ -7,14 +7,12 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; -using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Overlays.BeatmapListing; -using osu.Game.Rulesets; using osu.Game.Scoring; using osu.Game.Users; using osuTK.Input; @@ -92,7 +90,7 @@ namespace osu.Game.Tests.Visual.Online { AddAssert("is visible", () => overlay.State.Value == Visibility.Visible); - AddStep("show many results", () => fetchFor(Enumerable.Repeat(CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet, 100).ToArray())); + AddStep("show many results", () => fetchFor(Enumerable.Repeat(CreateAPIBeatmapSet(Ruleset.Value), 10).ToArray())); AddUntilStep("placeholder hidden", () => !overlay.ChildrenOfType().Any(d => d.IsPresent)); @@ -114,7 +112,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("fetch for 0 beatmaps", () => fetchFor()); AddUntilStep("placeholder shown", () => overlay.ChildrenOfType().SingleOrDefault()?.IsPresent == true); - AddStep("fetch for 1 beatmap", () => fetchFor(CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet)); + AddStep("fetch for 1 beatmap", () => fetchFor(CreateAPIBeatmapSet(Ruleset.Value))); AddUntilStep("placeholder hidden", () => !overlay.ChildrenOfType().Any(d => d.IsPresent)); AddStep("fetch for 0 beatmaps", () => fetchFor()); @@ -188,7 +186,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestUserWithoutSupporterUsesSupporterOnlyFiltersWithResults() { - AddStep("fetch for 1 beatmap", () => fetchFor(CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet)); + AddStep("fetch for 1 beatmap", () => fetchFor(CreateAPIBeatmapSet(Ruleset.Value))); AddStep("set dummy as non-supporter", () => ((DummyAPIAccess)API).LocalUser.Value.IsSupporter = false); // only Rank Achieved filter @@ -218,7 +216,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestUserWithSupporterUsesSupporterOnlyFiltersWithResults() { - AddStep("fetch for 1 beatmap", () => fetchFor(CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet)); + AddStep("fetch for 1 beatmap", () => fetchFor(CreateAPIBeatmapSet(Ruleset.Value))); AddStep("set dummy as supporter", () => ((DummyAPIAccess)API).LocalUser.Value.IsSupporter = true); // only Rank Achieved filter @@ -247,10 +245,10 @@ namespace osu.Game.Tests.Visual.Online private static int searchCount; - private void fetchFor(params BeatmapSetInfo[] beatmaps) + private void fetchFor(params APIBeatmapSet[] beatmaps) { setsForResponse.Clear(); - setsForResponse.AddRange(beatmaps.Select(b => new TestAPIBeatmapSet(b))); + setsForResponse.AddRange(beatmaps); // trigger arbitrary change for fetching. searchControl.Query.Value = $"search {searchCount++}"; @@ -286,17 +284,5 @@ namespace osu.Game.Tests.Visual.Online !overlay.ChildrenOfType().Any(d => d.IsPresent) && !overlay.ChildrenOfType().Any(d => d.IsPresent)); } - - private class TestAPIBeatmapSet : APIBeatmapSet - { - private readonly BeatmapSetInfo beatmapSet; - - public TestAPIBeatmapSet(BeatmapSetInfo beatmapSet) - { - this.beatmapSet = beatmapSet; - } - - public override BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets) => beatmapSet; - } } } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 24d0e09649..7fbdd47394 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -119,7 +119,7 @@ namespace osu.Game.Online.API.Requests.Responses public string Tags { get; set; } = string.Empty; [JsonProperty(@"beatmaps")] - private IEnumerable beatmaps { get; set; } = Array.Empty(); + public IEnumerable Beatmaps { get; set; } = Array.Empty(); public virtual BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets) { @@ -132,7 +132,7 @@ namespace osu.Game.Online.API.Requests.Responses OnlineInfo = this }; - beatmapSet.Beatmaps = beatmaps.Select(b => + beatmapSet.Beatmaps = Beatmaps.Select(b => { var beatmap = b.ToBeatmapInfo(rulesets); beatmap.BeatmapSet = beatmapSet; @@ -157,7 +157,7 @@ namespace osu.Game.Online.API.Requests.Responses #region Implementation of IBeatmapSetInfo - IEnumerable IBeatmapSetInfo.Beatmaps => beatmaps; + IEnumerable IBeatmapSetInfo.Beatmaps => Beatmaps; IBeatmapMetadataInfo IBeatmapSetInfo.Metadata => metadata; diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 03434961ea..90e85f7716 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -20,6 +20,7 @@ using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Online.API; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -174,6 +175,56 @@ namespace osu.Game.Tests.Visual protected virtual IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset); + protected APIBeatmapSet CreateAPIBeatmapSet(RulesetInfo ruleset) + { + var beatmap = CreateBeatmap(ruleset).BeatmapInfo; + + return new APIBeatmapSet + { + Covers = beatmap.BeatmapSet.Covers, + OnlineID = beatmap.BeatmapSet.OnlineID, + Status = beatmap.BeatmapSet.Status, + Preview = beatmap.BeatmapSet.Preview, + HasFavourited = beatmap.BeatmapSet.HasFavourited, + PlayCount = beatmap.BeatmapSet.PlayCount, + FavouriteCount = beatmap.BeatmapSet.FavouriteCount, + BPM = beatmap.BeatmapSet.BPM, + HasExplicitContent = beatmap.BeatmapSet.HasExplicitContent, + HasVideo = beatmap.BeatmapSet.HasVideo, + HasStoryboard = beatmap.BeatmapSet.HasStoryboard, + Submitted = beatmap.BeatmapSet.Submitted, + Ranked = beatmap.BeatmapSet.Ranked, + LastUpdated = beatmap.BeatmapSet.LastUpdated, + TrackId = beatmap.BeatmapSet.TrackId, + Title = beatmap.BeatmapSet.Metadata.Title, + TitleUnicode = beatmap.BeatmapSet.Metadata.TitleUnicode, + Artist = beatmap.BeatmapSet.Metadata.Artist, + ArtistUnicode = beatmap.BeatmapSet.Metadata.ArtistUnicode, + Author = beatmap.BeatmapSet.Metadata.Author, + AuthorID = beatmap.BeatmapSet.Metadata.AuthorID, + AuthorString = beatmap.BeatmapSet.Metadata.AuthorString, + Availability = beatmap.BeatmapSet.Availability, + Genre = beatmap.BeatmapSet.Genre, + Language = beatmap.BeatmapSet.Language, + Source = beatmap.BeatmapSet.Metadata.Source, + Tags = beatmap.BeatmapSet.Metadata.Tags, + Beatmaps = new[] + { + new APIBeatmap + { + OnlineID = beatmap.OnlineID, + OnlineBeatmapSetID = beatmap.BeatmapSet.OnlineID, + Status = beatmap.Status, + Checksum = beatmap.MD5Hash, + AuthorID = beatmap.Metadata.AuthorID, + RulesetID = beatmap.RulesetID, + StarRating = beatmap.StarDifficulty, + DifficultyName = beatmap.Version, + } + } + }; + } + protected WorkingBeatmap CreateWorkingBeatmap(RulesetInfo ruleset) => CreateWorkingBeatmap(CreateBeatmap(ruleset)); From 94175bfb4a5b675b840ccce8fa1fcf3928e0baf9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Oct 2021 14:25:01 +0900 Subject: [PATCH 035/129] Update `PreviewTrackManager` to use `IBeatmapSetInfo` --- .../Components/TestScenePreviewTrackManager.cs | 4 ++-- osu.Game/Audio/PreviewTrackManager.cs | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index 9a999a4931..89e20043fb 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -224,7 +224,7 @@ namespace osu.Game.Tests.Visual.Components public new PreviewTrack CurrentTrack => base.CurrentTrack; - protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore); + protected override TrackManagerPreviewTrack CreatePreviewTrack(IBeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore); public override bool UpdateSubTree() { @@ -240,7 +240,7 @@ namespace osu.Game.Tests.Visual.Components public new Track Track => base.Track; - public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackManager) + public TestPreviewTrack(IBeatmapSetInfo beatmapSetInfo, ITrackStore trackManager) : base(beatmapSetInfo, trackManager) { this.trackManager = trackManager; diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 1de9e1561f..26787c362b 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -43,11 +43,11 @@ namespace osu.Game.Audio } /// - /// Retrieves a for a . + /// Retrieves a for a . /// - /// The to retrieve the preview track for. + /// The to retrieve the preview track for. /// The playable . - public PreviewTrack Get(BeatmapSetInfo beatmapSetInfo) + public PreviewTrack Get(IBeatmapSetInfo beatmapSetInfo) { var track = CreatePreviewTrack(beatmapSetInfo, trackStore); @@ -91,7 +91,7 @@ namespace osu.Game.Audio /// /// Creates the . /// - protected virtual TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => + protected virtual TrackManagerPreviewTrack CreatePreviewTrack(IBeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TrackManagerPreviewTrack(beatmapSetInfo, trackStore); public class TrackManagerPreviewTrack : PreviewTrack @@ -99,10 +99,10 @@ namespace osu.Game.Audio [Resolved(canBeNull: true)] public IPreviewTrackOwner Owner { get; private set; } - private readonly BeatmapSetInfo beatmapSetInfo; + private readonly IBeatmapSetInfo beatmapSetInfo; private readonly ITrackStore trackManager; - public TrackManagerPreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackManager) + public TrackManagerPreviewTrack(IBeatmapSetInfo beatmapSetInfo, ITrackStore trackManager) { this.beatmapSetInfo = beatmapSetInfo; this.trackManager = trackManager; @@ -114,7 +114,7 @@ namespace osu.Game.Audio Logger.Log($"A {nameof(PreviewTrack)} was created without a containing {nameof(IPreviewTrackOwner)}. An owner should be added for correct behaviour."); } - protected override Track GetTrack() => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineBeatmapSetID}.mp3"); + protected override Track GetTrack() => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineID}.mp3"); } private class PreviewTrackStore : AudioCollectionManager, ITrackStore From cb36a23cdc639f57568cc2fca8dcaad47efa8b20 Mon Sep 17 00:00:00 2001 From: Roxie Wattz Date: Sun, 24 Oct 2021 22:52:10 -0700 Subject: [PATCH 036/129] Update osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs Suggested by peppy. Changes name and description of setting Co-authored-by: Dean Herbert --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index a57b22451d..59ac6746a0 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Mods { public class OsuModHidden : ModHidden, IHidesApproachCircles { - [SettingSource("Don't fade out hit circles", "This makes the hidden mod only remove approach circles, similar to Ouendan 2's Easy difficulties.")] + [SettingSource("Only fade approach circles", "The main object body will not fade when enabled.")] public Bindable NoHitCircles { get; } = new BindableBool(false); public override string Description => @"Play with no approach circles and fading circles/sliders."; From 045dd94a6effae7aa1e0c13aaf30b42333d7d62b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Oct 2021 14:44:49 +0900 Subject: [PATCH 037/129] Move online metrics out of `BeatmapSetInfo` model --- .../Online/TestSceneBeatmapSetOverlay.cs | 8 ++-- .../TestSceneBeatmapSetOverlayDetails.cs | 6 +-- .../SongSelect/TestSceneBeatmapDetails.cs | 16 ++++++-- osu.Game/Beatmaps/BeatmapInfo.cs | 2 +- osu.Game/Beatmaps/BeatmapSetInfo.cs | 7 ++-- osu.Game/Beatmaps/BeatmapSetMetrics.cs | 17 -------- osu.Game/Beatmaps/IBeatmapOnlineInfo.cs | 17 ++++++++ osu.Game/Beatmaps/IBeatmapSetOnlineInfo.cs | 5 +++ .../API/Requests/Responses/APIBeatmap.cs | 10 ++--- .../API/Requests/Responses/APIBeatmapSet.cs | 5 +-- osu.Game/Overlays/BeatmapSet/Details.cs | 2 +- osu.Game/Screens/Select/BeatmapDetails.cs | 39 +++++++++---------- .../Screens/Select/Details/UserRatings.cs | 25 ++++++------ 13 files changed, 86 insertions(+), 73 deletions(-) delete mode 100644 osu.Game/Beatmaps/BeatmapSetMetrics.cs create mode 100644 osu.Game/Beatmaps/IBeatmapOnlineInfo.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index ef89a86e79..da033e324c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -73,10 +73,10 @@ namespace osu.Game.Tests.Visual.Online Ranked = DateTime.Now, BPM = 111, HasVideo = true, + Ratings = Enumerable.Range(0, 11).ToArray(), HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), }, - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = new List { new BeatmapInfo @@ -153,8 +153,8 @@ namespace osu.Game.Tests.Visual.Online Covers = new BeatmapSetOnlineCovers(), Language = new BeatmapSetOnlineLanguage { Id = 3, Name = "English" }, Genre = new BeatmapSetOnlineGenre { Id = 4, Name = "Rock" }, + Ratings = Enumerable.Range(0, 11).ToArray(), }, - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = new List { new BeatmapInfo @@ -228,8 +228,8 @@ namespace osu.Game.Tests.Visual.Online OnlineInfo = new APIBeatmapSet { Covers = new BeatmapSetOnlineCovers(), + Ratings = Enumerable.Range(0, 11).ToArray(), }, - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = beatmaps }); }); @@ -316,8 +316,8 @@ namespace osu.Game.Tests.Visual.Online HasVideo = true, HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), + Ratings = Enumerable.Range(0, 11).ToArray(), }, - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = beatmaps, }; } diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs index c15c9f44e4..f16d5aaa23 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs @@ -39,14 +39,13 @@ namespace osu.Game.Tests.Visual.Online var secondSet = createSet(); AddStep("set first set", () => details.BeatmapSet = firstSet); - AddAssert("ratings set", () => details.Ratings.Metrics == firstSet.Metrics); + AddAssert("ratings set", () => details.Ratings.Ratings == firstSet.Ratings); AddStep("set second set", () => details.BeatmapSet = secondSet); - AddAssert("ratings set", () => details.Ratings.Metrics == secondSet.Metrics); + AddAssert("ratings set", () => details.Ratings.Ratings == secondSet.Ratings); static BeatmapSetInfo createSet() => new BeatmapSetInfo { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).Select(_ => RNG.Next(10)).ToArray() }, Beatmaps = new List { new BeatmapInfo @@ -60,6 +59,7 @@ namespace osu.Game.Tests.Visual.Online }, OnlineInfo = new APIBeatmapSet { + Ratings = Enumerable.Range(0, 11).Select(_ => RNG.Next(10)).ToArray(), Status = BeatmapSetOnlineStatus.Ranked } }; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index d5b4fb9a80..6b508878bf 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.API; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Screens.Select; namespace osu.Game.Tests.Visual.SongSelect @@ -34,7 +35,10 @@ namespace osu.Game.Tests.Visual.SongSelect { BeatmapSet = new BeatmapSetInfo { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + OnlineInfo = new APIBeatmapSet + { + Ratings = Enumerable.Range(0, 11).ToArray(), + } }, Version = "All Metrics", Metadata = new BeatmapMetadata @@ -65,7 +69,10 @@ namespace osu.Game.Tests.Visual.SongSelect { BeatmapSet = new BeatmapSetInfo { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + OnlineInfo = new APIBeatmapSet + { + Ratings = Enumerable.Range(0, 11).ToArray(), + } }, Version = "All Metrics", Metadata = new BeatmapMetadata @@ -95,7 +102,10 @@ namespace osu.Game.Tests.Visual.SongSelect { BeatmapSet = new BeatmapSetInfo { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + OnlineInfo = new APIBeatmapSet + { + Ratings = Enumerable.Range(0, 11).ToArray(), + } }, Version = "Only Ratings", Metadata = new BeatmapMetadata diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 3bcc00f5de..6da50657a6 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -16,7 +16,7 @@ namespace osu.Game.Beatmaps { [ExcludeFromDynamicCompile] [Serializable] - public class BeatmapInfo : IEquatable, IHasPrimaryKey, IBeatmapInfo + public class BeatmapInfo : IEquatable, IHasPrimaryKey, IBeatmapInfo, IBeatmapOnlineInfo { public int ID { get; set; } diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 0c032e1482..ae32ad000e 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -38,9 +38,6 @@ namespace osu.Game.Beatmaps [NotMapped] public APIBeatmapSet OnlineInfo { get; set; } - [NotMapped] - public BeatmapSetMetrics Metrics { get; set; } - /// /// The maximum star difficulty of all beatmaps in this set. /// @@ -172,6 +169,10 @@ namespace osu.Game.Beatmaps [JsonIgnore] public int? TrackId => OnlineInfo?.TrackId; + [NotMapped] + [JsonIgnore] + public int[] Ratings => OnlineInfo?.Ratings; + #endregion } } diff --git a/osu.Game/Beatmaps/BeatmapSetMetrics.cs b/osu.Game/Beatmaps/BeatmapSetMetrics.cs deleted file mode 100644 index 51c5de19a6..0000000000 --- a/osu.Game/Beatmaps/BeatmapSetMetrics.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using Newtonsoft.Json; - -namespace osu.Game.Beatmaps -{ - public class BeatmapSetMetrics - { - /// - /// Total vote counts of user ratings on a scale of 0..10 where 0 is unused (probably will be fixed at API?). - /// - [JsonProperty("ratings")] - public int[] Ratings { get; set; } = Array.Empty(); - } -} diff --git a/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs b/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs new file mode 100644 index 0000000000..4898e45c56 --- /dev/null +++ b/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable enable + +namespace osu.Game.Beatmaps +{ + /// + /// Beatmap info retrieved for previewing locally. + /// + public interface IBeatmapOnlineInfo + { + int? MaxCombo { get; } + + BeatmapMetrics? Metrics { get; } + } +} diff --git a/osu.Game/Beatmaps/IBeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/IBeatmapSetOnlineInfo.cs index 1d2bb46bde..6def6ec21d 100644 --- a/osu.Game/Beatmaps/IBeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapSetOnlineInfo.cs @@ -97,5 +97,10 @@ namespace osu.Game.Beatmaps /// Non-null only if the track is linked to a featured artist track entry. /// int? TrackId { get; } + + /// + /// Total vote counts of user ratings on a scale of 0..10 where 0 is unused (probably will be fixed at API?). + /// + int[]? Ratings { get; } } } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index 6e43ac5504..6a05811bba 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets; namespace osu.Game.Online.API.Requests.Responses { - public class APIBeatmap : IBeatmapInfo + public class APIBeatmap : IBeatmapInfo, IBeatmapOnlineInfo { [JsonProperty(@"id")] public int OnlineID { get; set; } @@ -69,10 +69,10 @@ namespace osu.Game.Online.API.Requests.Responses public string DifficultyName { get; set; } = string.Empty; [JsonProperty(@"failtimes")] - private BeatmapMetrics? metrics { get; set; } + public BeatmapMetrics? Metrics { get; set; } [JsonProperty(@"max_combo")] - private int? maxCombo { get; set; } + public int? MaxCombo { get; set; } public virtual BeatmapInfo ToBeatmapInfo(RulesetStore rulesets) { @@ -90,8 +90,8 @@ namespace osu.Game.Online.API.Requests.Responses Status = Status, MD5Hash = Checksum, BeatmapSet = set, - Metrics = metrics, - MaxCombo = maxCombo, + Metrics = Metrics, + MaxCombo = MaxCombo, BaseDifficulty = new BeatmapDifficulty { DrainRate = drainRate, diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 24d0e09649..17b1e9d3fe 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -58,8 +58,8 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"last_updated")] public DateTimeOffset? LastUpdated { get; set; } - [JsonProperty(@"ratings")] - private int[] ratings { get; set; } = Array.Empty(); + [JsonProperty("ratings")] + public int[] Ratings { get; set; } = Array.Empty(); [JsonProperty(@"track_id")] public int? TrackId { get; set; } @@ -128,7 +128,6 @@ namespace osu.Game.Online.API.Requests.Responses OnlineBeatmapSetID = OnlineID, Metadata = metadata, Status = Status, - Metrics = new BeatmapSetMetrics { Ratings = ratings }, OnlineInfo = this }; diff --git a/osu.Game/Overlays/BeatmapSet/Details.cs b/osu.Game/Overlays/BeatmapSet/Details.cs index 92361ae4f8..d6720e5f35 100644 --- a/osu.Game/Overlays/BeatmapSet/Details.cs +++ b/osu.Game/Overlays/BeatmapSet/Details.cs @@ -52,7 +52,7 @@ namespace osu.Game.Overlays.BeatmapSet private void updateDisplay() { - Ratings.Metrics = BeatmapSet?.Metrics; + Ratings.Ratings = BeatmapSet?.Ratings; ratingBox.Alpha = BeatmapSet?.OnlineInfo?.Status > 0 ? 1 : 0; } diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 6ace92370c..8dbe438ab5 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Select private const float transition_duration = 250; private readonly AdvancedStats advanced; - private readonly UserRatings ratings; + private readonly UserRatings ratingsDisplay; private readonly MetadataSection description, source, tags; private readonly Container failRetryContainer; private readonly FailRetryGraph failRetryGraph; @@ -43,6 +43,9 @@ namespace osu.Game.Screens.Select private BeatmapInfo beatmapInfo; + private BeatmapMetrics metrics; + private int[] ratings; + public BeatmapInfo BeatmapInfo { get => beatmapInfo; @@ -52,6 +55,9 @@ namespace osu.Game.Screens.Select beatmapInfo = value; + metrics = beatmapInfo?.Metrics; + ratings = beatmapInfo?.BeatmapSet.Ratings; + Scheduler.AddOnce(updateStatistics); } } @@ -110,7 +116,7 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.X, Height = 134, Padding = new MarginPadding { Horizontal = spacing, Top = spacing }, - Child = ratings = new UserRatings + Child = ratingsDisplay = new UserRatings { RelativeSizeAxes = Axes.Both, }, @@ -176,7 +182,7 @@ namespace osu.Game.Screens.Select tags.Text = BeatmapInfo?.Metadata?.Tags; // metrics may have been previously fetched - if (BeatmapInfo?.BeatmapSet?.Metrics != null && BeatmapInfo?.Metrics != null) + if (ratings != null && metrics != null) { updateMetrics(); return; @@ -201,14 +207,8 @@ namespace osu.Game.Screens.Select // the beatmap has been changed since we started the lookup. return; - var b = res.ToBeatmapInfo(rulesets); - - if (requestedBeatmap.BeatmapSet == null) - requestedBeatmap.BeatmapSet = b.BeatmapSet; - else - requestedBeatmap.BeatmapSet.Metrics = b.BeatmapSet.Metrics; - - requestedBeatmap.Metrics = b.Metrics; + ratings = res.BeatmapSet?.Ratings; + metrics = res.Metrics; updateMetrics(); }); @@ -232,24 +232,23 @@ namespace osu.Game.Screens.Select private void updateMetrics() { - var hasRatings = beatmapInfo?.BeatmapSet?.Metrics?.Ratings?.Any() ?? false; - var hasRetriesFails = (beatmapInfo?.Metrics?.Retries?.Any() ?? false) || (beatmapInfo?.Metrics?.Fails?.Any() ?? false); + var hasMetrics = (metrics?.Retries?.Any() ?? false) || (metrics?.Fails?.Any() ?? false); - if (hasRatings) + if (ratings?.Any() ?? false) { - ratings.Metrics = beatmapInfo.BeatmapSet.Metrics; - ratings.FadeIn(transition_duration); + ratingsDisplay.Ratings = ratings; + ratingsDisplay.FadeIn(transition_duration); } else { // loading or just has no data server-side. - ratings.Metrics = new BeatmapSetMetrics { Ratings = new int[10] }; - ratings.FadeTo(0.25f, transition_duration); + ratingsDisplay.Ratings = new int[10]; + ratingsDisplay.FadeTo(0.25f, transition_duration); } - if (hasRetriesFails) + if (hasMetrics) { - failRetryGraph.Metrics = beatmapInfo.Metrics; + failRetryGraph.Metrics = metrics; failRetryContainer.FadeIn(transition_duration); } else diff --git a/osu.Game/Screens/Select/Details/UserRatings.cs b/osu.Game/Screens/Select/Details/UserRatings.cs index eabc476db9..aa316d6e40 100644 --- a/osu.Game/Screens/Select/Details/UserRatings.cs +++ b/osu.Game/Screens/Select/Details/UserRatings.cs @@ -1,15 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using System.Linq; -using osu.Framework.Extensions.LocalisationExtensions; -using osu.Game.Beatmaps; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Screens.Select.Details @@ -22,20 +21,20 @@ namespace osu.Game.Screens.Select.Details private readonly Container graphContainer; private readonly BarGraph graph; - private BeatmapSetMetrics metrics; + private int[] ratings; - public BeatmapSetMetrics Metrics + public int[] Ratings { - get => metrics; + get => ratings; set { - if (value == metrics) return; + if (value == ratings) return; - metrics = value; + ratings = value; const int rating_range = 10; - if (metrics == null) + if (ratings == null) { negativeRatings.Text = 0.ToLocalisableString(@"N0"); positiveRatings.Text = 0.ToLocalisableString(@"N0"); @@ -44,15 +43,15 @@ namespace osu.Game.Screens.Select.Details } else { - var ratings = Metrics.Ratings.Skip(1).Take(rating_range); // adjust for API returning weird empty data at 0. + var usableRange = Ratings.Skip(1).Take(rating_range); // adjust for API returning weird empty data at 0. - var negativeCount = ratings.Take(rating_range / 2).Sum(); - var totalCount = ratings.Sum(); + var negativeCount = usableRange.Take(rating_range / 2).Sum(); + var totalCount = usableRange.Sum(); negativeRatings.Text = negativeCount.ToLocalisableString(@"N0"); positiveRatings.Text = (totalCount - negativeCount).ToLocalisableString(@"N0"); ratingsBar.Length = totalCount == 0 ? 0 : (float)negativeCount / totalCount; - graph.Values = ratings.Take(rating_range).Select(r => (float)r); + graph.Values = usableRange.Take(rating_range).Select(r => (float)r); } } } From 60df0151c024bdc47bf1b4b111d521bda184bf5c Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 7 Jul 2021 20:24:05 +0900 Subject: [PATCH 038/129] Add very basic distance snap grid for catch editor --- .../Editor/TestSceneCatchDistanceSnapGrid.cs | 91 +++++++++++++++ .../Edit/CatchDistanceSnapGrid.cs | 107 ++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs create mode 100644 osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs new file mode 100644 index 0000000000..2be0b7e9b2 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs @@ -0,0 +1,91 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Edit; +using osu.Game.Rulesets.Catch.Edit.Blueprints.Components; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Tests.Visual; +using osuTK; + +namespace osu.Game.Rulesets.Catch.Tests.Editor +{ + public class TestSceneCatchDistanceSnapGrid : OsuManualInputManagerTestScene + { + private readonly ManualClock manualClock = new ManualClock(); + + [Cached(typeof(Playfield))] + private readonly CatchPlayfield playfield; + + private ScrollingHitObjectContainer hitObjectContainer => playfield.HitObjectContainer; + + private readonly CatchDistanceSnapGrid distanceGrid; + + private readonly FruitOutline fruitOutline; + + private readonly Fruit fruit = new Fruit(); + + public TestSceneCatchDistanceSnapGrid() + { + Child = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Width = 500, + + Children = new Drawable[] + { + new ScrollingTestContainer(ScrollingDirection.Down) + { + RelativeSizeAxes = Axes.Both, + Child = playfield = new CatchPlayfield(new BeatmapDifficulty()) + { + RelativeSizeAxes = Axes.Both, + Clock = new FramedClock(manualClock) + } + }, + distanceGrid = new CatchDistanceSnapGrid(new double[] { 0, -1, 1 }), + fruitOutline = new FruitOutline() + }, + }; + } + + protected override void Update() + { + base.Update(); + + distanceGrid.StartTime = 100; + distanceGrid.StartX = 250; + + Vector2 screenSpacePosition = InputManager.CurrentState.Mouse.Position; + + var result = distanceGrid.GetSnappedPosition(screenSpacePosition); + + if (result != null) + { + fruit.OriginalX = hitObjectContainer.ToLocalSpace(result.ScreenSpacePosition).X; + + if (result.Time != null) + fruit.StartTime = result.Time.Value; + } + + fruitOutline.Position = CatchHitObjectUtils.GetStartPosition(hitObjectContainer, fruit); + fruitOutline.UpdateFrom(fruit); + } + + protected override bool OnScroll(ScrollEvent e) + { + manualClock.CurrentTime -= e.ScrollDelta.Y * 50; + return true; + } + } +} diff --git a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs new file mode 100644 index 0000000000..5808b332b0 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs @@ -0,0 +1,107 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using JetBrains.Annotations; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Lines; +using osu.Framework.Graphics.Primitives; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.UI.Scrolling; +using osuTK; + +namespace osu.Game.Rulesets.Catch.Edit +{ + public class CatchDistanceSnapGrid : CompositeDrawable + { + public double StartTime { get; set; } + + public float StartX { get; set; } + + private readonly double[] velocities; + + private readonly List verticalPaths = new List(); + + private readonly List> verticalLineVertices = new List>(); + + [Resolved] + private Playfield playfield { get; set; } + + private ScrollingHitObjectContainer hitObjectContainer => (ScrollingHitObjectContainer)playfield.HitObjectContainer; + + public CatchDistanceSnapGrid(double[] velocities) + { + RelativeSizeAxes = Axes.Both; + Anchor = Anchor.BottomLeft; + + this.velocities = velocities; + + for (int i = 0; i < velocities.Length; i++) + { + verticalPaths.Add(new SmoothPath + { + PathRadius = 2, + Alpha = 0.5f, + }); + + verticalLineVertices.Add(new List { Vector2.Zero, Vector2.Zero }); + } + + AddRangeInternal(verticalPaths); + } + + protected override void Update() + { + base.Update(); + + float startY = hitObjectContainer.PositionAtTime(StartTime); + + for (int i = 0; i < velocities.Length; i++) + { + double velocity = velocities[i]; + + // The line ends at the top of the screen. + double endTime = hitObjectContainer.TimeAtPosition(-hitObjectContainer.DrawHeight, hitObjectContainer.Time.Current); + + float x = (float)((endTime - StartTime) * velocity); + float y = hitObjectContainer.PositionAtTime(endTime, StartTime); + + List lineVertices = verticalLineVertices[i]; + lineVertices[0] = new Vector2(StartX, startY); + lineVertices[1] = lineVertices[0] + new Vector2(x, y); + + var verticalPath = verticalPaths[i]; + verticalPath.Vertices = verticalLineVertices[i]; + verticalPath.OriginPosition = verticalPath.PositionInBoundingBox(Vector2.Zero); + } + } + + [CanBeNull] + public SnapResult GetSnappedPosition(Vector2 screenSpacePosition) + { + double time = hitObjectContainer.TimeAtScreenSpacePosition(screenSpacePosition); + + return enumerateSnappingCandidates(time) + .OrderBy(pos => Vector2.DistanceSquared(screenSpacePosition, pos.ScreenSpacePosition)) + .FirstOrDefault(); + } + + private IEnumerable enumerateSnappingCandidates(double time) + { + float y = hitObjectContainer.PositionAtTime(time); + + foreach (double velocity in velocities) + { + float x = (float)(StartX + (time - StartTime) * velocity); + Vector2 screenSpacePosition = hitObjectContainer.ToScreenSpace(new Vector2(x, y + hitObjectContainer.DrawHeight)); + yield return new SnapResult(screenSpacePosition, time); + } + } + + protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) => false; + } +} From 20baae90945da9ad276e2277d5497172e7276baf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Oct 2021 15:12:11 +0900 Subject: [PATCH 039/129] Move online metrics out of `BeatmapInfo` model --- .../Online/TestSceneBeatmapSetOverlay.cs | 48 ++++++++++--------- .../TestSceneBeatmapSetOverlayDetails.cs | 11 +++-- .../TestSceneBeatmapSetOverlaySuccessRate.cs | 29 +++++++---- .../SongSelect/TestSceneBeatmapDetails.cs | 33 ++++++++----- osu.Game/Beatmaps/BeatmapInfo.cs | 24 ++++++++-- osu.Game/Beatmaps/BeatmapOnlineInfo.cs | 31 ------------ osu.Game/Beatmaps/IBeatmapOnlineInfo.cs | 23 +++++++++ .../API/Requests/Responses/APIBeatmap.cs | 17 ++----- osu.Game/Screens/Select/BeatmapDetails.cs | 4 +- osu.Game/Tests/Beatmaps/TestBeatmap.cs | 2 +- 10 files changed, 124 insertions(+), 98 deletions(-) delete mode 100644 osu.Game/Beatmaps/BeatmapOnlineInfo.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index da033e324c..3b0c2f5a7a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -92,17 +92,17 @@ namespace osu.Game.Tests.Visual.Online OverallDifficulty = 4.5f, ApproachRate = 6, }, - OnlineInfo = new BeatmapOnlineInfo + OnlineInfo = new APIBeatmap { CircleCount = 111, SliderCount = 12, PlayCount = 222, PassCount = 21, - }, - Metrics = new BeatmapMetrics - { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), + }, }, }, }, @@ -170,17 +170,17 @@ namespace osu.Game.Tests.Visual.Online OverallDifficulty = 7, ApproachRate = 6, }, - OnlineInfo = new BeatmapOnlineInfo + OnlineInfo = new APIBeatmap { CircleCount = 123, SliderCount = 45, PlayCount = 567, PassCount = 89, - }, - Metrics = new BeatmapMetrics - { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), + }, }, }, }, @@ -204,12 +204,14 @@ namespace osu.Game.Tests.Visual.Online Version = ruleset.Name, Ruleset = ruleset, BaseDifficulty = new BeatmapDifficulty(), - OnlineInfo = new BeatmapOnlineInfo(), - Metrics = new BeatmapMetrics + OnlineInfo = new APIBeatmap { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), - }, + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), + }, + } }); } @@ -288,12 +290,14 @@ namespace osu.Game.Tests.Visual.Online { OverallDifficulty = 3.5f, }, - OnlineInfo = new BeatmapOnlineInfo(), - Metrics = new BeatmapMetrics + OnlineInfo = new APIBeatmap { - Fails = Enumerable.Range(1, 100).Select(j => j % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(j => j % 12 - 6).ToArray(), - }, + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(j => j % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(j => j % 12 - 6).ToArray(), + }, + } }); } diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs index f16d5aaa23..078e50e0d9 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs @@ -50,11 +50,14 @@ namespace osu.Game.Tests.Visual.Online { new BeatmapInfo { - Metrics = new BeatmapMetrics + OnlineInfo = new APIBeatmap { - Fails = Enumerable.Range(1, 100).Select(_ => RNG.Next(10)).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(_ => RNG.Next(10)).ToArray(), - }, + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(_ => RNG.Next(10)).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(_ => RNG.Next(10)).ToArray(), + }, + } } }, OnlineInfo = new APIBeatmapSet diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs index fe8e33f783..84d0b9f868 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs @@ -11,6 +11,7 @@ using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Overlays.BeatmapSet; using osu.Game.Screens.Select.Details; @@ -66,10 +67,13 @@ namespace osu.Game.Tests.Visual.Online static BeatmapInfo createBeatmap() => new BeatmapInfo { - Metrics = new BeatmapMetrics + OnlineInfo = new APIBeatmap { - Fails = Enumerable.Range(1, 100).Select(_ => RNG.Next(10)).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(_ => RNG.Next(10)).ToArray(), + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(_ => RNG.Next(10)).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(_ => RNG.Next(10)).ToArray(), + } } }; } @@ -79,13 +83,16 @@ namespace osu.Game.Tests.Visual.Online { AddStep("set beatmap", () => successRate.BeatmapInfo = new BeatmapInfo { - Metrics = new BeatmapMetrics + OnlineInfo = new APIBeatmap { - Fails = Enumerable.Range(1, 100).ToArray(), + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).ToArray(), + } } }); - AddAssert("graph max values correct", - () => successRate.ChildrenOfType().All(graph => graph.MaxValue == 100)); + + AddAssert("graph max values correct", () => successRate.ChildrenOfType().All(graph => graph.MaxValue == 100)); } [Test] @@ -93,11 +100,13 @@ namespace osu.Game.Tests.Visual.Online { AddStep("set beatmap", () => successRate.BeatmapInfo = new BeatmapInfo { - Metrics = new BeatmapMetrics() + OnlineInfo = new APIBeatmap + { + Metrics = new BeatmapMetrics(), + } }); - AddAssert("graph max values correct", - () => successRate.ChildrenOfType().All(graph => graph.MaxValue == 0)); + AddAssert("graph max values correct", () => successRate.ChildrenOfType().All(graph => graph.MaxValue == 0)); } private class GraphExposingSuccessRate : SuccessRate diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index 6b508878bf..4bdb8539ba 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs @@ -54,11 +54,14 @@ namespace osu.Game.Tests.Visual.SongSelect ApproachRate = 3.5f, }, StarDifficulty = 5.3f, - Metrics = new BeatmapMetrics + OnlineInfo = new APIBeatmap { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), - }, + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), + }, + } }); } @@ -87,11 +90,14 @@ namespace osu.Game.Tests.Visual.SongSelect ApproachRate = 3.5f, }, StarDifficulty = 5.3f, - Metrics = new BeatmapMetrics + OnlineInfo = new APIBeatmap { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), - }, + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), + }, + } }); } @@ -143,11 +149,14 @@ namespace osu.Game.Tests.Visual.SongSelect ApproachRate = 7, }, StarDifficulty = 2.91f, - Metrics = new BeatmapMetrics + OnlineInfo = new APIBeatmap { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), - }, + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), + }, + } }); } diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 6da50657a6..fb599853c7 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -47,10 +47,7 @@ namespace osu.Game.Beatmaps public BeatmapDifficulty BaseDifficulty { get; set; } [NotMapped] - public BeatmapMetrics Metrics { get; set; } - - [NotMapped] - public BeatmapOnlineInfo OnlineInfo { get; set; } + public IBeatmapOnlineInfo OnlineInfo { get; set; } [NotMapped] public int? MaxCombo { get; set; } @@ -192,5 +189,24 @@ namespace osu.Game.Beatmaps double IBeatmapInfo.StarRating => StarDifficulty; #endregion + + #region Implementation of IBeatmapOnlineInfo + + [JsonIgnore] + public int CircleCount => OnlineInfo.CircleCount; + + [JsonIgnore] + public int SliderCount => OnlineInfo.SliderCount; + + [JsonIgnore] + public int PlayCount => OnlineInfo.PlayCount; + + [JsonIgnore] + public int PassCount => OnlineInfo.PassCount; + + [JsonIgnore] + public BeatmapMetrics Metrics => OnlineInfo.Metrics; + + #endregion } } diff --git a/osu.Game/Beatmaps/BeatmapOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapOnlineInfo.cs deleted file mode 100644 index bfeacd9bfc..0000000000 --- a/osu.Game/Beatmaps/BeatmapOnlineInfo.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Beatmaps -{ - /// - /// Beatmap info retrieved for previewing locally without having the beatmap downloaded. - /// - public class BeatmapOnlineInfo - { - /// - /// The amount of circles in this beatmap. - /// - public int CircleCount { get; set; } - - /// - /// The amount of sliders in this beatmap. - /// - public int SliderCount { get; set; } - - /// - /// The amount of plays this beatmap has. - /// - public int PlayCount { get; set; } - - /// - /// The amount of passes this beatmap has. - /// - public int PassCount { get; set; } - } -} diff --git a/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs b/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs index 4898e45c56..9f8e739759 100644 --- a/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs @@ -10,8 +10,31 @@ namespace osu.Game.Beatmaps /// public interface IBeatmapOnlineInfo { + /// + /// The max combo of this beatmap. + /// int? MaxCombo { get; } + /// + /// The amount of circles in this beatmap. + /// + public int CircleCount { get; } + + /// + /// The amount of sliders in this beatmap. + /// + public int SliderCount { get; } + + /// + /// The amount of plays this beatmap has. + /// + public int PlayCount { get; } + + /// + /// The amount of passes this beatmap has. + /// + public int PassCount { get; } + BeatmapMetrics? Metrics { get; } } } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index 6a05811bba..f0f97cc11c 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -31,10 +31,10 @@ namespace osu.Game.Online.API.Requests.Responses public APIBeatmapSet? BeatmapSet { get; set; } [JsonProperty(@"playcount")] - private int playCount { get; set; } + public int PlayCount { get; set; } [JsonProperty(@"passcount")] - private int passCount { get; set; } + public int PassCount { get; set; } [JsonProperty(@"mode_int")] public int RulesetID { get; set; } @@ -60,10 +60,10 @@ namespace osu.Game.Online.API.Requests.Responses private double lengthInSeconds { get; set; } [JsonProperty(@"count_circles")] - private int circleCount { get; set; } + public int CircleCount { get; set; } [JsonProperty(@"count_sliders")] - private int sliderCount { get; set; } + public int SliderCount { get; set; } [JsonProperty(@"version")] public string DifficultyName { get; set; } = string.Empty; @@ -90,7 +90,6 @@ namespace osu.Game.Online.API.Requests.Responses Status = Status, MD5Hash = Checksum, BeatmapSet = set, - Metrics = Metrics, MaxCombo = MaxCombo, BaseDifficulty = new BeatmapDifficulty { @@ -99,13 +98,7 @@ namespace osu.Game.Online.API.Requests.Responses ApproachRate = approachRate, OverallDifficulty = overallDifficulty, }, - OnlineInfo = new BeatmapOnlineInfo - { - PlayCount = playCount, - PassCount = passCount, - CircleCount = circleCount, - SliderCount = sliderCount, - }, + OnlineInfo = this, }; } diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 8dbe438ab5..9fab36229f 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -55,8 +55,8 @@ namespace osu.Game.Screens.Select beatmapInfo = value; - metrics = beatmapInfo?.Metrics; - ratings = beatmapInfo?.BeatmapSet.Ratings; + metrics = beatmapInfo?.OnlineInfo?.Metrics; + ratings = beatmapInfo?.BeatmapSet?.Ratings; Scheduler.AddOnce(updateStatistics); } diff --git a/osu.Game/Tests/Beatmaps/TestBeatmap.cs b/osu.Game/Tests/Beatmaps/TestBeatmap.cs index d8e72d31a7..15b72ce6e3 100644 --- a/osu.Game/Tests/Beatmaps/TestBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestBeatmap.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Beatmaps BeatmapInfo.BeatmapSet.Metadata = BeatmapInfo.Metadata; BeatmapInfo.BeatmapSet.Beatmaps = new List { BeatmapInfo }; BeatmapInfo.Length = 75000; - BeatmapInfo.OnlineInfo = new BeatmapOnlineInfo(); + BeatmapInfo.OnlineInfo = new APIBeatmap(); BeatmapInfo.BeatmapSet.OnlineInfo = new APIBeatmapSet { Status = BeatmapSetOnlineStatus.Ranked, From 4969ab0599a9f60158a40fe51798cf9420e4b9da Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Oct 2021 15:12:21 +0900 Subject: [PATCH 040/129] Add forgotten `JsonIgnore` rules on interface types Just to avoid them getting serialised as part of the "new" .osu serialisation format. --- osu.Game/Beatmaps/BeatmapInfo.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index fb599853c7..7be58e6472 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -181,11 +181,22 @@ namespace osu.Game.Beatmaps #region Implementation of IBeatmapInfo + [JsonIgnore] string IBeatmapInfo.DifficultyName => Version; + + [JsonIgnore] IBeatmapMetadataInfo IBeatmapInfo.Metadata => Metadata; + + [JsonIgnore] IBeatmapDifficultyInfo IBeatmapInfo.Difficulty => BaseDifficulty; + + [JsonIgnore] IBeatmapSetInfo IBeatmapInfo.BeatmapSet => BeatmapSet; + + [JsonIgnore] IRulesetInfo IBeatmapInfo.Ruleset => Ruleset; + + [JsonIgnore] double IBeatmapInfo.StarRating => StarDifficulty; #endregion From 2c308f3008c9c08e5ec94029965a4a601a6701f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Oct 2021 15:34:41 +0900 Subject: [PATCH 041/129] Rename `BeatmapMetrics` to `APIFailTimes` --- .../Visual/Online/TestSceneBeatmapSetOverlay.cs | 8 ++++---- .../Online/TestSceneBeatmapSetOverlayDetails.cs | 2 +- .../TestSceneBeatmapSetOverlaySuccessRate.cs | 10 +++++----- .../Visual/SongSelect/TestSceneBeatmapDetails.cs | 6 +++--- .../{BeatmapMetrics.cs => APIFailTimes.cs} | 2 +- osu.Game/Beatmaps/BeatmapInfo.cs | 2 +- osu.Game/Beatmaps/IBeatmapOnlineInfo.cs | 2 +- .../Online/API/Requests/Responses/APIBeatmap.cs | 2 +- osu.Game/Overlays/BeatmapSet/SuccessRate.cs | 2 +- osu.Game/Screens/Select/BeatmapDetails.cs | 15 ++++++++------- osu.Game/Screens/Select/Details/FailRetryGraph.cs | 14 +++++++------- 11 files changed, 33 insertions(+), 32 deletions(-) rename osu.Game/Beatmaps/{BeatmapMetrics.cs => APIFailTimes.cs} (96%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 3b0c2f5a7a..7f9b56e873 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -98,7 +98,7 @@ namespace osu.Game.Tests.Visual.Online SliderCount = 12, PlayCount = 222, PassCount = 21, - Metrics = new BeatmapMetrics + FailTimes = new APIFailTimes { Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), @@ -176,7 +176,7 @@ namespace osu.Game.Tests.Visual.Online SliderCount = 45, PlayCount = 567, PassCount = 89, - Metrics = new BeatmapMetrics + FailTimes = new APIFailTimes { Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), @@ -206,7 +206,7 @@ namespace osu.Game.Tests.Visual.Online BaseDifficulty = new BeatmapDifficulty(), OnlineInfo = new APIBeatmap { - Metrics = new BeatmapMetrics + FailTimes = new APIFailTimes { Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), @@ -292,7 +292,7 @@ namespace osu.Game.Tests.Visual.Online }, OnlineInfo = new APIBeatmap { - Metrics = new BeatmapMetrics + FailTimes = new APIFailTimes { Fails = Enumerable.Range(1, 100).Select(j => j % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(j => j % 12 - 6).ToArray(), diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs index 078e50e0d9..d14f9f47d1 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs @@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual.Online { OnlineInfo = new APIBeatmap { - Metrics = new BeatmapMetrics + FailTimes = new APIFailTimes { Fails = Enumerable.Range(1, 100).Select(_ => RNG.Next(10)).ToArray(), Retries = Enumerable.Range(-2, 100).Select(_ => RNG.Next(10)).ToArray(), diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs index 84d0b9f868..b3b67fcbca 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs @@ -60,16 +60,16 @@ namespace osu.Game.Tests.Visual.Online var secondBeatmap = createBeatmap(); AddStep("set first set", () => successRate.BeatmapInfo = firstBeatmap); - AddAssert("ratings set", () => successRate.Graph.Metrics == firstBeatmap.Metrics); + AddAssert("ratings set", () => successRate.Graph.FailTimes == firstBeatmap.FailTimes); AddStep("set second set", () => successRate.BeatmapInfo = secondBeatmap); - AddAssert("ratings set", () => successRate.Graph.Metrics == secondBeatmap.Metrics); + AddAssert("ratings set", () => successRate.Graph.FailTimes == secondBeatmap.FailTimes); static BeatmapInfo createBeatmap() => new BeatmapInfo { OnlineInfo = new APIBeatmap { - Metrics = new BeatmapMetrics + FailTimes = new APIFailTimes { Fails = Enumerable.Range(1, 100).Select(_ => RNG.Next(10)).ToArray(), Retries = Enumerable.Range(-2, 100).Select(_ => RNG.Next(10)).ToArray(), @@ -85,7 +85,7 @@ namespace osu.Game.Tests.Visual.Online { OnlineInfo = new APIBeatmap { - Metrics = new BeatmapMetrics + FailTimes = new APIFailTimes { Fails = Enumerable.Range(1, 100).ToArray(), } @@ -102,7 +102,7 @@ namespace osu.Game.Tests.Visual.Online { OnlineInfo = new APIBeatmap { - Metrics = new BeatmapMetrics(), + FailTimes = new APIFailTimes(), } }); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index 4bdb8539ba..1125e16d91 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs @@ -56,7 +56,7 @@ namespace osu.Game.Tests.Visual.SongSelect StarDifficulty = 5.3f, OnlineInfo = new APIBeatmap { - Metrics = new BeatmapMetrics + FailTimes = new APIFailTimes { Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), @@ -92,7 +92,7 @@ namespace osu.Game.Tests.Visual.SongSelect StarDifficulty = 5.3f, OnlineInfo = new APIBeatmap { - Metrics = new BeatmapMetrics + FailTimes = new APIFailTimes { Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), @@ -151,7 +151,7 @@ namespace osu.Game.Tests.Visual.SongSelect StarDifficulty = 2.91f, OnlineInfo = new APIBeatmap { - Metrics = new BeatmapMetrics + FailTimes = new APIFailTimes { Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), diff --git a/osu.Game/Beatmaps/BeatmapMetrics.cs b/osu.Game/Beatmaps/APIFailTimes.cs similarity index 96% rename from osu.Game/Beatmaps/BeatmapMetrics.cs rename to osu.Game/Beatmaps/APIFailTimes.cs index b164aa6b30..7218906b38 100644 --- a/osu.Game/Beatmaps/BeatmapMetrics.cs +++ b/osu.Game/Beatmaps/APIFailTimes.cs @@ -9,7 +9,7 @@ namespace osu.Game.Beatmaps /// /// Beatmap metrics based on accumulated online data from community plays. /// - public class BeatmapMetrics + public class APIFailTimes { /// /// Points of failure on a relative time scale (usually 0..100). diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 7be58e6472..571809db36 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -216,7 +216,7 @@ namespace osu.Game.Beatmaps public int PassCount => OnlineInfo.PassCount; [JsonIgnore] - public BeatmapMetrics Metrics => OnlineInfo.Metrics; + public APIFailTimes FailTimes => OnlineInfo.FailTimes; #endregion } diff --git a/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs b/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs index 9f8e739759..385646eeaa 100644 --- a/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs @@ -35,6 +35,6 @@ namespace osu.Game.Beatmaps /// public int PassCount { get; } - BeatmapMetrics? Metrics { get; } + APIFailTimes? FailTimes { get; } } } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index f0f97cc11c..de86f0f875 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -69,7 +69,7 @@ namespace osu.Game.Online.API.Requests.Responses public string DifficultyName { get; set; } = string.Empty; [JsonProperty(@"failtimes")] - public BeatmapMetrics? Metrics { get; set; } + public APIFailTimes? FailTimes { get; set; } [JsonProperty(@"max_combo")] public int? MaxCombo { get; set; } diff --git a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs index 4a9b8244a5..604c4e1949 100644 --- a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs +++ b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs @@ -48,7 +48,7 @@ namespace osu.Game.Overlays.BeatmapSet successRate.Length = rate; percentContainer.ResizeWidthTo(successRate.Length, 250, Easing.InOutCubic); - Graph.Metrics = beatmapInfo?.Metrics; + Graph.FailTimes = beatmapInfo?.FailTimes; } public SuccessRate() diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 9fab36229f..16455940bf 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -43,7 +43,8 @@ namespace osu.Game.Screens.Select private BeatmapInfo beatmapInfo; - private BeatmapMetrics metrics; + private APIFailTimes failTimes; + private int[] ratings; public BeatmapInfo BeatmapInfo @@ -55,7 +56,7 @@ namespace osu.Game.Screens.Select beatmapInfo = value; - metrics = beatmapInfo?.OnlineInfo?.Metrics; + failTimes = beatmapInfo?.OnlineInfo?.FailTimes; ratings = beatmapInfo?.BeatmapSet?.Ratings; Scheduler.AddOnce(updateStatistics); @@ -182,7 +183,7 @@ namespace osu.Game.Screens.Select tags.Text = BeatmapInfo?.Metadata?.Tags; // metrics may have been previously fetched - if (ratings != null && metrics != null) + if (ratings != null && failTimes != null) { updateMetrics(); return; @@ -208,7 +209,7 @@ namespace osu.Game.Screens.Select return; ratings = res.BeatmapSet?.Ratings; - metrics = res.Metrics; + failTimes = res.FailTimes; updateMetrics(); }); @@ -232,7 +233,7 @@ namespace osu.Game.Screens.Select private void updateMetrics() { - var hasMetrics = (metrics?.Retries?.Any() ?? false) || (metrics?.Fails?.Any() ?? false); + var hasMetrics = (failTimes?.Retries?.Any() ?? false) || (failTimes?.Fails?.Any() ?? false); if (ratings?.Any() ?? false) { @@ -248,12 +249,12 @@ namespace osu.Game.Screens.Select if (hasMetrics) { - failRetryGraph.Metrics = metrics; + failRetryGraph.FailTimes = failTimes; failRetryContainer.FadeIn(transition_duration); } else { - failRetryGraph.Metrics = new BeatmapMetrics + failRetryGraph.FailTimes = new APIFailTimes { Fails = new int[100], Retries = new int[100], diff --git a/osu.Game/Screens/Select/Details/FailRetryGraph.cs b/osu.Game/Screens/Select/Details/FailRetryGraph.cs index 7cc80acfd3..ecaf02cb30 100644 --- a/osu.Game/Screens/Select/Details/FailRetryGraph.cs +++ b/osu.Game/Screens/Select/Details/FailRetryGraph.cs @@ -16,19 +16,19 @@ namespace osu.Game.Screens.Select.Details { private readonly BarGraph retryGraph, failGraph; - private BeatmapMetrics metrics; + private APIFailTimes failTimes; - public BeatmapMetrics Metrics + public APIFailTimes FailTimes { - get => metrics; + get => failTimes; set { - if (value == metrics) return; + if (value == failTimes) return; - metrics = value; + failTimes = value; - var retries = Metrics?.Retries ?? Array.Empty(); - var fails = Metrics?.Fails ?? Array.Empty(); + var retries = FailTimes?.Retries ?? Array.Empty(); + var fails = FailTimes?.Fails ?? Array.Empty(); var retriesAndFails = sumRetriesAndFails(retries, fails); float maxValue = retriesAndFails.Any() ? retriesAndFails.Max() : 0; From 67ef1c40e64ca935a5f4b9ee666b72cb15da9182 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Oct 2021 15:59:40 +0900 Subject: [PATCH 042/129] Allow API beatmap requests using interface type --- osu.Game/Online/API/Requests/GetBeatmapRequest.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs index 901f7365b8..aa0d51641e 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs @@ -4,17 +4,23 @@ using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; +#nullable enable + namespace osu.Game.Online.API.Requests { public class GetBeatmapRequest : APIRequest { - private readonly BeatmapInfo beatmapInfo; + private readonly IBeatmapInfo beatmapInfo; - public GetBeatmapRequest(BeatmapInfo beatmapInfo) + private readonly string filename; + + public GetBeatmapRequest(IBeatmapInfo beatmapInfo) { this.beatmapInfo = beatmapInfo; + + filename = (beatmapInfo as BeatmapInfo)?.Path ?? string.Empty; } - protected override string Target => $@"beatmaps/lookup?id={beatmapInfo.OnlineBeatmapID}&checksum={beatmapInfo.MD5Hash}&filename={System.Uri.EscapeUriString(beatmapInfo.Path ?? string.Empty)}"; + protected override string Target => $@"beatmaps/lookup?id={beatmapInfo.OnlineID}&checksum={beatmapInfo.MD5Hash}&filename={System.Uri.EscapeUriString(filename)}"; } } From 7a92c7ab7e0c2c888845f0a16dbf8189ecc50ea2 Mon Sep 17 00:00:00 2001 From: Roxie Wattz Date: Mon, 25 Oct 2021 00:25:32 -0700 Subject: [PATCH 043/129] Move condition to separate switch statement No clue if this is how peppy wanted me to do it but it still works --- .../Mods/TestSceneOsuModHidden.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 107 +++++++++++------- 2 files changed, 65 insertions(+), 44 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs index f25df90737..1fd601cec5 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs @@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods [Test] public void OuendanTwoHidden() => CreateModTest(new ModTestData { - Mod = new OsuModHidden { NoHitCircles = { Value = true } }, + Mod = new OsuModHidden { OnlyFadeApproachCircles = { Value = true } }, Autoplay = true, Beatmap = new Beatmap { diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 59ac6746a0..12e2035e80 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Mods public class OsuModHidden : ModHidden, IHidesApproachCircles { [SettingSource("Only fade approach circles", "The main object body will not fade when enabled.")] - public Bindable NoHitCircles { get; } = new BindableBool(false); + public Bindable OnlyFadeApproachCircles { get; } = new BindableBool(false); public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; @@ -67,69 +67,90 @@ namespace osu.Game.Rulesets.Osu.Mods (double fadeStartTime, double fadeDuration) = getFadeOutParameters(drawableOsuObject); - switch (drawableObject) + if (!OnlyFadeApproachCircles.Value) { - case DrawableSliderTail _: - using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) - if (!NoHitCircles.Value) + switch (drawableObject) + { + case DrawableSliderTail _: + using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) drawableObject.FadeOut(fadeDuration); - break; + break; - case DrawableSliderRepeat sliderRepeat: - using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) - // only apply to circle piece – reverse arrow is not affected by hidden. - if (!NoHitCircles.Value) + case DrawableSliderRepeat sliderRepeat: + using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) + // only apply to circle piece – reverse arrow is not affected by hidden. sliderRepeat.CirclePiece.FadeOut(fadeDuration); - break; + break; - case DrawableHitCircle circle: - Drawable fadeTarget = circle; + case DrawableHitCircle circle: + Drawable fadeTarget = circle; - if (increaseVisibility) - { - // only fade the circle piece (not the approach circle) for the increased visibility object. - if (!NoHitCircles.Value) + if (increaseVisibility) + { + // only fade the circle piece (not the approach circle) for the increased visibility object. fadeTarget = circle.CirclePiece; - } - else - { - // we don't want to see the approach circle - using (circle.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimePreempt)) - circle.ApproachCircle.Hide(); - } + } + else + { + // we don't want to see the approach circle + using (circle.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimePreempt)) + circle.ApproachCircle.Hide(); + } - using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) - if (!NoHitCircles.Value) + using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) fadeTarget.FadeOut(fadeDuration); - break; + break; - case DrawableSlider slider: - using (slider.BeginAbsoluteSequence(fadeStartTime)) - if (!NoHitCircles.Value) + case DrawableSlider slider: + using (slider.BeginAbsoluteSequence(fadeStartTime)) slider.Body.FadeOut(fadeDuration, Easing.Out); - break; + break; - case DrawableSliderTick sliderTick: - using (sliderTick.BeginAbsoluteSequence(fadeStartTime)) - if (!NoHitCircles.Value) + case DrawableSliderTick sliderTick: + using (sliderTick.BeginAbsoluteSequence(fadeStartTime)) sliderTick.FadeOut(fadeDuration); - break; + break; - case DrawableSpinner spinner: - // hide elements we don't care about. - // todo: hide background + case DrawableSpinner spinner: + // hide elements we don't care about. + // todo: hide background - spinner.Body.OnSkinChanged += () => hideSpinnerApproachCircle(spinner); - hideSpinnerApproachCircle(spinner); + spinner.Body.OnSkinChanged += () => hideSpinnerApproachCircle(spinner); + hideSpinnerApproachCircle(spinner); - using (spinner.BeginAbsoluteSequence(fadeStartTime)) - spinner.FadeOut(fadeDuration); + using (spinner.BeginAbsoluteSequence(fadeStartTime)) + spinner.FadeOut(fadeDuration); - break; + break; + } + } else + { + switch(drawableObject) + { + case DrawableHitCircle circle: + if (!increaseVisibility) + { + // we don't want to see the approach circle + using (circle.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimePreempt)) + circle.ApproachCircle.Hide(); + } + break; + + case DrawableSpinner spinner: + // hide elements we don't care about. + // todo: hide background + + spinner.Body.OnSkinChanged += () => hideSpinnerApproachCircle(spinner); + hideSpinnerApproachCircle(spinner); + break; + + default: + break; + } } } From 6d1cd0a3a14d28b237c827cf8ba62ca5c2658824 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 25 Oct 2021 16:37:44 +0900 Subject: [PATCH 044/129] Add distance snapping to catch editor --- .../Edit/CatchHitObjectComposer.cs | 116 +++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index 050c2f625d..9b779d3370 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -2,14 +2,23 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input; using osu.Game.Beatmaps; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; +using osu.Game.Screens.Edit.Components.TernaryButtons; using osu.Game.Screens.Edit.Compose.Components; using osuTK; @@ -17,6 +26,14 @@ namespace osu.Game.Rulesets.Catch.Edit { public class CatchHitObjectComposer : HitObjectComposer { + private const float distance_snap_radius = 50; + + private CatchDistanceSnapGrid distanceSnapGrid; + + private readonly Bindable distanceSnapToggle = new Bindable(); + + private InputManager inputManager; + public CatchHitObjectComposer(CatchRuleset ruleset) : base(ruleset) { @@ -30,6 +47,27 @@ namespace osu.Game.Rulesets.Catch.Edit RelativeSizeAxes = Axes.Both, PlayfieldBorderStyle = { Value = PlayfieldBorderStyle.Corners } }); + + LayerBelowRuleset.Add(distanceSnapGrid = new CatchDistanceSnapGrid(new[] + { + 0.0, + Catcher.BASE_SPEED, -Catcher.BASE_SPEED, + Catcher.BASE_SPEED / 2, -Catcher.BASE_SPEED / 2, + })); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + inputManager = GetContainingInputManager(); + } + + protected override void Update() + { + base.Update(); + + updateDistanceSnapGrid(); } protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) => @@ -42,14 +80,90 @@ namespace osu.Game.Rulesets.Catch.Edit new BananaShowerCompositionTool() }; + protected override IEnumerable CreateTernaryButtons() => base.CreateTernaryButtons().Concat(new[] + { + new TernaryButton(distanceSnapToggle, "Distance Snap", () => new SpriteIcon { Icon = FontAwesome.Solid.Ruler }) + }); + public override SnapResult SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition) { var result = base.SnapScreenSpacePositionToValidTime(screenSpacePosition); - // TODO: implement position snap result.ScreenSpacePosition.X = screenSpacePosition.X; + + if (distanceSnapGrid.IsPresent && distanceSnapGrid.GetSnappedPosition(result.ScreenSpacePosition) is SnapResult snapResult && + Vector2.Distance(snapResult.ScreenSpacePosition, result.ScreenSpacePosition) < distance_snap_radius) + { + result = snapResult; + } + return result; } protected override ComposeBlueprintContainer CreateBlueprintContainer() => new CatchBlueprintContainer(this); + + [CanBeNull] + private PalpableCatchHitObject getPreviousHitObject(double time) + { + var hitObject = EditorBeatmap.HitObjects.OfType().LastOrDefault(h => h.GetEndTime() < time && !(h is BananaShower)); + + switch (hitObject) + { + case Fruit fruit: + return fruit; + + case JuiceStream juiceStream: + return juiceStream.NestedHitObjects.OfType().LastOrDefault(h => !(h is TinyDroplet)); + + default: + return null; + } + } + + [CanBeNull] + private PalpableCatchHitObject getDistanceSnapGridSourceHitObject() + { + switch (BlueprintContainer.CurrentTool) + { + case SelectTool _: + if (EditorBeatmap.SelectedHitObjects.Count == 0) + return null; + + double minTime = EditorBeatmap.SelectedHitObjects.Min(hitObject => hitObject.StartTime); + return getPreviousHitObject(minTime); + + case FruitCompositionTool _: + case JuiceStreamCompositionTool _: + if (!CursorInPlacementArea) + return null; + + if (EditorBeatmap.PlacementObject.Value is JuiceStream) + { + // Juice stream path is not subject to snapping. + return null; + } + + double timeAtCursor = ((CatchPlayfield)Playfield).TimeAtScreenSpacePosition(inputManager.CurrentState.Mouse.Position); + return getPreviousHitObject(timeAtCursor); + + default: + return null; + } + } + + private void updateDistanceSnapGrid() + { + var sourceHitObject = getDistanceSnapGridSourceHitObject(); + + if (distanceSnapToggle.Value != TernaryState.True || sourceHitObject == null) + { + distanceSnapGrid.Hide(); + } + else + { + distanceSnapGrid.Show(); + distanceSnapGrid.StartTime = sourceHitObject.GetEndTime(); + distanceSnapGrid.StartX = sourceHitObject.EffectiveX; + } + } } } From 6adb0f068b340672aa7218c1129a6bd466037acd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Oct 2021 16:44:52 +0900 Subject: [PATCH 045/129] Fix multiple issues with json serialisation of online info (causing tournament failures) --- osu.Game.Tournament.Tests/TournamentTestScene.cs | 2 +- osu.Game/Beatmaps/BeatmapInfo.cs | 3 ++- osu.Game/Online/API/Requests/Responses/APIBeatmap.cs | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament.Tests/TournamentTestScene.cs b/osu.Game.Tournament.Tests/TournamentTestScene.cs index 3ea58e9867..ce9fd91ff1 100644 --- a/osu.Game.Tournament.Tests/TournamentTestScene.cs +++ b/osu.Game.Tournament.Tests/TournamentTestScene.cs @@ -161,7 +161,7 @@ namespace osu.Game.Tournament.Tests Artist = "Test Artist", ID = RNG.Next(0, 1000000) }, - OnlineInfo = new BeatmapOnlineInfo(), + OnlineInfo = new APIBeatmap(), }; protected override ITestSceneTestRunner CreateRunner() => new TournamentTestSceneTestRunner(); diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 571809db36..9069ea4404 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -9,6 +9,7 @@ using System.Linq; using Newtonsoft.Json; using osu.Framework.Testing; using osu.Game.Database; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osu.Game.Scoring; @@ -47,7 +48,7 @@ namespace osu.Game.Beatmaps public BeatmapDifficulty BaseDifficulty { get; set; } [NotMapped] - public IBeatmapOnlineInfo OnlineInfo { get; set; } + public APIBeatmap OnlineInfo { get; set; } [NotMapped] public int? MaxCombo { get; set; } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index de86f0f875..a677844d66 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -74,6 +74,8 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"max_combo")] public int? MaxCombo { get; set; } + public double BPM { get; set; } + public virtual BeatmapInfo ToBeatmapInfo(RulesetStore rulesets) { var set = BeatmapSet?.ToBeatmapSet(rulesets); @@ -120,7 +122,7 @@ namespace osu.Game.Online.API.Requests.Responses public IRulesetInfo Ruleset => new RulesetInfo { ID = RulesetID }; - public double BPM => throw new NotImplementedException(); + [JsonIgnore] public string Hash => throw new NotImplementedException(); #endregion From 6802e9ec109c34309529a10b950038e54cc62015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 25 Oct 2021 20:20:40 +0200 Subject: [PATCH 046/129] Remove `FixedWidth` and add `AutoSizeAxes` specs to all usages --- .../TestSceneBeatmapSetOnlineStatusPill.cs | 9 +++++-- .../Drawables/BeatmapSetOnlineStatusPill.cs | 26 ------------------- .../BeatmapListing/Panels/GridBeatmapPanel.cs | 1 + .../BeatmapListing/Panels/ListBeatmapPanel.cs | 1 + .../BeatmapSet/BeatmapSetHeaderContent.cs | 1 + osu.Game/Screens/Select/BeatmapInfoWedge.cs | 1 + .../Select/Carousel/SetPanelContent.cs | 1 + 7 files changed, 12 insertions(+), 28 deletions(-) diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs index 2d61385269..c48b63ac89 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs @@ -28,6 +28,7 @@ namespace osu.Game.Tests.Visual.Beatmaps Spacing = new Vector2(0, 10), ChildrenEnumerable = Enum.GetValues(typeof(BeatmapSetOnlineStatus)).Cast().Select(status => new BeatmapSetOnlineStatusPill { + AutoSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, Status = status @@ -41,8 +42,12 @@ namespace osu.Game.Tests.Visual.Beatmaps { AddStep("create themed content", () => CreateThemedContent(OverlayColourScheme.Red)); - AddStep("set fixed width", () => statusPills.ForEach(pill => pill.FixedWidth = 90)); - AddStep("unset fixed width", () => statusPills.ForEach(pill => pill.FixedWidth = null)); + AddStep("set fixed width", () => statusPills.ForEach(pill => + { + pill.AutoSizeAxes = Axes.Y; + pill.Width = 90; + })); + AddStep("unset fixed width", () => statusPills.ForEach(pill => pill.AutoSizeAxes = Axes.Both)); } } } diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs index 848bab6394..ec098f4ca2 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs @@ -47,31 +47,6 @@ namespace osu.Game.Beatmaps.Drawables set => statusText.Padding = value; } - private float? fixedWidth; - - /// - /// When set to a non- value, the pill will be forcibly sized to the given width. - /// When set to a value, the pill will autosize to its contents. - /// - public float? FixedWidth - { - get => fixedWidth; - set - { - fixedWidth = value; - - if (fixedWidth == null) - { - AutoSizeAxes = Axes.Both; - } - else - { - AutoSizeAxes = Axes.Y; - Width = fixedWidth.Value; - } - } - } - private readonly OsuSpriteText statusText; private readonly Box background; @@ -83,7 +58,6 @@ namespace osu.Game.Beatmaps.Drawables public BeatmapSetOnlineStatusPill() { - AutoSizeAxes = Axes.Both; Masking = true; Children = new Drawable[] diff --git a/osu.Game/Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs b/osu.Game/Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs index c078127353..4a0fa59c31 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs @@ -243,6 +243,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels statusContainer.Add(new BeatmapSetOnlineStatusPill { + AutoSizeAxes = Axes.Both, TextSize = 12, TextPadding = new MarginPadding { Horizontal = 10, Vertical = 5 }, Status = SetInfo.OnlineInfo?.Status ?? BeatmapSetOnlineStatus.None, diff --git a/osu.Game/Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs b/osu.Game/Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs index 5011749c5f..63d651f9de 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs @@ -257,6 +257,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels statusContainer.Add(new BeatmapSetOnlineStatusPill { + AutoSizeAxes = Axes.Both, TextSize = 12, TextPadding = new MarginPadding { Horizontal = 10, Vertical = 4 }, Status = SetInfo.OnlineInfo?.Status ?? BeatmapSetOnlineStatus.None, diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs index df88b06879..6f85846720 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs @@ -198,6 +198,7 @@ namespace osu.Game.Overlays.BeatmapSet { onlineStatusPill = new BeatmapSetOnlineStatusPill { + AutoSizeAxes = Axes.Both, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, TextSize = 14, diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index ac191a38f2..2de72beaad 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -257,6 +257,7 @@ namespace osu.Game.Screens.Select }, StatusPill = new BeatmapSetOnlineStatusPill { + AutoSizeAxes = Axes.Both, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Shear = -wedged_container_shear, diff --git a/osu.Game/Screens/Select/Carousel/SetPanelContent.cs b/osu.Game/Screens/Select/Carousel/SetPanelContent.cs index 9fb640ba1a..f2054677b0 100644 --- a/osu.Game/Screens/Select/Carousel/SetPanelContent.cs +++ b/osu.Game/Screens/Select/Carousel/SetPanelContent.cs @@ -60,6 +60,7 @@ namespace osu.Game.Screens.Select.Carousel { new BeatmapSetOnlineStatusPill { + AutoSizeAxes = Axes.Both, Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, Margin = new MarginPadding { Right = 5 }, From 0fb2307420e8a8affa2c36e9da722f1884c9881b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 25 Oct 2021 21:00:05 +0200 Subject: [PATCH 047/129] Add back using directive Was removed for being unneeded in a prerequisite PR but then ended up leading to compilation failures in the dependent PR. --- osu.Game.Tournament.Tests/TournamentTestScene.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tournament.Tests/TournamentTestScene.cs b/osu.Game.Tournament.Tests/TournamentTestScene.cs index e941c9e2bd..ce9fd91ff1 100644 --- a/osu.Game.Tournament.Tests/TournamentTestScene.cs +++ b/osu.Game.Tournament.Tests/TournamentTestScene.cs @@ -8,6 +8,7 @@ using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Beatmaps; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osu.Game.Tests.Visual; using osu.Game.Tournament.IO; From c9a2c6c031e4be032e9b9ecfdf0f9e5faf3be63b Mon Sep 17 00:00:00 2001 From: Roxie Wattz Date: Mon, 25 Oct 2021 14:09:22 -0700 Subject: [PATCH 048/129] Reworking the Ouendan 2 Hidden code AGAIN Not finished. Will be finished in a later commit. --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 117 ++++++++------------- 1 file changed, 45 insertions(+), 72 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 12e2035e80..e93120b321 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -50,15 +50,15 @@ namespace osu.Game.Rulesets.Osu.Mods protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) { - applyState(hitObject, true); + applyHiddenState(hitObject, true, OnlyFadeApproachCircles.Value); } protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state) { - applyState(hitObject, false); + applyHiddenState(hitObject, false, OnlyFadeApproachCircles.Value); } - private void applyState(DrawableHitObject drawableObject, bool increaseVisibility) + private void applyHiddenState(DrawableHitObject drawableObject, bool hideApproachCircle, bool hideCirclePiece) { if (!(drawableObject is DrawableOsuHitObject drawableOsuObject)) return; @@ -67,90 +67,63 @@ namespace osu.Game.Rulesets.Osu.Mods (double fadeStartTime, double fadeDuration) = getFadeOutParameters(drawableOsuObject); - if (!OnlyFadeApproachCircles.Value) + switch (drawableObject) { - switch (drawableObject) - { - case DrawableSliderTail _: - using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) - drawableObject.FadeOut(fadeDuration); + case DrawableSliderTail _: + using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) + drawableObject.FadeOut(fadeDuration); - break; + break; - case DrawableSliderRepeat sliderRepeat: - using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) - // only apply to circle piece – reverse arrow is not affected by hidden. - sliderRepeat.CirclePiece.FadeOut(fadeDuration); + case DrawableSliderRepeat sliderRepeat: + using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) + // only apply to circle piece – reverse arrow is not affected by hidden. + sliderRepeat.CirclePiece.FadeOut(fadeDuration); - break; + break; - case DrawableHitCircle circle: - Drawable fadeTarget = circle; + case DrawableHitCircle circle: + Drawable fadeTarget = circle; - if (increaseVisibility) - { - // only fade the circle piece (not the approach circle) for the increased visibility object. - fadeTarget = circle.CirclePiece; - } - else - { - // we don't want to see the approach circle - using (circle.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimePreempt)) - circle.ApproachCircle.Hide(); - } + if (hideApproachCircle) + { + // only fade the circle piece (not the approach circle) for the increased visibility object. + fadeTarget = circle.CirclePiece; + } + else + { + // we don't want to see the approach circle + using (circle.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimePreempt)) + circle.ApproachCircle.Hide(); + } - using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) - fadeTarget.FadeOut(fadeDuration); - break; + using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) + fadeTarget.FadeOut(fadeDuration); + break; - case DrawableSlider slider: - using (slider.BeginAbsoluteSequence(fadeStartTime)) - slider.Body.FadeOut(fadeDuration, Easing.Out); + case DrawableSlider slider: + using (slider.BeginAbsoluteSequence(fadeStartTime)) + slider.Body.FadeOut(fadeDuration, Easing.Out); - break; + break; - case DrawableSliderTick sliderTick: - using (sliderTick.BeginAbsoluteSequence(fadeStartTime)) - sliderTick.FadeOut(fadeDuration); + case DrawableSliderTick sliderTick: + using (sliderTick.BeginAbsoluteSequence(fadeStartTime)) + sliderTick.FadeOut(fadeDuration); - break; + break; - case DrawableSpinner spinner: - // hide elements we don't care about. - // todo: hide background + case DrawableSpinner spinner: + // hide elements we don't care about. + // todo: hide background - spinner.Body.OnSkinChanged += () => hideSpinnerApproachCircle(spinner); - hideSpinnerApproachCircle(spinner); + spinner.Body.OnSkinChanged += () => hideSpinnerApproachCircle(spinner); + hideSpinnerApproachCircle(spinner); - using (spinner.BeginAbsoluteSequence(fadeStartTime)) - spinner.FadeOut(fadeDuration); + using (spinner.BeginAbsoluteSequence(fadeStartTime)) + spinner.FadeOut(fadeDuration); - break; - } - } else - { - switch(drawableObject) - { - case DrawableHitCircle circle: - if (!increaseVisibility) - { - // we don't want to see the approach circle - using (circle.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimePreempt)) - circle.ApproachCircle.Hide(); - } - break; - - case DrawableSpinner spinner: - // hide elements we don't care about. - // todo: hide background - - spinner.Body.OnSkinChanged += () => hideSpinnerApproachCircle(spinner); - hideSpinnerApproachCircle(spinner); - break; - - default: - break; - } + break; } } From 2c92f1a0b70ab1ef912d148fd08ae53a3cfc4b34 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 26 Oct 2021 10:41:17 +0900 Subject: [PATCH 049/129] Use array for fixed-size list --- osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs index 5808b332b0..1b9705e8dc 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Catch.Edit private readonly List verticalPaths = new List(); - private readonly List> verticalLineVertices = new List>(); + private readonly List verticalLineVertices = new List(); [Resolved] private Playfield playfield { get; set; } @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Catch.Edit Alpha = 0.5f, }); - verticalLineVertices.Add(new List { Vector2.Zero, Vector2.Zero }); + verticalLineVertices.Add(new[] { Vector2.Zero, Vector2.Zero }); } AddRangeInternal(verticalPaths); @@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Catch.Edit float x = (float)((endTime - StartTime) * velocity); float y = hitObjectContainer.PositionAtTime(endTime, StartTime); - List lineVertices = verticalLineVertices[i]; + Vector2[] lineVertices = verticalLineVertices[i]; lineVertices[0] = new Vector2(StartX, startY); lineVertices[1] = lineVertices[0] + new Vector2(x, y); From 865be5a10b1405c185e80a9c32ca7bb2ee57bc23 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 26 Oct 2021 11:00:44 +0900 Subject: [PATCH 050/129] Fix distance snap grid rendering inverted when out of bounds --- osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs index 1b9705e8dc..db7b910f96 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; @@ -63,9 +64,11 @@ namespace osu.Game.Rulesets.Catch.Edit for (int i = 0; i < velocities.Length; i++) { double velocity = velocities[i]; + var verticalPath = verticalPaths[i]; // The line ends at the top of the screen. - double endTime = hitObjectContainer.TimeAtPosition(-hitObjectContainer.DrawHeight, hitObjectContainer.Time.Current); + double topScreenTime = hitObjectContainer.TimeAtPosition(-hitObjectContainer.DrawHeight, hitObjectContainer.Time.Current); + double endTime = Math.Max(StartTime, topScreenTime); float x = (float)((endTime - StartTime) * velocity); float y = hitObjectContainer.PositionAtTime(endTime, StartTime); @@ -74,7 +77,6 @@ namespace osu.Game.Rulesets.Catch.Edit lineVertices[0] = new Vector2(StartX, startY); lineVertices[1] = lineVertices[0] + new Vector2(x, y); - var verticalPath = verticalPaths[i]; verticalPath.Vertices = verticalLineVertices[i]; verticalPath.OriginPosition = verticalPath.PositionInBoundingBox(Vector2.Zero); } From 9f49a1df8beba494a89dd432ee19959ed04a0aae Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 26 Oct 2021 11:00:55 +0900 Subject: [PATCH 051/129] Handle the case of cursor below the start time of distance snap --- osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs index db7b910f96..667cb4a9b5 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs @@ -87,6 +87,16 @@ namespace osu.Game.Rulesets.Catch.Edit { double time = hitObjectContainer.TimeAtScreenSpacePosition(screenSpacePosition); + // If the cursor is below the distance snap grid, snap to the origin. + // Not returning `null` to retain the continuous snapping behavior when the cursor is slightly below the origin. + // This behavior is not currently visible in the editor because editor chooses the snap start time based on the mouse position. + if (time <= StartTime) + { + float y = hitObjectContainer.PositionAtTime(StartTime); + Vector2 originPosition = hitObjectContainer.ToScreenSpace(new Vector2(StartX, y)); + return new SnapResult(originPosition, StartTime); + } + return enumerateSnappingCandidates(time) .OrderBy(pos => Vector2.DistanceSquared(screenSpacePosition, pos.ScreenSpacePosition)) .FirstOrDefault(); From 068217557e686660854a78bcafbf024b3301b5f6 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 26 Oct 2021 11:12:10 +0900 Subject: [PATCH 052/129] Add doc comment on catch distance snap grid --- osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs index 667cb4a9b5..d999115d81 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs @@ -17,6 +17,10 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Edit { + /// + /// The guide lines used in the osu!catch editor to compose patterns that can be caught with constant speed. + /// Currently, only forward placement (an object is snapped based on the previous object, not the opposite) is supported. + /// public class CatchDistanceSnapGrid : CompositeDrawable { public double StartTime { get; set; } From b7a719de716f611443fed8f67e9c92a4a2fddc4c Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 26 Oct 2021 11:14:12 +0900 Subject: [PATCH 053/129] Rename method --- osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index 9b779d3370..9c67e4600b 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Catch.Edit protected override ComposeBlueprintContainer CreateBlueprintContainer() => new CatchBlueprintContainer(this); [CanBeNull] - private PalpableCatchHitObject getPreviousHitObject(double time) + private PalpableCatchHitObject getLastSnappableHitObject(double time) { var hitObject = EditorBeatmap.HitObjects.OfType().LastOrDefault(h => h.GetEndTime() < time && !(h is BananaShower)); @@ -129,7 +129,7 @@ namespace osu.Game.Rulesets.Catch.Edit return null; double minTime = EditorBeatmap.SelectedHitObjects.Min(hitObject => hitObject.StartTime); - return getPreviousHitObject(minTime); + return getLastSnappableHitObject(minTime); case FruitCompositionTool _: case JuiceStreamCompositionTool _: @@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Catch.Edit } double timeAtCursor = ((CatchPlayfield)Playfield).TimeAtScreenSpacePosition(inputManager.CurrentState.Mouse.Position); - return getPreviousHitObject(timeAtCursor); + return getLastSnappableHitObject(timeAtCursor); default: return null; From c5d765029ce2383f5d0fe22977acd617a981dcb3 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 26 Oct 2021 11:17:04 +0900 Subject: [PATCH 054/129] Don't compute source object for distance snap grid when it is not enabled --- .../Edit/CatchHitObjectComposer.cs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index 9c67e4600b..67055fb5e0 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -152,18 +152,23 @@ namespace osu.Game.Rulesets.Catch.Edit private void updateDistanceSnapGrid() { - var sourceHitObject = getDistanceSnapGridSourceHitObject(); - - if (distanceSnapToggle.Value != TernaryState.True || sourceHitObject == null) + if (distanceSnapToggle.Value != TernaryState.True) { distanceSnapGrid.Hide(); + return; } - else + + var sourceHitObject = getDistanceSnapGridSourceHitObject(); + + if (sourceHitObject == null) { - distanceSnapGrid.Show(); - distanceSnapGrid.StartTime = sourceHitObject.GetEndTime(); - distanceSnapGrid.StartX = sourceHitObject.EffectiveX; + distanceSnapGrid.Hide(); + return; } + + distanceSnapGrid.Show(); + distanceSnapGrid.StartTime = sourceHitObject.GetEndTime(); + distanceSnapGrid.StartX = sourceHitObject.EffectiveX; } } } From e7b19cb72489a32ac725ddbdfc25cfa2539056c9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 11:30:26 +0900 Subject: [PATCH 055/129] Rename test and fix incorrect layout --- .../Mods/TestSceneOsuModHidden.cs | 12 ++++++------ osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs index 1fd601cec5..71b575abe2 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs @@ -118,7 +118,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods }); [Test] - public void OuendanTwoHidden() => CreateModTest(new ModTestData + public void TestApproachCirclesOnly() => CreateModTest(new ModTestData { Mod = new OsuModHidden { OnlyFadeApproachCircles = { Value = true } }, Autoplay = true, @@ -129,22 +129,22 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods new HitCircle { StartTime = 1000, - Position = new Vector2(206,142) + Position = new Vector2(206, 142) }, new HitCircle { StartTime = 2000, - Position = new Vector2(306,142) + Position = new Vector2(306, 142) }, new Slider { StartTime = 3000, - Position = new Vector2(156,242), - Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, new Vector2(200,0), }) + Position = new Vector2(156, 242), + Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, new Vector2(200, 0), }) }, new Spinner { - Position = new Vector2(256,192), + Position = new Vector2(256, 192), StartTime = 7000, EndTime = 9000 } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index e93120b321..ed329f02b3 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -15,7 +15,6 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Skinning; - namespace osu.Game.Rulesets.Osu.Mods { public class OsuModHidden : ModHidden, IHidesApproachCircles From 0757044b1571bc5f9f2bec360296814f85a0f408 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 11:42:15 +0900 Subject: [PATCH 056/129] Refactor logic to work --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 27 ++++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index ed329f02b3..c4444bf4f8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -49,15 +49,15 @@ namespace osu.Game.Rulesets.Osu.Mods protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) { - applyHiddenState(hitObject, true, OnlyFadeApproachCircles.Value); + applyHiddenState(hitObject, true); } protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state) { - applyHiddenState(hitObject, false, OnlyFadeApproachCircles.Value); + applyHiddenState(hitObject, false); } - private void applyHiddenState(DrawableHitObject drawableObject, bool hideApproachCircle, bool hideCirclePiece) + private void applyHiddenState(DrawableHitObject drawableObject, bool increaseVisibility) { if (!(drawableObject is DrawableOsuHitObject drawableOsuObject)) return; @@ -66,6 +66,19 @@ namespace osu.Game.Rulesets.Osu.Mods (double fadeStartTime, double fadeDuration) = getFadeOutParameters(drawableOsuObject); + // process approach circle hiding first (to allow for early return below). + if (!increaseVisibility) + { + if (drawableObject is DrawableHitCircle circle) + { + using (circle.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimePreempt)) + circle.ApproachCircle.Hide(); + } + } + + if (OnlyFadeApproachCircles.Value) + return; + switch (drawableObject) { case DrawableSliderTail _: @@ -84,17 +97,11 @@ namespace osu.Game.Rulesets.Osu.Mods case DrawableHitCircle circle: Drawable fadeTarget = circle; - if (hideApproachCircle) + if (increaseVisibility) { // only fade the circle piece (not the approach circle) for the increased visibility object. fadeTarget = circle.CirclePiece; } - else - { - // we don't want to see the approach circle - using (circle.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimePreempt)) - circle.ApproachCircle.Hide(); - } using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) fadeTarget.FadeOut(fadeDuration); From 5d1170aaf4879459d027e03d15b33c4a3bf28b6f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 11:57:51 +0900 Subject: [PATCH 057/129] Remove unnecessary null check --- osu.Game/Audio/PreviewTrackManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 26787c362b..ca63add31d 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -114,7 +114,7 @@ namespace osu.Game.Audio Logger.Log($"A {nameof(PreviewTrack)} was created without a containing {nameof(IPreviewTrackOwner)}. An owner should be added for correct behaviour."); } - protected override Track GetTrack() => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineID}.mp3"); + protected override Track GetTrack() => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo.OnlineID}.mp3"); } private class PreviewTrackStore : AudioCollectionManager, ITrackStore From d7ac94038a1d01e5240e0340cf15bb6890f8a6a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 12:04:18 +0900 Subject: [PATCH 058/129] Update `GetBeatmapRequest` to use `AddParameter` --- osu.Game/Online/API/Requests/GetBeatmapRequest.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs index aa0d51641e..6cd45a41df 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.IO.Network; using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; @@ -21,6 +22,17 @@ namespace osu.Game.Online.API.Requests filename = (beatmapInfo as BeatmapInfo)?.Path ?? string.Empty; } - protected override string Target => $@"beatmaps/lookup?id={beatmapInfo.OnlineID}&checksum={beatmapInfo.MD5Hash}&filename={System.Uri.EscapeUriString(filename)}"; + protected override WebRequest CreateWebRequest() + { + var request = base.CreateWebRequest(); + + request.AddParameter(@"id", beatmapInfo.OnlineID.ToString()); + request.AddParameter(@"checksum", beatmapInfo.MD5Hash); + request.AddParameter(@"filename", filename); + + return request; + } + + protected override string Target => @"beatmaps/lookup"; } } From 8b85c78b0defe810b34a324f5a0c6b85bb35e18f Mon Sep 17 00:00:00 2001 From: Roxie Wattz Date: Mon, 25 Oct 2021 20:16:45 -0700 Subject: [PATCH 059/129] Add processing of Spinner approach circles --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index c4444bf4f8..e5cc08c886 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -74,6 +74,11 @@ namespace osu.Game.Rulesets.Osu.Mods using (circle.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimePreempt)) circle.ApproachCircle.Hide(); } + else if (drawableObject is DrawableSpinner spinner) + { + spinner.Body.OnSkinChanged += () => hideSpinnerApproachCircle(spinner); + hideSpinnerApproachCircle(spinner); + } } if (OnlyFadeApproachCircles.Value) @@ -123,9 +128,6 @@ namespace osu.Game.Rulesets.Osu.Mods // hide elements we don't care about. // todo: hide background - spinner.Body.OnSkinChanged += () => hideSpinnerApproachCircle(spinner); - hideSpinnerApproachCircle(spinner); - using (spinner.BeginAbsoluteSequence(fadeStartTime)) spinner.FadeOut(fadeDuration); From a582976851306ea1f567768381b70df8e26fc9e3 Mon Sep 17 00:00:00 2001 From: Jason Won Date: Tue, 26 Oct 2021 00:05:46 -0400 Subject: [PATCH 060/129] reversing slider maintains shape --- osu.Game/Rulesets/Objects/SliderPathExtensions.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/SliderPathExtensions.cs b/osu.Game/Rulesets/Objects/SliderPathExtensions.cs index 663746bfca..052fc7c775 100644 --- a/osu.Game/Rulesets/Objects/SliderPathExtensions.cs +++ b/osu.Game/Rulesets/Objects/SliderPathExtensions.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Objects public static void Reverse(this SliderPath sliderPath, out Vector2 positionalOffset) { var points = sliderPath.ControlPoints.ToArray(); - positionalOffset = points.Last().Position; + positionalOffset = sliderPath.PositionAt(1); sliderPath.ControlPoints.Clear(); @@ -32,7 +32,10 @@ namespace osu.Game.Rulesets.Objects // propagate types forwards to last null type if (i == points.Length - 1) + { p.Type = lastType; + p.Position = Vector2.Zero; + } else if (p.Type != null) (p.Type, lastType) = (lastType, p.Type); From 6c38028d068e796fbeeda82587c22d9a7da4c6c2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 13:55:02 +0900 Subject: [PATCH 061/129] Fix gameplay chat display not losing focus on escape key press Closes #15293. --- .../Multiplayer/TestSceneGameplayChatDisplay.cs | 12 ++++++++++++ .../OnlinePlay/Multiplayer/GameplayChatDisplay.cs | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs index a3a1cacb0d..512d206a06 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs @@ -92,6 +92,18 @@ namespace osu.Game.Tests.Visual.Multiplayer assertChatFocused(true); } + [Test] + public void TestFocusLostOnBackKey() + { + setLocalUserPlaying(true); + + assertChatFocused(false); + AddStep("press tab", () => InputManager.Key(Key.Tab)); + assertChatFocused(true); + AddStep("press escape", () => InputManager.Key(Key.Escape)); + assertChatFocused(false); + } + [Test] public void TestFocusOnTabKeyWhenNotExpanded() { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs index af0c50a848..ff24035d0e 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs @@ -10,6 +10,7 @@ using osu.Game.Input.Bindings; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Match.Components; using osu.Game.Screens.Play; +using osuTK.Input; namespace osu.Game.Screens.OnlinePlay.Multiplayer { @@ -75,6 +76,15 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { switch (e.Action) { + case GlobalAction.Back: + if (Textbox.HasFocus) + { + Schedule(() => Textbox.KillFocus()); + return true; + } + + break; + case GlobalAction.ToggleChatFocus: if (Textbox.HasFocus) { From 26fb9af0218fadff0bfebfa2985525db253cb236 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 13:58:07 +0900 Subject: [PATCH 062/129] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index f552aff2f2..9e0d31e7e5 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 32d6eeab29..a9555b555e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 92abab036a..1669573c26 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From 370775af68ec8cdab445182c2b8d457c1f932eef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 14:05:07 +0900 Subject: [PATCH 063/129] Fix some surrounding code formatting --- osu.Game/Database/ArchiveModelManager.cs | 6 ++--- osu.Game/Graphics/ScreenshotManager.cs | 34 +++++++++++++----------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index a0ca23eaec..f3ed2d735b 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -462,10 +462,10 @@ namespace osu.Game.Database if (retrievedItem == null) throw new ArgumentException(@"Specified model could not be found", nameof(item)); - var filename = $"{getValidFilename(item.ToString())}{HandledExtensions.First()}"; + string filename = $"{getValidFilename(item.ToString())}{HandledExtensions.First()}"; - using (var outputStream = exportStorage.GetStream(filename, FileAccess.Write, FileMode.Create)) - ExportModelTo(retrievedItem, outputStream); + using (var stream = exportStorage.GetStream(filename, FileAccess.Write, FileMode.Create)) + ExportModelTo(retrievedItem, stream); exportStorage.PresentFileExternally(filename); } diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index c21986f6c4..e652f07239 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -109,40 +109,42 @@ namespace osu.Game.Graphics if (Interlocked.Decrement(ref screenShotTasks) == 0 && cursorVisibility.Value == false) cursorVisibility.Value = true; - var fileName = getFileName(); - if (fileName == null) return; + string filename = getFilename(); - var stream = storage.GetStream(fileName, FileAccess.Write); + if (filename == null) return; - switch (screenshotFormat.Value) + using (var stream = storage.GetStream(filename, FileAccess.Write)) { - case ScreenshotFormat.Png: - await image.SaveAsPngAsync(stream).ConfigureAwait(false); - break; + switch (screenshotFormat.Value) + { + case ScreenshotFormat.Png: + await image.SaveAsPngAsync(stream).ConfigureAwait(false); + break; - case ScreenshotFormat.Jpg: - const int jpeg_quality = 92; + case ScreenshotFormat.Jpg: + const int jpeg_quality = 92; - await image.SaveAsJpegAsync(stream, new JpegEncoder { Quality = jpeg_quality }).ConfigureAwait(false); - break; + await image.SaveAsJpegAsync(stream, new JpegEncoder { Quality = jpeg_quality }).ConfigureAwait(false); + break; - default: - throw new InvalidOperationException($"Unknown enum member {nameof(ScreenshotFormat)} {screenshotFormat.Value}."); + default: + throw new InvalidOperationException($"Unknown enum member {nameof(ScreenshotFormat)} {screenshotFormat.Value}."); + } } notificationOverlay.Post(new SimpleNotification { - Text = $"{fileName} saved!", + Text = $"{filename} saved!", Activated = () => { - storage.PresentFileExternally(fileName); + storage.PresentFileExternally(filename); return true; } }); } }); - private string getFileName() + private string getFilename() { var dt = DateTime.Now; var fileExt = screenshotFormat.ToString().ToLowerInvariant(); From de7a908be29e2dfb6dbddc3837f894467e07233d Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 26 Oct 2021 14:51:52 +0900 Subject: [PATCH 064/129] Cut distance snap lines at playfield border in catch editor --- .../Edit/CatchDistanceSnapGrid.cs | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs index d999115d81..137ac1fc59 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Lines; using osu.Framework.Graphics.Primitives; +using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; @@ -27,6 +28,8 @@ namespace osu.Game.Rulesets.Catch.Edit public float StartX { get; set; } + private const double max_vertical_line_length_in_time = CatchPlayfield.WIDTH / Catcher.BASE_SPEED * 2; + private readonly double[] velocities; private readonly List verticalPaths = new List(); @@ -63,27 +66,42 @@ namespace osu.Game.Rulesets.Catch.Edit { base.Update(); - float startY = hitObjectContainer.PositionAtTime(StartTime); + double currentTime = hitObjectContainer.Time.Current; for (int i = 0; i < velocities.Length; i++) { double velocity = velocities[i]; - var verticalPath = verticalPaths[i]; - // The line ends at the top of the screen. - double topScreenTime = hitObjectContainer.TimeAtPosition(-hitObjectContainer.DrawHeight, hitObjectContainer.Time.Current); - double endTime = Math.Max(StartTime, topScreenTime); + // The line ends at the top of the playfield. + double endTime = hitObjectContainer.TimeAtPosition(-hitObjectContainer.DrawHeight, currentTime); - float x = (float)((endTime - StartTime) * velocity); - float y = hitObjectContainer.PositionAtTime(endTime, StartTime); + // Non-vertical lines are cut at the sides of the playfield. + // Vertical lines are cut at some reasonable length. + if (velocity > 0) + endTime = Math.Min(endTime, StartTime + (CatchPlayfield.WIDTH - StartX) / velocity); + else if (velocity < 0) + endTime = Math.Min(endTime, StartTime + StartX / -velocity); + else + endTime = Math.Min(endTime, StartTime + max_vertical_line_length_in_time); Vector2[] lineVertices = verticalLineVertices[i]; - lineVertices[0] = new Vector2(StartX, startY); - lineVertices[1] = lineVertices[0] + new Vector2(x, y); + lineVertices[0] = calculatePosition(velocity, StartTime); + lineVertices[1] = calculatePosition(velocity, endTime); + var verticalPath = verticalPaths[i]; verticalPath.Vertices = verticalLineVertices[i]; verticalPath.OriginPosition = verticalPath.PositionInBoundingBox(Vector2.Zero); } + + Vector2 calculatePosition(double velocity, double time) + { + // Don't draw inverted lines. + time = Math.Max(time, StartTime); + + float x = StartX + (float)((time - StartTime) * velocity); + float y = hitObjectContainer.PositionAtTime(time, currentTime); + return new Vector2(x, y); + } } [CanBeNull] From 81fee02c2bc90553093304cfc938abd883faad45 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 15:46:15 +0900 Subject: [PATCH 065/129] Fix slider paths being extended even when the last two points are equal --- osu.Game/Rulesets/Objects/SliderPath.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 9cc215589b..0dec0655b9 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -280,6 +280,13 @@ namespace osu.Game.Rulesets.Objects if (ExpectedDistance.Value is double expectedDistance && calculatedLength != expectedDistance) { + // In osu-stable, if the last two control points of a slider are equal, extension is not performed. + if (ControlPoints.Count >= 2 && ControlPoints[^1].Position == ControlPoints[^2].Position && expectedDistance > calculatedLength) + { + cumulativeLength.Add(calculatedLength); + return; + } + // The last length is always incorrect cumulativeLength.RemoveAt(cumulativeLength.Count - 1); From b259192a8aac895db3f2f1b2c1f6c21ca3ebb485 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 16:06:02 +0900 Subject: [PATCH 066/129] Add failing test coverage showing hitobject local control points are defaults --- osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs index ab2bc4649a..af3d9beb69 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs @@ -56,6 +56,11 @@ namespace osu.Game.Tests.Visual.Editing checkMutations(); + // After placement these must be non-default as defaults are read-only. + AddAssert("Placed object has non-default control points", () => + editorBeatmap.HitObjects[0].SampleControlPoint != SampleControlPoint.DEFAULT && + editorBeatmap.HitObjects[0].DifficultyControlPoint != DifficultyControlPoint.DEFAULT); + AddStep("Save", () => InputManager.Keys(PlatformAction.Save)); checkMutations(); From dae7cdc4c50efeaec5d2fab48d10e25360f7f669 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 15:59:48 +0900 Subject: [PATCH 067/129] Ensure `HitObject`-local control points are non-default after `ApplyDefaults` We will probably want to make this whole flow more efficient in the future, but this should suffice for now. --- osu.Game/Rulesets/Objects/HitObject.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 035ebe10cb..a80b3d0fa5 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -119,6 +119,8 @@ namespace osu.Game.Rulesets.Objects DifficultyControlPoint = (DifficultyControlPoint)legacyInfo.DifficultyPointAt(StartTime).DeepClone(); DifficultyControlPoint.Time = StartTime; } + else if (DifficultyControlPoint == DifficultyControlPoint.DEFAULT) + DifficultyControlPoint = new DifficultyControlPoint(); ApplyDefaultsToSelf(controlPointInfo, difficulty); @@ -128,6 +130,8 @@ namespace osu.Game.Rulesets.Objects SampleControlPoint = (SampleControlPoint)legacyInfo.SamplePointAt(this.GetEndTime() + control_point_leniency).DeepClone(); SampleControlPoint.Time = this.GetEndTime() + control_point_leniency; } + else if (SampleControlPoint == SampleControlPoint.DEFAULT) + SampleControlPoint = new SampleControlPoint(); nestedHitObjects.Clear(); From ea55ba7ba9f4526129e37c484773d7a64c8568eb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 16:08:21 +0900 Subject: [PATCH 068/129] Remove unused using statement --- osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs index ff24035d0e..0e73f65f8b 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs @@ -10,7 +10,6 @@ using osu.Game.Input.Bindings; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Match.Components; using osu.Game.Screens.Play; -using osuTK.Input; namespace osu.Game.Screens.OnlinePlay.Multiplayer { From e92def0ba28ef701f576d83e1cf8cd32ee34319f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 17:19:29 +0900 Subject: [PATCH 069/129] Fix `LegacyBeatmapEncoder` using incorrect path length value --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 1dc270ee63..7cd4244cd0 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -460,7 +460,7 @@ namespace osu.Game.Beatmaps.Formats var curveData = pathData as IHasPathWithRepeats; writer.Write(FormattableString.Invariant($"{(curveData?.RepeatCount ?? 0) + 1},")); - writer.Write(FormattableString.Invariant($"{pathData.Path.Distance},")); + writer.Write(FormattableString.Invariant($"{pathData.Path.ExpectedDistance.Value ?? pathData.Path.Distance},")); if (curveData != null) { From aa0762ebe20a1153dfdbadc50f517ac5642ac995 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 17:35:03 +0900 Subject: [PATCH 070/129] Add test coverage for failing slider case --- .../Formats/LegacyBeatmapDecoderTest.cs | 17 +++++++++++++++++ .../duplicate-last-position-slider.osu | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 osu.Game.Tests/Resources/duplicate-last-position-slider.osu diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index cb12d03620..d37e09aa29 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -775,5 +775,22 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.That(seventh.ControlPoints[4].Type == null); } } + + [Test] + public void TestSliderLengthExtensionEdgeCase() + { + var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + + using (var resStream = TestResources.OpenResource("duplicate-last-position-slider.osu")) + using (var stream = new LineBufferedReader(resStream)) + { + var decoded = decoder.Decode(stream); + + var path = ((IHasPath)decoded.HitObjects[0]).Path; + + Assert.That(path.ExpectedDistance.Value, Is.EqualTo(2)); + Assert.That(path.Distance, Is.EqualTo(1)); + } + } } } diff --git a/osu.Game.Tests/Resources/duplicate-last-position-slider.osu b/osu.Game.Tests/Resources/duplicate-last-position-slider.osu new file mode 100644 index 0000000000..782dd4263e --- /dev/null +++ b/osu.Game.Tests/Resources/duplicate-last-position-slider.osu @@ -0,0 +1,19 @@ +osu file format v14 + +[Difficulty] +HPDrainRate:7 +CircleSize:10 +OverallDifficulty:9 +ApproachRate:10 +SliderMultiplier:0.4 +SliderTickRate:1 + +[TimingPoints] +382,923.076923076923,3,2,1,75,1,0 +382,-1000,3,2,1,75,0,0 + +[HitObjects] + +// Importantly, the last position is specified twice. +// In this case, osu-stable doesn't extend the slider length even when the "expected" length is higher than the actual. +261,171,25305,6,0,B|262:171|262:171|262:171,1,2,8|0,0:0|0:0,0:0:0:0: From 708d40931b8009d3c036df32ad0487ab43abc6f1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 16:36:54 +0900 Subject: [PATCH 071/129] Add back remaining attempt display on playlist room screen --- .../Playlists/PlaylistsRoomSubScreen.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index d5e423a438..5f2e444165 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -153,6 +153,22 @@ namespace osu.Game.Screens.OnlinePlay.Playlists }, }, new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Alpha = Room.MaxAttempts.Value != null ? 1 : 0, + Margin = new MarginPadding { Bottom = 10 }, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new OverlinedHeader("Progress"), + new RoomLocalUserInfo(), + } + }, + }, + new Drawable[] { new OverlinedHeader("Leaderboard") }, @@ -162,6 +178,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists }, RowDimensions = new[] { + new Dimension(GridSizeMode.AutoSize), new Dimension(GridSizeMode.AutoSize), new Dimension(GridSizeMode.AutoSize), new Dimension(), From bffd9162ba15055260021053a2bcfc5b23f13fd2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 16:40:45 +0900 Subject: [PATCH 072/129] Tint attempt count red when no attempts remain --- osu.Game/Screens/OnlinePlay/Components/RoomLocalUserInfo.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomLocalUserInfo.cs b/osu.Game/Screens/OnlinePlay/Components/RoomLocalUserInfo.cs index 1fcf7f2277..3bad6cb183 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomLocalUserInfo.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomLocalUserInfo.cs @@ -14,6 +14,9 @@ namespace osu.Game.Screens.OnlinePlay.Components { private OsuSpriteText attemptDisplay; + [Resolved] + private OsuColour colours { get; set; } + public RoomLocalUserInfo() { AutoSizeAxes = Axes.Both; @@ -54,6 +57,9 @@ namespace osu.Game.Screens.OnlinePlay.Components { int remaining = MaxAttempts.Value.Value - UserScore.Value.PlaylistItemAttempts.Sum(a => a.Attempts); attemptDisplay.Text += $" ({remaining} remaining)"; + + if (remaining == 0) + attemptDisplay.Colour = colours.RedLight; } } else From 1c578f285accf3f17168708ba5c6aa1fd402f6ec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 16:54:55 +0900 Subject: [PATCH 073/129] Disable playlist start button when attempts have been exhausted --- .../Playlists/PlaylistsReadyButton.cs | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs index 9ac1fe1722..ea85a8bcc1 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs @@ -32,11 +32,32 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Triangles.ColourLight = colours.GreenLight; } + private bool hasRemainingAttempts = true; + + protected override void LoadComplete() + { + base.LoadComplete(); + + userScore.BindValueChanged(aggregate => + { + if (maxAttempts.Value == null) + return; + + int remaining = maxAttempts.Value.Value - aggregate.NewValue.PlaylistItemAttempts.Sum(a => a.Attempts); + + hasRemainingAttempts = remaining > 0; + }); + } + protected override void Update() { base.Update(); - Enabled.Value = endDate.Value != null && DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(gameBeatmap.Value.Track.Length) < endDate.Value; + Enabled.Value = hasRemainingAttempts && enoughTimeLeft; } + + private bool enoughTimeLeft => + // This should probably consider the length of the currently selected item, rather than a constant 30 seconds. + endDate.Value != null && DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(gameBeatmap.Value.Track.Length) < endDate.Value; } } From 42d8d4fd380bcdc2fdd4a7b96178b7f4a551386f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 16:55:24 +0900 Subject: [PATCH 074/129] Add tooltips to start button to explain why it's not clickable --- .../OnlinePlay/Components/ReadyButton.cs | 18 +++++++++++-- .../Playlists/PlaylistsReadyButton.cs | 25 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs index 8f85608b29..5a4a0a0fba 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs @@ -3,13 +3,15 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Localisation; using osu.Game.Graphics.UserInterface; using osu.Game.Online; using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Components { - public abstract class ReadyButton : TriangleButton + public abstract class ReadyButton : TriangleButton, IHasTooltip { public new readonly BindableBool Enabled = new BindableBool(); @@ -24,6 +26,18 @@ namespace osu.Game.Screens.OnlinePlay.Components Enabled.BindValueChanged(_ => updateState(), true); } - private void updateState() => base.Enabled.Value = availability.Value.State == DownloadState.LocallyAvailable && Enabled.Value; + private void updateState() => + base.Enabled.Value = availability.Value.State == DownloadState.LocallyAvailable && Enabled.Value; + + public virtual LocalisableString TooltipText + { + get + { + if (Enabled.Value) + return string.Empty; + + return "Beatmap not downloaded"; + } + } } } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs index ea85a8bcc1..24f112ef0c 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs @@ -2,8 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Online.Rooms; @@ -16,6 +18,12 @@ namespace osu.Game.Screens.OnlinePlay.Playlists [Resolved(typeof(Room), nameof(Room.EndDate))] private Bindable endDate { get; set; } + [Resolved(typeof(Room), nameof(Room.MaxAttempts))] + private Bindable maxAttempts { get; set; } + + [Resolved(typeof(Room), nameof(Room.UserScore))] + private Bindable userScore { get; set; } + [Resolved] private IBindable gameBeatmap { get; set; } @@ -56,6 +64,23 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Enabled.Value = hasRemainingAttempts && enoughTimeLeft; } + public override LocalisableString TooltipText + { + get + { + if (Enabled.Value) + return string.Empty; + + if (!enoughTimeLeft) + return "No time left!"; + + if (!hasRemainingAttempts) + return "Attempts exhausted!"; + + return base.TooltipText; + } + } + private bool enoughTimeLeft => // This should probably consider the length of the currently selected item, rather than a constant 30 seconds. endDate.Value != null && DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(gameBeatmap.Value.Track.Length) < endDate.Value; From c15bfb2cf44d569062961a7ed59aee738b7684bc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 18:13:28 +0900 Subject: [PATCH 075/129] Handle bindable changes to fix new playlist creation not showing correct details --- .../OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 5f2e444165..6d2a426e70 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -37,6 +37,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists private MatchLeaderboard leaderboard; private SelectionPollingComponent selectionPollingComponent; + private FillFlowContainer progressSection; + public PlaylistsRoomSubScreen(Room room) : base(room, false) // Editing is temporarily not allowed. { @@ -67,6 +69,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Schedule(() => SelectedItem.Value = Room.Playlist.FirstOrDefault()); } }, true); + + Room.MaxAttempts.BindValueChanged(attempts => progressSection.Alpha = Room.MaxAttempts.Value != null ? 1 : 0, true); } protected override Drawable CreateMainContent() => new GridContainer @@ -154,11 +158,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists }, new Drawable[] { - new FillFlowContainer + progressSection = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Alpha = Room.MaxAttempts.Value != null ? 1 : 0, + Alpha = 0, Margin = new MarginPadding { Bottom = 10 }, Direction = FillDirection.Vertical, Children = new Drawable[] From 1147c6cbfc60584536237a15459b101c248a3e3c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Oct 2021 19:56:54 +0900 Subject: [PATCH 076/129] Remove unnecessary default value --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index e5cc08c886..e162f805a1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Mods public class OsuModHidden : ModHidden, IHidesApproachCircles { [SettingSource("Only fade approach circles", "The main object body will not fade when enabled.")] - public Bindable OnlyFadeApproachCircles { get; } = new BindableBool(false); + public Bindable OnlyFadeApproachCircles { get; } = new BindableBool(); public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; From e5050b90a56a08bffbacb951d91cd83a4a30fba0 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 26 Oct 2021 20:09:48 +0900 Subject: [PATCH 077/129] Don't assume catcher dash speed is 2x the walk speed --- .../Beatmaps/CatchBeatmapProcessor.cs | 2 +- .../Edit/CatchHitObjectComposer.cs | 4 ++-- .../Replays/CatchAutoGenerator.cs | 11 ++++------- osu.Game.Rulesets.Catch/UI/Catcher.cs | 15 ++++++++++----- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 87cc2c45e8..346a09cac8 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -233,7 +233,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps int thisDirection = nextObject.EffectiveX > currentObject.EffectiveX ? 1 : -1; double timeToNext = nextObject.StartTime - currentObject.StartTime - 1000f / 60f / 4; // 1/4th of a frame of grace time, taken from osu-stable double distanceToNext = Math.Abs(nextObject.EffectiveX - currentObject.EffectiveX) - (lastDirection == thisDirection ? lastExcess : halfCatcherWidth); - float distanceToHyper = (float)(timeToNext * Catcher.BASE_SPEED - distanceToNext); + float distanceToHyper = (float)(timeToNext * Catcher.BASE_DASH_SPEED - distanceToNext); if (distanceToHyper < 0) { diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index 67055fb5e0..164f465438 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -51,8 +51,8 @@ namespace osu.Game.Rulesets.Catch.Edit LayerBelowRuleset.Add(distanceSnapGrid = new CatchDistanceSnapGrid(new[] { 0.0, - Catcher.BASE_SPEED, -Catcher.BASE_SPEED, - Catcher.BASE_SPEED / 2, -Catcher.BASE_SPEED / 2, + Catcher.BASE_DASH_SPEED, -Catcher.BASE_DASH_SPEED, + Catcher.BASE_WALK_SPEED, -Catcher.BASE_WALK_SPEED, })); } diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index 2fc05701db..7c84cb24f3 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -26,9 +26,6 @@ namespace osu.Game.Rulesets.Catch.Replays if (Beatmap.HitObjects.Count == 0) return; - // todo: add support for HT DT - const double dash_speed = Catcher.BASE_SPEED; - const double movement_speed = dash_speed / 2; float lastPosition = CatchPlayfield.CENTER_X; double lastTime = 0; @@ -47,8 +44,8 @@ namespace osu.Game.Rulesets.Catch.Replays // The case where positionChange > 0 and timeAvailable == 0 results in PositiveInfinity which provides expected beheaviour. double speedRequired = positionChange == 0 ? 0 : positionChange / timeAvailable; - bool dashRequired = speedRequired > movement_speed; - bool impossibleJump = speedRequired > movement_speed * 2; + bool dashRequired = speedRequired > Catcher.BASE_WALK_SPEED; + bool impossibleJump = speedRequired > Catcher.BASE_DASH_SPEED; // todo: get correct catcher size, based on difficulty CS. const float catcher_width_half = Catcher.BASE_SIZE * 0.3f * 0.5f; @@ -73,7 +70,7 @@ namespace osu.Game.Rulesets.Catch.Replays else if (dashRequired) { // we do a movement in two parts - the dash part then the normal part... - double timeAtNormalSpeed = positionChange / movement_speed; + double timeAtNormalSpeed = positionChange / Catcher.BASE_WALK_SPEED; double timeWeNeedToSave = timeAtNormalSpeed - timeAvailable; double timeAtDashSpeed = timeWeNeedToSave / 2; @@ -86,7 +83,7 @@ namespace osu.Game.Rulesets.Catch.Replays } else { - double timeBefore = positionChange / movement_speed; + double timeBefore = positionChange / Catcher.BASE_WALK_SPEED; addFrame(h.StartTime - timeBefore, lastPosition); addFrame(h.StartTime, h.EffectiveX); diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 3745099010..a70dbcf25e 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -57,14 +57,19 @@ namespace osu.Game.Rulesets.Catch.UI public bool CatchFruitOnPlate { get; set; } = true; /// - /// The relative space to cover in 1 millisecond. based on 1 game pixel per millisecond as in osu-stable. + /// The speed of the catcher when the catcher is dashing. /// - public const double BASE_SPEED = 1.0; + public const double BASE_DASH_SPEED = 1.0; /// - /// The current speed of the catcher. + /// The speed of the catcher when the catcher is not dashing. /// - public double Speed => (Dashing ? 1 : 0.5) * BASE_SPEED * hyperDashModifier; + public const double BASE_WALK_SPEED = 0.5; + + /// + /// The current speed of the catcher with the hyper-dash modifier applied. + /// + public double Speed => (Dashing ? BASE_DASH_SPEED : BASE_WALK_SPEED) * hyperDashModifier; /// /// The amount by which caught fruit should be scaled down to fit on the plate. @@ -230,7 +235,7 @@ namespace osu.Game.Rulesets.Catch.UI double positionDifference = target.EffectiveX - X; var velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); - SetHyperDashState(Math.Abs(velocity), target.EffectiveX); + SetHyperDashState(Math.Abs(velocity) / BASE_DASH_SPEED, target.EffectiveX); } else SetHyperDashState(); From 393d118eef783c14f5534710bdc7fbf99c971c76 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 26 Oct 2021 20:20:43 +0900 Subject: [PATCH 078/129] Fix compilation failure overlooked in merge --- osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs index 137ac1fc59..9a78c7ff86 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Edit public float StartX { get; set; } - private const double max_vertical_line_length_in_time = CatchPlayfield.WIDTH / Catcher.BASE_SPEED * 2; + private const double max_vertical_line_length_in_time = CatchPlayfield.WIDTH / Catcher.BASE_WALK_SPEED; private readonly double[] velocities; From 411586bac36ae84807ab3f8076b280c5a0b8dcbc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 22:12:56 +0900 Subject: [PATCH 079/129] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 9e0d31e7e5..552675d706 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -51,7 +51,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a9555b555e..8ba6e41d53 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 1669573c26..e55dbb3bfe 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -71,7 +71,7 @@ - + From 670fcea68d07b2f89ae2a70414ba6d960fca1228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 26 Oct 2021 18:56:34 +0200 Subject: [PATCH 080/129] Rename some variables --- osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs b/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs index 026bb6c1cb..10de06a550 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.Mods private IBindable isBreakTime; private PeriodTracker spinnerPeriods; - private float targetAlpha; + private float comboBasedAlpha; [SettingSource( "Hidden at combo", @@ -76,15 +76,15 @@ namespace osu.Game.Rulesets.Osu.Mods currentCombo = scoreProcessor.Combo.GetBoundCopy(); currentCombo.BindValueChanged(combo => { - targetAlpha = Math.Max(min_alpha, 1 - (float)combo.NewValue / HiddenComboCount.Value); + comboBasedAlpha = Math.Max(min_alpha, 1 - (float)combo.NewValue / HiddenComboCount.Value); }, true); } public virtual void Update(Playfield playfield) { - var overrideAlpha = isBreakTime.Value || spinnerPeriods.IsInAny(playfield.Clock.CurrentTime); - var targetOverriddenAlpha = overrideAlpha ? 1 : targetAlpha; - playfield.Cursor.Alpha = (float)Interpolation.Lerp(playfield.Cursor.Alpha, targetOverriddenAlpha, Math.Clamp(playfield.Time.Elapsed / transition_duration, 0, 1)); + var shouldAlwaysShowCursor = isBreakTime.Value || spinnerPeriods.IsInAny(playfield.Clock.CurrentTime); + var targetAlpha = shouldAlwaysShowCursor ? 1 : comboBasedAlpha; + playfield.Cursor.Alpha = (float)Interpolation.Lerp(playfield.Cursor.Alpha, targetAlpha, Math.Clamp(playfield.Time.Elapsed / transition_duration, 0, 1)); } } From 1a77e98537b30269e32472edd3aa504034a541eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 17 Oct 2021 15:52:40 +0200 Subject: [PATCH 081/129] Implement difficulty spectrum display --- .../TestSceneDifficultySpectrumDisplay.cs | 84 +++++++++++++ .../Drawables/DifficultySpectrumDisplay.cs | 114 ++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs create mode 100644 osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs new file mode 100644 index 0000000000..8925c68ef4 --- /dev/null +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs @@ -0,0 +1,84 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; +using osu.Game.Online.API.Requests.Responses; +using osuTK; + +namespace osu.Game.Tests.Visual.Beatmaps +{ + public class TestSceneDifficultySpectrumDisplay : OsuTestScene + { + private static APIBeatmapSet createBeatmapSetWith(params (int rulesetId, double stars)[] difficulties) => new APIBeatmapSet + { + Beatmaps = difficulties.Select(difficulty => new APIBeatmap + { + RulesetID = difficulty.rulesetId, + StarRating = difficulty.stars + }).ToList() + }; + + [Test] + public void TestSingleRuleset() + { + var beatmapSet = createBeatmapSetWith( + (rulesetId: 0, stars: 2.0), + (rulesetId: 0, stars: 3.2), + (rulesetId: 0, stars: 5.6)); + + createDisplay(beatmapSet); + } + + [Test] + public void TestMultipleRulesets() + { + var beatmapSet = createBeatmapSetWith( + (rulesetId: 0, stars: 2.0), + (rulesetId: 3, stars: 2.3), + (rulesetId: 0, stars: 3.2), + (rulesetId: 1, stars: 4.3), + (rulesetId: 0, stars: 5.6)); + + createDisplay(beatmapSet); + } + + [Test] + public void TestUnknownRuleset() + { + var beatmapSet = createBeatmapSetWith( + (rulesetId: 0, stars: 2.0), + (rulesetId: 3, stars: 2.3), + (rulesetId: 0, stars: 3.2), + (rulesetId: 1, stars: 4.3), + (rulesetId: 0, stars: 5.6), + (rulesetId: 15, stars: 7.8)); + + createDisplay(beatmapSet); + } + + [Test] + public void TestMaximumUncollapsed() + { + var beatmapSet = createBeatmapSetWith(Enumerable.Range(0, 12).Select(i => (rulesetId: i % 4, stars: 2.5 + i * 0.25)).ToArray()); + createDisplay(beatmapSet); + } + + [Test] + public void TestMinimumCollapsed() + { + var beatmapSet = createBeatmapSetWith(Enumerable.Range(0, 13).Select(i => (rulesetId: i % 4, stars: 2.5 + i * 0.25)).ToArray()); + createDisplay(beatmapSet); + } + + private void createDisplay(IBeatmapSetInfo beatmapSetInfo) => AddStep("create spectrum display", () => Child = new DifficultySpectrumDisplay(beatmapSetInfo) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(3) + }); + } +} diff --git a/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs new file mode 100644 index 0000000000..a773f6b12c --- /dev/null +++ b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs @@ -0,0 +1,114 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets; +using osuTK; + +namespace osu.Game.Beatmaps.Drawables +{ + public class DifficultySpectrumDisplay : CompositeDrawable + { + public DifficultySpectrumDisplay(IBeatmapSetInfo beatmapSet) + { + AutoSizeAxes = Axes.Both; + + FillFlowContainer flow; + + InternalChild = flow = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(10, 0), + Direction = FillDirection.Horizontal, + }; + + // matching web: https://github.com/ppy/osu-web/blob/d06d8c5e735eb1f48799b1654b528e9a7afb0a35/resources/assets/lib/beatmapset-panel.tsx#L127 + bool collapsed = beatmapSet.Beatmaps.Count() > 12; + + foreach (var rulesetGrouping in beatmapSet.Beatmaps.GroupBy(beatmap => beatmap.Ruleset.OnlineID)) + { + flow.Add(new RulesetDifficultyGroup(rulesetGrouping.Key, rulesetGrouping, collapsed)); + } + } + + private class RulesetDifficultyGroup : FillFlowContainer + { + private readonly int rulesetId; + private readonly IEnumerable beatmapInfos; + private readonly bool collapsed; + + public RulesetDifficultyGroup(int rulesetId, IEnumerable beatmapInfos, bool collapsed) + { + this.rulesetId = rulesetId; + this.beatmapInfos = beatmapInfos; + this.collapsed = collapsed; + } + + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) + { + AutoSizeAxes = Axes.Both; + Spacing = new Vector2(1, 0); + Direction = FillDirection.Horizontal; + + var icon = rulesets.GetRuleset(rulesetId)?.CreateInstance()?.CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle }; + Add(icon.With(i => + { + i.Size = new Vector2(14); + i.Anchor = i.Origin = Anchor.Centre; + })); + + if (!collapsed) + { + foreach (var beatmapInfo in beatmapInfos.OrderBy(bi => bi.StarRating)) + Add(new DifficultyDot(beatmapInfo.StarRating)); + } + else + { + Add(new OsuSpriteText + { + Text = beatmapInfos.Count().ToLocalisableString(@"N0"), + Font = OsuFont.Default.With(size: 12), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Padding = new MarginPadding { Bottom = 1 } + }); + } + } + } + + private class DifficultyDot : CircularContainer + { + private readonly double starDifficulty; + + public DifficultyDot(double starDifficulty) + { + this.starDifficulty = starDifficulty; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Width = 4; + Height = 8; + Anchor = Origin = Anchor.Centre; + Masking = true; + + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.ForStarDifficulty(starDifficulty) + }; + } + } + } +} From 3de994449df8831228ff1b0ed096b948732baf04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 17 Oct 2021 16:05:55 +0200 Subject: [PATCH 082/129] Add support for changing dimensions of difficulty spectrum display --- .../TestSceneDifficultySpectrumDisplay.cs | 28 ++++++++- .../Drawables/DifficultySpectrumDisplay.cs | 63 +++++++++++++++++-- 2 files changed, 86 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs index 8925c68ef4..1f38b05879 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs @@ -13,6 +13,8 @@ namespace osu.Game.Tests.Visual.Beatmaps { public class TestSceneDifficultySpectrumDisplay : OsuTestScene { + private DifficultySpectrumDisplay display; + private static APIBeatmapSet createBeatmapSetWith(params (int rulesetId, double stars)[] difficulties) => new APIBeatmapSet { Beatmaps = difficulties.Select(difficulty => new APIBeatmap @@ -74,7 +76,31 @@ namespace osu.Game.Tests.Visual.Beatmaps createDisplay(beatmapSet); } - private void createDisplay(IBeatmapSetInfo beatmapSetInfo) => AddStep("create spectrum display", () => Child = new DifficultySpectrumDisplay(beatmapSetInfo) + [Test] + public void TestAdjustableDotSize() + { + var beatmapSet = createBeatmapSetWith( + (rulesetId: 0, stars: 2.0), + (rulesetId: 3, stars: 2.3), + (rulesetId: 0, stars: 3.2), + (rulesetId: 1, stars: 4.3), + (rulesetId: 0, stars: 5.6)); + + createDisplay(beatmapSet); + + AddStep("change dot dimensions", () => + { + display.DotSize = new Vector2(8, 12); + display.DotSpacing = 2; + }); + AddStep("change dot dimensions back", () => + { + display.DotSize = new Vector2(4, 8); + display.DotSpacing = 1; + }); + } + + private void createDisplay(IBeatmapSetInfo beatmapSetInfo) => AddStep("create spectrum display", () => Child = display = new DifficultySpectrumDisplay(beatmapSetInfo) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs index a773f6b12c..1feaa88350 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs @@ -18,12 +18,40 @@ namespace osu.Game.Beatmaps.Drawables { public class DifficultySpectrumDisplay : CompositeDrawable { + private Vector2 dotSize = new Vector2(4, 8); + + public Vector2 DotSize + { + get => dotSize; + set + { + dotSize = value; + + if (IsLoaded) + updateDotDimensions(); + } + } + + private float dotSpacing = 1; + + public float DotSpacing + { + get => dotSpacing; + set + { + dotSpacing = value; + + if (IsLoaded) + updateDotDimensions(); + } + } + + private readonly FillFlowContainer flow; + public DifficultySpectrumDisplay(IBeatmapSetInfo beatmapSet) { AutoSizeAxes = Axes.Both; - FillFlowContainer flow; - InternalChild = flow = new FillFlowContainer { AutoSizeAxes = Axes.Both, @@ -40,6 +68,21 @@ namespace osu.Game.Beatmaps.Drawables } } + protected override void LoadComplete() + { + base.LoadComplete(); + updateDotDimensions(); + } + + private void updateDotDimensions() + { + foreach (var group in flow) + { + group.DotSize = DotSize; + group.DotSpacing = DotSpacing; + } + } + private class RulesetDifficultyGroup : FillFlowContainer { private readonly int rulesetId; @@ -53,6 +96,20 @@ namespace osu.Game.Beatmaps.Drawables this.collapsed = collapsed; } + public Vector2 DotSize + { + set + { + foreach (var dot in Children.OfType()) + dot.Size = value; + } + } + + public float DotSpacing + { + set => Spacing = new Vector2(value, 0); + } + [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { @@ -98,8 +155,6 @@ namespace osu.Game.Beatmaps.Drawables [BackgroundDependencyLoader] private void load(OsuColour colours) { - Width = 4; - Height = 8; Anchor = Origin = Anchor.Centre; Masking = true; From d80a73b63da0c275e0818c3de814db8f5ce38388 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Oct 2021 12:53:02 +0900 Subject: [PATCH 083/129] Use explicit primitive types --- osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs b/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs index 10de06a550..501c0a55bd 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs @@ -82,8 +82,8 @@ namespace osu.Game.Rulesets.Osu.Mods public virtual void Update(Playfield playfield) { - var shouldAlwaysShowCursor = isBreakTime.Value || spinnerPeriods.IsInAny(playfield.Clock.CurrentTime); - var targetAlpha = shouldAlwaysShowCursor ? 1 : comboBasedAlpha; + bool shouldAlwaysShowCursor = isBreakTime.Value || spinnerPeriods.IsInAny(playfield.Clock.CurrentTime); + float targetAlpha = shouldAlwaysShowCursor ? 1 : comboBasedAlpha; playfield.Cursor.Alpha = (float)Interpolation.Lerp(playfield.Cursor.Alpha, targetAlpha, Math.Clamp(playfield.Time.Elapsed / transition_duration, 0, 1)); } } From 1d7e97625aa14927701eb3487721fe0c68d26778 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Oct 2021 12:57:43 +0900 Subject: [PATCH 084/129] Update `var` usage inspections to disallow for built-in types --- .editorconfig | 2 +- osu.sln.DotSettings | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index 3c4997c88d..be5652954b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -113,7 +113,7 @@ dotnet_style_qualification_for_event = false:warning dotnet_style_predefined_type_for_locals_parameters_members = true:warning dotnet_style_predefined_type_for_member_access = true:warning csharp_style_var_when_type_is_apparent = true:none -csharp_style_var_for_built_in_types = true:none +csharp_style_var_for_built_in_types = false:warning csharp_style_var_elsewhere = true:silent #Style - modifiers diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 3af986543e..f35bdfce66 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -207,7 +207,7 @@ HINT WARNING WARNING - DO_NOT_SHOW + SUGGESTION DO_NOT_SHOW DO_NOT_SHOW WARNING @@ -301,6 +301,9 @@ True 200 CHOP_IF_LONG + UseExplicitType + UseVarWhenEvident + UseVarWhenEvident False False AABB From 6944151486e677bfd11f2390163aca9161defbbf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Oct 2021 13:04:41 +0900 Subject: [PATCH 085/129] Apply batch fixing of built-in types using `var` --- osu.Desktop/OsuGameDesktop.cs | 4 +- osu.Desktop/Program.cs | 12 +-- .../TestSceneJuiceStreamSelectionBlueprint.cs | 2 +- .../TestSceneCatcher.cs | 4 +- .../TestSceneDrawableHitObjects.cs | 2 +- .../Preprocessing/CatchDifficultyHitObject.cs | 2 +- .../Mods/CatchModHidden.cs | 4 +- .../Replays/CatchFramedReplayInputHandler.cs | 2 +- .../Legacy/CatchLegacySkinTransformer.cs | 2 +- osu.Game.Rulesets.Catch/UI/Catcher.cs | 6 +- .../ManiaPlacementBlueprintTestScene.cs | 2 +- .../ManiaBeatmapConversionTest.cs | 2 +- .../ManiaColumnTypeTest.cs | 2 +- .../Beatmaps/ManiaBeatmapConverter.cs | 6 +- .../Legacy/DistanceObjectPatternGenerator.cs | 2 +- .../Legacy/HitObjectPatternGenerator.cs | 2 +- .../Difficulty/Skills/Strain.cs | 4 +- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- .../MathUtils/LegacySortHelper.cs | 2 +- .../Mods/ManiaModMirror.cs | 2 +- .../Mods/ManiaModRandom.cs | 2 +- .../Objects/Drawables/DrawableHoldNoteTick.cs | 2 +- .../Replays/ManiaAutoGenerator.cs | 2 +- .../Legacy/ManiaLegacySkinTransformer.cs | 2 +- .../TestSceneHitCircleArea.cs | 2 +- .../TestSceneSpinnerRotation.cs | 2 +- .../Preprocessing/OsuDifficultyHitObject.cs | 2 +- .../Difficulty/Skills/Aim.cs | 2 +- .../Components/PathControlPointPiece.cs | 4 +- .../Edit/Checks/CheckLowDiffOverlaps.cs | 8 +- .../Edit/Checks/CheckTimeDistanceEquality.cs | 8 +- .../Edit/OsuRectangularPositionSnapGrid.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 8 +- osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs | 8 +- osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs | 28 ++--- .../Connections/FollowPointConnection.cs | 2 +- .../Connections/FollowPointLifetimeEntry.cs | 2 +- .../Connections/FollowPointRenderer.cs | 2 +- .../Skinning/Default/SnakingSliderBody.cs | 8 +- .../Default/SpinnerRotationTracker.cs | 4 +- .../Skinning/Legacy/LegacyMainCirclePiece.cs | 2 +- .../Skinning/Legacy/LegacyOldStyleSpinner.cs | 2 +- .../Statistics/AccuracyHeatmap.cs | 2 +- .../Utils/OsuHitObjectGenerationUtils.cs | 10 +- .../TestSceneSampleOutput.cs | 2 +- .../Beatmaps/TaikoBeatmapConverter.cs | 2 +- .../Objects/Drawables/DrawableHit.cs | 4 +- .../Objects/Drawables/DrawableSwell.cs | 6 +- .../Legacy/TaikoLegacySkinTransformer.cs | 6 +- .../UI/DrumRollHitContainer.cs | 2 +- .../UI/TaikoMascotAnimation.cs | 2 +- .../Beatmaps/Formats/LegacyDecoderTest.cs | 2 +- .../Beatmaps/IO/ImportBeatmapTest.cs | 30 +++--- .../Beatmaps/IO/LineBufferedReaderTest.cs | 2 +- .../Beatmaps/IO/OszArchiveReaderTest.cs | 4 +- .../Database/BeatmapImporterTests.cs | 26 ++--- .../NonVisual/BarLineGeneratorTest.cs | 2 +- .../NonVisual/CustomDataDirectoryTest.cs | 6 +- .../NonVisual/FramedReplayInputHandlerTest.cs | 2 +- .../NonVisual/LimitedCapacityQueueTest.cs | 6 +- .../StatefulMultiplayerClientTest.cs | 2 +- osu.Game.Tests/NonVisual/ReverseQueueTest.cs | 6 +- ...TestMultiplayerMessagePackSerialization.cs | 8 +- osu.Game.Tests/Resources/TestResources.cs | 4 +- .../Editing/TestSceneBeatDivisorControl.cs | 2 +- .../Editing/TestSceneEditorBeatmapCreation.cs | 2 +- .../Gameplay/TestSceneGameplayMenuOverlay.cs | 2 +- .../TestSceneMultiSpectatorLeaderboard.cs | 4 +- .../TestSceneMultiSpectatorScreen.cs | 4 +- .../Multiplayer/TestSceneMultiplayer.cs | 2 +- ...TestSceneMultiplayerGameplayLeaderboard.cs | 6 +- ...ceneMultiplayerGameplayLeaderboardTeams.cs | 2 +- .../TestSceneMultiplayerParticipantsList.cs | 2 +- .../Visual/Online/TestSceneChatOverlay.cs | 4 +- .../Visual/Online/TestSceneRankGraph.cs | 8 +- .../Online/TestSceneStandAloneChatDisplay.cs | 2 +- .../Visual/Online/TestSceneWikiHeader.cs | 2 +- .../Visual/Online/TestSceneWikiSidebar.cs | 4 +- .../TestSceneBreadcrumbControlHeader.cs | 8 +- .../TestSceneFooterButtonMods.cs | 4 +- .../Visual/UserInterface/TestSceneOsuIcon.cs | 2 +- osu.Game.Tournament/Components/SongBar.cs | 10 +- osu.Game.Tournament/IPC/FileBasedIPC.cs | 14 +-- osu.Game.Tournament/JsonPointConverter.cs | 2 +- osu.Game.Tournament/Models/TournamentTeam.cs | 8 +- .../Components/TournamentMatchScoreDisplay.cs | 2 +- .../Components/DrawableTournamentMatch.cs | 6 +- .../Screens/Ladder/LadderDragContainer.cs | 2 +- .../Screens/Setup/ResolutionSelector.cs | 2 +- .../Screens/Setup/StablePathSelectScreen.cs | 4 +- osu.Game.Tournament/TournamentGame.cs | 2 +- osu.Game.Tournament/TournamentGameBase.cs | 2 +- osu.Game/Audio/Effects/AudioFilter.cs | 2 +- osu.Game/Beatmaps/Beatmap.cs | 2 +- osu.Game/Beatmaps/BeatmapInfoExtensions.cs | 2 +- .../Beatmaps/BeatmapMetadataInfoExtensions.cs | 4 +- .../ControlPoints/ControlPointInfo.cs | 4 +- osu.Game/Beatmaps/DifficultyRecommender.cs | 4 +- .../Beatmaps/Formats/LegacyBeatmapEncoder.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 4 +- .../Formats/LegacyStoryboardDecoder.cs | 102 +++++++++--------- osu.Game/Beatmaps/Formats/Parsing.cs | 6 +- osu.Game/Beatmaps/MetadataUtils.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmapCache.cs | 2 +- osu.Game/Collections/CollectionManager.cs | 8 +- osu.Game/Configuration/OsuConfigManager.cs | 4 +- osu.Game/Database/ArchiveModelManager.cs | 2 +- osu.Game/Database/DatabaseBackedStore.cs | 2 +- osu.Game/Database/RealmContextFactory.cs | 6 +- osu.Game/Database/StableImportManager.cs | 2 +- osu.Game/Database/UserLookupCache.cs | 2 +- osu.Game/Graphics/Backgrounds/Triangles.cs | 2 +- .../Containers/ConstrainedIconContainer.cs | 2 +- .../Containers/LogoTrackingContainer.cs | 2 +- .../Graphics/Containers/SectionsContainer.cs | 4 +- .../SelectionCycleFillFlowContainer.cs | 2 +- osu.Game/Graphics/Cursor/MenuCursor.cs | 2 +- osu.Game/Graphics/ErrorTextFlowContainer.cs | 2 +- osu.Game/Graphics/ParticleExplosion.cs | 4 +- osu.Game/Graphics/ParticleSpewer.cs | 14 +-- osu.Game/Graphics/ScreenshotManager.cs | 6 +- .../UserInterface/BreadcrumbControl.cs | 4 +- .../Graphics/UserInterface/OsuSliderBar.cs | 4 +- .../Graphics/UserInterface/StarCounter.cs | 4 +- .../Graphics/UserInterface/TwoLayerButton.cs | 2 +- osu.Game/IO/LineBufferedReader.cs | 4 +- .../Converters/TypedListConverter.cs | 4 +- osu.Game/IO/StableStorage.cs | 4 +- osu.Game/IO/WrappedStorage.cs | 2 +- .../Bindings/DatabasedKeyBindingContainer.cs | 2 +- osu.Game/Input/RealmKeyBindingStore.cs | 2 +- .../ResourceManagerLocalisationStore.cs | 2 +- osu.Game/Online/API/APIDownloadRequest.cs | 2 +- osu.Game/Online/Chat/Channel.cs | 4 +- osu.Game/Online/Chat/ChannelManager.cs | 4 +- osu.Game/Online/Chat/MessageFormatter.cs | 22 ++-- osu.Game/Online/Chat/NowPlayingCommand.cs | 2 +- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 2 +- osu.Game/Online/Leaderboards/Leaderboard.cs | 8 +- .../Rooms/IndexPlaylistScoresRequest.cs | 2 +- osu.Game/Online/Spectator/SpectatorClient.cs | 2 +- osu.Game/OsuGame.cs | 10 +- .../BeatmapSet/BeatmapRulesetTabItem.cs | 2 +- osu.Game/Overlays/BeatmapSet/Info.cs | 2 +- .../Scores/ScoreTableRowBackground.cs | 2 +- osu.Game/Overlays/BeatmapSet/SuccessRate.cs | 2 +- osu.Game/Overlays/ChatOverlay.cs | 2 +- .../Comments/CommentMarkdownContainer.cs | 2 +- osu.Game/Overlays/Comments/DrawableComment.cs | 4 +- osu.Game/Overlays/Comments/VotePill.cs | 2 +- .../Dashboard/CurrentlyPlayingDisplay.cs | 4 +- .../Friends/FriendOnlineStreamControl.cs | 4 +- osu.Game/Overlays/HoldToConfirmOverlay.cs | 2 +- osu.Game/Overlays/Mods/ModSection.cs | 4 +- osu.Game/Overlays/MusicController.cs | 6 +- osu.Game/Overlays/News/Sidebar/NewsSidebar.cs | 4 +- osu.Game/Overlays/News/Sidebar/YearsPanel.cs | 4 +- .../Header/Components/PreviousUsernames.cs | 2 +- .../Profile/Header/Components/RankGraph.cs | 2 +- .../Profile/Header/MedalHeaderContainer.cs | 2 +- .../Sections/Historical/ProfileLineChart.cs | 18 ++-- .../Sections/Audio/AudioDevicesSettings.cs | 2 +- .../Sections/Input/KeyBindingsSubsection.cs | 2 +- .../Settings/Sections/Input/MouseSettings.cs | 4 +- .../Sections/Input/RotationPresetButtons.cs | 2 +- .../Sections/Input/RulesetBindingsSection.cs | 2 +- .../Overlays/Settings/Sections/SkinSection.cs | 2 +- .../Overlays/Settings/SettingsNumberBox.cs | 2 +- osu.Game/Overlays/TabControlOverlayHeader.cs | 2 +- osu.Game/Overlays/Toolbar/ToolbarButton.cs | 2 +- osu.Game/Overlays/Volume/VolumeMeter.cs | 2 +- .../Wiki/Markdown/WikiNoticeContainer.cs | 2 +- osu.Game/Overlays/Wiki/WikiMainPage.cs | 4 +- osu.Game/Overlays/WikiOverlay.cs | 2 +- .../Difficulty/DifficultyCalculator.cs | 4 +- .../Rulesets/Edit/Checks/CheckAudioInVideo.cs | 2 +- .../Rulesets/Edit/Checks/CheckAudioQuality.cs | 2 +- .../Edit/Checks/CheckBackgroundQuality.cs | 2 +- .../Rulesets/Edit/Checks/CheckFewHitsounds.cs | 6 +- .../Rulesets/Edit/Checks/CheckFilePresence.cs | 4 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 4 +- osu.Game/Rulesets/Mods/ModBarrelRoll.cs | 4 +- osu.Game/Rulesets/Objects/BarLineGenerator.cs | 2 +- .../Objects/Drawables/DrawableHitObject.cs | 2 +- .../Objects/Legacy/ConvertHitObjectParser.cs | 2 +- .../Rulesets/Objects/SliderEventGenerator.cs | 16 +-- .../Rulesets/Objects/SliderPathExtensions.cs | 2 +- osu.Game/Rulesets/RulesetInfo.cs | 2 +- osu.Game/Rulesets/RulesetStore.cs | 6 +- osu.Game/Rulesets/Scoring/HitWindows.cs | 2 +- .../Algorithms/ConstantScrollAlgorithm.cs | 2 +- .../Algorithms/SequentialScrollAlgorithm.cs | 4 +- osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs | 16 +-- osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs | 2 +- .../Scoring/Legacy/ScoreInfoExtensions.cs | 2 +- osu.Game/Scoring/LegacyDatabasedScore.cs | 2 +- osu.Game/Scoring/ScoreManager.cs | 2 +- osu.Game/Screens/Edit/BindableBeatDivisor.cs | 2 +- .../Compose/Components/BeatDivisorControl.cs | 4 +- .../Compose/Components/BlueprintContainer.cs | 6 +- .../Compose/Components/DistanceSnapGrid.cs | 4 +- .../Components/EditorSelectionHandler.cs | 4 +- .../Timeline/TimelineBlueprintContainer.cs | 2 +- .../Timeline/TimelineHitObjectBlueprint.cs | 8 +- .../Timeline/TimelineTickDisplay.cs | 6 +- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Edit/EditorBeatmap.cs | 4 +- osu.Game/Screens/Edit/EditorChangeHandler.cs | 2 +- .../Edit/LegacyEditorBeatmapPatcher.cs | 2 +- osu.Game/Screens/Edit/Timing/GroupSection.cs | 2 +- osu.Game/Screens/Menu/IntroScreen.cs | 2 +- osu.Game/Screens/Menu/OsuLogo.cs | 4 +- .../Components/OnlinePlayBackgroundScreen.cs | 2 +- .../Participants/ParticipantPanel.cs | 2 +- .../Spectate/MultiSpectatorScreen.cs | 10 +- osu.Game/Screens/Play/Break/BreakInfoLine.cs | 2 +- osu.Game/Screens/Play/BreakTracker.cs | 2 +- osu.Game/Screens/Play/HUD/FailingLayer.cs | 2 +- .../HUD/HitErrorMeters/BarHitErrorMeter.cs | 6 +- .../Screens/Play/HUD/MatchScoreDisplay.cs | 2 +- .../HUD/MultiplayerGameplayLeaderboard.cs | 2 +- osu.Game/Screens/Play/SongProgressGraph.cs | 8 +- osu.Game/Screens/Play/SongProgressInfo.cs | 2 +- osu.Game/Screens/Play/SquareGraph.cs | 2 +- osu.Game/Screens/Play/SubmittingPlayer.cs | 2 +- .../Expanded/ExpandedPanelMiddleContent.cs | 4 +- osu.Game/Screens/Ranking/ResultsScreen.cs | 2 +- .../Ranking/Statistics/UnstableRate.cs | 8 +- osu.Game/Screens/Select/BeatmapDetails.cs | 2 +- .../Select/Carousel/CarouselBeatmap.cs | 6 +- .../Select/Carousel/CarouselBeatmapSet.cs | 4 +- .../Carousel/DrawableCarouselBeatmapSet.cs | 2 +- .../Screens/Select/Details/FailRetryGraph.cs | 8 +- .../Screens/Select/Details/UserRatings.cs | 4 +- osu.Game/Screens/Select/FilterControl.cs | 2 +- osu.Game/Screens/Select/FilterQueryParser.cs | 8 +- osu.Game/Screens/Spectate/SpectatorScreen.cs | 14 +-- osu.Game/Skinning/DefaultSkin.cs | 2 +- .../Skinning/Editor/SkinBlueprintContainer.cs | 2 +- osu.Game/Skinning/LegacyManiaSkinDecoder.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 10 +- osu.Game/Skinning/LegacySkinDecoder.cs | 2 +- osu.Game/Skinning/LegacySkinResourceStore.cs | 4 +- osu.Game/Skinning/LegacySpriteText.cs | 2 +- osu.Game/Skinning/ResourceStoreBackedSkin.cs | 2 +- osu.Game/Skinning/Skin.cs | 2 +- osu.Game/Stores/BeatmapImporter.cs | 2 +- osu.Game/Stores/RealmArchiveModelImporter.cs | 2 +- osu.Game/Stores/RealmRulesetStore.cs | 6 +- osu.Game/Storyboards/CommandLoop.cs | 4 +- osu.Game/Storyboards/CommandTimeline.cs | 2 +- osu.Game/Storyboards/CommandTimelineGroup.cs | 2 +- .../Drawables/DrawableStoryboardVideo.cs | 2 +- osu.Game/Storyboards/Storyboard.cs | 4 +- .../Tests/Beatmaps/BeatmapConversionTest.cs | 4 +- .../Beatmaps/DifficultyCalculatorTest.cs | 2 +- .../Visual/DependencyProvidingContainer.cs | 2 +- osu.Game/Tests/Visual/SkinnableTestScene.cs | 4 +- osu.Game/Updater/SimpleUpdateManager.cs | 2 +- osu.Game/Updater/UpdateManager.cs | 4 +- osu.Game/Utils/StatelessRNG.cs | 2 +- 263 files changed, 572 insertions(+), 572 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 4de1e84fbf..19e1252a4d 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -156,7 +156,7 @@ namespace osu.Desktop { lock (importableFiles) { - var firstExtension = Path.GetExtension(filePaths.First()); + string firstExtension = Path.GetExtension(filePaths.First()); if (filePaths.Any(f => Path.GetExtension(f) != firstExtension)) return; @@ -177,7 +177,7 @@ namespace osu.Desktop { Logger.Log($"Handling batch import of {importableFiles.Count} files"); - var paths = importableFiles.ToArray(); + string[] paths = importableFiles.ToArray(); importableFiles.Clear(); Task.Factory.StartNew(() => Import(paths), TaskCreationOptions.LongRunning); diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index 8ccd23b418..898f7d5105 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -22,17 +22,17 @@ namespace osu.Desktop public static int Main(string[] args) { // Back up the cwd before DesktopGameHost changes it - var cwd = Environment.CurrentDirectory; + string cwd = Environment.CurrentDirectory; string gameName = base_game_name; bool tournamentClient = false; - foreach (var arg in args) + foreach (string arg in args) { - var split = arg.Split('='); + string[] split = arg.Split('='); - var key = split[0]; - var val = split.Length > 1 ? split[1] : string.Empty; + string key = split[0]; + string val = split.Length > 1 ? split[1] : string.Empty; switch (key) { @@ -62,7 +62,7 @@ namespace osu.Desktop { var importer = new ArchiveImportIPCChannel(host); - foreach (var file in args) + foreach (string file in args) { Console.WriteLine(@"Importing {0}", file); if (!importer.ImportAsync(Path.GetFullPath(file, cwd)).Wait(3000)) diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs index 155d033dd0..fb77fb1efd 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor AddAssert("correct outline count", () => { - var expected = hitObject.NestedHitObjects.Count(h => !(h is TinyDroplet)); + int expected = hitObject.NestedHitObjects.Count(h => !(h is TinyDroplet)); return this.ChildrenOfType().Count() == expected; }); AddAssert("correct vertex piece count", () => diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index f291bfed13..29a7b03ad3 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Catch.Tests [Test] public void TestCatcherCatchWidth() { - var halfWidth = Catcher.CalculateCatchWidth(new BeatmapDifficulty { CircleSize = 0 }) / 2; + float halfWidth = Catcher.CalculateCatchWidth(new BeatmapDifficulty { CircleSize = 0 }) / 2; AddStep("catch fruit", () => { attemptCatch(new Fruit { X = -halfWidth + 1 }); @@ -237,7 +237,7 @@ namespace osu.Game.Rulesets.Catch.Tests private void attemptCatch(Func hitObject, int count) { - for (var i = 0; i < count; i++) + for (int i = 0; i < count; i++) attemptCatch(hitObject(), out _, out _); } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs index e7c7dc3c98..3c61eb19e5 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs @@ -118,7 +118,7 @@ namespace osu.Game.Rulesets.Catch.Tests private void spawnJuiceStream(bool hit = false) { - var xCoords = getXCoords(hit); + float xCoords = getXCoords(hit); var juice = new JuiceStream { diff --git a/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs index e19098c580..b22ec93b43 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Preprocessing : base(hitObject, lastObject, clockRate) { // We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps. - var scalingFactor = normalized_hitobject_radius / halfCatcherWidth; + float scalingFactor = normalized_hitobject_radius / halfCatcherWidth; NormalizedPosition = BaseObject.EffectiveX * scalingFactor; LastNormalizedPosition = LastObject.EffectiveX * scalingFactor; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs b/osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs index d48edbcd74..4b6f79df88 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs @@ -52,8 +52,8 @@ namespace osu.Game.Rulesets.Catch.Mods { var hitObject = drawable.HitObject; - var offset = hitObject.TimePreempt * fade_out_offset_multiplier; - var duration = offset - hitObject.TimePreempt * fade_out_duration_multiplier; + double offset = hitObject.TimePreempt * fade_out_offset_multiplier; + double duration = offset - hitObject.TimePreempt * fade_out_duration_multiplier; using (drawable.BeginAbsoluteSequence(hitObject.StartTime - offset)) drawable.FadeOut(duration); diff --git a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs index 137328b1c3..bd742ce6a6 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Catch.Replays public override void CollectPendingInputs(List inputs) { - var position = Interpolation.ValueAt(CurrentTime, StartFrame.Position, EndFrame.Position, StartFrame.Time, EndFrame.Time); + float position = Interpolation.ValueAt(CurrentTime, StartFrame.Position, EndFrame.Position, StartFrame.Time, EndFrame.Time); inputs.Add(new CatchReplayState { diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs index 10fc4e78b2..7177a18cc3 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy return null; case CatchSkinComponents.Catcher: - var version = GetConfig(LegacySkinConfiguration.LegacySetting.Version)?.Value ?? 1; + decimal version = GetConfig(LegacySkinConfiguration.LegacySetting.Version)?.Value ?? 1; if (version < 2.3m) { diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 3745099010..1061bd2fc9 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -226,9 +226,9 @@ namespace osu.Game.Rulesets.Catch.UI if (result.IsHit && hitObject.HyperDash) { var target = hitObject.HyperDashTarget; - var timeDifference = target.StartTime - hitObject.StartTime; + double timeDifference = target.StartTime - hitObject.StartTime; double positionDifference = target.EffectiveX - X; - var velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); + double velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); SetHyperDashState(Math.Abs(velocity), target.EffectiveX); } @@ -266,7 +266,7 @@ namespace osu.Game.Rulesets.Catch.UI /// When this catcher crosses this position, this catcher ends hyper-dashing. public void SetHyperDashState(double modifier = 1, float targetPosition = -1) { - var wasHyperDashing = HyperDashing; + bool wasHyperDashing = HyperDashing; if (modifier <= 1 || X == targetPosition) { diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs index ece523e84c..94f385bbf1 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor protected override SnapResult SnapForBlueprint(PlacementBlueprint blueprint) { - var time = column.TimeAtScreenSpacePosition(InputManager.CurrentState.Mouse.Position); + double time = column.TimeAtScreenSpacePosition(InputManager.CurrentState.Mouse.Position); var pos = column.ScreenSpacePositionAtTime(time); return new SnapResult(pos, time, column); diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index 3d4bc4748b..948f088b4e 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Mania.Tests public int CompareTo(ConvertValue other) { - var result = StartTime.CompareTo(other.StartTime); + int result = StartTime.CompareTo(other.StartTime); if (result != 0) return result; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaColumnTypeTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaColumnTypeTest.cs index 40a6e1fdae..66fe6d8cc5 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaColumnTypeTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaColumnTypeTest.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.Tests private IEnumerable getResults(StageDefinition definition) { - for (var i = 0; i < definition.Columns; i++) + for (int i = 0; i < definition.Columns; i++) yield return definition.GetTypeOfColumn(i); } } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index ebfbaccd31..9d0aaec2ba 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -42,8 +42,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps { IsForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(ruleset.RulesetInfo); - var roundedCircleSize = Math.Round(beatmap.Difficulty.CircleSize); - var roundedOverallDifficulty = Math.Round(beatmap.Difficulty.OverallDifficulty); + double roundedCircleSize = Math.Round(beatmap.Difficulty.CircleSize); + double roundedOverallDifficulty = Math.Round(beatmap.Difficulty.OverallDifficulty); if (IsForCurrentRuleset) { @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps public static int GetColumnCountForNonConvert(BeatmapInfo beatmapInfo) { - var roundedCircleSize = Math.Round(beatmapInfo.BaseDifficulty.CircleSize); + double roundedCircleSize = Math.Round(beatmapInfo.BaseDifficulty.CircleSize); return (int)Math.Max(1, roundedCircleSize); } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 1ed045f7e0..77538cc2ac 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -493,7 +493,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (!(HitObject is IHasPathWithRepeats curveData)) return null; - var index = SegmentDuration == 0 ? 0 : (time - StartTime) / SegmentDuration; + int index = SegmentDuration == 0 ? 0 : (time - StartTime) / SegmentDuration; // avoid slicing the list & creating copies, if at all possible. return index == 0 ? curveData.NodeSamples : curveData.NodeSamples.Skip(index).ToList(); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 54c37e9742..53b059b4e2 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -302,7 +302,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy var pattern = new Pattern(); - int noteCount = getRandomNoteCountMirrored(centreProbability, p2, p3, out var addToCentre); + int noteCount = getRandomNoteCountMirrored(centreProbability, p2, p3, out bool addToCentre); int columnLimit = (TotalColumns % 2 == 0 ? TotalColumns : TotalColumns - 1) / 2; int nextColumn = GetRandomColumn(upperBound: columnLimit); diff --git a/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs b/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs index 01d930d585..ab6bd78ece 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs @@ -35,8 +35,8 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills protected override double StrainValueOf(DifficultyHitObject current) { var maniaCurrent = (ManiaDifficultyHitObject)current; - var endTime = maniaCurrent.EndTime; - var column = maniaCurrent.BaseObject.Column; + double endTime = maniaCurrent.EndTime; + int column = maniaCurrent.BaseObject.Column; double holdFactor = 1.0; // Factor to all additional strains in case something else is held double holdAddition = 0; // Addition to the current note in case it's a hold and has to be released awkwardly diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 1f79dae280..a9b16c61d4 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -316,7 +316,7 @@ namespace osu.Game.Rulesets.Mania case PlayfieldType.Dual: { - var keys = getDualStageKeyCount(variant); + int keys = getDualStageKeyCount(variant); return $"{keys}K + {keys}K"; } } diff --git a/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs b/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs index 0f4829028f..a0e2958bae 100644 --- a/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs +++ b/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs @@ -122,7 +122,7 @@ namespace osu.Game.Rulesets.Mania.MathUtils while (i <= n / 2) { - var child = 2 * i; + int child = 2 * i; if (child < n && comparer.Compare(keys[lo + child - 1], keys[lo + child]) < 0) { diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs index f01884c97f..9c3744ea98 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Mods public void ApplyToBeatmap(IBeatmap beatmap) { - var availableColumns = ((ManiaBeatmap)beatmap).TotalColumns; + int availableColumns = ((ManiaBeatmap)beatmap).TotalColumns; beatmap.HitObjects.OfType().ForEach(h => h.Column = availableColumns - 1 - h.Column); } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs index 6f2d4fe91e..f5d1a34d73 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.Mods Seed.Value ??= RNG.Next(); var rng = new Random((int)Seed.Value); - var availableColumns = ((ManiaBeatmap)beatmap).TotalColumns; + int availableColumns = ((ManiaBeatmap)beatmap).TotalColumns; var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(item => rng.Next()).ToList(); beatmap.HitObjects.OfType().ForEach(h => h.Column = shuffledColumns[h.Column]); diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index f040dad135..cffa79322e 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -97,7 +97,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (Time.Current < HitObject.StartTime) return; - var startTime = holdStartTime?.Invoke(); + double? startTime = holdStartTime?.Invoke(); if (startTime == null || startTime > HitObject.StartTime) ApplyResult(r => r.Type = r.Judgement.MinResult); diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index 517b708691..efe144ac03 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -75,7 +75,7 @@ namespace osu.Game.Rulesets.Mania.Replays { var currentObject = Beatmap.HitObjects[i]; var nextObjectInColumn = GetNextObject(i); // Get the next object that requires pressing the same button - var releaseTime = calculateReleaseTime(currentObject, nextObjectInColumn); + double releaseTime = calculateReleaseTime(currentObject, nextObjectInColumn); yield return new HitPoint { Time = currentObject.StartTime, Column = currentObject.Column }; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs index 814a737034..cc3b3f348f 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy isLegacySkin = new Lazy(() => GetConfig(LegacySkinConfiguration.LegacySetting.Version) != null); hasKeyTexture = new Lazy(() => { - var keyImage = this.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.KeyImage, 0)?.Value ?? "mania-key1"; + string keyImage = this.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.KeyImage, 0)?.Value ?? "mania-key1"; return this.GetAnimation(keyImage, true, true) != null; }); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs index 575523b168..07bbd6379a 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs @@ -97,7 +97,7 @@ namespace osu.Game.Rulesets.Osu.Tests private void scheduleHit() => AddStep("schedule action", () => { - var delay = hitCircle.StartTime - hitCircle.HitWindows.WindowFor(HitResult.Great) - Time.Current; + double delay = hitCircle.StartTime - hitCircle.HitWindows.WindowFor(HitResult.Great) - Time.Current; Scheduler.AddDelayed(() => hitAreaReceptor.OnPressed(new KeyBindingPressEvent(GetContainingInputManager().CurrentState, OsuAction.LeftButton)), delay); }); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index 52ab39cfbd..de795241bf 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -148,7 +148,7 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("player score matching expected bonus score", () => { // multipled by 2 to nullify the score multiplier. (autoplay mod selected) - var totalScore = ((ScoreExposedPlayer)Player).ScoreProcessor.TotalScore.Value * 2; + double totalScore = ((ScoreExposedPlayer)Player).ScoreProcessor.TotalScore.Value * 2; return totalScore == (int)(drawableSpinner.Result.RateAdjustedRotation / 360) * new SpinnerTick().CreateJudgement().MaxNumericResult; }); diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs index 5e5993aefe..49ac6a7af3 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -123,7 +123,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing // Skip the head circle var scoringTimes = slider.NestedHitObjects.Skip(1).Select(t => t.StartTime); - foreach (var time in scoringTimes) + foreach (double time in scoringTimes) computeVertex(time); } diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs index d8f4aa1229..64ca567a15 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills { const double scale = 90; - var angleBonus = Math.Sqrt( + double angleBonus = Math.Sqrt( Math.Max(osuPrevious.JumpDistance - scale, 0) * Math.Pow(Math.Sin(osuCurrent.Angle.Value - angle_bonus_begin), 2) * Math.Max(osuCurrent.JumpDistance - scale, 0)); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 2cc95e1891..b3e0566a98 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -184,7 +184,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { Vector2[] oldControlPoints = slider.Path.ControlPoints.Select(cp => cp.Position).ToArray(); var oldPosition = slider.Position; - var oldStartTime = slider.StartTime; + double oldStartTime = slider.StartTime; if (ControlPoint == slider.Path.ControlPoints[0]) { @@ -205,7 +205,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components if (!slider.Path.HasValidLength) { - for (var i = 0; i < slider.Path.ControlPoints.Count; i++) + for (int i = 0; i < slider.Path.ControlPoints.Count; i++) slider.Path.ControlPoints[i].Position = oldControlPoints[i]; slider.Position = oldPosition; diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckLowDiffOverlaps.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckLowDiffOverlaps.cs index 1dd859b5b8..084a3e5ea1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Checks/CheckLowDiffOverlaps.cs +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckLowDiffOverlaps.cs @@ -47,14 +47,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks if (!(hitObjects[i + 1] is OsuHitObject nextHitObject) || nextHitObject is Spinner) continue; - var deltaTime = nextHitObject.StartTime - hitObject.GetEndTime(); + double deltaTime = nextHitObject.StartTime - hitObject.GetEndTime(); if (deltaTime >= hitObject.TimeFadeIn + hitObject.TimePreempt) // The objects are not visible at the same time (without mods), hence skipping. continue; - var distanceSq = (hitObject.StackedEndPosition - nextHitObject.StackedPosition).LengthSquared; - var diameter = (hitObject.Radius - overlap_leniency) * 2; - var diameterSq = diameter * diameter; + float distanceSq = (hitObject.StackedEndPosition - nextHitObject.StackedPosition).LengthSquared; + double diameter = (hitObject.Radius - overlap_leniency) * 2; + double diameterSq = diameter * diameter; bool areOverlapping = distanceSq < diameterSq; diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckTimeDistanceEquality.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckTimeDistanceEquality.cs index 6420d9558e..585bd35bd9 100644 --- a/osu.Game.Rulesets.Osu/Edit/Checks/CheckTimeDistanceEquality.cs +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckTimeDistanceEquality.cs @@ -88,21 +88,21 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks if (!(hitObjects[i + 1] is OsuHitObject nextHitObject) || nextHitObject is Spinner) continue; - var deltaTime = nextHitObject.StartTime - hitObject.GetEndTime(); + double deltaTime = nextHitObject.StartTime - hitObject.GetEndTime(); // Ignore objects that are far enough apart in time to not be considered the same pattern. if (deltaTime > pattern_lifetime) continue; // Relying on FastInvSqrt is probably good enough here. We'll be taking the difference between distances later, hence square not being sufficient. - var distance = (hitObject.StackedEndPosition - nextHitObject.StackedPosition).LengthFast; + float distance = (hitObject.StackedEndPosition - nextHitObject.StackedPosition).LengthFast; // Ignore stacks and half-stacks, as these are close enough to where they can't be confused for being time-distanced. if (distance < stack_leniency) continue; var observedTimeDistance = new ObservedTimeDistance(nextHitObject.StartTime, deltaTime, distance); - var expectedDistance = getExpectedDistance(prevObservedTimeDistances, observedTimeDistance); + double expectedDistance = getExpectedDistance(prevObservedTimeDistances, observedTimeDistance); if (expectedDistance == 0) { @@ -125,7 +125,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks private double getExpectedDistance(IEnumerable prevObservedTimeDistances, ObservedTimeDistance observedTimeDistance) { - var observations = prevObservedTimeDistances.Count(); + int observations = prevObservedTimeDistances.Count(); int count = 0; double sum = 0; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs index b8ff92bd37..d1c81b51bc 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Edit [BackgroundDependencyLoader] private void load() { - var gridSizeIndex = Array.IndexOf(grid_sizes, editorBeatmap.BeatmapInfo.GridSize); + int gridSizeIndex = Array.IndexOf(grid_sizes, editorBeatmap.BeatmapInfo.GridSize); if (gridSizeIndex >= 0) currentGridSizeIndex = gridSizeIndex; updateSpacing(); diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 3102db270e..ad4c5dfd5d 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -170,7 +170,7 @@ namespace osu.Game.Rulesets.Osu.Mods base.LoadComplete(); var firstObj = beatmap.HitObjects[0]; - var startDelay = firstObj.StartTime - firstObj.TimePreempt; + double startDelay = firstObj.StartTime - firstObj.TimePreempt; using (BeginAbsoluteSequence(startDelay + break_close_late)) leaveBreak(); diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index e162f805a1..d602fe67ee 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -155,11 +155,11 @@ namespace osu.Game.Rulesets.Osu.Mods static (double fadeStartTime, double fadeDuration) getParameters(OsuHitObject hitObject) { - var fadeOutStartTime = hitObject.StartTime - hitObject.TimePreempt + hitObject.TimeFadeIn; - var fadeOutDuration = hitObject.TimePreempt * fade_out_duration_multiplier; + double fadeOutStartTime = hitObject.StartTime - hitObject.TimePreempt + hitObject.TimeFadeIn; + double fadeOutDuration = hitObject.TimePreempt * fade_out_duration_multiplier; // new duration from completed fade in to end (before fading out) - var longFadeDuration = hitObject.GetEndTime() - fadeOutStartTime; + double longFadeDuration = hitObject.GetEndTime() - fadeOutStartTime; switch (hitObject) { @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.Mods return (fadeOutStartTime, longFadeDuration); case SliderTick _: - var tickFadeOutDuration = Math.Min(hitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000); + double tickFadeOutDuration = Math.Min(hitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000); return (hitObject.StartTime - tickFadeOutDuration, tickFadeOutDuration); case Spinner _: diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs index 1a2e5d92b4..9b9ebcad04 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs @@ -124,7 +124,7 @@ namespace osu.Game.Rulesets.Osu.Mods // to allow jumps and prevent too sharp turns during streams. // Allow maximum jump angle when jump distance is more than half of playfield diagonal length - var randomAngleRad = rateOfChangeMultiplier * 2 * Math.PI * Math.Min(1f, distanceToPrev / (playfield_diagonal * 0.5f)); + double randomAngleRad = rateOfChangeMultiplier * 2 * Math.PI * Math.Min(1f, distanceToPrev / (playfield_diagonal * 0.5f)); current.AngleRad = (float)randomAngleRad + previous.AngleRad; if (current.AngleRad < 0) @@ -171,11 +171,11 @@ namespace osu.Game.Rulesets.Osu.Mods // Clamp slider position to the placement area // If the slider is larger than the playfield, force it to stay at the original position - var newX = possibleMovementBounds.Width < 0 + float newX = possibleMovementBounds.Width < 0 ? objectInfo.PositionOriginal.X : Math.Clamp(previousPosition.X, possibleMovementBounds.Left, possibleMovementBounds.Right); - var newY = possibleMovementBounds.Height < 0 + float newY = possibleMovementBounds.Height < 0 ? objectInfo.PositionOriginal.Y : Math.Clamp(previousPosition.Y, possibleMovementBounds.Top, possibleMovementBounds.Bottom); @@ -235,7 +235,7 @@ namespace osu.Game.Rulesets.Osu.Mods } // Take the circle radius into account. - var radius = (float)slider.Radius; + float radius = (float)slider.Radius; minX -= radius; minY -= radius; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs index c7f4811701..31474e8fbb 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Osu.Mods // because the spinner is under the gameplay clock, it is affected by rate adjustments on the track; // for that reason using ElapsedFrameTime directly leads to fewer SPM with Half Time and more SPM with Double Time. // for spinners we want the real (wall clock) elapsed time; to achieve that, unapply the clock rate locally here. - var rateIndependentElapsedTime = spinner.Clock.ElapsedFrameTime / spinner.Clock.Rate; + double rateIndependentElapsedTime = spinner.Clock.ElapsedFrameTime / spinner.Clock.Rate; spinner.RotationTracker.AddRotation(MathUtils.RadiansToDegrees((float)rateIndependentElapsedTime * 0.03f)); } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs index bf70a63ab5..5285380097 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs @@ -193,8 +193,8 @@ namespace osu.Game.Rulesets.Osu.Mods private IEnumerable generateBeats(IBeatmap beatmap) { - var startTime = originalHitObjects.First().StartTime; - var endTime = originalHitObjects.Last().GetEndTime(); + double startTime = originalHitObjects.First().StartTime; + double endTime = originalHitObjects.Last().GetEndTime(); var beats = beatmap.ControlPointInfo.TimingPoints // Ignore timing points after endTime @@ -208,9 +208,9 @@ namespace osu.Game.Rulesets.Osu.Mods .ToList(); // Remove beats that are too close to the next one (e.g. due to timing point changes) - for (var i = beats.Count - 2; i >= 0; i--) + for (int i = beats.Count - 2; i >= 0; i--) { - var beat = beats[i]; + double beat = beats[i]; if (!definitelyBigger(beats[i + 1] - beat, beatmap.ControlPointInfo.TimingPointAt(beat).BeatLength / 2)) beats.RemoveAt(i); @@ -250,13 +250,13 @@ namespace osu.Game.Rulesets.Osu.Mods // Other kinds of combo info are also added in the process var combos = hitObjects.GroupBy(x => x.ComboIndex).ToList(); - for (var i = 0; i < combos.Count; i++) + for (int i = 0; i < combos.Count; i++) { var group = combos[i].ToList(); group.First().NewCombo = true; group.Last().LastInCombo = true; - for (var j = 0; j < group.Count; j++) + for (int j = 0; j < group.Count; j++) { var x = group[j]; x.ComboIndex = i; @@ -273,17 +273,17 @@ namespace osu.Game.Rulesets.Osu.Mods const float two_pi = MathF.PI * 2; - var direction = two_pi * nextSingle(); - var maxComboIndex = hitObjects.Last().ComboIndex; + float direction = two_pi * nextSingle(); + int maxComboIndex = hitObjects.Last().ComboIndex; - for (var i = 0; i < hitObjects.Count; i++) + for (int i = 0; i < hitObjects.Count; i++) { var obj = hitObjects[i]; var lastPos = i == 0 ? Vector2.Divide(OsuPlayfield.BASE_SIZE, 2) : hitObjects[i - 1].Position; - var distance = maxComboIndex == 0 + float distance = maxComboIndex == 0 ? (float)obj.Radius : mapRange(obj.ComboIndex, 0, maxComboIndex, (float)obj.Radius, max_base_distance); if (obj.NewCombo) distance *= 1.5f; @@ -292,7 +292,7 @@ namespace osu.Game.Rulesets.Osu.Mods // Attempt to place the circle at a place that does not overlap with previous ones - var tryCount = 0; + int tryCount = 0; // for checking overlap var precedingObjects = hitObjects.SkipLast(hitObjects.Count - i).TakeLast(overlap_check_count).ToList(); @@ -363,7 +363,7 @@ namespace osu.Game.Rulesets.Osu.Mods { var beats = new List(); int i = 0; - var currentTime = timingPoint.Time; + double currentTime = timingPoint.Time; while (!definitelyBigger(currentTime, mapEndTime) && controlPointInfo.TimingPointAt(currentTime) == timingPoint) { @@ -377,7 +377,7 @@ namespace osu.Game.Rulesets.Osu.Mods private OsuHitObject getClosestHitObject(List hitObjects, double time) { - var precedingIndex = hitObjects.FindLastIndex(h => h.StartTime < time); + int precedingIndex = hitObjects.FindLastIndex(h => h.StartTime < time); if (precedingIndex == hitObjects.Count - 1) return hitObjects[precedingIndex]; @@ -457,7 +457,7 @@ namespace osu.Game.Rulesets.Osu.Mods private void clampToPlayfield(OsuHitObject obj) { var position = obj.Position; - var radius = (float)obj.Radius; + float radius = (float)obj.Radius; if (position.Y < radius) position.Y = radius; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs index 001ea6c4ad..e88d09e6d9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector; Vector2 pointEndPosition = startPosition + fraction * distanceVector; - GetFadeTimes(start, end, (float)d / distance, out var fadeInTime, out var fadeOutTime); + GetFadeTimes(start, end, (float)d / distance, out double fadeInTime, out double fadeOutTime); FollowPoint fp; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointLifetimeEntry.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointLifetimeEntry.cs index 30ff6b8984..ad656d2085 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointLifetimeEntry.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointLifetimeEntry.cs @@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections // The lifetime start will match the fade-in time of the first follow point. float fraction = (int)(FollowPointConnection.SPACING * 1.5) / distanceVector.Length; - FollowPointConnection.GetFadeTimes(Start, End, fraction, out var fadeInTime, out _); + FollowPointConnection.GetFadeTimes(Start, End, fraction, out double fadeInTime, out _); LifetimeStart = fadeInTime; LifetimeEnd = double.MaxValue; // This will be set by the connection. diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 21e6619444..011e9fa85d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { var newEntry = new FollowPointLifetimeEntry(hitObject); - var index = lifetimeEntries.AddInPlace(newEntry, Comparer.Create((e1, e2) => + int index = lifetimeEntries.AddInPlace(newEntry, Comparer.Create((e1, e2) => { int comp = e1.Start.StartTime.CompareTo(e2.Start.StartTime); diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SnakingSliderBody.cs index 7b7a89d5e2..42d3840158 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SnakingSliderBody.cs @@ -70,8 +70,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default Slider slider = drawableSlider.HitObject; - var span = slider.SpanAt(completionProgress); - var spanProgress = slider.ProgressAt(completionProgress); + int span = slider.SpanAt(completionProgress); + double spanProgress = slider.ProgressAt(completionProgress); double start = 0; double end = SnakingIn.Value ? Math.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; @@ -110,8 +110,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default snakedPosition = Path.PositionInBoundingBox(Vector2.Zero); snakedPathOffset = Path.PositionInBoundingBox(Path.Vertices[0]); - var lastSnakedStart = SnakedStart ?? 0; - var lastSnakedEnd = SnakedEnd ?? 0; + double lastSnakedStart = SnakedStart ?? 0; + double lastSnakedEnd = SnakedEnd ?? 0; SnakedStart = null; SnakedEnd = null; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs index 9393a589eb..4313e99b13 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs @@ -62,9 +62,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default protected override void Update() { base.Update(); - var thisAngle = -MathUtils.RadiansToDegrees(MathF.Atan2(mousePosition.X - DrawSize.X / 2, mousePosition.Y - DrawSize.Y / 2)); + float thisAngle = -MathUtils.RadiansToDegrees(MathF.Atan2(mousePosition.X - DrawSize.X / 2, mousePosition.Y - DrawSize.Y / 2)); - var delta = thisAngle - lastAngle; + float delta = thisAngle - lastAngle; if (Tracking) AddRotation(delta); diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs index d1c9b1bf92..f4422a4806 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs @@ -158,7 +158,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy if (hasNumber) { - var legacyVersion = skin.GetConfig(LegacySetting.Version)?.Value; + decimal? legacyVersion = skin.GetConfig(LegacySetting.Version)?.Value; if (legacyVersion >= 2.0m) // legacy skins of version 2.0 and newer only apply very short fade out to the number piece. diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs index e3e8f3ce88..ea122d47bb 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs @@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy // careful: need to call this exactly once for all calculations in a frame // as the function has a random factor in it - var metreHeight = getMetreHeight(DrawableSpinner.Progress); + float metreHeight = getMetreHeight(DrawableSpinner.Progress); // hack to make the metre blink up from below than down from above. // move down the container to be able to apply masking for the metre, diff --git a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs index 24a660e69e..3c2077b3c8 100644 --- a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs +++ b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs @@ -216,7 +216,7 @@ namespace osu.Game.Rulesets.Osu.Statistics // Likewise sin(pi/2)=1 and sin(3pi/2)=-1, whereas we actually want these values to appear on the bottom/top respectively, so the y-coordinate also needs to be inverted. // // We also need to apply the anti-clockwise rotation. - var rotatedAngle = finalAngle - MathUtils.DegreesToRadians(rotation); + double rotatedAngle = finalAngle - MathUtils.DegreesToRadians(rotation); var rotatedCoordinate = -1 * new Vector2((float)Math.Cos(rotatedAngle), (float)Math.Sin(rotatedAngle)); Vector2 localCentre = new Vector2(points_per_dimension - 1) / 2; diff --git a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs index bfd6ac3ad3..97a4b14a62 100644 --- a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs +++ b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Osu.Utils /// The new position of the hit object, relative to the previous one. public static Vector2 RotateAwayFromEdge(Vector2 prevObjectPos, Vector2 posRelativeToPrev, float rotationRatio = 0.5f) { - var relativeRotationDistance = 0f; + float relativeRotationDistance = 0f; if (prevObjectPos.X < playfield_middle.X) { @@ -88,16 +88,16 @@ namespace osu.Game.Rulesets.Osu.Utils /// The rotated vector. public static Vector2 RotateVectorTowardsVector(Vector2 initial, Vector2 destination, float rotationRatio) { - var initialAngleRad = MathF.Atan2(initial.Y, initial.X); - var destAngleRad = MathF.Atan2(destination.Y, destination.X); + float initialAngleRad = MathF.Atan2(initial.Y, initial.X); + float destAngleRad = MathF.Atan2(destination.Y, destination.X); - var diff = destAngleRad - initialAngleRad; + float diff = destAngleRad - initialAngleRad; while (diff < -MathF.PI) diff += 2 * MathF.PI; while (diff > MathF.PI) diff -= 2 * MathF.PI; - var finalAngleRad = initialAngleRad + rotationRatio * diff; + float finalAngleRad = initialAngleRad + rotationRatio * diff; return new Vector2( initial.Length * MathF.Cos(finalAngleRad), diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs index 296468d98d..97c8d9eeb5 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Taiko.Tests { base.SetUpSteps(); - var expectedSampleNames = new[] + string[] expectedSampleNames = new[] { string.Empty, string.Empty, diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 32aad6c36a..5c5b3f9daa 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps { case IHasDistance distanceData: { - if (shouldConvertSliderToHits(obj, beatmap, distanceData, out var taikoDuration, out var tickSpacing)) + if (shouldConvertSliderToHits(obj, beatmap, distanceData, out int taikoDuration, out double tickSpacing)) { List> allSamples = obj is IHasPathWithRepeats curveData ? curveData.NodeSamples : new List>(new[] { samples }); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 97adc5f197..863672b3fa 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -109,7 +109,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables var corrected = samples.ToList(); - for (var i = 0; i < corrected.Count; i++) + for (int i = 0; i < corrected.Count; i++) { var s = corrected[i]; @@ -156,7 +156,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables validActionPressed = HitActions.Contains(e.Action); // Only count this as handled if the new judgement is a hit - var result = UpdateResult(true); + bool result = UpdateResult(true); if (IsHit) HitAction = e.Action; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 2d19296d06..77243218ce 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -185,9 +185,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables nextTick?.TriggerResult(true); - var numHits = ticks.Count(r => r.IsHit); + int numHits = ticks.Count(r => r.IsHit); - var completion = (float)numHits / HitObject.RequiredHits; + float completion = (float)numHits / HitObject.RequiredHits; expandingRing .FadeTo(expandingRing.Alpha + Math.Clamp(completion / 16, 0.1f, 0.6f), 50) @@ -273,7 +273,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (Time.Current < HitObject.StartTime) return false; - var isCentre = e.Action == TaikoAction.LeftCentre || e.Action == TaikoAction.RightCentre; + bool isCentre = e.Action == TaikoAction.LeftCentre || e.Action == TaikoAction.RightCentre; // Ensure alternating centre and rim hits if (lastWasCentre == isCentre) diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs index a3ecbbc436..bbc8f0abea 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs @@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy case TaikoSkinComponents.TaikoExplosionOk: case TaikoSkinComponents.TaikoExplosionGreat: - var hitName = getHitName(taikoComponent.Component); + string hitName = getHitName(taikoComponent.Component); var hitSprite = this.GetAnimation(hitName, true, false); if (hitSprite != null) @@ -162,10 +162,10 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { get { - foreach (var name in base.LookupNames) + foreach (string name in base.LookupNames) yield return name.Insert(name.LastIndexOf('/') + 1, "taiko-"); - foreach (var name in base.LookupNames) + foreach (string name in base.LookupNames) yield return name; } } diff --git a/osu.Game.Rulesets.Taiko/UI/DrumRollHitContainer.cs b/osu.Game.Rulesets.Taiko/UI/DrumRollHitContainer.cs index 263454c78a..ae37840825 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrumRollHitContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrumRollHitContainer.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Taiko.UI base.Update(); // Remove any auxiliary hit notes that were spawned during a drum roll but subsequently rewound. - for (var i = AliveInternalChildren.Count - 1; i >= 0; i--) + for (int i = AliveInternalChildren.Count - 1; i >= 0; i--) { var flyingHit = (DrawableFlyingHit)AliveInternalChildren[i]; if (Time.Current <= flyingHit.HitObject.StartTime) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs b/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs index 3706acbe23..c496c05236 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs @@ -122,7 +122,7 @@ namespace osu.Game.Rulesets.Taiko.UI if (skin == null) return; - foreach (var frameIndex in clear_animation_sequence) + foreach (int frameIndex in clear_animation_sequence) { var texture = getAnimationFrame(skin, TaikoMascotAnimationState.Clear, frameIndex); diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs index 335a6aeeb0..4334c4d7a2 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs @@ -40,7 +40,7 @@ namespace osu.Game.Tests.Beatmaps.Formats protected override bool ShouldSkipLine(string line) { - var result = base.ShouldSkipLine(line); + bool result = base.ShouldSkipLine(line); if (!result) ParsedLines.Add(line); diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 4cc71717ff..935194db58 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -82,7 +82,7 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = LoadOsuIntoHost(host); - var tempPath = TestResources.GetTestBeatmapForImport(); + string tempPath = TestResources.GetTestBeatmapForImport(); var manager = osu.Dependencies.Get(); @@ -144,7 +144,7 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = LoadOsuIntoHost(host); - var temp = TestResources.GetTestBeatmapForImport(); + string temp = TestResources.GetTestBeatmapForImport(); string extractedFolder = $"{temp}_extracted"; Directory.CreateDirectory(extractedFolder); @@ -196,7 +196,7 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = LoadOsuIntoHost(host); - var temp = TestResources.GetTestBeatmapForImport(); + string temp = TestResources.GetTestBeatmapForImport(); string extractedFolder = $"{temp}_extracted"; Directory.CreateDirectory(extractedFolder); @@ -251,7 +251,7 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = LoadOsuIntoHost(host); - var temp = TestResources.GetTestBeatmapForImport(); + string temp = TestResources.GetTestBeatmapForImport(); string extractedFolder = $"{temp}_extracted"; Directory.CreateDirectory(extractedFolder); @@ -302,7 +302,7 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = LoadOsuIntoHost(host); - var temp = TestResources.GetTestBeatmapForImport(); + string temp = TestResources.GetTestBeatmapForImport(); string extractedFolder = $"{temp}_extracted"; Directory.CreateDirectory(extractedFolder); @@ -424,7 +424,7 @@ namespace osu.Game.Tests.Beatmaps.IO checkBeatmapCount(osu, 12); checkSingleReferencedFileCount(osu, 18); - var brokenTempFilename = TestResources.GetTestBeatmapForImport(); + string brokenTempFilename = TestResources.GetTestBeatmapForImport(); MemoryStream brokenOsu = new MemoryStream(); MemoryStream brokenOsz = new MemoryStream(await File.ReadAllBytesAsync(brokenTempFilename)); @@ -594,7 +594,7 @@ namespace osu.Game.Tests.Beatmaps.IO var osu = LoadOsuIntoHost(host); - var temp = TestResources.GetTestBeatmapForImport(); + string temp = TestResources.GetTestBeatmapForImport(); var importer = new ArchiveImportIPCChannel(client); if (!importer.ImportAsync(temp).Wait(10000)) @@ -619,7 +619,7 @@ namespace osu.Game.Tests.Beatmaps.IO try { var osu = LoadOsuIntoHost(host); - var temp = TestResources.GetTestBeatmapForImport(); + string temp = TestResources.GetTestBeatmapForImport(); using (File.OpenRead(temp)) await osu.Dependencies.Get().Import(temp); ensureLoaded(osu); @@ -642,7 +642,7 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = LoadOsuIntoHost(host); - var temp = TestResources.GetTestBeatmapForImport(); + string temp = TestResources.GetTestBeatmapForImport(); string extractedFolder = $"{temp}_extracted"; Directory.CreateDirectory(extractedFolder); @@ -684,7 +684,7 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = LoadOsuIntoHost(host); - var temp = TestResources.GetTestBeatmapForImport(); + string temp = TestResources.GetTestBeatmapForImport(); string extractedFolder = $"{temp}_extracted"; string subfolder = Path.Combine(extractedFolder, "subfolder"); @@ -729,7 +729,7 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = LoadOsuIntoHost(host); - var temp = TestResources.GetTestBeatmapForImport(); + string temp = TestResources.GetTestBeatmapForImport(); string extractedFolder = $"{temp}_extracted"; string dataFolder = Path.Combine(extractedFolder, "actual_data"); @@ -784,7 +784,7 @@ namespace osu.Game.Tests.Beatmaps.IO var osu = LoadOsuIntoHost(host); var manager = osu.Dependencies.Get(); - var temp = TestResources.GetTestBeatmapForImport(); + string temp = TestResources.GetTestBeatmapForImport(); await osu.Dependencies.Get().Import(temp); // Update via the beatmap, not the beatmap info, to ensure correct linking @@ -814,7 +814,7 @@ namespace osu.Game.Tests.Beatmaps.IO var osu = LoadOsuIntoHost(host); var manager = osu.Dependencies.Get(); - var temp = TestResources.GetTestBeatmapForImport(); + string temp = TestResources.GetTestBeatmapForImport(); await osu.Dependencies.Get().Import(temp); BeatmapSetInfo setToUpdate = manager.GetAllUsableBeatmapSets()[0]; @@ -905,7 +905,7 @@ namespace osu.Game.Tests.Beatmaps.IO public static async Task LoadQuickOszIntoOsu(OsuGameBase osu) { - var temp = TestResources.GetQuickTestBeatmapForImport(); + string temp = TestResources.GetQuickTestBeatmapForImport(); var manager = osu.Dependencies.Get(); @@ -920,7 +920,7 @@ namespace osu.Game.Tests.Beatmaps.IO public static async Task LoadOszIntoOsu(OsuGameBase osu, string path = null, bool virtualTrack = false) { - var temp = path ?? TestResources.GetTestBeatmapForImport(virtualTrack); + string temp = path ?? TestResources.GetTestBeatmapForImport(virtualTrack); var manager = osu.Dependencies.Get(); diff --git a/osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.cs index 25517ad615..5e37f01c81 100644 --- a/osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.cs @@ -114,7 +114,7 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.AreEqual("this line is gone", bufferedReader.ReadLine()); Assert.AreEqual("this one shouldn't be", bufferedReader.PeekLine()); - var endingLines = bufferedReader.ReadToEnd().Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + string[] endingLines = bufferedReader.ReadToEnd().Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); Assert.AreEqual(3, endingLines.Length); Assert.AreEqual("this one shouldn't be", endingLines[0]); Assert.AreEqual("these ones", endingLines[1]); diff --git a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs index 2c1e39c2cf..d11da5e2a3 100644 --- a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs @@ -36,8 +36,8 @@ namespace osu.Game.Tests.Beatmaps.IO "Soleily - Renatus (MMzz) [Muzukashii].osu", "Soleily - Renatus (MMzz) [Oni].osu" }; - var maps = reader.Filenames.ToArray(); - foreach (var map in expected) + string[] maps = reader.Filenames.ToArray(); + foreach (string map in expected) Assert.Contains(map, maps); } } diff --git a/osu.Game.Tests/Database/BeatmapImporterTests.cs b/osu.Game.Tests/Database/BeatmapImporterTests.cs index 4cdcf507b6..a21f935f6b 100644 --- a/osu.Game.Tests/Database/BeatmapImporterTests.cs +++ b/osu.Game.Tests/Database/BeatmapImporterTests.cs @@ -94,7 +94,7 @@ namespace osu.Game.Tests.Database using var importer = new BeatmapImporter(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage); - var tempPath = TestResources.GetTestBeatmapForImport(); + string? tempPath = TestResources.GetTestBeatmapForImport(); ILive? importedSet; @@ -144,7 +144,7 @@ namespace osu.Game.Tests.Database using var importer = new BeatmapImporter(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage); - var temp = TestResources.GetTestBeatmapForImport(); + string? temp = TestResources.GetTestBeatmapForImport(); string extractedFolder = $"{temp}_extracted"; Directory.CreateDirectory(extractedFolder); @@ -193,7 +193,7 @@ namespace osu.Game.Tests.Database using var importer = new BeatmapImporter(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage); - var temp = TestResources.GetTestBeatmapForImport(); + string? temp = TestResources.GetTestBeatmapForImport(); string extractedFolder = $"{temp}_extracted"; Directory.CreateDirectory(extractedFolder); @@ -245,7 +245,7 @@ namespace osu.Game.Tests.Database using var importer = new BeatmapImporter(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage); - var temp = TestResources.GetTestBeatmapForImport(); + string? temp = TestResources.GetTestBeatmapForImport(); string extractedFolder = $"{temp}_extracted"; Directory.CreateDirectory(extractedFolder); @@ -293,7 +293,7 @@ namespace osu.Game.Tests.Database using var importer = new BeatmapImporter(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage); - var temp = TestResources.GetTestBeatmapForImport(); + string? temp = TestResources.GetTestBeatmapForImport(); string extractedFolder = $"{temp}_extracted"; Directory.CreateDirectory(extractedFolder); @@ -391,7 +391,7 @@ namespace osu.Game.Tests.Database checkBeatmapCount(realmFactory.Context, 12); checkSingleReferencedFileCount(realmFactory.Context, 18); - var brokenTempFilename = TestResources.GetTestBeatmapForImport(); + string? brokenTempFilename = TestResources.GetTestBeatmapForImport(); MemoryStream brokenOsu = new MemoryStream(); MemoryStream brokenOsz = new MemoryStream(await File.ReadAllBytesAsync(brokenTempFilename)); @@ -522,7 +522,7 @@ namespace osu.Game.Tests.Database using var importer = new BeatmapImporter(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage); - var temp = TestResources.GetTestBeatmapForImport(); + string? temp = TestResources.GetTestBeatmapForImport(); using (File.OpenRead(temp)) await importer.Import(temp); ensureLoaded(realmFactory.Context); @@ -539,7 +539,7 @@ namespace osu.Game.Tests.Database using var importer = new BeatmapImporter(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage); - var temp = TestResources.GetTestBeatmapForImport(); + string? temp = TestResources.GetTestBeatmapForImport(); string extractedFolder = $"{temp}_extracted"; Directory.CreateDirectory(extractedFolder); @@ -575,7 +575,7 @@ namespace osu.Game.Tests.Database using var importer = new BeatmapImporter(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage); - var temp = TestResources.GetTestBeatmapForImport(); + string? temp = TestResources.GetTestBeatmapForImport(); string extractedFolder = $"{temp}_extracted"; string subfolder = Path.Combine(extractedFolder, "subfolder"); @@ -617,7 +617,7 @@ namespace osu.Game.Tests.Database using var importer = new BeatmapImporter(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage); - var temp = TestResources.GetTestBeatmapForImport(); + string? temp = TestResources.GetTestBeatmapForImport(); string extractedFolder = $"{temp}_extracted"; string dataFolder = Path.Combine(extractedFolder, "actual_data"); @@ -668,7 +668,7 @@ namespace osu.Game.Tests.Database using var importer = new BeatmapImporter(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage); - var temp = TestResources.GetTestBeatmapForImport(); + string? temp = TestResources.GetTestBeatmapForImport(); await importer.Import(temp); // Update via the beatmap, not the beatmap info, to ensure correct linking @@ -685,7 +685,7 @@ namespace osu.Game.Tests.Database public static async Task LoadQuickOszIntoOsu(BeatmapImporter importer, Realm realm) { - var temp = TestResources.GetQuickTestBeatmapForImport(); + string? temp = TestResources.GetQuickTestBeatmapForImport(); var importedSet = await importer.Import(new ImportTask(temp)); @@ -700,7 +700,7 @@ namespace osu.Game.Tests.Database public static async Task LoadOszIntoStore(BeatmapImporter importer, Realm realm, string? path = null, bool virtualTrack = false) { - var temp = path ?? TestResources.GetTestBeatmapForImport(virtualTrack); + string? temp = path ?? TestResources.GetTestBeatmapForImport(virtualTrack); var importedSet = await importer.Import(new ImportTask(temp)); diff --git a/osu.Game.Tests/NonVisual/BarLineGeneratorTest.cs b/osu.Game.Tests/NonVisual/BarLineGeneratorTest.cs index e663e1128e..834c05fd08 100644 --- a/osu.Game.Tests/NonVisual/BarLineGeneratorTest.cs +++ b/osu.Game.Tests/NonVisual/BarLineGeneratorTest.cs @@ -49,7 +49,7 @@ namespace osu.Game.Tests.NonVisual for (int i = 0; i * beat_length_denominator < barLines.Count; i++) { var barLine = barLines[i * beat_length_denominator]; - var expectedTime = beat_length_numerator * (int)signature * i; + int expectedTime = beat_length_numerator * (int)signature * i; // every seventh bar's start time should be at least greater than the whole number we expect. // It cannot be less, as that can affect overlapping scroll algorithms diff --git a/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs b/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs index 5e14af5c27..8a063b3c6e 100644 --- a/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs +++ b/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs @@ -87,7 +87,7 @@ namespace osu.Game.Tests.NonVisual File.WriteAllText(actualTestFile, "test"); var rulesetStorage = storage.GetStorageForDirectory("rulesets"); - var lookupPath = rulesetStorage.GetFiles(".").Single(); + string lookupPath = rulesetStorage.GetFiles(".").Single(); Assert.That(lookupPath, Is.EqualTo("test")); } @@ -140,7 +140,7 @@ namespace osu.Game.Tests.NonVisual Assert.That(osuStorage, Is.Not.Null); - foreach (var file in osuStorage.IgnoreFiles) + foreach (string file in osuStorage.IgnoreFiles) { // avoid touching realm files which may be a pipe and break everything. // this is also done locally inside OsuStorage via the IgnoreFiles list. @@ -149,7 +149,7 @@ namespace osu.Game.Tests.NonVisual Assert.That(storage.Exists(file), Is.False); } - foreach (var dir in osuStorage.IgnoreDirectories) + foreach (string dir in osuStorage.IgnoreDirectories) { Assert.That(Directory.Exists(Path.Combine(originalDirectory, dir))); Assert.That(storage.ExistsDirectory(dir), Is.False); diff --git a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs index 407dec936b..99d394b454 100644 --- a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs +++ b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs @@ -347,7 +347,7 @@ namespace osu.Game.Tests.NonVisual { for (int i = 0; i < 1000; i++) { - var time = handler.SetFrameFromTime(destination); + double? time = handler.SetFrameFromTime(destination); if (time == null || time == destination) return; } diff --git a/osu.Game.Tests/NonVisual/LimitedCapacityQueueTest.cs b/osu.Game.Tests/NonVisual/LimitedCapacityQueueTest.cs index a04415bc7f..e1eaf213d6 100644 --- a/osu.Game.Tests/NonVisual/LimitedCapacityQueueTest.cs +++ b/osu.Game.Tests/NonVisual/LimitedCapacityQueueTest.cs @@ -30,7 +30,7 @@ namespace osu.Game.Tests.NonVisual Assert.Throws(() => _ = queue.Dequeue()); int count = 0; - foreach (var _ in queue) + foreach (int _ in queue) count++; Assert.AreEqual(0, count); @@ -50,7 +50,7 @@ namespace osu.Game.Tests.NonVisual Assert.AreEqual(i, queue[i]); int j = 0; - foreach (var item in queue) + foreach (int item in queue) Assert.AreEqual(j++, item); for (int i = queue.Count; i < queue.Count + capacity; i++) @@ -71,7 +71,7 @@ namespace osu.Game.Tests.NonVisual Assert.AreEqual(count - capacity + i, queue[i]); int j = count - capacity; - foreach (var item in queue) + foreach (int item in queue) Assert.AreEqual(j++, item); for (int i = queue.Count; i < queue.Count + capacity; i++) diff --git a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs index 07ec86b0e7..8e2259bce8 100644 --- a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs +++ b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs @@ -84,7 +84,7 @@ namespace osu.Game.Tests.NonVisual.Multiplayer { for (int i = 0; i < userCount; ++i) { - var userId = Client.Room?.Users[i].UserID ?? throw new AssertionException("Room cannot be null!"); + int userId = Client.Room?.Users[i].UserID ?? throw new AssertionException("Room cannot be null!"); Client.ChangeUserState(userId, state); } }); diff --git a/osu.Game.Tests/NonVisual/ReverseQueueTest.cs b/osu.Game.Tests/NonVisual/ReverseQueueTest.cs index 93cd9403ce..808c8d14f0 100644 --- a/osu.Game.Tests/NonVisual/ReverseQueueTest.cs +++ b/osu.Game.Tests/NonVisual/ReverseQueueTest.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tests.NonVisual }); int count = 0; - foreach (var unused in queue) + foreach (char unused in queue) count++; Assert.AreEqual(0, count); @@ -72,7 +72,7 @@ namespace osu.Game.Tests.NonVisual // Assert correct item return and no longer in queue after dequeueing Assert.AreEqual('a', queue[5]); - var dequeuedItem = queue.Dequeue(); + char dequeuedItem = queue.Dequeue(); Assert.AreEqual('a', dequeuedItem); Assert.AreEqual(5, queue.Count); @@ -133,7 +133,7 @@ namespace osu.Game.Tests.NonVisual int expectedValueIndex = 0; // Assert items are enumerated in correct order - foreach (var item in queue) + foreach (char item in queue) { Assert.AreEqual(expectedValues[expectedValueIndex], item); expectedValueIndex++; diff --git a/osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs b/osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs index 5491774e26..1027b722d1 100644 --- a/osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs +++ b/osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Online MatchState = new TeamVersusRoomState() }; - var serialized = MessagePackSerializer.Serialize(room); + byte[] serialized = MessagePackSerializer.Serialize(room); var deserialized = MessagePackSerializer.Deserialize(serialized); @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Online { var state = new TeamVersusUserState(); - var serialized = MessagePackSerializer.Serialize(typeof(MatchUserState), state); + byte[] serialized = MessagePackSerializer.Serialize(typeof(MatchUserState), state); var deserialized = MessagePackSerializer.Deserialize(serialized); Assert.IsTrue(deserialized is TeamVersusUserState); @@ -44,7 +44,7 @@ namespace osu.Game.Tests.Online var state = new TeamVersusUserState(); // SignalR serialises using the actual type, rather than a base specification. - var serialized = MessagePackSerializer.Serialize(typeof(TeamVersusUserState), state); + byte[] serialized = MessagePackSerializer.Serialize(typeof(TeamVersusUserState), state); // works with explicit type specified. MessagePackSerializer.Deserialize(serialized); @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Online var state = new TeamVersusUserState(); // SignalR serialises using the actual type, rather than a base specification. - var serialized = MessagePackSerializer.Serialize(typeof(TeamVersusUserState), state, SignalRUnionWorkaroundResolver.OPTIONS); + byte[] serialized = MessagePackSerializer.Serialize(typeof(TeamVersusUserState), state, SignalRUnionWorkaroundResolver.OPTIONS); // works with explicit type specified. MessagePackSerializer.Deserialize(serialized); diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs index 839366d98e..dff9478852 100644 --- a/osu.Game.Tests/Resources/TestResources.cs +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tests.Resources /// A path to a copy of a beatmap archive (osz). Should be deleted after use. public static string GetQuickTestBeatmapForImport() { - var tempPath = getTempFilename(); + string tempPath = getTempFilename(); using (var stream = OpenResource("Archives/241526 Soleily - Renatus_virtual_quick.osz")) using (var newFile = File.Create(tempPath)) stream.CopyTo(newFile); @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Resources /// A path to a copy of a beatmap archive (osz). Should be deleted after use. public static string GetTestBeatmapForImport(bool virtualTrack = false) { - var tempPath = getTempFilename(); + string tempPath = getTempFilename(); using (var stream = GetTestBeatmapStream(virtualTrack)) using (var newFile = File.Create(tempPath)) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs index 6cf5e6a987..ed7bb9e301 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs @@ -72,7 +72,7 @@ namespace osu.Game.Tests.Visual.Editing private Vector2 getPositionForDivisor(int divisor) { - var relativePosition = (float)Math.Clamp(divisor, 0, 16) / 16; + float relativePosition = (float)Math.Clamp(divisor, 0, 16) / 16; var sliderDrawQuad = tickSliderBar.ScreenSpaceDrawQuad; return new Vector2( sliderDrawQuad.TopLeft.X + sliderDrawQuad.Width * relativePosition, diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs index 440d66ff9f..92c8131568 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.Editing { var setup = Editor.ChildrenOfType().First(); - var temp = TestResources.GetTestBeatmapForImport(); + string temp = TestResources.GetTestBeatmapForImport(); string extractedFolder = $"{temp}_extracted"; Directory.CreateDirectory(extractedFolder); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs index 477ac70501..abd43e7427 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual.Gameplay { showOverlay(); - var retryCount = 0; + int retryCount = 0; AddRepeatStep("Add retry", () => { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs index ade24b8740..bd5320354e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { PLAYER_2_ID, new ManualClock() } }; - foreach (var (userId, _) in clocks) + foreach ((int userId, var _) in clocks) { SpectatorClient.StartPlay(userId, 0); OnlinePlayDependencies.Client.AddUser(new User { Id = userId }); @@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("add clock sources", () => { - foreach (var (userId, clock) in clocks) + foreach ((int userId, var clock) in clocks) leaderboard.AddClock(userId, clock); }); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index bfcb55ce33..8d878b993c 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -289,7 +289,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestSpectatingDuringGameplay() { - var players = new[] { PLAYER_1_ID, PLAYER_2_ID }; + int[] players = new[] { PLAYER_1_ID, PLAYER_2_ID }; start(players); sendFrames(players, 300); @@ -326,7 +326,7 @@ namespace osu.Game.Tests.Visual.Multiplayer for (int count = 3; count >= 0; count--) { - var id = PLAYER_1_ID + count; + int id = PLAYER_1_ID + count; end(id); AddUntilStep($"{id} area grayed", () => getInstance(id).Colour != Color4.White); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 2bb77395ef..f4a72dd7e7 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -582,7 +582,7 @@ namespace osu.Game.Tests.Visual.Multiplayer // Gameplay runs in real-time, so we need to incrementally check if gameplay has finished in order to not time out. for (double i = 1000; i < TestResources.QUICK_BEATMAP_LENGTH; i += 1000) { - var time = i; + double time = i; AddUntilStep($"wait for time > {i}", () => this.ChildrenOfType().SingleOrDefault()?.GameplayClock.CurrentTime > time); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index 3317ddc767..eff107faee 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual.Multiplayer var playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); var multiplayerUsers = new List(); - foreach (var user in users) + foreach (int user in users) { SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0); multiplayerUsers.Add(OnlinePlayDependencies.Client.AddUser(new User { Id = user }, true)); @@ -89,7 +89,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestUserQuit() { - foreach (var user in users) + foreach (int user in users) AddStep($"mark user {user} quit", () => Client.RemoveUser(LookupCache.GetUserAsync(user).Result.AsNonNull())); } @@ -114,7 +114,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public void RandomlyUpdateState() { - foreach (var userId in PlayingUsers) + foreach (int userId in PlayingUsers) { if (RNG.NextBool()) continue; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index dfaf2f1dc3..32114fa500 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Visual.Multiplayer var playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); var multiplayerUsers = new List(); - foreach (var user in users) + foreach (int user in users) { SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0); var roomUser = OnlinePlayDependencies.Client.AddUser(new User { Id = user }, true); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs index d1980b03c7..e50b150f94 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs @@ -112,7 +112,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddRepeatStep("increment progress", () => { - var progress = this.ChildrenOfType().Single().User.BeatmapAvailability.DownloadProgress ?? 0; + float progress = this.ChildrenOfType().Single().User.BeatmapAvailability.DownloadProgress ?? 0; Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(progress + RNG.NextSingle(0.1f))); }, 25); diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index ab4e1b4457..99c3b398ab 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -190,8 +190,8 @@ namespace osu.Game.Tests.Visual.Online for (int zeroBasedIndex = 0; zeroBasedIndex < 10; ++zeroBasedIndex) { - var oneBasedIndex = zeroBasedIndex + 1; - var targetNumberKey = oneBasedIndex % 10; + int oneBasedIndex = zeroBasedIndex + 1; + int targetNumberKey = oneBasedIndex % 10; var targetChannel = channels[zeroBasedIndex]; AddStep($"Press Alt+{targetNumberKey}", () => pressChannelHotkey(targetNumberKey)); AddAssert($"Channel #{oneBasedIndex} is selected", () => currentChannel == targetChannel); diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs index 5bf9e31309..f577140e17 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs @@ -24,10 +24,10 @@ namespace osu.Game.Tests.Visual.Online { RankGraph graph; - var data = new int[89]; - var dataWithZeros = new int[89]; - var smallData = new int[89]; - var edgyData = new int[89]; + int[] data = new int[89]; + int[] dataWithZeros = new int[89]; + int[] smallData = new int[89]; + int[] edgyData = new int[89]; for (int i = 0; i < 89; i++) data[i] = dataWithZeros[i] = (i + 1) * 1000; diff --git a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs index 165fff99dd..b3b8d75c46 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs @@ -171,7 +171,7 @@ namespace osu.Game.Tests.Visual.Online { var indices = chatDisplay.FillFlow.OfType().Select(ds => chatDisplay.FillFlow.IndexOf(ds)); - foreach (var i in indices) + foreach (int i in indices) { if (i < chatDisplay.FillFlow.Count && chatDisplay.FillFlow[i + 1] is DrawableChannel.DaySeparator) return false; diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs index 08e61d19f4..27e989df76 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs @@ -75,7 +75,7 @@ namespace osu.Game.Tests.Visual.Online private bool checkBreadcrumb() { - var result = header.TabControlItems.Contains(wikiPageData.Value.Title); + bool result = header.TabControlItems.Contains(wikiPageData.Value.Title); if (wikiPageData.Value.Subtitle != null) result = header.TabControlItems.Contains(wikiPageData.Value.Subtitle) && result; diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiSidebar.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiSidebar.cs index b4f1997bb0..862b3667b1 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiSidebar.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiSidebar.cs @@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.Online { AddStep("Add TOC", () => { - for (var i = 0; i < 10; i++) + for (int i = 0; i < 10; i++) addTitle($"This is a very long title {i + 1}"); }); } @@ -46,7 +46,7 @@ namespace osu.Game.Tests.Visual.Online { AddStep("Add TOC", () => { - for (var i = 0; i < 10; i++) + for (int i = 0; i < 10; i++) addTitle($"This is a very long title {i + 1}", i % 4 != 0); }); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControlHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControlHeader.cs index 90c3e142df..7bc75f1c44 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControlHeader.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControlHeader.cs @@ -31,18 +31,18 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] public void TestAddAndRemoveItem() { - foreach (var item in items.Skip(1)) + foreach (string item in items.Skip(1)) AddStep($"Add {item} item", () => header.AddItem(item)); - foreach (var item in items.Reverse().SkipLast(3)) + foreach (string item in items.Reverse().SkipLast(3)) AddStep($"Remove {item} item", () => header.RemoveItem(item)); AddStep("Clear items", () => header.ClearItems()); - foreach (var item in items) + foreach (string item in items) AddStep($"Add {item} item", () => header.AddItem(item)); - foreach (var item in items) + foreach (string item in items) AddStep($"Remove {item} item", () => header.RemoveItem(item)); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs index 8d1572769f..0631059d1a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs @@ -73,8 +73,8 @@ namespace osu.Game.Tests.Visual.UserInterface private bool assertModsMultiplier(IEnumerable mods) { - var multiplier = mods.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier); - var expectedValue = multiplier.Equals(1.0) ? string.Empty : $"{multiplier:N2}x"; + double multiplier = mods.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier); + string expectedValue = multiplier.Equals(1.0) ? string.Empty : $"{multiplier:N2}x"; return expectedValue == footerButtonMods.MultiplierText.Current.Value; } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs index 096bccae9e..0bc4ac12d6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.UserInterface foreach (var p in typeof(OsuIcon).GetProperties(BindingFlags.Public | BindingFlags.Static)) { - var propValue = p.GetValue(null); + object propValue = p.GetValue(null); Debug.Assert(propValue != null); flow.Add(new Icon($"{nameof(OsuIcon)}.{p.Name}", (IconUsage)propValue)); diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 13888699ef..60be7dec91 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -101,12 +101,12 @@ namespace osu.Game.Tournament.Components return; } - var bpm = beatmapInfo.BeatmapSet.OnlineInfo.BPM; - var length = beatmapInfo.Length; + double bpm = beatmapInfo.BeatmapSet.OnlineInfo.BPM; + double length = beatmapInfo.Length; string hardRockExtra = ""; string srExtra = ""; - var ar = beatmapInfo.BaseDifficulty.ApproachRate; + float ar = beatmapInfo.BaseDifficulty.ApproachRate; if ((mods & LegacyMods.HardRock) > 0) { @@ -252,9 +252,9 @@ namespace osu.Game.Tournament.Components s.Font = OsuFont.Torus.With(weight: bold ? FontWeight.Bold : FontWeight.Regular, size: 15); } - for (var i = 0; i < tuples.Length; i++) + for (int i = 0; i < tuples.Length; i++) { - var (heading, content) = tuples[i]; + (string heading, string content) = tuples[i]; if (i > 0) { diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 7010a30eb7..6dde265bd6 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -46,7 +46,7 @@ namespace osu.Game.Tournament.IPC [BackgroundDependencyLoader] private void load() { - var stablePath = stableInfo.StablePath ?? findStablePath(); + string stablePath = stableInfo.StablePath ?? findStablePath(); initialiseIPCStorage(stablePath); } @@ -78,8 +78,8 @@ namespace osu.Game.Tournament.IPC using (var stream = IPCStorage.GetStream(file_ipc_filename)) using (var sr = new StreamReader(stream)) { - var beatmapId = int.Parse(sr.ReadLine().AsNonNull()); - var mods = int.Parse(sr.ReadLine().AsNonNull()); + int beatmapId = int.Parse(sr.ReadLine().AsNonNull()); + int mods = int.Parse(sr.ReadLine().AsNonNull()); if (lastBeatmapId != beatmapId) { @@ -187,10 +187,10 @@ namespace osu.Game.Tournament.IPC [CanBeNull] private string findStablePath() { - var stableInstallPath = findFromEnvVar() ?? - findFromRegistry() ?? - findFromLocalAppData() ?? - findFromDotFolder(); + string stableInstallPath = findFromEnvVar() ?? + findFromRegistry() ?? + findFromLocalAppData() ?? + findFromDotFolder(); Logger.Log($"Stable path for tourney usage: {stableInstallPath}"); return stableInstallPath; diff --git a/osu.Game.Tournament/JsonPointConverter.cs b/osu.Game.Tournament/JsonPointConverter.cs index 9c82f8ac06..32bbe2dc18 100644 --- a/osu.Game.Tournament/JsonPointConverter.cs +++ b/osu.Game.Tournament/JsonPointConverter.cs @@ -40,7 +40,7 @@ namespace osu.Game.Tournament if (reader.TokenType == JsonToken.PropertyName) { - var name = reader.Value?.ToString(); + string name = reader.Value?.ToString(); int? val = reader.ReadAsInt32(); if (val == null) diff --git a/osu.Game.Tournament/Models/TournamentTeam.cs b/osu.Game.Tournament/Models/TournamentTeam.cs index 7074ae413c..d895e4b538 100644 --- a/osu.Game.Tournament/Models/TournamentTeam.cs +++ b/osu.Game.Tournament/Models/TournamentTeam.cs @@ -36,10 +36,10 @@ namespace osu.Game.Tournament.Models { get { - var ranks = Players.Select(p => p.Statistics?.GlobalRank) - .Where(i => i.HasValue) - .Select(i => i.Value) - .ToArray(); + int[] ranks = Players.Select(p => p.Statistics?.GlobalRank) + .Where(i => i.HasValue) + .Select(i => i.Value) + .ToArray(); if (ranks.Length == 0) return 0; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs index 77101e4023..813bed86ae 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs @@ -114,7 +114,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components var winningBar = score1.Value > score2.Value ? score1Bar : score2Bar; var losingBar = score1.Value <= score2.Value ? score1Bar : score2Bar; - var diff = Math.Max(score1.Value, score2.Value) - Math.Min(score1.Value, score2.Value); + int diff = Math.Max(score1.Value, score2.Value) - Math.Min(score1.Value, score2.Value); losingBar.ResizeWidthTo(0, 400, Easing.OutQuint); winningBar.ResizeWidthTo(Math.Min(0.4f, MathF.Pow(diff / 1500000f, 0.5f) / 2), 400, Easing.OutQuint); diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs index 6937c69dbf..3e950310cf 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs @@ -208,7 +208,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { if (Match.Round.Value == null) return; - var instaWinAmount = Match.Round.Value.BestOf.Value / 2; + int instaWinAmount = Match.Round.Value.BestOf.Value / 2; Match.Completed.Value = Match.Round.Value.BestOf.Value > 0 && (Match.Team1Score.Value + Match.Team2Score.Value >= Match.Round.Value.BestOf.Value || Match.Team1Score.Value > instaWinAmount || Match.Team2Score.Value > instaWinAmount); @@ -243,8 +243,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { foreach (var conditional in Match.ConditionalMatches) { - var team1Match = conditional.Acronyms.Contains(Match.Team1Acronym); - var team2Match = conditional.Acronyms.Contains(Match.Team2Acronym); + bool team1Match = conditional.Acronyms.Contains(Match.Team1Acronym); + bool team2Match = conditional.Acronyms.Contains(Match.Team2Acronym); if (team1Match && team2Match) Match.Date.Value = conditional.Date.Value; diff --git a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs index fa03518c47..f98bfd087d 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs @@ -34,7 +34,7 @@ namespace osu.Game.Tournament.Screens.Ladder protected override bool OnScroll(ScrollEvent e) { - var newScale = Math.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); + float newScale = Math.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); this.MoveTo(target -= e.MousePosition * (newScale - scale), 2000, Easing.OutQuint); this.ScaleTo(scale = newScale, 2000, Easing.OutQuint); diff --git a/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs b/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs index 4b518ea7c7..e53110651b 100644 --- a/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs +++ b/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs @@ -31,7 +31,7 @@ namespace osu.Game.Tournament.Screens.Setup return; // box contains text - if (!int.TryParse(numberBox.Text, out var number)) + if (!int.TryParse(numberBox.Text, out int number)) { // at this point, the only reason we can arrive here is if the input number was too big to parse into an int // so clamp to max allowed value diff --git a/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs index 3752d9d3be..8e9b32231f 100644 --- a/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs @@ -37,7 +37,7 @@ namespace osu.Game.Tournament.Screens.Setup private void load(Storage storage, OsuColour colours) { var initialStorage = (ipc as FileBasedIPC)?.IPCStorage ?? storage; - var initialPath = new DirectoryInfo(initialStorage.GetFullPath(string.Empty)).Parent?.FullName; + string initialPath = new DirectoryInfo(initialStorage.GetFullPath(string.Empty)).Parent?.FullName; AddRangeInternal(new Drawable[] { @@ -129,7 +129,7 @@ namespace osu.Game.Tournament.Screens.Setup protected virtual void ChangePath() { - var target = directorySelector.CurrentPath.Value.FullName; + string target = directorySelector.CurrentPath.Value.FullName; var fileBasedIpc = ipc as FileBasedIPC; Logger.Log($"Changing Stable CE location to {target}"); diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index f3927bb852..f03f815b83 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -134,7 +134,7 @@ namespace osu.Game.Tournament windowSize.BindValueChanged(size => ScheduleAfterChildren(() => { - var minWidth = (int)(size.NewValue.Height / 768f * TournamentSceneManager.REQUIRED_WIDTH) - 1; + int minWidth = (int)(size.NewValue.Height / 768f * TournamentSceneManager.REQUIRED_WIDTH) - 1; heightWarning.Alpha = size.NewValue.Width < minWidth ? 1 : 0; }), true); diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index a6b0fa5cfc..978be720df 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -109,7 +109,7 @@ namespace osu.Game.Tournament // link matches to rounds foreach (var round in ladder.Rounds) { - foreach (var id in round.Matches) + foreach (int id in round.Matches) { var found = ladder.Matches.FirstOrDefault(p => p.ID == id); diff --git a/osu.Game/Audio/Effects/AudioFilter.cs b/osu.Game/Audio/Effects/AudioFilter.cs index d2a39e9db7..9446967173 100644 --- a/osu.Game/Audio/Effects/AudioFilter.cs +++ b/osu.Game/Audio/Effects/AudioFilter.cs @@ -103,7 +103,7 @@ namespace osu.Game.Audio.Effects ensureAttached(); - var filterIndex = mixer.Effects.IndexOf(filter); + int filterIndex = mixer.Effects.IndexOf(filter); if (filterIndex < 0) return; diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index b2211e26cf..98087994b7 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -93,7 +93,7 @@ namespace osu.Game.Beatmaps if (t.Time > lastTime) return (beatLength: t.BeatLength, 0); - var nextTime = i == ControlPointInfo.TimingPoints.Count - 1 ? lastTime : ControlPointInfo.TimingPoints[i + 1].Time; + double nextTime = i == ControlPointInfo.TimingPoints.Count - 1 ? lastTime : ControlPointInfo.TimingPoints[i + 1].Time; return (beatLength: t.BeatLength, duration: nextTime - t.Time); }) // Aggregate durations into a set of (beatLength, duration) tuples for each beat length diff --git a/osu.Game/Beatmaps/BeatmapInfoExtensions.cs b/osu.Game/Beatmaps/BeatmapInfoExtensions.cs index 836302c424..c35370d572 100644 --- a/osu.Game/Beatmaps/BeatmapInfoExtensions.cs +++ b/osu.Game/Beatmaps/BeatmapInfoExtensions.cs @@ -22,7 +22,7 @@ namespace osu.Game.Beatmaps if (includeDifficultyName) { - var versionString = getVersionString(beatmapInfo); + string versionString = getVersionString(beatmapInfo); return new RomanisableString($"{metadata.GetPreferred(true)} {versionString}".Trim(), $"{metadata.GetPreferred(false)} {versionString}".Trim()); } diff --git a/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs b/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs index ee946eeeec..732b76e967 100644 --- a/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs +++ b/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs @@ -37,8 +37,8 @@ namespace osu.Game.Beatmaps 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; + string artistUnicode = string.IsNullOrEmpty(metadataInfo.ArtistUnicode) ? metadataInfo.Artist : metadataInfo.ArtistUnicode; + string titleUnicode = string.IsNullOrEmpty(metadataInfo.TitleUnicode) ? metadataInfo.Title : metadataInfo.TitleUnicode; return new RomanisableString($"{artistUnicode} - {titleUnicode} {author}".Trim(), $"{metadataInfo.Artist} - {metadataInfo.Title} {author}".Trim()); } diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 9d738ecbfb..246d1f8af5 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -180,8 +180,8 @@ namespace osu.Game.Beatmaps.ControlPoints private static double getClosestSnappedTime(TimingControlPoint timingPoint, double time, int beatDivisor) { - var beatLength = timingPoint.BeatLength / beatDivisor; - var beatLengths = (int)Math.Round((time - timingPoint.Time) / beatLength, MidpointRounding.AwayFromZero); + double beatLength = timingPoint.BeatLength / beatDivisor; + int beatLengths = (int)Math.Round((time - timingPoint.Time) / beatLength, MidpointRounding.AwayFromZero); return timingPoint.Time + beatLengths * beatLength; } diff --git a/osu.Game/Beatmaps/DifficultyRecommender.cs b/osu.Game/Beatmaps/DifficultyRecommender.cs index b1b1e58ab7..86f5e0dabf 100644 --- a/osu.Game/Beatmaps/DifficultyRecommender.cs +++ b/osu.Game/Beatmaps/DifficultyRecommender.cs @@ -59,12 +59,12 @@ namespace osu.Game.Beatmaps { foreach (var r in orderedRulesets) { - if (!recommendedDifficultyMapping.TryGetValue(r, out var recommendation)) + if (!recommendedDifficultyMapping.TryGetValue(r, out double recommendation)) continue; BeatmapInfo beatmapInfo = beatmaps.Where(b => b.Ruleset.Equals(r)).OrderBy(b => { - var difference = b.StarDifficulty - recommendation; + double difference = b.StarDifficulty - recommendation; return difference >= 0 ? difference * 2 : difference * -1; // prefer easier over harder }).FirstOrDefault(); diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 7cd4244cd0..89541a0845 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -295,7 +295,7 @@ namespace osu.Game.Beatmaps.Formats writer.WriteLine("[Colours]"); - for (var i = 0; i < colours.Count; i++) + for (int i = 0; i < colours.Count; i++) { var comboColour = colours[i]; diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index cf6c827af5..56525ddb14 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -89,7 +89,7 @@ namespace osu.Game.Beatmaps.Formats protected string StripComments(string line) { - var index = line.AsSpan().IndexOf("//".AsSpan()); + int index = line.AsSpan().IndexOf("//".AsSpan()); if (index > 0) return line.Substring(0, index); @@ -135,7 +135,7 @@ namespace osu.Game.Beatmaps.Formats protected KeyValuePair SplitKeyVal(string line, char separator = ':') { - var split = line.Split(separator, 2); + string[] split = line.Split(separator, 2); return new KeyValuePair ( diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 0f15e28c00..90a96e2ac8 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -77,7 +77,7 @@ namespace osu.Game.Beatmaps.Formats private void handleEvents(string line) { - var depth = 0; + int depth = 0; foreach (char c in line) { @@ -104,8 +104,8 @@ namespace osu.Game.Beatmaps.Formats { case LegacyEventType.Video: { - var offset = Parsing.ParseInt(split[1]); - var path = CleanFilename(split[2]); + int offset = Parsing.ParseInt(split[1]); + string path = CleanFilename(split[2]); storyboard.GetLayer("Video").Add(new StoryboardVideo(path, offset)); break; @@ -113,11 +113,11 @@ namespace osu.Game.Beatmaps.Formats case LegacyEventType.Sprite: { - var layer = parseLayer(split[1]); + string layer = parseLayer(split[1]); var origin = parseOrigin(split[2]); - var path = CleanFilename(split[3]); - var x = Parsing.ParseFloat(split[4], Parsing.MAX_COORDINATE_VALUE); - var y = Parsing.ParseFloat(split[5], Parsing.MAX_COORDINATE_VALUE); + string path = CleanFilename(split[3]); + float x = Parsing.ParseFloat(split[4], Parsing.MAX_COORDINATE_VALUE); + float y = Parsing.ParseFloat(split[5], Parsing.MAX_COORDINATE_VALUE); storyboardSprite = new StoryboardSprite(path, origin, new Vector2(x, y)); storyboard.GetLayer(layer).Add(storyboardSprite); break; @@ -125,13 +125,13 @@ namespace osu.Game.Beatmaps.Formats case LegacyEventType.Animation: { - var layer = parseLayer(split[1]); + string layer = parseLayer(split[1]); var origin = parseOrigin(split[2]); - var path = CleanFilename(split[3]); - var x = Parsing.ParseFloat(split[4], Parsing.MAX_COORDINATE_VALUE); - var y = Parsing.ParseFloat(split[5], Parsing.MAX_COORDINATE_VALUE); - var frameCount = Parsing.ParseInt(split[6]); - var frameDelay = Parsing.ParseDouble(split[7]); + string path = CleanFilename(split[3]); + float x = Parsing.ParseFloat(split[4], Parsing.MAX_COORDINATE_VALUE); + float y = Parsing.ParseFloat(split[5], Parsing.MAX_COORDINATE_VALUE); + int frameCount = Parsing.ParseInt(split[6]); + double frameDelay = Parsing.ParseDouble(split[7]); if (FormatVersion < 6) // this is random as hell but taken straight from osu-stable. @@ -145,10 +145,10 @@ namespace osu.Game.Beatmaps.Formats case LegacyEventType.Sample: { - var time = Parsing.ParseDouble(split[1]); - var layer = parseLayer(split[2]); - var path = CleanFilename(split[3]); - var volume = split.Length > 4 ? Parsing.ParseFloat(split[4]) : 100; + double time = Parsing.ParseDouble(split[1]); + string layer = parseLayer(split[2]); + string path = CleanFilename(split[3]); + float volume = split.Length > 4 ? Parsing.ParseFloat(split[4]) : 100; storyboard.GetLayer(layer).Add(new StoryboardSampleInfo(path, time, (int)volume)); break; } @@ -159,24 +159,24 @@ namespace osu.Game.Beatmaps.Formats if (depth < 2) timelineGroup = storyboardSprite?.TimelineGroup; - var commandType = split[0]; + string commandType = split[0]; switch (commandType) { case "T": { - var triggerName = split[1]; - var startTime = split.Length > 2 ? Parsing.ParseDouble(split[2]) : double.MinValue; - var endTime = split.Length > 3 ? Parsing.ParseDouble(split[3]) : double.MaxValue; - var groupNumber = split.Length > 4 ? Parsing.ParseInt(split[4]) : 0; + string triggerName = split[1]; + double startTime = split.Length > 2 ? Parsing.ParseDouble(split[2]) : double.MinValue; + double endTime = split.Length > 3 ? Parsing.ParseDouble(split[3]) : double.MaxValue; + int groupNumber = split.Length > 4 ? Parsing.ParseInt(split[4]) : 0; timelineGroup = storyboardSprite?.AddTrigger(triggerName, startTime, endTime, groupNumber); break; } case "L": { - var startTime = Parsing.ParseDouble(split[1]); - var repeatCount = Parsing.ParseInt(split[2]); + double startTime = Parsing.ParseDouble(split[1]); + int repeatCount = Parsing.ParseInt(split[2]); timelineGroup = storyboardSprite?.AddLoop(startTime, Math.Max(0, repeatCount - 1)); break; } @@ -187,51 +187,51 @@ namespace osu.Game.Beatmaps.Formats split[3] = split[2]; var easing = (Easing)Parsing.ParseInt(split[1]); - var startTime = Parsing.ParseDouble(split[2]); - var endTime = Parsing.ParseDouble(split[3]); + double startTime = Parsing.ParseDouble(split[2]); + double endTime = Parsing.ParseDouble(split[3]); switch (commandType) { case "F": { - var startValue = Parsing.ParseFloat(split[4]); - var endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue; + float startValue = Parsing.ParseFloat(split[4]); + float endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue; timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue); break; } case "S": { - var startValue = Parsing.ParseFloat(split[4]); - var endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue; + float startValue = Parsing.ParseFloat(split[4]); + float endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue; timelineGroup?.Scale.Add(easing, startTime, endTime, startValue, endValue); break; } case "V": { - var startX = Parsing.ParseFloat(split[4]); - var startY = Parsing.ParseFloat(split[5]); - var endX = split.Length > 6 ? Parsing.ParseFloat(split[6]) : startX; - var endY = split.Length > 7 ? Parsing.ParseFloat(split[7]) : startY; + float startX = Parsing.ParseFloat(split[4]); + float startY = Parsing.ParseFloat(split[5]); + float endX = split.Length > 6 ? Parsing.ParseFloat(split[6]) : startX; + float endY = split.Length > 7 ? Parsing.ParseFloat(split[7]) : startY; timelineGroup?.VectorScale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY)); break; } case "R": { - var startValue = Parsing.ParseFloat(split[4]); - var endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue; + float startValue = Parsing.ParseFloat(split[4]); + float endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue; timelineGroup?.Rotation.Add(easing, startTime, endTime, MathUtils.RadiansToDegrees(startValue), MathUtils.RadiansToDegrees(endValue)); break; } case "M": { - var startX = Parsing.ParseFloat(split[4]); - var startY = Parsing.ParseFloat(split[5]); - var endX = split.Length > 6 ? Parsing.ParseFloat(split[6]) : startX; - var endY = split.Length > 7 ? Parsing.ParseFloat(split[7]) : startY; + float startX = Parsing.ParseFloat(split[4]); + float startY = Parsing.ParseFloat(split[5]); + float endX = split.Length > 6 ? Parsing.ParseFloat(split[6]) : startX; + float endY = split.Length > 7 ? Parsing.ParseFloat(split[7]) : startY; timelineGroup?.X.Add(easing, startTime, endTime, startX, endX); timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY); break; @@ -239,28 +239,28 @@ namespace osu.Game.Beatmaps.Formats case "MX": { - var startValue = Parsing.ParseFloat(split[4]); - var endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue; + float startValue = Parsing.ParseFloat(split[4]); + float endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue; timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue); break; } case "MY": { - var startValue = Parsing.ParseFloat(split[4]); - var endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue; + float startValue = Parsing.ParseFloat(split[4]); + float endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue; timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue); break; } case "C": { - var startRed = Parsing.ParseFloat(split[4]); - var startGreen = Parsing.ParseFloat(split[5]); - var startBlue = Parsing.ParseFloat(split[6]); - var endRed = split.Length > 7 ? Parsing.ParseFloat(split[7]) : startRed; - var endGreen = split.Length > 8 ? Parsing.ParseFloat(split[8]) : startGreen; - var endBlue = split.Length > 9 ? Parsing.ParseFloat(split[9]) : startBlue; + float startRed = Parsing.ParseFloat(split[4]); + float startGreen = Parsing.ParseFloat(split[5]); + float startBlue = Parsing.ParseFloat(split[6]); + float endRed = split.Length > 7 ? Parsing.ParseFloat(split[7]) : startRed; + float endGreen = split.Length > 8 ? Parsing.ParseFloat(split[8]) : startGreen; + float endBlue = split.Length > 9 ? Parsing.ParseFloat(split[9]) : startBlue; timelineGroup?.Colour.Add(easing, startTime, endTime, new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1), new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1)); @@ -269,7 +269,7 @@ namespace osu.Game.Beatmaps.Formats case "P": { - var type = split[4]; + string type = split[4]; switch (type) { diff --git a/osu.Game/Beatmaps/Formats/Parsing.cs b/osu.Game/Beatmaps/Formats/Parsing.cs index c4795a6931..4d512fdeed 100644 --- a/osu.Game/Beatmaps/Formats/Parsing.cs +++ b/osu.Game/Beatmaps/Formats/Parsing.cs @@ -17,7 +17,7 @@ namespace osu.Game.Beatmaps.Formats public static float ParseFloat(string input, float parseLimit = (float)MAX_PARSE_VALUE) { - var output = float.Parse(input, CultureInfo.InvariantCulture); + float output = float.Parse(input, CultureInfo.InvariantCulture); if (output < -parseLimit) throw new OverflowException("Value is too low"); if (output > parseLimit) throw new OverflowException("Value is too high"); @@ -29,7 +29,7 @@ namespace osu.Game.Beatmaps.Formats public static double ParseDouble(string input, double parseLimit = MAX_PARSE_VALUE) { - var output = double.Parse(input, CultureInfo.InvariantCulture); + double output = double.Parse(input, CultureInfo.InvariantCulture); if (output < -parseLimit) throw new OverflowException("Value is too low"); if (output > parseLimit) throw new OverflowException("Value is too high"); @@ -41,7 +41,7 @@ namespace osu.Game.Beatmaps.Formats public static int ParseInt(string input, int parseLimit = (int)MAX_PARSE_VALUE) { - var output = int.Parse(input, CultureInfo.InvariantCulture); + int output = int.Parse(input, CultureInfo.InvariantCulture); if (output < -parseLimit) throw new OverflowException("Value is too low"); if (output > parseLimit) throw new OverflowException("Value is too high"); diff --git a/osu.Game/Beatmaps/MetadataUtils.cs b/osu.Game/Beatmaps/MetadataUtils.cs index 56f5e3fe35..b27c59b4de 100644 --- a/osu.Game/Beatmaps/MetadataUtils.cs +++ b/osu.Game/Beatmaps/MetadataUtils.cs @@ -35,7 +35,7 @@ namespace osu.Game.Beatmaps var stringBuilder = new StringBuilder(str.Length); - foreach (var c in str) + foreach (char c in str) { if (IsRomanised(c)) stringBuilder.Append(c); diff --git a/osu.Game/Beatmaps/WorkingBeatmapCache.cs b/osu.Game/Beatmaps/WorkingBeatmapCache.cs index cf83345e2a..65f84984c2 100644 --- a/osu.Game/Beatmaps/WorkingBeatmapCache.cs +++ b/osu.Game/Beatmaps/WorkingBeatmapCache.cs @@ -206,7 +206,7 @@ namespace osu.Game.Beatmaps { var decoder = Decoder.GetDecoder(stream); - var storyboardFilename = BeatmapSetInfo?.Files.FirstOrDefault(f => f.Filename.EndsWith(".osb", StringComparison.OrdinalIgnoreCase))?.Filename; + string storyboardFilename = BeatmapSetInfo?.Files.FirstOrDefault(f => f.Filename.EndsWith(".osb", StringComparison.OrdinalIgnoreCase))?.Filename; // todo: support loading from both set-wide storyboard *and* beatmap specific. if (string.IsNullOrEmpty(storyboardFilename)) diff --git a/osu.Game/Collections/CollectionManager.cs b/osu.Game/Collections/CollectionManager.cs index 6f9d9cd8a8..9ff92032b7 100644 --- a/osu.Game/Collections/CollectionManager.cs +++ b/osu.Game/Collections/CollectionManager.cs @@ -250,7 +250,7 @@ namespace osu.Game.Collections /// private void backgroundSave() { - var current = Interlocked.Increment(ref lastSave); + int current = Interlocked.Increment(ref lastSave); Task.Delay(100).ContinueWith(task => { if (current != lastSave) @@ -270,7 +270,7 @@ namespace osu.Game.Collections // This is NOT thread-safe!! try { - var tempPath = Path.GetTempFileName(); + string tempPath = Path.GetTempFileName(); using (var ms = new MemoryStream()) { @@ -296,8 +296,8 @@ namespace osu.Game.Collections using (var fs = File.OpenWrite(tempPath)) ms.WriteTo(fs); - var databasePath = storage.GetFullPath(database_name); - var databaseBackupPath = storage.GetFullPath(database_backup_name); + string databasePath = storage.GetFullPath(database_name); + string databaseBackupPath = storage.GetFullPath(database_backup_name); // Back up the existing database, clearing any existing backup. if (File.Exists(databaseBackupPath)) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 6d37f68473..1beef89b51 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -160,12 +160,12 @@ namespace osu.Game.Configuration public void Migrate() { // arrives as 2020.123.0 - var rawVersion = Get(OsuSetting.Version); + string rawVersion = Get(OsuSetting.Version); if (rawVersion.Length < 6) return; - var pieces = rawVersion.Split('.'); + string[] pieces = rawVersion.Split('.'); // on a fresh install or when coming from a non-release build, execution will end here. // we don't want to run migrations in such cases. diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index f3ed2d735b..c180edbed2 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -675,7 +675,7 @@ namespace osu.Game.Database { MemoryStream hashable = new MemoryStream(); - foreach (var file in reader.Filenames.Where(f => HashableFileTypes.Any(ext => f.EndsWith(ext, StringComparison.OrdinalIgnoreCase))).OrderBy(f => f)) + foreach (string file in reader.Filenames.Where(f => HashableFileTypes.Any(ext => f.EndsWith(ext, StringComparison.OrdinalIgnoreCase))).OrderBy(f => f)) { using (Stream s = reader.GetStream(file)) s.CopyTo(hashable); diff --git a/osu.Game/Database/DatabaseBackedStore.cs b/osu.Game/Database/DatabaseBackedStore.cs index e6b6a0ac2f..a11efba54b 100644 --- a/osu.Game/Database/DatabaseBackedStore.cs +++ b/osu.Game/Database/DatabaseBackedStore.cs @@ -27,7 +27,7 @@ namespace osu.Game.Database if (context.Entry(obj).State != EntityState.Detached) return; - var id = obj.ID; + int id = obj.ID; var foundObject = lookupSource?.SingleOrDefault(t => t.ID == id) ?? context.Find(id); if (foundObject != null) obj = foundObject; diff --git a/osu.Game/Database/RealmContextFactory.cs b/osu.Game/Database/RealmContextFactory.cs index 3d0bb34dc1..ffb1c96261 100644 --- a/osu.Game/Database/RealmContextFactory.cs +++ b/osu.Game/Database/RealmContextFactory.cs @@ -156,7 +156,7 @@ namespace osu.Game.Database void convertOnlineIDs() where T : RealmObject { - var className = typeof(T).Name.Replace(@"Realm", string.Empty); + string? className = typeof(T).Name.Replace(@"Realm", string.Empty); // version was not bumped when the beatmap/ruleset models were added // therefore we must manually check for their presence to avoid throwing on the `DynamicApi` calls. @@ -170,8 +170,8 @@ namespace osu.Game.Database for (int i = 0; i < itemCount; i++) { - var oldItem = oldItems.ElementAt(i); - var newItem = newItems.ElementAt(i); + dynamic? oldItem = oldItems.ElementAt(i); + dynamic? newItem = newItems.ElementAt(i); long? nullableOnlineID = oldItem?.OnlineID; newItem.OnlineID = (int)(nullableOnlineID ?? -1); diff --git a/osu.Game/Database/StableImportManager.cs b/osu.Game/Database/StableImportManager.cs index 63a6db35c0..fe8c14c085 100644 --- a/osu.Game/Database/StableImportManager.cs +++ b/osu.Game/Database/StableImportManager.cs @@ -78,7 +78,7 @@ namespace osu.Game.Database var taskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Schedule(() => dialogOverlay.Push(new StableDirectoryLocationDialog(taskCompletionSource))); - var stablePath = await taskCompletionSource.Task.ConfigureAwait(false); + string stablePath = await taskCompletionSource.Task.ConfigureAwait(false); return cachedStorage = new StableStorage(stablePath, desktopGameHost); } diff --git a/osu.Game/Database/UserLookupCache.cs b/osu.Game/Database/UserLookupCache.cs index ff81637efb..3626f5e83a 100644 --- a/osu.Game/Database/UserLookupCache.cs +++ b/osu.Game/Database/UserLookupCache.cs @@ -37,7 +37,7 @@ namespace osu.Game.Database { var userLookupTasks = new List>(); - foreach (var u in userIds) + foreach (int u in userIds) { userLookupTasks.Add(GetUserAsync(u, token).ContinueWith(task => { diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index ab8763e576..450c93f37c 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -214,7 +214,7 @@ namespace osu.Game.Graphics.Backgrounds float u1 = 1 - nextRandom(); //uniform(0,1] random floats float u2 = 1 - nextRandom(); float randStdNormal = (float)(Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2)); // random normal(0,1) - var scale = Math.Max(triangleScale * (mean + std_dev * randStdNormal), 0.1f); // random normal(mean,stdDev^2) + float scale = Math.Max(triangleScale * (mean + std_dev * randStdNormal), 0.1f); // random normal(mean,stdDev^2) return new TriangleParticle { Scale = scale }; } diff --git a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs b/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs index 9d3f342a70..9e1af1944c 100644 --- a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs +++ b/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs @@ -43,7 +43,7 @@ namespace osu.Game.Graphics.Containers // - If we were to use RelativeSize/FillMode, we'd need to set the Icon's RelativeSizeAxes directly. // We can't do this because we would need access to AutoSizeAxes to set it to none. // Other issues come up along the way too, so it's not a good solution. - var fitScale = Math.Min(DrawSize.X / InternalChild.DrawSize.X, DrawSize.Y / InternalChild.DrawSize.Y); + float fitScale = Math.Min(DrawSize.X / InternalChild.DrawSize.X, DrawSize.Y / InternalChild.DrawSize.Y); InternalChild.Scale = new Vector2(fitScale); InternalChild.Anchor = Anchor.Centre; InternalChild.Origin = Anchor.Centre; diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index dadd7d5240..f89f3a5e76 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -109,7 +109,7 @@ namespace osu.Game.Graphics.Containers { double elapsedDuration = (double)(Time.Current - startTime); - var amount = (float)Interpolation.ApplyEasing(easing, Math.Min(elapsedDuration / duration, 1)); + float amount = (float)Interpolation.ApplyEasing(easing, Math.Min(elapsedDuration / duration, 1)); // Interpolate the position of the logo, where amount 0 is where the logo was when it first began interpolating, and amount 1 is the target location. Logo.Position = Vector2.Lerp(startPosition.Value, localPos, amount); diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 76492cab55..540ca85809 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -182,7 +182,7 @@ namespace osu.Game.Graphics.Containers protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source) { - var result = base.OnInvalidate(invalidation, source); + bool result = base.OnInvalidate(invalidation, source); if (source == InvalidationSource.Child && (invalidation & Invalidation.DrawSize) != 0) { @@ -240,7 +240,7 @@ namespace osu.Game.Graphics.Containers headerBackgroundContainer.Height = expandableHeaderSize + fixedHeaderSize; headerBackgroundContainer.Y = ExpandableHeader?.Y ?? 0; - var smallestSectionHeight = Children.Count > 0 ? Children.Min(d => d.Height) : 0; + float smallestSectionHeight = Children.Count > 0 ? Children.Min(d => d.Height) : 0; // scroll offset is our fixed header height if we have it plus 10% of content height // plus 5% to fix floating point errors and to not have a section instantly unselect when scrolling upwards diff --git a/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs b/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs index 90b2d20e4d..4ddaa09be6 100644 --- a/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs +++ b/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs @@ -40,7 +40,7 @@ namespace osu.Game.Graphics.Containers public void Select(T item) { - var newIndex = IndexOf(item); + int newIndex = IndexOf(item); if (newIndex < 0) setSelected(null); diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index fd8f016860..3fa90e2330 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -44,7 +44,7 @@ namespace osu.Game.Graphics.Cursor if (dragRotationState != DragRotationState.NotDragging) { var position = e.MousePosition; - var distance = Vector2Extensions.Distance(position, positionMouseDown); + float distance = Vector2Extensions.Distance(position, positionMouseDown); // don't start rotating until we're moved a minimum distance away from the mouse down location, // else it can have an annoying effect. diff --git a/osu.Game/Graphics/ErrorTextFlowContainer.cs b/osu.Game/Graphics/ErrorTextFlowContainer.cs index f17a2a2c3d..486382bf33 100644 --- a/osu.Game/Graphics/ErrorTextFlowContainer.cs +++ b/osu.Game/Graphics/ErrorTextFlowContainer.cs @@ -28,7 +28,7 @@ namespace osu.Game.Graphics if (errors == null) return; - foreach (var error in errors) + foreach (string error in errors) errorDrawables.AddRange(AddParagraph(error, cp => cp.Colour = Color4.Red)); } } diff --git a/osu.Game/Graphics/ParticleExplosion.cs b/osu.Game/Graphics/ParticleExplosion.cs index 094cc87bbe..ec1077eb81 100644 --- a/osu.Game/Graphics/ParticleExplosion.cs +++ b/osu.Game/Graphics/ParticleExplosion.cs @@ -89,7 +89,7 @@ namespace osu.Game.Graphics protected override void Blit(Action vertexAction) { - var time = currentTime - startTime; + double time = currentTime - startTime; foreach (var p in parts) { @@ -136,7 +136,7 @@ namespace osu.Game.Graphics public Vector2 PositionAtTime(double time) { - var travelledDistance = distance * progressAtTime(time); + float travelledDistance = distance * progressAtTime(time); return new Vector2(0.5f) + travelledDistance * new Vector2(MathF.Sin(direction), MathF.Cos(direction)); } diff --git a/osu.Game/Graphics/ParticleSpewer.cs b/osu.Game/Graphics/ParticleSpewer.cs index 54a2b1e890..4fc6c4527f 100644 --- a/osu.Game/Graphics/ParticleSpewer.cs +++ b/osu.Game/Graphics/ParticleSpewer.cs @@ -109,18 +109,18 @@ namespace osu.Game.Graphics { foreach (var p in particles) { - var timeSinceStart = currentTime - p.StartTime; + float timeSinceStart = currentTime - p.StartTime; // ignore particles from the future. // these can appear when seeking in replays. if (timeSinceStart < 0) continue; - var alpha = p.AlphaAtTime(timeSinceStart); + float alpha = p.AlphaAtTime(timeSinceStart); if (alpha <= 0) continue; var pos = p.PositionAtTime(timeSinceStart, gravity, maxDuration); - var scale = p.ScaleAtTime(timeSinceStart); - var angle = p.AngleAtTime(timeSinceStart); + float scale = p.ScaleAtTime(timeSinceStart); + float angle = p.AngleAtTime(timeSinceStart); var rect = createDrawRect(pos, scale); @@ -139,8 +139,8 @@ namespace osu.Game.Graphics private RectangleF createDrawRect(Vector2 position, float scale) { - var width = Texture.DisplayWidth * scale; - var height = Texture.DisplayHeight * scale; + float width = Texture.DisplayWidth * scale; + float height = Texture.DisplayHeight * scale; if (relativePositionAxes.HasFlagFast(Axes.X)) position.X *= sourceSize.X; @@ -188,7 +188,7 @@ namespace osu.Game.Graphics public Vector2 PositionAtTime(float timeSinceStart, float gravity, float maxDuration) { - var progress = progressAtTime(timeSinceStart); + float progress = progressAtTime(timeSinceStart); var currentGravity = new Vector2(0, gravity * Duration / maxDuration * progress); return StartPosition + (Velocity + currentGravity) * timeSinceStart / maxDuration; diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index e652f07239..1f7f93b3c3 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -147,15 +147,15 @@ namespace osu.Game.Graphics private string getFilename() { var dt = DateTime.Now; - var fileExt = screenshotFormat.ToString().ToLowerInvariant(); + string fileExt = screenshotFormat.ToString().ToLowerInvariant(); - var withoutIndex = $"osu_{dt:yyyy-MM-dd_HH-mm-ss}.{fileExt}"; + string withoutIndex = $"osu_{dt:yyyy-MM-dd_HH-mm-ss}.{fileExt}"; if (!storage.Exists(withoutIndex)) return withoutIndex; for (ulong i = 1; i < ulong.MaxValue; i++) { - var indexedName = $"osu_{dt:yyyy-MM-dd_HH-mm-ss}-{i}.{fileExt}"; + string indexedName = $"osu_{dt:yyyy-MM-dd_HH-mm-ss}-{i}.{fileExt}"; if (!storage.Exists(indexedName)) return indexedName; } diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index fb5ff4aad3..d06c227d4b 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -33,8 +33,8 @@ namespace osu.Game.Graphics.UserInterface { foreach (var t in TabContainer.Children.OfType()) { - var tIndex = TabContainer.IndexOf(t); - var tabIndex = TabContainer.IndexOf(TabMap[index.NewValue]); + int tIndex = TabContainer.IndexOf(t); + int tabIndex = TabContainer.IndexOf(TabMap[index.NewValue]); t.State = tIndex > tabIndex ? Visibility.Hidden : Visibility.Visible; t.Chevron.FadeTo(tIndex >= tabIndex ? 0f : 1f, 500, Easing.OutQuint); diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 6963f7335e..d4310dc901 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -216,10 +216,10 @@ namespace osu.Game.Graphics.UserInterface } else { - var decimalPrecision = normalise(CurrentNumber.Precision.ToDecimal(NumberFormatInfo.InvariantInfo), max_decimal_digits); + decimal decimalPrecision = normalise(CurrentNumber.Precision.ToDecimal(NumberFormatInfo.InvariantInfo), max_decimal_digits); // Find the number of significant digits (we could have less than 5 after normalize()) - var significantDigits = findPrecision(decimalPrecision); + int significantDigits = findPrecision(decimalPrecision); TooltipText = floatValue.ToString($"N{significantDigits}"); } diff --git a/osu.Game/Graphics/UserInterface/StarCounter.cs b/osu.Game/Graphics/UserInterface/StarCounter.cs index 32b788b5dc..b66f371801 100644 --- a/osu.Game/Graphics/UserInterface/StarCounter.cs +++ b/osu.Game/Graphics/UserInterface/StarCounter.cs @@ -89,7 +89,7 @@ namespace osu.Game.Graphics.UserInterface public void ReplayAnimation() { - var t = current; + float t = current; ResetCount(); Current = t; } @@ -105,7 +105,7 @@ namespace osu.Game.Graphics.UserInterface private void animate(float newValue) { - for (var i = 0; i < stars.Children.Count; i++) + for (int i = 0; i < stars.Children.Count; i++) { var star = stars.Children[i]; diff --git a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs index 969309bc79..1f5d29571d 100644 --- a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs +++ b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs @@ -236,7 +236,7 @@ namespace osu.Game.Graphics.UserInterface { base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes); - var beatLength = timingPoint.BeatLength; + double beatLength = timingPoint.BeatLength; float amplitudeAdjust = Math.Min(1, 0.4f + amplitudes.Maximum); diff --git a/osu.Game/IO/LineBufferedReader.cs b/osu.Game/IO/LineBufferedReader.cs index 018321dc9a..a6b8c9492a 100644 --- a/osu.Game/IO/LineBufferedReader.cs +++ b/osu.Game/IO/LineBufferedReader.cs @@ -32,7 +32,7 @@ namespace osu.Game.IO if (lineBuffer.Count > 0) return lineBuffer.Peek(); - var line = streamReader.ReadLine(); + string line = streamReader.ReadLine(); if (line != null) lineBuffer.Enqueue(line); return line; @@ -50,7 +50,7 @@ namespace osu.Game.IO ///
public string ReadToEnd() { - var remainingText = streamReader.ReadToEnd(); + string remainingText = streamReader.ReadToEnd(); if (lineBuffer.Count == 0) return remainingText; diff --git a/osu.Game/IO/Serialization/Converters/TypedListConverter.cs b/osu.Game/IO/Serialization/Converters/TypedListConverter.cs index 174fbf9983..715c83b07e 100644 --- a/osu.Game/IO/Serialization/Converters/TypedListConverter.cs +++ b/osu.Game/IO/Serialization/Converters/TypedListConverter.cs @@ -60,7 +60,7 @@ namespace osu.Game.IO.Serialization.Converters if (tok["$type"] == null) throw new JsonException("Expected $type token."); - var typeName = lookupTable[(int)tok["$type"]]; + string typeName = lookupTable[(int)tok["$type"]]; var instance = (T)Activator.CreateInstance(Type.GetType(typeName).AsNonNull()); serializer.Populate(itemReader, instance); @@ -80,7 +80,7 @@ namespace osu.Game.IO.Serialization.Converters var type = item.GetType(); var assemblyName = type.Assembly.GetName(); - var typeString = $"{type.FullName}, {assemblyName.Name}"; + string typeString = $"{type.FullName}, {assemblyName.Name}"; if (requiresTypeVersion) typeString += $", {assemblyName.Version}"; diff --git a/osu.Game/IO/StableStorage.cs b/osu.Game/IO/StableStorage.cs index d4b0d300ff..f5a8c4dc9e 100644 --- a/osu.Game/IO/StableStorage.cs +++ b/osu.Game/IO/StableStorage.cs @@ -34,7 +34,7 @@ namespace osu.Game.IO private string locateSongsDirectory() { - var configFile = GetFiles(".", $"osu!.{Environment.UserName}.cfg").SingleOrDefault(); + string configFile = GetFiles(".", $"osu!.{Environment.UserName}.cfg").SingleOrDefault(); if (configFile != null) { @@ -47,7 +47,7 @@ namespace osu.Game.IO { if (!line.StartsWith("BeatmapDirectory", StringComparison.OrdinalIgnoreCase)) continue; - var customDirectory = line.Split('=').LastOrDefault()?.Trim(); + string customDirectory = line.Split('=').LastOrDefault()?.Trim(); if (customDirectory != null && Path.IsPathFullyQualified(customDirectory)) return customDirectory; diff --git a/osu.Game/IO/WrappedStorage.cs b/osu.Game/IO/WrappedStorage.cs index aadc4e760b..6f0f898de3 100644 --- a/osu.Game/IO/WrappedStorage.cs +++ b/osu.Game/IO/WrappedStorage.cs @@ -60,7 +60,7 @@ namespace osu.Game.IO { string localRoot = GetFullPath(string.Empty); - foreach (var path in paths) + foreach (string path in paths) yield return Path.GetRelativePath(localRoot, UnderlyingStorage.GetFullPath(path)); } diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs index 10376c1866..5dced23614 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs @@ -52,7 +52,7 @@ namespace osu.Game.Input.Bindings { if (ruleset == null || ruleset.ID.HasValue) { - var rulesetId = ruleset?.ID; + int? rulesetId = ruleset?.ID; realmKeyBindings = realmFactory.Context.All() .Where(b => b.RulesetID == rulesetId && b.Variant == variant); diff --git a/osu.Game/Input/RealmKeyBindingStore.cs b/osu.Game/Input/RealmKeyBindingStore.cs index 5fa3ccdeb9..c65e36e478 100644 --- a/osu.Game/Input/RealmKeyBindingStore.cs +++ b/osu.Game/Input/RealmKeyBindingStore.cs @@ -65,7 +65,7 @@ namespace osu.Game.Input foreach (var ruleset in rulesets) { var instance = ruleset.CreateInstance(); - foreach (var variant in instance.AvailableVariants) + foreach (int variant in instance.AvailableVariants) insertDefaults(realm, existingBindings, instance.GetDefaultKeyBindings(variant), ruleset.ID, variant); } diff --git a/osu.Game/Localisation/ResourceManagerLocalisationStore.cs b/osu.Game/Localisation/ResourceManagerLocalisationStore.cs index 6a4e38fb38..82dc0ad110 100644 --- a/osu.Game/Localisation/ResourceManagerLocalisationStore.cs +++ b/osu.Game/Localisation/ResourceManagerLocalisationStore.cs @@ -27,7 +27,7 @@ namespace osu.Game.Localisation public string Get(string lookup) { - var split = lookup.Split(':'); + string[] split = lookup.Split(':'); if (split.Length < 2) return null; diff --git a/osu.Game/Online/API/APIDownloadRequest.cs b/osu.Game/Online/API/APIDownloadRequest.cs index 63bb3e2287..11753e05ba 100644 --- a/osu.Game/Online/API/APIDownloadRequest.cs +++ b/osu.Game/Online/API/APIDownloadRequest.cs @@ -23,7 +23,7 @@ namespace osu.Game.Online.API protected override WebRequest CreateWebRequest() { - var file = Path.GetTempFileName(); + string file = Path.GetTempFileName(); File.Move(file, filename = Path.ChangeExtension(file, FileExtension)); diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index 187a3e5dfc..9b463a6348 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -26,7 +26,7 @@ namespace osu.Game.Online.Chat { set { - foreach (var id in value) + foreach (int id in value) Users.Add(new User { Id = id }); } } @@ -131,7 +131,7 @@ namespace osu.Game.Online.Chat Messages.AddRange(messages); - var maxMessageId = messages.Max(m => m.Id); + long? maxMessageId = messages.Max(m => m.Id); if (maxMessageId > LastMessageId) LastMessageId = maxMessageId; diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 47d5955fb0..52c9387185 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -218,7 +218,7 @@ namespace osu.Game.Online.Chat if (target == null) return; - var parameters = text.Split(' ', 2); + string[] parameters = text.Split(' ', 2); string command = parameters[0]; string content = parameters.Length == 2 ? parameters[1] : string.Empty; @@ -306,7 +306,7 @@ namespace osu.Game.Online.Chat { var req = new ListChannelsRequest(); - var joinDefaults = JoinedChannels.Count == 0; + bool joinDefaults = JoinedChannels.Count == 0; req.Success += channels => { diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 201ba6239b..5a90638dcd 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -70,14 +70,14 @@ namespace osu.Game.Online.Chat foreach (Match m in regex.Matches(result.Text, startIndex)) { - var index = m.Index - captureOffset; + int index = m.Index - captureOffset; - var displayText = string.Format(display, + string? displayText = string.Format(display, m.Groups[0], m.Groups["text"].Value, m.Groups["url"].Value).Trim(); - var linkText = string.Format(link, + string linkText = string.Format(link, m.Groups[0], m.Groups["text"].Value, m.Groups["url"].Value).Trim(); @@ -109,9 +109,9 @@ namespace osu.Game.Online.Chat { foreach (Match m in regex.Matches(result.Text, startIndex)) { - var index = m.Index; - var linkText = m.Groups["link"].Value; - var indexLength = linkText.Length; + int index = m.Index; + string? linkText = m.Groups["link"].Value; + int indexLength = linkText.Length; var details = GetLinkDetails(linkText); var link = new Link(linkText, index, indexLength, details.Action, details.Argument); @@ -126,7 +126,7 @@ namespace osu.Game.Online.Chat public static LinkDetails GetLinkDetails(string url) { - var args = url.Split('/', StringSplitOptions.RemoveEmptyEntries); + string[]? args = url.Split('/', StringSplitOptions.RemoveEmptyEntries); args[0] = args[0].TrimEnd(':'); switch (args[0]) @@ -136,7 +136,7 @@ namespace osu.Game.Online.Chat // length > 3 since all these links need another argument to work if (args.Length > 3 && args[1].EndsWith(websiteRootUrl, StringComparison.OrdinalIgnoreCase)) { - var mainArg = args[3]; + string? mainArg = args[3]; switch (args[2]) { @@ -145,7 +145,7 @@ namespace osu.Game.Online.Chat case "beatmaps": { string trimmed = mainArg.Split('?').First(); - if (int.TryParse(trimmed, out var id)) + if (int.TryParse(trimmed, out int id)) return new LinkDetails(LinkAction.OpenBeatmap, id.ToString()); break; @@ -159,7 +159,7 @@ namespace osu.Game.Online.Chat // handle discussion links externally for now return new LinkDetails(LinkAction.External, url); - if (args.Length > 4 && int.TryParse(args[4], out var id)) + if (args.Length > 4 && int.TryParse(args[4], out int id)) // https://osu.ppy.sh/beatmapsets/1154158#osu/2768184 return new LinkDetails(LinkAction.OpenBeatmap, id.ToString()); @@ -273,7 +273,7 @@ namespace osu.Game.Online.Chat // handle channels handleMatches(channel_regex, "{0}", "osu://chan/{0}", result, startIndex, LinkAction.OpenChannel); - var empty = ""; + string empty = ""; while (space-- > 0) empty += "\0"; diff --git a/osu.Game/Online/Chat/NowPlayingCommand.cs b/osu.Game/Online/Chat/NowPlayingCommand.cs index 89eb00a45a..adb3d88df6 100644 --- a/osu.Game/Online/Chat/NowPlayingCommand.cs +++ b/osu.Game/Online/Chat/NowPlayingCommand.cs @@ -57,7 +57,7 @@ namespace osu.Game.Online.Chat break; } - var beatmapString = beatmapInfo.OnlineBeatmapID.HasValue ? $"[{api.WebsiteRootUrl}/b/{beatmapInfo.OnlineBeatmapID} {beatmapInfo}]" : beatmapInfo.ToString(); + string beatmapString = beatmapInfo.OnlineBeatmapID.HasValue ? $"[{api.WebsiteRootUrl}/b/{beatmapInfo.OnlineBeatmapID} {beatmapInfo}]" : beatmapInfo.ToString(); channelManager.PostMessage($"is {verb} {beatmapString}", true, target); Expire(); diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 6ed2055e65..ede76235b1 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -85,7 +85,7 @@ namespace osu.Game.Online.Chat private void postMessage(TextBox sender, bool newtext) { - var text = Textbox.Text.Trim(); + string text = Textbox.Text.Trim(); if (string.IsNullOrWhiteSpace(text)) return; diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index e3ac9f603d..515cc6fd73 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -350,8 +350,8 @@ namespace osu.Game.Online.Leaderboards { base.UpdateAfterChildren(); - var fadeBottom = scrollContainer.Current + scrollContainer.DrawHeight; - var fadeTop = scrollContainer.Current + LeaderboardScore.HEIGHT; + float fadeBottom = scrollContainer.Current + scrollContainer.DrawHeight; + float fadeTop = scrollContainer.Current + LeaderboardScore.HEIGHT; if (!scrollContainer.IsScrolledToEnd()) fadeBottom -= LeaderboardScore.HEIGHT; @@ -361,8 +361,8 @@ namespace osu.Game.Online.Leaderboards foreach (var c in scrollFlow.Children) { - var topY = c.ToSpaceOfOtherDrawable(Vector2.Zero, scrollFlow).Y; - var bottomY = topY + LeaderboardScore.HEIGHT; + float topY = c.ToSpaceOfOtherDrawable(Vector2.Zero, scrollFlow).Y; + float bottomY = topY + LeaderboardScore.HEIGHT; bool requireTopFade = FadeTop && topY <= fadeTop; bool requireBottomFade = FadeBottom && bottomY >= fadeBottom; diff --git a/osu.Game/Online/Rooms/IndexPlaylistScoresRequest.cs b/osu.Game/Online/Rooms/IndexPlaylistScoresRequest.cs index abce2093e3..bd9f254e1a 100644 --- a/osu.Game/Online/Rooms/IndexPlaylistScoresRequest.cs +++ b/osu.Game/Online/Rooms/IndexPlaylistScoresRequest.cs @@ -47,7 +47,7 @@ namespace osu.Game.Online.Rooms req.AddCursor(Cursor); - foreach (var (key, value) in IndexParams.Properties) + foreach ((string key, var value) in IndexParams.Properties) req.AddParameter(key, value.ToString()); } diff --git a/osu.Game/Online/Spectator/SpectatorClient.cs b/osu.Game/Online/Spectator/SpectatorClient.cs index b597b2f214..f9366674d8 100644 --- a/osu.Game/Online/Spectator/SpectatorClient.cs +++ b/osu.Game/Online/Spectator/SpectatorClient.cs @@ -80,7 +80,7 @@ namespace osu.Game.Online.Spectator watchingUsers.Clear(); // resubscribe to watched users. - foreach (var userId in users) + foreach (int userId in users) WatchUser(userId); // re-send state in case it wasn't received diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 985451fd6f..304904e776 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -336,7 +336,7 @@ namespace osu.Game ShowChangelogListing(); else { - var changelogArgs = link.Argument.Split("/"); + string[] changelogArgs = link.Argument.Split("/"); ShowChangelogBuild(changelogArgs[0], changelogArgs[1]); } @@ -622,7 +622,7 @@ namespace osu.Game foreach (var language in Enum.GetValues(typeof(Language)).OfType()) { - var cultureCode = language.ToCultureCode(); + string cultureCode = language.ToCultureCode(); try { @@ -870,7 +870,7 @@ namespace osu.Game { if (args?.Length > 0) { - var paths = args.Where(a => !a.StartsWith('-')).ToArray(); + string[] paths = args.Where(a => !a.StartsWith('-')).ToArray(); if (paths.Length > 0) Task.Run(() => Import(paths)); } @@ -913,7 +913,7 @@ namespace osu.Game } else if (recentLogCount == short_term_display_limit) { - var logFile = $@"{entry.Target.ToString().ToLowerInvariant()}.log"; + string logFile = $@"{entry.Target.ToString().ToLowerInvariant()}.log"; Schedule(() => Notifications.Post(new SimpleNotification { @@ -1059,7 +1059,7 @@ namespace osu.Game ScreenOffsetContainer.Padding = new MarginPadding { Top = toolbarOffset }; overlayOffsetContainer.Padding = new MarginPadding { Top = toolbarOffset }; - var horizontalOffset = 0f; + float horizontalOffset = 0f; // Content.ToLocalSpace() is used instead of this.ToLocalSpace() to correctly calculate the offset with scaling modes active. // Content is a child of a scaling container with ScalingMode.Everything set, while the game itself is never scaled. diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs index cb258edced..79c95d6646 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs @@ -64,7 +64,7 @@ namespace osu.Game.Overlays.BeatmapSet BeatmapSet.BindValueChanged(setInfo => { - var beatmapsCount = setInfo.NewValue?.Beatmaps.Count(b => b.Ruleset.Equals(Value)) ?? 0; + int beatmapsCount = setInfo.NewValue?.Beatmaps.Count(b => b.Ruleset.Equals(Value)) ?? 0; count.Text = beatmapsCount.ToString(); countContainer.FadeTo(beatmapsCount > 0 ? 1 : 0); diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index 8bc5c6d27e..970e9bbf42 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -119,7 +119,7 @@ namespace osu.Game.Overlays.BeatmapSet tags.Text = b.NewValue?.Metadata.Tags ?? string.Empty; genre.Text = b.NewValue?.OnlineInfo?.Genre.Name ?? string.Empty; language.Text = b.NewValue?.OnlineInfo?.Language.Name ?? string.Empty; - var setHasLeaderboard = b.NewValue?.OnlineInfo?.Status > 0; + bool setHasLeaderboard = b.NewValue?.OnlineInfo?.Status > 0; successRate.Alpha = setHasLeaderboard ? 1 : 0; notRankedPlaceholder.Alpha = setHasLeaderboard ? 0 : 1; Height = setHasLeaderboard ? 270 : base_height; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs index d84e1eff8c..b6079b36ab 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs @@ -50,7 +50,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores [BackgroundDependencyLoader] private void load(OsuColour colours, OverlayColourProvider colourProvider, IAPIProvider api) { - var isOwnScore = api.LocalUser.Value.Id == score.UserID; + bool isOwnScore = api.LocalUser.Value.Id == score.UserID; if (isOwnScore) background.Colour = colours.GreenDarker; diff --git a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs index 604c4e1949..40a3c9fe8b 100644 --- a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs +++ b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs @@ -43,7 +43,7 @@ namespace osu.Game.Overlays.BeatmapSet int passCount = beatmapInfo?.OnlineInfo?.PassCount ?? 0; int playCount = beatmapInfo?.OnlineInfo?.PlayCount ?? 0; - var rate = playCount != 0 ? (float)passCount / playCount : 0; + float rate = playCount != 0 ? (float)passCount / playCount : 0; successPercent.Text = rate.ToLocalisableString(@"0.#%"); successRate.Length = rate; percentContainer.ResizeWidthTo(successRate.Length, 250, Easing.InOutCubic); diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 4b27335c7c..cc3ce63bf7 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -479,7 +479,7 @@ namespace osu.Game.Overlays private void postMessage(TextBox textbox, bool newText) { - var text = textbox.Text.Trim(); + string text = textbox.Text.Trim(); if (string.IsNullOrWhiteSpace(text)) return; diff --git a/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs b/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs index aeab292b0d..3971a61363 100644 --- a/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs +++ b/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Comments protected override float GetFontSizeByLevel(int level) { - var defaultFontSize = base.GetFontSizeByLevel(6); + float defaultFontSize = base.GetFontSizeByLevel(6); switch (level) { diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index a44f3a7643..43f4177bd0 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -362,8 +362,8 @@ namespace osu.Game.Overlays.Comments private void updateButtonsState() { - var loadedReplesCount = loadedReplies.Count; - var hasUnloadedReplies = loadedReplesCount != Comment.RepliesCount; + int loadedReplesCount = loadedReplies.Count; + bool hasUnloadedReplies = loadedReplesCount != Comment.RepliesCount; loadRepliesButton.FadeTo(hasUnloadedReplies && loadedReplesCount == 0 ? 1 : 0); showMoreButton.FadeTo(hasUnloadedReplies && loadedReplesCount > 0 ? 1 : 0); diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index cf3c470f96..093cdce66e 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -67,7 +67,7 @@ namespace osu.Game.Overlays.Comments AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; hoverLayer.Colour = Color4.Black.Opacity(0.5f); - var ownComment = api.LocalUser.Value.Id == comment.UserId; + bool ownComment = api.LocalUser.Value.Id == comment.UserId; if (!ownComment) Action = onAction; diff --git a/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs index 3051ca7dbe..454dd500fe 100644 --- a/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs +++ b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs @@ -61,7 +61,7 @@ namespace osu.Game.Overlays.Dashboard switch (e.Action) { case NotifyCollectionChangedAction.Add: - foreach (var id in e.NewItems.OfType().ToArray()) + foreach (int id in e.NewItems.OfType().ToArray()) { users.GetUserAsync(id).ContinueWith(u => { @@ -81,7 +81,7 @@ namespace osu.Game.Overlays.Dashboard break; case NotifyCollectionChangedAction.Remove: - foreach (var u in e.OldItems.OfType()) + foreach (int u in e.OldItems.OfType()) userFlow.FirstOrDefault(card => card.User.Id == u)?.Expire(); break; diff --git a/osu.Game/Overlays/Dashboard/Friends/FriendOnlineStreamControl.cs b/osu.Game/Overlays/Dashboard/Friends/FriendOnlineStreamControl.cs index 28546ceab8..d7f66e35b5 100644 --- a/osu.Game/Overlays/Dashboard/Friends/FriendOnlineStreamControl.cs +++ b/osu.Game/Overlays/Dashboard/Friends/FriendOnlineStreamControl.cs @@ -15,8 +15,8 @@ namespace osu.Game.Overlays.Dashboard.Friends { Clear(); - var userCount = users.Count; - var onlineUsersCount = users.Count(user => user.IsOnline); + int userCount = users.Count; + int onlineUsersCount = users.Count(user => user.IsOnline); AddItem(new FriendStream(OnlineStatus.All, userCount)); AddItem(new FriendStream(OnlineStatus.Online, onlineUsersCount)); diff --git a/osu.Game/Overlays/HoldToConfirmOverlay.cs b/osu.Game/Overlays/HoldToConfirmOverlay.cs index 0542f66b5b..cb6275bd7c 100644 --- a/osu.Game/Overlays/HoldToConfirmOverlay.cs +++ b/osu.Game/Overlays/HoldToConfirmOverlay.cs @@ -49,7 +49,7 @@ namespace osu.Game.Overlays Progress.ValueChanged += p => { - var target = p.NewValue * finalFillAlpha; + double target = p.NewValue * finalFillAlpha; audioVolume.Value = 1 - target; overlay.Alpha = (float)target; diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index faad23a4e1..5bf8cddd0c 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -96,7 +96,7 @@ namespace osu.Game.Overlays.Mods if (ToggleKeys != null) { - var index = Array.IndexOf(ToggleKeys, e.Key); + int index = Array.IndexOf(ToggleKeys, e.Key); if (index > -1 && index < Buttons.Count) Buttons[index].SelectNext(e.ShiftPressed ? -1 : 1); } @@ -196,7 +196,7 @@ namespace osu.Game.Overlays.Mods { foreach (var mod in newSelectedMods) { - var index = Array.FindIndex(button.Mods, m1 => mod.GetType() == m1.GetType()); + int index = Array.FindIndex(button.Mods, m1 => mod.GetType() == m1.GetType()); if (index < 0) continue; diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 8fd50c3df2..97c7aaeaeb 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -238,7 +238,7 @@ namespace osu.Game.Overlays if (beatmap.Disabled) return PreviousTrackResult.None; - var currentTrackPosition = CurrentTrack.CurrentTime; + double currentTrackPosition = CurrentTrack.CurrentTime; if (currentTrackPosition >= restart_cutoff_point) { @@ -329,8 +329,8 @@ namespace osu.Game.Overlays else { // figure out the best direction based on order in playlist. - var last = BeatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count(); - var next = newWorking == null ? -1 : BeatmapSets.TakeWhile(b => b.ID != newWorking.BeatmapSetInfo?.ID).Count(); + int last = BeatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count(); + int next = newWorking == null ? -1 : BeatmapSets.TakeWhile(b => b.ID != newWorking.BeatmapSetInfo?.ID).Count(); direction = last > next ? TrackChangeDirection.Prev : TrackChangeDirection.Next; } diff --git a/osu.Game/Overlays/News/Sidebar/NewsSidebar.cs b/osu.Game/Overlays/News/Sidebar/NewsSidebar.cs index 35cd6eb03b..fe965385d8 100644 --- a/osu.Game/Overlays/News/Sidebar/NewsSidebar.cs +++ b/osu.Game/Overlays/News/Sidebar/NewsSidebar.cs @@ -61,11 +61,11 @@ namespace osu.Game.Overlays.News.Sidebar var keys = lookup.Select(kvp => kvp.Key); var sortedKeys = keys.OrderByDescending(k => k).ToList(); - var year = metadata.NewValue.CurrentYear; + int year = metadata.NewValue.CurrentYear; for (int i = 0; i < sortedKeys.Count; i++) { - var month = sortedKeys[i]; + int month = sortedKeys[i]; var posts = lookup[month]; monthsFlow.Add(new MonthSection(month, year, posts) diff --git a/osu.Game/Overlays/News/Sidebar/YearsPanel.cs b/osu.Game/Overlays/News/Sidebar/YearsPanel.cs index b07c9924b9..58c0f6ac82 100644 --- a/osu.Game/Overlays/News/Sidebar/YearsPanel.cs +++ b/osu.Game/Overlays/News/Sidebar/YearsPanel.cs @@ -69,9 +69,9 @@ namespace osu.Game.Overlays.News.Sidebar return; } - var currentYear = metadata.Value.CurrentYear; + int currentYear = metadata.Value.CurrentYear; - foreach (var y in metadata.Value.Years) + foreach (int y in metadata.Value.Years) yearsFlow.Add(new YearButton(y, y == currentYear)); Show(); diff --git a/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs b/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs index 14eeb4e5f0..b1076ba39b 100644 --- a/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs +++ b/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs @@ -111,7 +111,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { text.Text = string.Empty; - var usernames = user.NewValue?.PreviousUsernames; + string[] usernames = user.NewValue?.PreviousUsernames; if (usernames?.Any() ?? false) { diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index ca5f26e375..d6e515d8a1 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Profile.Header.Components protected override UserGraphTooltipContent GetTooltipContent(int index, int rank) { - var days = ranked_days - index + 1; + int days = ranked_days - index + 1; return new UserGraphTooltipContent( UsersStrings.ShowRankGlobalSimple, diff --git a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs index e7df4eb5eb..f6419db540 100644 --- a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs @@ -72,7 +72,7 @@ namespace osu.Game.Overlays.Profile.Header { Show(); - for (var index = 0; index < badges.Length; index++) + for (int index = 0; index < badges.Length; index++) { int displayIndex = index; LoadComponentAsync(new DrawableBadge(badges[index]), asyncBadge => diff --git a/osu.Game/Overlays/Profile/Sections/Historical/ProfileLineChart.cs b/osu.Game/Overlays/Profile/Sections/Historical/ProfileLineChart.cs index a75235359a..d402438376 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/ProfileLineChart.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/ProfileLineChart.cs @@ -116,10 +116,10 @@ namespace osu.Game.Overlays.Profile.Sections.Historical rowTicksContainer.Clear(); rowLinesContainer.Clear(); - var min = values.Select(v => v.Count).Min(); - var max = values.Select(v => v.Count).Max(); + long min = values.Select(v => v.Count).Min(); + long max = values.Select(v => v.Count).Max(); - var tickInterval = getTickInterval(max - min, 6); + long tickInterval = getTickInterval(max - min, 6); for (long currentTick = 0; currentTick <= max; currentTick += tickInterval) { @@ -145,7 +145,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical columnTicksContainer.Clear(); columnLinesContainer.Clear(); - var totalMonths = values.Length; + int totalMonths = values.Length; int monthsPerTick = 1; @@ -158,7 +158,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical for (int i = 0; i < totalMonths; i += monthsPerTick) { - var x = (float)i / (totalMonths - 1); + float x = (float)i / (totalMonths - 1); addColumnTick(x, values[i].Date); } } @@ -215,15 +215,15 @@ namespace osu.Game.Overlays.Profile.Sections.Historical { // this interval is what would be achieved if the interval was divided perfectly evenly into maxTicksCount ticks. // can contain ugly fractional parts. - var exactTickInterval = (float)range / (maxTicksCount - 1); + float exactTickInterval = (float)range / (maxTicksCount - 1); // the ideal ticks start with a 1, 2 or 5, and are multipliers of powers of 10. // first off, use log10 to calculate the number of digits in the "exact" interval. - var numberOfDigits = Math.Floor(Math.Log10(exactTickInterval)); - var tickBase = Math.Pow(10, numberOfDigits); + double numberOfDigits = Math.Floor(Math.Log10(exactTickInterval)); + double tickBase = Math.Pow(10, numberOfDigits); // then see how the exact tick relates to the power of 10. - var exactTickMultiplier = exactTickInterval / tickBase; + double exactTickMultiplier = exactTickInterval / tickBase; double tickMultiplier; diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index 0c54ae2763..858d555f06 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio var deviceItems = new List { string.Empty }; deviceItems.AddRange(audio.AudioDeviceNames); - var preferredDeviceName = audio.AudioDevice.Value; + string preferredDeviceName = audio.AudioDevice.Value; if (deviceItems.All(kv => kv != preferredDeviceName)) deviceItems.Add(preferredDeviceName); diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs index 2051af6f3c..be0830a7c2 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs @@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input [BackgroundDependencyLoader] private void load(RealmContextFactory realmFactory) { - var rulesetId = Ruleset?.ID; + int? rulesetId = Ruleset?.ID; List bindings; diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index a4da17c5cd..0334167759 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -86,7 +86,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input handlerSensitivity.BindValueChanged(val => { - var disabled = localSensitivity.Disabled; + bool disabled = localSensitivity.Disabled; localSensitivity.Disabled = false; localSensitivity.Value = val.NewValue; @@ -97,7 +97,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input windowMode.BindValueChanged(mode => { - var isFullscreen = mode.NewValue == WindowMode.Fullscreen; + bool isFullscreen = mode.NewValue == WindowMode.Fullscreen; if (isFullscreen) { diff --git a/osu.Game/Overlays/Settings/Sections/Input/RotationPresetButtons.cs b/osu.Game/Overlays/Settings/Sections/Input/RotationPresetButtons.cs index 3ef5ce8941..dbdf600002 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/RotationPresetButtons.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/RotationPresetButtons.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input for (int i = 0; i < preset_count; i++) { - var rotationValue = i * 90; + int rotationValue = i * 90; var rotationPreset = new RotationButton(rotationValue) { diff --git a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs index 5246051a4a..48cbe1b59e 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input var r = ruleset.CreateInstance(); - foreach (var variant in r.AvailableVariants) + foreach (int variant in r.AvailableVariants) Add(new VariantBindingsSubsection(ruleset, variant)); } } diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 00198235c5..cf5d70ba91 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -45,7 +45,7 @@ namespace osu.Game.Overlays.Settings.Sections { get { - var index = skinItems.FindIndex(s => s.ID > 0); + int index = skinItems.FindIndex(s => s.ID > 0); if (index < 0) index = skinItems.Count; diff --git a/osu.Game/Overlays/Settings/SettingsNumberBox.cs b/osu.Game/Overlays/Settings/SettingsNumberBox.cs index aca7a210b3..545f1050b2 100644 --- a/osu.Game/Overlays/Settings/SettingsNumberBox.cs +++ b/osu.Game/Overlays/Settings/SettingsNumberBox.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Settings { int? value = null; - if (int.TryParse(e.NewValue, out var intVal)) + if (int.TryParse(e.NewValue, out int intVal)) value = intVal; current.Value = value; diff --git a/osu.Game/Overlays/TabControlOverlayHeader.cs b/osu.Game/Overlays/TabControlOverlayHeader.cs index e6f7e250a7..1b0bd658d9 100644 --- a/osu.Game/Overlays/TabControlOverlayHeader.cs +++ b/osu.Game/Overlays/TabControlOverlayHeader.cs @@ -111,7 +111,7 @@ namespace osu.Game.Overlays else { var localisableDescription = enumValue.GetLocalisableDescription(); - var nonLocalisableDescription = enumValue.GetDescription(); + string nonLocalisableDescription = enumValue.GetDescription(); // If localisable == non-localisable, then we must have a basic string, so .ToLower() is used. Text.Text = localisableDescription.Equals(nonLocalisableDescription) diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index dd554200ca..ab37b3b355 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -207,7 +207,7 @@ namespace osu.Game.Overlays.Toolbar if (realmKeyBinding != null) { - var keyBindingString = realmKeyBinding.KeyCombination.ReadableString(); + string keyBindingString = realmKeyBinding.KeyCombination.ReadableString(); if (!string.IsNullOrEmpty(keyBindingString)) keyBindingTooltip.Text = $" ({keyBindingString})"; diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index ff28b45ebb..e2afd46c18 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -325,7 +325,7 @@ namespace osu.Game.Overlays.Volume delta *= accelerationModifier; accelerationModifier = Math.Min(max_acceleration, accelerationModifier * acceleration_multiplier); - var precision = Bindable.Precision; + double precision = Bindable.Precision; if (isPrecise) { diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs index 421806eea8..a22c18b0a4 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Wiki.Markdown AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; - foreach (var line in yamlFrontMatterBlock.Lines) + foreach (object line in yamlFrontMatterBlock.Lines) { switch (line.ToString()) { diff --git a/osu.Game/Overlays/Wiki/WikiMainPage.cs b/osu.Game/Overlays/Wiki/WikiMainPage.cs index c9ee2cbfd5..9416ec77f1 100644 --- a/osu.Game/Overlays/Wiki/WikiMainPage.cs +++ b/osu.Game/Overlays/Wiki/WikiMainPage.cs @@ -72,11 +72,11 @@ namespace osu.Game.Overlays.Wiki Debug.Assert(panelsNode.Length > 1); - var i = 0; + int i = 0; while (i < panelsNode.Length) { - var isFullWidth = panelsNode[i].HasClass("wiki-main-page-panel--full"); + bool isFullWidth = panelsNode[i].HasClass("wiki-main-page-panel--full"); if (isFullWidth) { diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index bde73b6180..44713d637d 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -140,7 +140,7 @@ namespace osu.Game.Overlays private void showParentPage() { - var parentPath = string.Join("/", path.Value.Split('/').SkipLast(1)); + string parentPath = string.Join("/", path.Value.Split('/').SkipLast(1)); ShowPage(parentPath); } diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index 200bbf3f92..eab81186d5 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -158,7 +158,7 @@ namespace osu.Game.Rulesets.Difficulty // Apply the rest of the remaining mods recursively. for (int i = 0; i < remainingMods.Length; i++) { - var (nextSet, nextCount) = flatten(remainingMods.Span[i]); + (var nextSet, int nextCount) = flatten(remainingMods.Span[i]); // Check if any mods in the next set are incompatible with any of the current set. if (currentSet.SelectMany(m => m.IncompatibleMods).Any(c => nextSet.Any(c.IsInstanceOfType))) @@ -185,7 +185,7 @@ namespace osu.Game.Rulesets.Difficulty foreach (var nested in multi.Mods) { - var (nestedSet, nestedCount) = flatten(nested); + (var nestedSet, int nestedCount) = flatten(nested); set = set.Concat(nestedSet); count += nestedCount; } diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioInVideo.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioInVideo.cs index ac2542beb0..255671c807 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAudioInVideo.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioInVideo.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Edit.Checks } } - foreach (var filename in videoPaths) + foreach (string filename in videoPaths) { string storagePath = beatmapSet.GetPathForFile(filename); diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs index 70d11883b7..08e0312b64 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable Run(BeatmapVerifierContext context) { - var audioFile = context.Beatmap.Metadata?.AudioFile; + string audioFile = context.Beatmap.Metadata?.AudioFile; if (audioFile == null) yield break; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs index 085c558eaf..8fa79e2ee8 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable Run(BeatmapVerifierContext context) { - var backgroundFile = context.Beatmap.Metadata?.BackgroundFile; + string backgroundFile = context.Beatmap.Metadata?.BackgroundFile; if (backgroundFile == null) yield break; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckFewHitsounds.cs b/osu.Game/Rulesets/Edit/Checks/CheckFewHitsounds.cs index 5185ba6c99..3358e81d5f 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckFewHitsounds.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckFewHitsounds.cs @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Edit.Checks } var hitObjectsByEndTime = hitObjectsIncludingNested.OrderBy(o => o.GetEndTime()).ToList(); - var hitObjectCount = hitObjectsByEndTime.Count; + int hitObjectCount = hitObjectsByEndTime.Count; for (int i = 0; i < hitObjectCount; ++i) { @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Edit.Checks private IEnumerable applyHitsoundUpdate(HitObject hitObject, bool isLastObject = false) { - var time = hitObject.GetEndTime(); + double time = hitObject.GetEndTime(); bool hasHitsound = hitObject.Samples.Any(isHitsound); bool couldHaveHitsound = hitObject.Samples.Any(isHitnormal); @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Edit.Checks // If there are no hitsounds we let the "No hitsounds" template take precedence. if (hasHitsound || (isLastObject && mapHasHitsounds)) { - var timeWithoutHitsounds = time - lastHitsoundTime; + double timeWithoutHitsounds = time - lastHitsoundTime; if (timeWithoutHitsounds > problem_threshold_time && objectsWithoutHitsounds > problem_threshold_objects) yield return new IssueTemplateLongPeriodProblem(this).Create(lastHitsoundTime, timeWithoutHitsounds); diff --git a/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs index 36a0bf8c5d..abedee143a 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable Run(BeatmapVerifierContext context) { - var filename = GetFilename(context.Beatmap); + string filename = GetFilename(context.Beatmap); if (filename == null) { @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Edit.Checks } // If the file is set, also make sure it still exists. - var storagePath = context.Beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(filename); + string storagePath = context.Beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(filename); if (storagePath != null) yield break; diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 91cc80e930..8bad9aa11f 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -223,7 +223,7 @@ namespace osu.Game.Rulesets.Edit if (e.ControlPressed || e.AltPressed || e.SuperPressed) return false; - if (checkLeftToggleFromKey(e.Key, out var leftIndex)) + if (checkLeftToggleFromKey(e.Key, out int leftIndex)) { var item = toolboxCollection.Items.ElementAtOrDefault(leftIndex); @@ -235,7 +235,7 @@ namespace osu.Game.Rulesets.Edit } } - if (checkRightToggleFromKey(e.Key, out var rightIndex)) + if (checkRightToggleFromKey(e.Key, out int rightIndex)) { var item = togglesCollection.ElementAtOrDefault(rightIndex); diff --git a/osu.Game/Rulesets/Mods/ModBarrelRoll.cs b/osu.Game/Rulesets/Mods/ModBarrelRoll.cs index 872daadd46..4acbcf3e74 100644 --- a/osu.Game/Rulesets/Mods/ModBarrelRoll.cs +++ b/osu.Game/Rulesets/Mods/ModBarrelRoll.cs @@ -49,8 +49,8 @@ namespace osu.Game.Rulesets.Mods // scale the playfield to allow all hitobjects to stay within the visible region. var playfieldSize = drawableRuleset.Playfield.DrawSize; - var minSide = MathF.Min(playfieldSize.X, playfieldSize.Y); - var maxSide = MathF.Max(playfieldSize.X, playfieldSize.Y); + float minSide = MathF.Min(playfieldSize.X, playfieldSize.Y); + float maxSide = MathF.Max(playfieldSize.X, playfieldSize.Y); drawableRuleset.Playfield.Scale = new Vector2(minSide / maxSide); } } diff --git a/osu.Game/Rulesets/Objects/BarLineGenerator.cs b/osu.Game/Rulesets/Objects/BarLineGenerator.cs index 9556b52735..e78aa5a5a0 100644 --- a/osu.Game/Rulesets/Objects/BarLineGenerator.cs +++ b/osu.Game/Rulesets/Objects/BarLineGenerator.cs @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Objects for (double t = currentTimingPoint.Time; Precision.DefinitelyBigger(endTime, t); t += barLength, currentBeat++) { - var roundedTime = Math.Round(t, MidpointRounding.AwayFromZero); + double roundedTime = Math.Round(t, MidpointRounding.AwayFromZero); // in the case of some bar lengths, rounding errors can cause t to be slightly less than // the expected whole number value due to floating point inaccuracies. diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 29d8a475ef..01817147ae 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -568,7 +568,7 @@ namespace osu.Game.Rulesets.Objects.Drawables if (Result != null && Result.HasResult) { - var endTime = HitObject.GetEndTime(); + double endTime = HitObject.GetEndTime(); if (Result.TimeOffset + endTime > Time.Current) { diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 0942a7264d..b341d2ddab 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -130,7 +130,7 @@ namespace osu.Game.Rulesets.Objects.Legacy if (i >= adds.Length) break; - int.TryParse(adds[i], out var sound); + int.TryParse(adds[i], out int sound); nodeSoundTypes[i] = (LegacyHitSoundType)sound; } } diff --git a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs index ba38c7f77d..bae5a5e8d9 100644 --- a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs +++ b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs @@ -18,10 +18,10 @@ namespace osu.Game.Rulesets.Objects // This exists for edge cases such as /b/1573664 where the beatmap has been edited by the user, and should never be reached in normal usage. const double max_length = 100000; - var length = Math.Min(max_length, totalDistance); + double length = Math.Min(max_length, totalDistance); tickDistance = Math.Clamp(tickDistance, 0, length); - var minDistanceFromEnd = velocity * 10; + double minDistanceFromEnd = velocity * 10; yield return new SliderEventDescriptor { @@ -34,10 +34,10 @@ namespace osu.Game.Rulesets.Objects if (tickDistance != 0) { - for (var span = 0; span < spanCount; span++) + for (int span = 0; span < spanCount; span++) { - var spanStartTime = startTime + span * spanDuration; - var reversed = span % 2 == 1; + double spanStartTime = startTime + span * spanDuration; + bool reversed = span % 2 == 1; var ticks = generateTicks(span, spanStartTime, spanDuration, reversed, length, tickDistance, minDistanceFromEnd, cancellationToken); @@ -115,7 +115,7 @@ namespace osu.Game.Rulesets.Objects private static IEnumerable generateTicks(int spanIndex, double spanStartTime, double spanDuration, bool reversed, double length, double tickDistance, double minDistanceFromEnd, CancellationToken cancellationToken = default) { - for (var d = tickDistance; d <= length; d += tickDistance) + for (double d = tickDistance; d <= length; d += tickDistance) { cancellationToken.ThrowIfCancellationRequested(); @@ -123,8 +123,8 @@ namespace osu.Game.Rulesets.Objects break; // Always generate ticks from the start of the path rather than the span to ensure that ticks in repeat spans are positioned identically to those in non-repeat spans - var pathProgress = d / length; - var timeProgress = reversed ? 1 - pathProgress : pathProgress; + double pathProgress = d / length; + double timeProgress = reversed ? 1 - pathProgress : pathProgress; yield return new SliderEventDescriptor { diff --git a/osu.Game/Rulesets/Objects/SliderPathExtensions.cs b/osu.Game/Rulesets/Objects/SliderPathExtensions.cs index 052fc7c775..1308fff7ae 100644 --- a/osu.Game/Rulesets/Objects/SliderPathExtensions.cs +++ b/osu.Game/Rulesets/Objects/SliderPathExtensions.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Objects PathType? lastType = null; - for (var i = 0; i < points.Length; i++) + for (int i = 0; i < points.Length; i++) { var p = points[i]; p.Position -= positionalOffset; diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index 8cd3fa8c63..8083041a3b 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets { unchecked { - var hashCode = ID.HasValue ? ID.GetHashCode() : 0; + int hashCode = ID.HasValue ? ID.GetHashCode() : 0; hashCode = (hashCode * 397) ^ (InstantiationInfo != null ? InstantiationInfo.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (Name != null ? Name.GetHashCode() : 0); hashCode = (hashCode * 397) ^ Available.GetHashCode(); diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index a9e04a02b5..391bf2c07d 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -168,7 +168,7 @@ namespace osu.Game.Rulesets var rulesets = rulesetStorage.GetFiles(".", $"{ruleset_library_prefix}.*.dll"); - foreach (var ruleset in rulesets.Where(f => !f.Contains("Tests"))) + foreach (string ruleset in rulesets.Where(f => !f.Contains("Tests"))) loadRulesetFromFile(rulesetStorage.GetFullPath(ruleset)); } @@ -176,7 +176,7 @@ namespace osu.Game.Rulesets { try { - var files = Directory.GetFiles(RuntimeInfo.StartupDirectory, $"{ruleset_library_prefix}.*.dll"); + string[] files = Directory.GetFiles(RuntimeInfo.StartupDirectory, $"{ruleset_library_prefix}.*.dll"); foreach (string file in files.Where(f => !Path.GetFileName(f).Contains("Tests"))) loadRulesetFromFile(file); @@ -189,7 +189,7 @@ namespace osu.Game.Rulesets private void loadRulesetFromFile(string file) { - var filename = Path.GetFileNameWithoutExtension(file); + string filename = Path.GetFileNameWithoutExtension(file); if (loadedAssemblies.Values.Any(t => Path.GetFileNameWithoutExtension(t.Assembly.Location) == filename)) return; diff --git a/osu.Game/Rulesets/Scoring/HitWindows.cs b/osu.Game/Rulesets/Scoring/HitWindows.cs index 3ffd1eb66b..2d008b58ba 100644 --- a/osu.Game/Rulesets/Scoring/HitWindows.cs +++ b/osu.Game/Rulesets/Scoring/HitWindows.cs @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Scoring { foreach (var range in GetRanges()) { - var value = IBeatmapDifficultyInfo.DifficultyRange(difficulty, (range.Min, range.Average, range.Max)); + double value = IBeatmapDifficultyInfo.DifficultyRange(difficulty, (range.Min, range.Average, range.Max)); switch (range.Result) { diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs index 0d4283e319..ab6e07f424 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs @@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { public double GetDisplayStartTime(double originTime, float offset, double timeRange, float scrollLength) { - var adjustedTime = TimeAt(-offset, originTime, timeRange, scrollLength); + double adjustedTime = TimeAt(-offset, originTime, timeRange, scrollLength); return adjustedTime - timeRange; } diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/SequentialScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/SequentialScrollAlgorithm.cs index a1f68d7201..45d3b3bcd4 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/SequentialScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/SequentialScrollAlgorithm.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms public float GetLength(double startTime, double endTime, double timeRange, float scrollLength) { - var objectLength = relativePositionAt(endTime, timeRange) - relativePositionAt(startTime, timeRange); + double objectLength = relativePositionAt(endTime, timeRange) - relativePositionAt(startTime, timeRange); return (float)(objectLength * scrollLength); } @@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { generatePositionMappings(timeRange); - var mappingIndex = positionMappings.BinarySearch(search, comparer ?? Comparer.Default); + int mappingIndex = positionMappings.BinarySearch(search, comparer ?? Comparer.Default); if (mappingIndex < 0) { diff --git a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs index a1658b4cf3..379718195c 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs @@ -39,7 +39,7 @@ namespace osu.Game.Scoring.Legacy score.ScoreInfo = scoreInfo; - var version = sr.ReadInt32(); + int version = sr.ReadInt32(); workingBeatmap = GetBeatmap(sr.ReadString()); if (workingBeatmap is DummyWorkingBeatmap) @@ -77,7 +77,7 @@ namespace osu.Game.Scoring.Legacy scoreInfo.Date = sr.ReadDateTime(); - var compressedReplay = sr.ReadByteArray(); + byte[] compressedReplay = sr.ReadByteArray(); if (version >= 20140721) scoreInfo.OnlineScoreID = sr.ReadInt64(); @@ -228,11 +228,11 @@ namespace osu.Game.Scoring.Legacy float lastTime = 0; ReplayFrame currentFrame = null; - var frames = reader.ReadToEnd().Split(','); + string[] frames = reader.ReadToEnd().Split(','); - for (var i = 0; i < frames.Length; i++) + for (int i = 0; i < frames.Length; i++) { - var split = frames[i].Split('|'); + string[] split = frames[i].Split('|'); if (split.Length < 4) continue; @@ -243,9 +243,9 @@ namespace osu.Game.Scoring.Legacy continue; } - var diff = Parsing.ParseFloat(split[0]); - var mouseX = Parsing.ParseFloat(split[1], Parsing.MAX_COORDINATE_VALUE); - var mouseY = Parsing.ParseFloat(split[2], Parsing.MAX_COORDINATE_VALUE); + float diff = Parsing.ParseFloat(split[0]); + float mouseX = Parsing.ParseFloat(split[1], Parsing.MAX_COORDINATE_VALUE); + float mouseY = Parsing.ParseFloat(split[2], Parsing.MAX_COORDINATE_VALUE); lastTime += diff; diff --git a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs index 58e4192f77..5769406948 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs @@ -72,7 +72,7 @@ namespace osu.Game.Scoring.Legacy private byte[] createReplayData() { - var content = new ASCIIEncoding().GetBytes(replayStringContent); + byte[] content = new ASCIIEncoding().GetBytes(replayStringContent); using (var outStream = new MemoryStream()) { diff --git a/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs index b58f65800d..fc27261225 100644 --- a/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs +++ b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs @@ -130,7 +130,7 @@ namespace osu.Game.Scoring.Legacy private static int? getCount(ScoreInfo scoreInfo, HitResult result) { - if (scoreInfo.Statistics.TryGetValue(result, out var existing)) + if (scoreInfo.Statistics.TryGetValue(result, out int existing)) return existing; return null; diff --git a/osu.Game/Scoring/LegacyDatabasedScore.cs b/osu.Game/Scoring/LegacyDatabasedScore.cs index 8908775472..81892f65d0 100644 --- a/osu.Game/Scoring/LegacyDatabasedScore.cs +++ b/osu.Game/Scoring/LegacyDatabasedScore.cs @@ -16,7 +16,7 @@ namespace osu.Game.Scoring { ScoreInfo = score; - var replayFilename = score.Files.FirstOrDefault(f => f.Filename.EndsWith(".osr", StringComparison.InvariantCultureIgnoreCase))?.FileInfo.StoragePath; + string replayFilename = score.Files.FirstOrDefault(f => f.Filename.EndsWith(".osr", StringComparison.InvariantCultureIgnoreCase))?.FileInfo.StoragePath; if (replayFilename == null) return; diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index a9791fba7e..253591eb56 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -72,7 +72,7 @@ namespace osu.Game.Scoring } } - var totalScores = await Task.WhenAll(scores.Select(s => GetTotalScoreAsync(s, cancellationToken: cancellationToken))).ConfigureAwait(false); + long[] totalScores = await Task.WhenAll(scores.Select(s => GetTotalScoreAsync(s, cancellationToken: cancellationToken))).ConfigureAwait(false); return scores.Select((score, index) => (score, totalScore: totalScores[index])) .OrderByDescending(g => g.totalScore) diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index dfe2992a7c..1a350d7261 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -92,7 +92,7 @@ namespace osu.Game.Screens.Edit { int beat = index % beatDivisor; - foreach (var divisor in BindableBeatDivisor.VALID_DIVISORS) + foreach (int divisor in BindableBeatDivisor.VALID_DIVISORS) { if ((beat * divisor) % beatDivisor == 0) return divisor; diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 2dec3fd22e..de63b265d2 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -205,7 +205,7 @@ namespace osu.Game.Screens.Edit.Compose.Components [BackgroundDependencyLoader] private void load() { - foreach (var t in availableDivisors) + foreach (int t in availableDivisors) { AddInternal(new Tick { @@ -287,7 +287,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private void handleMouseInput(Vector2 screenSpaceMousePosition) { // copied from SliderBar so we can do custom spacing logic. - var xPosition = (ToLocalSpace(screenSpaceMousePosition).X - RangePadding) / UsableWidth; + float xPosition = (ToLocalSpace(screenSpaceMousePosition).X - RangePadding) / UsableWidth; CurrentNumber.Value = availableDivisors.OrderBy(d => Math.Abs(getMappedPosition(d) - xPosition)).First(); OnUserChange(Current.Value); diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 75d4d13f94..d7d4642a39 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -58,13 +58,13 @@ namespace osu.Game.Screens.Edit.Compose.Components switch (args.Action) { case NotifyCollectionChangedAction.Add: - foreach (var o in args.NewItems) + foreach (object o in args.NewItems) SelectionBlueprints.FirstOrDefault(b => b.Item == o)?.Select(); break; case NotifyCollectionChangedAction.Remove: - foreach (var o in args.OldItems) + foreach (object o in args.OldItems) SelectionBlueprints.FirstOrDefault(b => b.Item == o)?.Deselect(); break; @@ -468,7 +468,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (snapProvider != null) { // check for positional snap for every object in selection (for things like object-object snapping) - for (var i = 0; i < movementBlueprintOriginalPositions.Length; i++) + for (int i = 0; i < movementBlueprintOriginalPositions.Length; i++) { Vector2 originalPosition = movementBlueprintOriginalPositions[i]; var testPosition = originalPosition + distanceTravelled; diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 9d43e3258a..05bf405f3c 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -132,8 +132,8 @@ namespace osu.Game.Screens.Edit.Compose.Components protected ColourInfo GetColourForIndexFromPlacement(int placementIndex) { var timingPoint = beatmap.ControlPointInfo.TimingPointAt(StartTime); - var beatLength = timingPoint.BeatLength / beatDivisor.Value; - var beatIndex = (int)Math.Round((StartTime - timingPoint.Time) / beatLength); + double beatLength = timingPoint.BeatLength / beatDivisor.Value; + int beatIndex = (int)Math.Round((StartTime - timingPoint.Time) / beatLength); var colour = BindableBeatDivisor.GetColourFor(BindableBeatDivisor.GetDivisorForBeatIndex(beatIndex + placementIndex + 1, beatDivisor.Value), Colours); diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs index 246d4aa8d7..5f6e8de557 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Edit.Compose.Components ///
private void createStateBindables() { - foreach (var sampleName in HitSampleInfo.AllAdditions) + foreach (string sampleName in HitSampleInfo.AllAdditions) { var bindable = new Bindable { @@ -102,7 +102,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { SelectionNewComboState.Value = GetStateFromSelection(SelectedItems.OfType(), h => h.NewCombo); - foreach (var (sampleName, bindable) in SelectionSampleStates) + foreach ((string sampleName, var bindable) in SelectionSampleStates) { bindable.Value = GetStateFromSelection(SelectedItems, h => h.Samples.Any(s => s.Name == sampleName)); } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs index 73c38ba23f..a9e9ef5001 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs @@ -176,7 +176,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline if (timeline != null) { var timelineQuad = timeline.ScreenSpaceDrawQuad; - var mouseX = e.ScreenSpaceMousePosition.X; + float mouseX = e.ScreenSpaceMousePosition.X; // scroll if in a drag and dragging outside visible extents if (mouseX > timelineQuad.TopRight.X) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index e2458d45c9..80aa6972b1 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -397,7 +397,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline if (hitObject.DifficultyControlPoint == DifficultyControlPoint.DEFAULT) hitObject.DifficultyControlPoint = new DifficultyControlPoint(); - var newVelocity = hitObject.DifficultyControlPoint.SliderVelocity * (repeatHitObject.Duration / proposedDuration); + double newVelocity = hitObject.DifficultyControlPoint.SliderVelocity * (repeatHitObject.Duration / proposedDuration); if (Precision.AlmostEquals(newVelocity, hitObject.DifficultyControlPoint.SliderVelocity)) return; @@ -408,8 +408,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline else { // find the number of repeats which can fit in the requested time. - var lengthOfOneRepeat = repeatHitObject.Duration / (repeatHitObject.RepeatCount + 1); - var proposedCount = Math.Max(0, (int)Math.Round(proposedDuration / lengthOfOneRepeat) - 1); + double lengthOfOneRepeat = repeatHitObject.Duration / (repeatHitObject.RepeatCount + 1); + int proposedCount = Math.Max(0, (int)Math.Round(proposedDuration / lengthOfOneRepeat) - 1); if (proposedCount == repeatHitObject.RepeatCount) return; @@ -421,7 +421,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline break; case IHasDuration endTimeHitObject: - var snappedTime = Math.Max(hitObject.StartTime, beatSnapProvider.SnapTime(time)); + double snappedTime = Math.Max(hitObject.StartTime, beatSnapProvider.SnapTime(time)); if (endTimeHitObject.EndTime == snappedTime || Precision.AlmostEquals(snappedTime, hitObject.StartTime, beatmap.GetBeatLengthAtTime(snappedTime))) return; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs index 3aaf0451c8..1415014e59 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs @@ -104,10 +104,10 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline nextMinTick = null; nextMaxTick = null; - for (var i = 0; i < beatmap.ControlPointInfo.TimingPoints.Count; i++) + for (int i = 0; i < beatmap.ControlPointInfo.TimingPoints.Count; i++) { var point = beatmap.ControlPointInfo.TimingPoints[i]; - var until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : working.Value.Track.Length; + double until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : working.Value.Track.Length; int beat = 0; @@ -127,7 +127,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline int indexInBar = beat % ((int)point.TimeSignature * beatDivisor.Value); - var divisor = BindableBeatDivisor.GetDivisorForBeatIndex(beat, beatDivisor.Value); + int divisor = BindableBeatDivisor.GetDivisorForBeatIndex(beat, beatDivisor.Value); var colour = BindableBeatDivisor.GetColourFor(divisor, colours); // even though "bar lines" take up the full vertical space, we render them in two pieces because it allows for less anchor/origin churn. diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 512226413b..81b2847443 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -301,7 +301,7 @@ namespace osu.Game.Screens.Edit editorBeatmap.SelectedHitObjects.BindCollectionChanged((_, __) => { - var hasObjects = editorBeatmap.SelectedHitObjects.Count > 0; + bool hasObjects = editorBeatmap.SelectedHitObjects.Count > 0; cutMenuItem.Action.Disabled = !hasObjects; copyMenuItem.Action.Disabled = !hasObjects; diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index 2e84ef437a..98fad09192 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -183,7 +183,7 @@ namespace osu.Game.Screens.Edit public void Add(HitObject hitObject) { // Preserve existing sorting order in the beatmap - var insertionIndex = findInsertionIndex(PlayableBeatmap.HitObjects, hitObject.StartTime); + int insertionIndex = findInsertionIndex(PlayableBeatmap.HitObjects, hitObject.StartTime); Insert(insertionIndex + 1, hitObject); } @@ -332,7 +332,7 @@ namespace osu.Game.Screens.Edit // For now we'll remove and re-add the hitobject. This is not optimal and can be improved if required. mutableHitObjects.Remove(hitObject); - var insertionIndex = findInsertionIndex(PlayableBeatmap.HitObjects, hitObject.StartTime); + int insertionIndex = findInsertionIndex(PlayableBeatmap.HitObjects, hitObject.StartTime); mutableHitObjects.Insert(insertionIndex + 1, hitObject); Update(hitObject); diff --git a/osu.Game/Screens/Edit/EditorChangeHandler.cs b/osu.Game/Screens/Edit/EditorChangeHandler.cs index 2dcb416a03..333c518d3a 100644 --- a/osu.Game/Screens/Edit/EditorChangeHandler.cs +++ b/osu.Game/Screens/Edit/EditorChangeHandler.cs @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Edit using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) new LegacyBeatmapEncoder(editorBeatmap, editorBeatmap.BeatmapSkin).Encode(sw); - var newState = stream.ToArray(); + byte[] newState = stream.ToArray(); // if the previous state is binary equal we don't need to push a new one, unless this is the initial state. if (savedStates.Count > 0 && newState.SequenceEqual(savedStates[currentState])) return; diff --git a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs index d26856365e..3ed2a7efe2 100644 --- a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs +++ b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs @@ -82,7 +82,7 @@ namespace osu.Game.Screens.Edit if (toAdd.Count > 0) { IBeatmap newBeatmap = readBeatmap(newState); - foreach (var i in toAdd) + foreach (int i in toAdd) editorBeatmap.Insert(i, newBeatmap.HitObjects[i]); } diff --git a/osu.Game/Screens/Edit/Timing/GroupSection.cs b/osu.Game/Screens/Edit/Timing/GroupSection.cs index 2e2c380d4a..03059ff6e1 100644 --- a/osu.Game/Screens/Edit/Timing/GroupSection.cs +++ b/osu.Game/Screens/Edit/Timing/GroupSection.cs @@ -68,7 +68,7 @@ namespace osu.Game.Screens.Edit.Timing if (!isNew) return; - if (double.TryParse(sender.Text, out var newTime)) + if (double.TryParse(sender.Text, out double newTime)) { changeSelectedGroupTime(newTime); } diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 32fb9f1d6d..eb8d3dfea6 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -211,7 +211,7 @@ namespace osu.Game.Screens.Menu else { const int quick_appear = 350; - var initialMovementTime = logo.Alpha > 0.2f ? quick_appear : 0; + int initialMovementTime = logo.Alpha > 0.2f ? quick_appear : 0; logo.MoveTo(new Vector2(0.5f), initialMovementTime, Easing.OutQuint); diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index a9376325cd..f9388097ac 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -272,7 +272,7 @@ namespace osu.Game.Screens.Menu lastBeatIndex = beatIndex; - var beatLength = timingPoint.BeatLength; + double beatLength = timingPoint.BeatLength; float amplitudeAdjust = Math.Min(1, 0.4f + amplitudes.Maximum); @@ -337,7 +337,7 @@ namespace osu.Game.Screens.Menu if (musicController.CurrentTrack.IsRunning) { - var maxAmplitude = lastBeatIndex >= 0 ? musicController.CurrentTrack.CurrentAmplitudes.Maximum : 0; + float maxAmplitude = lastBeatIndex >= 0 ? musicController.CurrentTrack.CurrentAmplitudes.Maximum : 0; logoAmplitudeContainer.Scale = new Vector2((float)Interpolation.Damp(logoAmplitudeContainer.Scale.X, 1 - Math.Max(0, maxAmplitude - scale_adjust_cutoff) * 0.04f, 0.9f, Time.Elapsed)); if (maxAmplitude > velocity_adjust_cutoff) diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs index 8b6077b9f2..e2088c77d5 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs @@ -95,7 +95,7 @@ namespace osu.Game.Screens.OnlinePlay.Components public override bool OnExiting(IScreen next) { - var result = base.OnExiting(next); + bool result = base.OnExiting(next); this.MoveToX(0); return result; } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs index 79e305b765..e77b5d7b8c 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs @@ -186,7 +186,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants var ruleset = rulesets.GetRuleset(Room.Settings.RulesetID).CreateInstance(); - var currentModeRank = User.User?.RulesetsStatistics?.GetValueOrDefault(ruleset.ShortName)?.GlobalRank; + int? currentModeRank = User.User?.RulesetsStatistics?.GetValueOrDefault(ruleset.ShortName)?.GlobalRank; userRankText.Text = currentModeRank != null ? $"#{currentModeRank.Value:N0}" : string.Empty; userStateDisplay.UpdateStatus(User.State, User.BeatmapAvailability); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index 7bf8ce0e1a..57d0d2c198 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -180,11 +180,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { // Seek the master clock to the gameplay time. // This is chosen as the first available frame in the players' replays, which matches the seek by each individual SpectatorPlayer. - var startTime = instances.Where(i => i.Score != null) - .SelectMany(i => i.Score.Replay.Frames) - .Select(f => f.Time) - .DefaultIfEmpty(0) - .Min(); + double startTime = instances.Where(i => i.Score != null) + .SelectMany(i => i.Score.Replay.Frames) + .Select(f => f.Time) + .DefaultIfEmpty(0) + .Min(); masterClockContainer.Seek(startTime); masterClockContainer.Start(); diff --git a/osu.Game/Screens/Play/Break/BreakInfoLine.cs b/osu.Game/Screens/Play/Break/BreakInfoLine.cs index 0bc79d6e77..87f514ffd5 100644 --- a/osu.Game/Screens/Play/Break/BreakInfoLine.cs +++ b/osu.Game/Screens/Play/Break/BreakInfoLine.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Play.Break private void currentValueChanged(ValueChangedEvent e) { - var newText = prefix + Format(e.NewValue); + string newText = prefix + Format(e.NewValue); if (valueText.Text == newText) return; diff --git a/osu.Game/Screens/Play/BreakTracker.cs b/osu.Game/Screens/Play/BreakTracker.cs index 2f3673e91f..8441b7657e 100644 --- a/osu.Game/Screens/Play/BreakTracker.cs +++ b/osu.Game/Screens/Play/BreakTracker.cs @@ -51,7 +51,7 @@ namespace osu.Game.Screens.Play private void updateBreakTime() { - var time = Clock.CurrentTime; + double time = Clock.CurrentTime; isBreakTime.Value = breaks?.IsInAny(time) == true || time < gameplayStartTime diff --git a/osu.Game/Screens/Play/HUD/FailingLayer.cs b/osu.Game/Screens/Play/HUD/FailingLayer.cs index 424ee55766..ceb81f6b8d 100644 --- a/osu.Game/Screens/Play/HUD/FailingLayer.cs +++ b/osu.Game/Screens/Play/HUD/FailingLayer.cs @@ -90,7 +90,7 @@ namespace osu.Game.Screens.Play.HUD private void updateState() { // Don't display ever if the ruleset is not using a draining health display. - var showLayer = HealthProcessor is DrainingHealthProcessor && fadePlayfieldWhenHealthLow.Value && ShowHealth.Value; + bool showLayer = HealthProcessor is DrainingHealthProcessor && fadePlayfieldWhenHealthLow.Value && ShowHealth.Value; this.FadeTo(showLayer ? 1 : 0, fade_time, Easing.OutQuint); } diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index fb49dedce7..a8141c57da 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -157,11 +157,11 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters // max to avoid div-by-zero. maxHitWindow = Math.Max(1, windows.First().length); - for (var i = 0; i < windows.Length; i++) + for (int i = 0; i < windows.Length; i++) { - var (result, length) = windows[i]; + (var result, double length) = windows[i]; - var hitWindow = (float)(length / maxHitWindow); + float hitWindow = (float)(length / maxHitWindow); colourBarsEarly.Add(createColourBar(result, hitWindow, i == 0)); colourBarsLate.Add(createColourBar(result, hitWindow, i == 0)); diff --git a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs index b1c07512dd..88cf9529bf 100644 --- a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs +++ b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs @@ -133,7 +133,7 @@ namespace osu.Game.Screens.Play.HUD var winningBar = Team1Score.Value > Team2Score.Value ? score1Bar : score2Bar; var losingBar = Team1Score.Value <= Team2Score.Value ? score1Bar : score2Bar; - var diff = Math.Max(Team1Score.Value, Team2Score.Value) - Math.Min(Team1Score.Value, Team2Score.Value); + int diff = Math.Max(Team1Score.Value, Team2Score.Value) - Math.Min(Team1Score.Value, Team2Score.Value); losingBar.ResizeWidthTo(0, 400, Easing.OutQuint); winningBar.ResizeWidthTo(Math.Min(0.4f, MathF.Pow(diff / 1500000f, 0.5f) / 2), 400, Easing.OutQuint); diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 19cb6aeb50..7caf90f610 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -148,7 +148,7 @@ namespace osu.Game.Screens.Play.HUD switch (e.Action) { case NotifyCollectionChangedAction.Remove: - foreach (var userId in e.OldItems.OfType()) + foreach (int userId in e.OldItems.OfType()) { spectatorClient.StopWatchingUser(userId); diff --git a/osu.Game/Screens/Play/SongProgressGraph.cs b/osu.Game/Screens/Play/SongProgressGraph.cs index 78eb456bb5..f96de149ba 100644 --- a/osu.Game/Screens/Play/SongProgressGraph.cs +++ b/osu.Game/Screens/Play/SongProgressGraph.cs @@ -24,17 +24,17 @@ namespace osu.Game.Screens.Play if (!objects.Any()) return; - var firstHit = objects.First().StartTime; - var lastHit = objects.Max(o => o.GetEndTime()); + double firstHit = objects.First().StartTime; + double lastHit = objects.Max(o => o.GetEndTime()); if (lastHit == 0) lastHit = objects.Last().StartTime; - var interval = (lastHit - firstHit + 1) / granularity; + double interval = (lastHit - firstHit + 1) / granularity; foreach (var h in objects) { - var endTime = h.GetEndTime(); + double endTime = h.GetEndTime(); Debug.Assert(endTime >= h.StartTime); diff --git a/osu.Game/Screens/Play/SongProgressInfo.cs b/osu.Game/Screens/Play/SongProgressInfo.cs index 7441c335d2..7a458cdde0 100644 --- a/osu.Game/Screens/Play/SongProgressInfo.cs +++ b/osu.Game/Screens/Play/SongProgressInfo.cs @@ -82,7 +82,7 @@ namespace osu.Game.Screens.Play { base.Update(); - var time = gameplayClock?.CurrentTime ?? Time.Current; + double time = gameplayClock?.CurrentTime ?? Time.Current; double songCurrentTime = time - startTime; int currentPercent = Math.Max(0, Math.Min(100, (int)(songCurrentTime / songLength * 100))); diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 36ce131411..67abcb66e6 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -165,7 +165,7 @@ namespace osu.Game.Screens.Play return; } - var max = values.Max(); + int max = values.Max(); float step = values.Length / (float)ColumnCount; diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index 5faa384d03..76411c8c6b 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -116,7 +116,7 @@ namespace osu.Game.Screens.Play public override bool OnExiting(IScreen next) { - var exiting = base.OnExiting(next); + bool exiting = base.OnExiting(next); submitScore(Score.DeepClone()); diff --git a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs index 262d1e8293..c27d5227b5 100644 --- a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs +++ b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs @@ -62,12 +62,12 @@ namespace osu.Game.Screens.Ranking.Expanded { var beatmap = score.BeatmapInfo; var metadata = beatmap.BeatmapSet?.Metadata ?? beatmap.Metadata; - var creator = metadata.Author?.Username; + string creator = metadata.Author?.Username; var topStatistics = new List { new AccuracyStatistic(score.Accuracy), - new ComboStatistic(score.MaxCombo, !score.Statistics.TryGetValue(HitResult.Miss, out var missCount) || missCount == 0), + new ComboStatistic(score.MaxCombo, !score.Statistics.TryGetValue(HitResult.Miss, out int missCount) || missCount == 0), new PerformanceStatistic(score), }; diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs index af60296344..dacc4f5f9e 100644 --- a/osu.Game/Screens/Ranking/ResultsScreen.cs +++ b/osu.Game/Screens/Ranking/ResultsScreen.cs @@ -287,7 +287,7 @@ namespace osu.Game.Screens.Ranking detachedPanelContainer.Add(expandedPanel); // Move into its original location in the local container first, then to the final location. - var origLocation = detachedPanelContainer.ToLocalSpace(screenSpacePos).X; + float origLocation = detachedPanelContainer.ToLocalSpace(screenSpacePos).X; expandedPanel.MoveToX(origLocation) .Then() .MoveToX(StatisticsPanel.SIDE_PADDING, 150, Easing.OutQuint); diff --git a/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs b/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs index 055db143d1..cd2b292547 100644 --- a/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs +++ b/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs @@ -20,8 +20,8 @@ namespace osu.Game.Screens.Ranking.Statistics public UnstableRate(IEnumerable hitEvents) : base("Unstable Rate") { - var timeOffsets = hitEvents.Where(e => !(e.HitObject.HitWindows is HitWindows.EmptyHitWindows) && e.Result.IsHit()) - .Select(ev => ev.TimeOffset).ToArray(); + double[] timeOffsets = hitEvents.Where(e => !(e.HitObject.HitWindows is HitWindows.EmptyHitWindows) && e.Result.IsHit()) + .Select(ev => ev.TimeOffset).ToArray(); Value = 10 * standardDeviation(timeOffsets); } @@ -30,8 +30,8 @@ namespace osu.Game.Screens.Ranking.Statistics if (timeOffsets.Length == 0) return double.NaN; - var mean = timeOffsets.Average(); - var squares = timeOffsets.Select(offset => Math.Pow(offset - mean, 2)).Sum(); + double mean = timeOffsets.Average(); + double squares = timeOffsets.Select(offset => Math.Pow(offset - mean, 2)).Sum(); return Math.Sqrt(squares / timeOffsets.Length); } diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 16455940bf..dfbaa9c6a5 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -233,7 +233,7 @@ namespace osu.Game.Screens.Select private void updateMetrics() { - var hasMetrics = (failTimes?.Retries?.Any() ?? false) || (failTimes?.Fails?.Any() ?? false); + bool hasMetrics = (failTimes?.Retries?.Any() ?? false) || (failTimes?.Fails?.Any() ?? false); if (ratings?.Any() ?? false) { diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index d8c5aa760e..9e057808a7 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -57,9 +57,9 @@ namespace osu.Game.Screens.Select.Carousel if (match) { - var terms = BeatmapInfo.GetSearchableTerms(); + string[] terms = BeatmapInfo.GetSearchableTerms(); - foreach (var criteriaTerm in criteria.SearchTerms) + foreach (string criteriaTerm in criteria.SearchTerms) match &= terms.Any(term => term.Contains(criteriaTerm, StringComparison.InvariantCultureIgnoreCase)); // if a match wasn't found via text matching of terms, do a second catch-all check matching against online IDs. @@ -89,7 +89,7 @@ namespace osu.Game.Screens.Select.Carousel { default: case SortMode.Difficulty: - var ruleset = BeatmapInfo.RulesetID.CompareTo(otherBeatmap.BeatmapInfo.RulesetID); + int ruleset = BeatmapInfo.RulesetID.CompareTo(otherBeatmap.BeatmapInfo.RulesetID); if (ruleset != 0) return ruleset; return BeatmapInfo.StarDifficulty.CompareTo(otherBeatmap.BeatmapInfo.StarDifficulty); diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 0d7882bf17..e465f423bc 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -95,8 +95,8 @@ namespace osu.Game.Screens.Select.Carousel private int compareUsingAggregateMax(CarouselBeatmapSet other, Func func) { - var ourBeatmaps = ValidBeatmaps.Any(); - var otherBeatmaps = other.ValidBeatmaps.Any(); + bool ourBeatmaps = ValidBeatmaps.Any(); + bool otherBeatmaps = other.ValidBeatmaps.Any(); if (!ourBeatmaps && !otherBeatmaps) return 0; if (!ourBeatmaps) return -1; diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 9773bd5ce9..173b804d90 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -241,7 +241,7 @@ namespace osu.Game.Screens.Select.Carousel TernaryState state; - var countExisting = beatmapSet.Beatmaps.Count(b => collection.Beatmaps.Contains(b)); + int countExisting = beatmapSet.Beatmaps.Count(b => collection.Beatmaps.Contains(b)); if (countExisting == beatmapSet.Beatmaps.Count) state = TernaryState.True; diff --git a/osu.Game/Screens/Select/Details/FailRetryGraph.cs b/osu.Game/Screens/Select/Details/FailRetryGraph.cs index ecaf02cb30..312c55b242 100644 --- a/osu.Game/Screens/Select/Details/FailRetryGraph.cs +++ b/osu.Game/Screens/Select/Details/FailRetryGraph.cs @@ -27,9 +27,9 @@ namespace osu.Game.Screens.Select.Details failTimes = value; - var retries = FailTimes?.Retries ?? Array.Empty(); - var fails = FailTimes?.Fails ?? Array.Empty(); - var retriesAndFails = sumRetriesAndFails(retries, fails); + int[] retries = FailTimes?.Retries ?? Array.Empty(); + int[] fails = FailTimes?.Fails ?? Array.Empty(); + int[] retriesAndFails = sumRetriesAndFails(retries, fails); float maxValue = retriesAndFails.Any() ? retriesAndFails.Max() : 0; failGraph.MaxValue = maxValue; @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Select.Details private int[] sumRetriesAndFails(int[] retries, int[] fails) { - var result = new int[Math.Max(retries.Length, fails.Length)]; + int[] result = new int[Math.Max(retries.Length, fails.Length)]; for (int i = 0; i < retries.Length; ++i) result[i] = retries[i]; diff --git a/osu.Game/Screens/Select/Details/UserRatings.cs b/osu.Game/Screens/Select/Details/UserRatings.cs index aa316d6e40..c2be3528fc 100644 --- a/osu.Game/Screens/Select/Details/UserRatings.cs +++ b/osu.Game/Screens/Select/Details/UserRatings.cs @@ -45,8 +45,8 @@ namespace osu.Game.Screens.Select.Details { var usableRange = Ratings.Skip(1).Take(rating_range); // adjust for API returning weird empty data at 0. - var negativeCount = usableRange.Take(rating_range / 2).Sum(); - var totalCount = usableRange.Sum(); + int negativeCount = usableRange.Take(rating_range / 2).Sum(); + int totalCount = usableRange.Sum(); negativeRatings.Text = negativeCount.ToLocalisableString(@"N0"); positiveRatings.Text = (totalCount - negativeCount).ToLocalisableString(@"N0"); diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 298b6e49bd..e95bd7f653 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -39,7 +39,7 @@ namespace osu.Game.Screens.Select { Debug.Assert(ruleset.Value.ID != null); - var query = searchTextBox.Text; + string query = searchTextBox.Text; var criteria = new FilterCriteria { diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index a882148392..94df8addb3 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -22,9 +22,9 @@ namespace osu.Game.Screens.Select { foreach (Match match in query_syntax_regex.Matches(query)) { - var key = match.Groups["key"].Value.ToLower(); + string key = match.Groups["key"].Value.ToLower(); var op = parseOperator(match.Groups["op"].Value); - var value = match.Groups["value"].Value; + string value = match.Groups["value"].Value; if (tryParseKeywordCriteria(criteria, key, value, op)) query = query.Replace(match.ToString(), ""); @@ -310,10 +310,10 @@ namespace osu.Game.Screens.Select private static bool tryUpdateLengthRange(FilterCriteria criteria, Operator op, string val) { - if (!tryParseDoubleWithPoint(val.TrimEnd('m', 's', 'h'), out var length)) + if (!tryParseDoubleWithPoint(val.TrimEnd('m', 's', 'h'), out double length)) return false; - var scale = getLengthScale(val); + int scale = getLengthScale(val); return tryUpdateCriteriaRange(ref criteria.Length, op, length * scale, scale / 2.0); } } diff --git a/osu.Game/Screens/Spectate/SpectatorScreen.cs b/osu.Game/Screens/Spectate/SpectatorScreen.cs index 7861d4cb72..c8df01dae6 100644 --- a/osu.Game/Screens/Spectate/SpectatorScreen.cs +++ b/osu.Game/Screens/Spectate/SpectatorScreen.cs @@ -76,7 +76,7 @@ namespace osu.Game.Screens.Spectate managerUpdated = beatmaps.ItemUpdated.GetBoundCopy(); managerUpdated.BindValueChanged(beatmapUpdated); - foreach (var (id, _) in userMap) + foreach ((int id, var _) in userMap) spectatorClient.WatchUser(id); })); } @@ -86,7 +86,7 @@ namespace osu.Game.Screens.Spectate if (!e.NewValue.TryGetTarget(out var beatmapSet)) return; - foreach (var (userId, _) in userMap) + foreach ((int userId, var _) in userMap) { if (!playingUserStates.TryGetValue(userId, out var userState)) continue; @@ -101,20 +101,20 @@ namespace osu.Game.Screens.Spectate switch (e.Action) { case NotifyDictionaryChangedAction.Add: - foreach (var (userId, state) in e.NewItems.AsNonNull()) + foreach ((int userId, var state) in e.NewItems.AsNonNull()) onUserStateAdded(userId, state); break; case NotifyDictionaryChangedAction.Remove: - foreach (var (userId, _) in e.OldItems.AsNonNull()) + foreach ((int userId, var _) in e.OldItems.AsNonNull()) onUserStateRemoved(userId); break; case NotifyDictionaryChangedAction.Replace: - foreach (var (userId, _) in e.OldItems.AsNonNull()) + foreach ((int userId, var _) in e.OldItems.AsNonNull()) onUserStateRemoved(userId); - foreach (var (userId, state) in e.NewItems.AsNonNull()) + foreach ((int userId, var state) in e.NewItems.AsNonNull()) onUserStateAdded(userId, state); break; } @@ -219,7 +219,7 @@ namespace osu.Game.Screens.Spectate if (spectatorClient != null) { - foreach (var (userId, _) in userMap) + foreach ((int userId, var _) in userMap) spectatorClient.StopWatchingUser(userId); } diff --git a/osu.Game/Skinning/DefaultSkin.cs b/osu.Game/Skinning/DefaultSkin.cs index 8e03bddb4d..495f476417 100644 --- a/osu.Game/Skinning/DefaultSkin.cs +++ b/osu.Game/Skinning/DefaultSkin.cs @@ -42,7 +42,7 @@ namespace osu.Game.Skinning public override ISample GetSample(ISampleInfo sampleInfo) { - foreach (var lookup in sampleInfo.LookupNames) + foreach (string lookup in sampleInfo.LookupNames) { var sample = resources.AudioManager.Samples.Get(lookup); if (sample != null) diff --git a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs index c0cc2ab40e..d67bfb89ab 100644 --- a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs +++ b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs @@ -41,7 +41,7 @@ namespace osu.Game.Skinning.Editor if (targetContainers.Length == 0) { - var targetScreen = target.ChildrenOfType().LastOrDefault()?.GetType().Name ?? "this screen"; + string targetScreen = target.ChildrenOfType().LastOrDefault()?.GetType().Name ?? "this screen"; AddInternal(new ScreenWhiteBox.UnderConstructionMessage(targetScreen, "doesn't support skin customisation just yet.")); return; diff --git a/osu.Game/Skinning/LegacyManiaSkinDecoder.cs b/osu.Game/Skinning/LegacyManiaSkinDecoder.cs index 5308640bdd..7214c847a7 100644 --- a/osu.Game/Skinning/LegacyManiaSkinDecoder.cs +++ b/osu.Game/Skinning/LegacyManiaSkinDecoder.cs @@ -66,7 +66,7 @@ namespace osu.Game.Skinning { Debug.Assert(currentConfig != null); - foreach (var line in pendingLines) + foreach (string line in pendingLines) { var pair = SplitKeyVal(line); diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index b09620411b..ad40f2c775 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -306,7 +306,7 @@ namespace osu.Game.Skinning => source.CustomColours.TryGetValue(lookup, out var col) ? new Bindable(col) : null; private IBindable getManiaImage(LegacyManiaSkinConfiguration source, string lookup) - => source.ImageLookups.TryGetValue(lookup, out var image) ? new Bindable(image) : null; + => source.ImageLookups.TryGetValue(lookup, out string image) ? new Bindable(image) : null; [CanBeNull] private IBindable legacySettingLookup(LegacySkinConfiguration.LegacySetting legacySetting) @@ -326,7 +326,7 @@ namespace osu.Game.Skinning { try { - if (Configuration.ConfigDictionary.TryGetValue(lookup.ToString(), out var val)) + if (Configuration.ConfigDictionary.TryGetValue(lookup.ToString(), out string val)) { // special case for handling skins which use 1 or 0 to signify a boolean state. if (typeof(TValue) == typeof(bool)) @@ -472,7 +472,7 @@ namespace osu.Game.Skinning public override Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) { - foreach (var name in getFallbackNames(componentName)) + foreach (string name in getFallbackNames(componentName)) { float ratio = 2; var texture = Textures?.Get($"{name}@2x", wrapModeS, wrapModeT); @@ -504,7 +504,7 @@ namespace osu.Game.Skinning lookupNames = sampleInfo.LookupNames.SelectMany(getFallbackNames); } - foreach (var lookup in lookupNames) + foreach (string lookup in lookupNames) { var sample = Samples?.Get(lookup); @@ -529,7 +529,7 @@ namespace osu.Game.Skinning lookupNames = lookupNames.Where(name => !name.EndsWith(hitSample.Suffix, StringComparison.Ordinal)); } - foreach (var l in lookupNames) + foreach (string l in lookupNames) yield return l; // also for compatibility, try falling back to non-bank samples (so-called "universal" samples) as the last resort. diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 2700f84815..a4ce3d83ce 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -35,7 +35,7 @@ namespace osu.Game.Skinning case @"Version": if (pair.Value == "latest") skin.LegacyVersion = LegacySkinConfiguration.LATEST_VERSION; - else if (decimal.TryParse(pair.Value, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var version)) + else if (decimal.TryParse(pair.Value, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out decimal version)) skin.LegacyVersion = version; return; diff --git a/osu.Game/Skinning/LegacySkinResourceStore.cs b/osu.Game/Skinning/LegacySkinResourceStore.cs index 05d0dee05f..fb06bb54d0 100644 --- a/osu.Game/Skinning/LegacySkinResourceStore.cs +++ b/osu.Game/Skinning/LegacySkinResourceStore.cs @@ -26,9 +26,9 @@ namespace osu.Game.Skinning if (source.Files == null) yield break; - foreach (var filename in base.GetFilenames(name)) + foreach (string filename in base.GetFilenames(name)) { - var path = getPathForFile(filename.ToStandardisedPath()); + string path = getPathForFile(filename.ToStandardisedPath()); if (path != null) yield return path; } diff --git a/osu.Game/Skinning/LegacySpriteText.cs b/osu.Game/Skinning/LegacySpriteText.cs index 8fc6cbde7d..94383834fc 100644 --- a/osu.Game/Skinning/LegacySpriteText.cs +++ b/osu.Game/Skinning/LegacySpriteText.cs @@ -49,7 +49,7 @@ namespace osu.Game.Skinning public ITexturedCharacterGlyph Get(string fontName, char character) { - var lookup = getLookupName(character); + string lookup = getLookupName(character); var texture = skin.GetTexture($"{fontName}-{lookup}"); diff --git a/osu.Game/Skinning/ResourceStoreBackedSkin.cs b/osu.Game/Skinning/ResourceStoreBackedSkin.cs index f041b82cf4..4787b5a4e9 100644 --- a/osu.Game/Skinning/ResourceStoreBackedSkin.cs +++ b/osu.Game/Skinning/ResourceStoreBackedSkin.cs @@ -36,7 +36,7 @@ namespace osu.Game.Skinning public ISample? GetSample(ISampleInfo sampleInfo) { - foreach (var lookup in sampleInfo.LookupNames) + foreach (string? lookup in sampleInfo.LookupNames) { ISample? sample = samples.Get(lookup); if (sample != null) diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 92441f40da..f0413ff310 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -51,7 +51,7 @@ namespace osu.Game.Skinning if (fileInfo == null) continue; - var bytes = resources?.Files.Get(fileInfo.FileInfo.StoragePath); + byte[] bytes = resources?.Files.Get(fileInfo.FileInfo.StoragePath); if (bytes == null) continue; diff --git a/osu.Game/Stores/BeatmapImporter.cs b/osu.Game/Stores/BeatmapImporter.cs index 254127cc7e..787b1ddd60 100644 --- a/osu.Game/Stores/BeatmapImporter.cs +++ b/osu.Game/Stores/BeatmapImporter.cs @@ -123,7 +123,7 @@ namespace osu.Game.Stores // find any existing beatmaps in the database that have matching online ids List existingBeatmaps = new List(); - foreach (var id in beatmapIds) + foreach (int id in beatmapIds) existingBeatmaps.AddRange(realm.All().Where(b => b.OnlineID == id)); if (existingBeatmaps.Any()) diff --git a/osu.Game/Stores/RealmArchiveModelImporter.cs b/osu.Game/Stores/RealmArchiveModelImporter.cs index ec454d25fa..3398cc114d 100644 --- a/osu.Game/Stores/RealmArchiveModelImporter.cs +++ b/osu.Game/Stores/RealmArchiveModelImporter.cs @@ -426,7 +426,7 @@ namespace osu.Game.Stores { MemoryStream hashable = new MemoryStream(); - foreach (var file in reader.Filenames.Where(f => HashableFileTypes.Any(ext => f.EndsWith(ext, StringComparison.OrdinalIgnoreCase))).OrderBy(f => f)) + foreach (string? file in reader.Filenames.Where(f => HashableFileTypes.Any(ext => f.EndsWith(ext, StringComparison.OrdinalIgnoreCase))).OrderBy(f => f)) { using (Stream s = reader.GetStream(file)) s.CopyTo(hashable); diff --git a/osu.Game/Stores/RealmRulesetStore.cs b/osu.Game/Stores/RealmRulesetStore.cs index 27eb5d797f..eea9acea05 100644 --- a/osu.Game/Stores/RealmRulesetStore.cs +++ b/osu.Game/Stores/RealmRulesetStore.cs @@ -193,7 +193,7 @@ namespace osu.Game.Stores { var rulesets = rulesetStorage.GetFiles(@".", @$"{ruleset_library_prefix}.*.dll"); - foreach (var ruleset in rulesets.Where(f => !f.Contains(@"Tests"))) + foreach (string? ruleset in rulesets.Where(f => !f.Contains(@"Tests"))) loadRulesetFromFile(rulesetStorage.GetFullPath(ruleset)); } @@ -201,7 +201,7 @@ namespace osu.Game.Stores { try { - var files = Directory.GetFiles(RuntimeInfo.StartupDirectory, @$"{ruleset_library_prefix}.*.dll"); + string[]? files = Directory.GetFiles(RuntimeInfo.StartupDirectory, @$"{ruleset_library_prefix}.*.dll"); foreach (string file in files.Where(f => !Path.GetFileName(f).Contains("Tests"))) loadRulesetFromFile(file); @@ -214,7 +214,7 @@ namespace osu.Game.Stores private void loadRulesetFromFile(string file) { - var filename = Path.GetFileNameWithoutExtension(file); + string? filename = Path.GetFileNameWithoutExtension(file); if (loadedAssemblies.Values.Any(t => Path.GetFileNameWithoutExtension(t.Assembly.Location) == filename)) return; diff --git a/osu.Game/Storyboards/CommandLoop.cs b/osu.Game/Storyboards/CommandLoop.cs index 66db965803..0713cb8670 100644 --- a/osu.Game/Storyboards/CommandLoop.cs +++ b/osu.Game/Storyboards/CommandLoop.cs @@ -33,9 +33,9 @@ namespace osu.Game.Storyboards public override IEnumerable.TypedCommand> GetCommands(CommandTimelineSelector timelineSelector, double offset = 0) { - for (var loop = 0; loop < TotalIterations; loop++) + for (int loop = 0; loop < TotalIterations; loop++) { - var loopOffset = LoopStartTime + loop * CommandsDuration; + double loopOffset = LoopStartTime + loop * CommandsDuration; foreach (var command in base.GetCommands(timelineSelector, offset + loopOffset)) yield return command; } diff --git a/osu.Game/Storyboards/CommandTimeline.cs b/osu.Game/Storyboards/CommandTimeline.cs index c71806352d..8ded3ee975 100644 --- a/osu.Game/Storyboards/CommandTimeline.cs +++ b/osu.Game/Storyboards/CommandTimeline.cs @@ -57,7 +57,7 @@ namespace osu.Game.Storyboards public int CompareTo(ICommand other) { - var result = StartTime.CompareTo(other.StartTime); + int result = StartTime.CompareTo(other.StartTime); if (result != 0) return result; return EndTime.CompareTo(other.EndTime); diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index c478b91c22..e7de135ce8 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -65,7 +65,7 @@ namespace osu.Game.Storyboards { // if the first alpha command starts at zero it should be given priority over anything else. // this is due to it creating a state where the target is not present before that time, causing any other events to not be visible. - var earliestDisplay = EarliestDisplayedTime; + double? earliestDisplay = EarliestDisplayedTime; if (earliestDisplay != null) return earliestDisplay.Value; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs index d746ff5ae5..d21616955a 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs @@ -29,7 +29,7 @@ namespace osu.Game.Storyboards.Drawables [BackgroundDependencyLoader(true)] private void load(IBindable beatmap, TextureStore textureStore) { - var path = beatmap.Value.BeatmapSetInfo?.Files.Find(f => f.Filename.Equals(Video.Path, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath; + string path = beatmap.Value.BeatmapSetInfo?.Files.Find(f => f.Filename.Equals(Video.Path, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath; if (path == null) return; diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 38e0e4e38c..a25bf24491 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -77,7 +77,7 @@ namespace osu.Game.Storyboards { get { - var backgroundPath = BeatmapInfo.BeatmapSet?.Metadata?.BackgroundFile?.ToLowerInvariant(); + string backgroundPath = BeatmapInfo.BeatmapSet?.Metadata?.BackgroundFile?.ToLowerInvariant(); if (backgroundPath == null) return false; @@ -91,7 +91,7 @@ namespace osu.Game.Storyboards public Drawable CreateSpriteFromResourcePath(string path, TextureStore textureStore) { Drawable drawable = null; - var storyboardPath = BeatmapInfo.BeatmapSet?.Files.Find(f => f.Filename.Equals(path, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath; + string storyboardPath = BeatmapInfo.BeatmapSet?.Files.Find(f => f.Filename.Equals(path, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath; if (storyboardPath != null) drawable = new Sprite { Texture = textureStore.Get(storyboardPath) }; diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index 6d63525011..651874e4de 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -150,7 +150,7 @@ namespace osu.Game.Tests.Beatmaps using (var resStream = openResource($"{resource_namespace}.{name}{expected_conversion_suffix}.json")) using (var reader = new StreamReader(resStream)) { - var contents = reader.ReadToEnd(); + string contents = reader.ReadToEnd(); return JsonConvert.DeserializeObject(contents); } } @@ -173,7 +173,7 @@ namespace osu.Game.Tests.Beatmaps private Stream openResource(string name) { - var localPath = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)).AsNonNull(); + string localPath = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)).AsNonNull(); return Assembly.LoadFrom(Path.Combine(localPath, $"{ResourceAssembly}.dll")).GetManifestResourceStream($@"{ResourceAssembly}.Resources.{name}"); } diff --git a/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs b/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs index fdb3e1d465..e5b641b606 100644 --- a/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs +++ b/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs @@ -49,7 +49,7 @@ namespace osu.Game.Tests.Beatmaps private Stream openResource(string name) { - var localPath = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)).AsNonNull(); + string localPath = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)).AsNonNull(); return Assembly.LoadFrom(Path.Combine(localPath, $"{ResourceAssembly}.dll")).GetManifestResourceStream($@"{ResourceAssembly}.Resources.{name}"); } diff --git a/osu.Game/Tests/Visual/DependencyProvidingContainer.cs b/osu.Game/Tests/Visual/DependencyProvidingContainer.cs index c799cad61a..d1290fc5ac 100644 --- a/osu.Game/Tests/Visual/DependencyProvidingContainer.cs +++ b/osu.Game/Tests/Visual/DependencyProvidingContainer.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual { var dependencyContainer = new DependencyContainer(base.CreateChildDependencies(parent)); - foreach (var (type, value) in CachedDependencies) + foreach ((var type, object value) in CachedDependencies) dependencyContainer.CacheAs(type, value); return dependencyContainer; diff --git a/osu.Game/Tests/Visual/SkinnableTestScene.cs b/osu.Game/Tests/Visual/SkinnableTestScene.cs index ef44d0df24..000e7194bc 100644 --- a/osu.Game/Tests/Visual/SkinnableTestScene.cs +++ b/osu.Game/Tests/Visual/SkinnableTestScene.cs @@ -127,7 +127,7 @@ namespace osu.Game.Tests.Visual void updateSizing() { - var autoSize = created.RelativeSizeAxes == Axes.None; + bool autoSize = created.RelativeSizeAxes == Axes.None; foreach (var c in new[] { mainProvider, childContainer, skinProvider }) { @@ -202,7 +202,7 @@ namespace osu.Game.Tests.Visual { var match = Regex.Match(componentName, "-([0-9]*)"); - if (match.Length > 0 && int.TryParse(match.Groups[1].Value, out var number) && number < 60) + if (match.Length > 0 && int.TryParse(match.Groups[1].Value, out int number) && number < 60) return base.GetTexture(componentName.Replace($"-{number}", $"-{number % 2}"), wrapModeS, wrapModeT); } diff --git a/osu.Game/Updater/SimpleUpdateManager.cs b/osu.Game/Updater/SimpleUpdateManager.cs index e0409e34df..5e466cc57f 100644 --- a/osu.Game/Updater/SimpleUpdateManager.cs +++ b/osu.Game/Updater/SimpleUpdateManager.cs @@ -45,7 +45,7 @@ namespace osu.Game.Updater // avoid any discrepancies due to build suffixes for now. // eventually we will want to support release streams and consider these. version = version.Split('-').First(); - var latestTagName = latest.TagName.Split('-').First(); + string latestTagName = latest.TagName.Split('-').First(); if (latestTagName != version) { diff --git a/osu.Game/Updater/UpdateManager.cs b/osu.Game/Updater/UpdateManager.cs index 98ce2cb46c..28b828804c 100644 --- a/osu.Game/Updater/UpdateManager.cs +++ b/osu.Game/Updater/UpdateManager.cs @@ -39,9 +39,9 @@ namespace osu.Game.Updater Schedule(() => Task.Run(CheckForUpdateAsync)); - var version = game.Version; + string version = game.Version; - var lastVersion = config.Get(OsuSetting.Version); + string lastVersion = config.Get(OsuSetting.Version); if (game.IsDeployedBuild && version != lastVersion) { diff --git a/osu.Game/Utils/StatelessRNG.cs b/osu.Game/Utils/StatelessRNG.cs index cd169229e3..3db632fc42 100644 --- a/osu.Game/Utils/StatelessRNG.cs +++ b/osu.Game/Utils/StatelessRNG.cs @@ -37,7 +37,7 @@ namespace osu.Game.Utils { unchecked { - var combined = ((ulong)(uint)series << 32) | (uint)seed; + ulong combined = ((ulong)(uint)series << 32) | (uint)seed; // The xor operation is to not map (0, 0) to 0. return mix(combined ^ 0x12345678); } From 95837990f3a185abc9acf50f170ea387cdd8adcf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Oct 2021 13:09:30 +0900 Subject: [PATCH 086/129] Apply some second-pass inspections that appeared after previous changes --- .../MathUtils/LegacySortHelper.cs | 16 +++------------- .../TestSceneSampleOutput.cs | 3 ++- .../Multiplayer/TestSceneMultiSpectatorScreen.cs | 2 +- osu.Game/Database/RealmContextFactory.cs | 2 +- osu.Game/Online/Chat/MessageFormatter.cs | 2 +- osu.Game/Stores/RealmRulesetStore.cs | 2 +- 6 files changed, 9 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs b/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs index a0e2958bae..5c595323c3 100644 --- a/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs +++ b/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs @@ -62,9 +62,7 @@ namespace osu.Game.Rulesets.Mania.MathUtils if (i < j) { - T key = keys[i]; - keys[i] = keys[j]; - keys[j] = key; + (keys[i], keys[j]) = (keys[j], keys[i]); } i++; @@ -142,11 +140,7 @@ namespace osu.Game.Rulesets.Mania.MathUtils private static void swap(T[] a, int i, int j) { if (i != j) - { - T t = a[i]; - a[i] = a[j]; - a[j] = t; - } + (a[i], a[j]) = (a[j], a[i]); } private static void swapIfGreater(T[] keys, IComparer comparer, int a, int b) @@ -154,11 +148,7 @@ namespace osu.Game.Rulesets.Mania.MathUtils if (a != b) { if (comparer.Compare(keys[a], keys[b]) > 0) - { - T key = keys[a]; - keys[a] = keys[b]; - keys[b] = key; - } + (keys[a], keys[b]) = (keys[b], keys[a]); } } } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs index 97c8d9eeb5..e5c9358c26 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Taiko.Tests { base.SetUpSteps(); - string[] expectedSampleNames = new[] + string[] expectedSampleNames = { string.Empty, string.Empty, @@ -31,6 +31,7 @@ namespace osu.Game.Rulesets.Taiko.Tests HitSampleInfo.HIT_WHISTLE, HitSampleInfo.HIT_WHISTLE, }; + var actualSampleNames = new List(); // due to pooling we can't access all samples right away due to object re-use, diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 8d878b993c..7ff8c82145 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -289,7 +289,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestSpectatingDuringGameplay() { - int[] players = new[] { PLAYER_1_ID, PLAYER_2_ID }; + int[] players = { PLAYER_1_ID, PLAYER_2_ID }; start(players); sendFrames(players, 300); diff --git a/osu.Game/Database/RealmContextFactory.cs b/osu.Game/Database/RealmContextFactory.cs index ffb1c96261..013a2e9d64 100644 --- a/osu.Game/Database/RealmContextFactory.cs +++ b/osu.Game/Database/RealmContextFactory.cs @@ -156,7 +156,7 @@ namespace osu.Game.Database void convertOnlineIDs() where T : RealmObject { - string? className = typeof(T).Name.Replace(@"Realm", string.Empty); + string className = typeof(T).Name.Replace(@"Realm", string.Empty); // version was not bumped when the beatmap/ruleset models were added // therefore we must manually check for their presence to avoid throwing on the `DynamicApi` calls. diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 5a90638dcd..5e0f66443b 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -136,7 +136,7 @@ namespace osu.Game.Online.Chat // length > 3 since all these links need another argument to work if (args.Length > 3 && args[1].EndsWith(websiteRootUrl, StringComparison.OrdinalIgnoreCase)) { - string? mainArg = args[3]; + string mainArg = args[3]; switch (args[2]) { diff --git a/osu.Game/Stores/RealmRulesetStore.cs b/osu.Game/Stores/RealmRulesetStore.cs index eea9acea05..e9c04f652d 100644 --- a/osu.Game/Stores/RealmRulesetStore.cs +++ b/osu.Game/Stores/RealmRulesetStore.cs @@ -201,7 +201,7 @@ namespace osu.Game.Stores { try { - string[]? files = Directory.GetFiles(RuntimeInfo.StartupDirectory, @$"{ruleset_library_prefix}.*.dll"); + string[] files = Directory.GetFiles(RuntimeInfo.StartupDirectory, @$"{ruleset_library_prefix}.*.dll"); foreach (string file in files.Where(f => !Path.GetFileName(f).Contains("Tests"))) loadRulesetFromFile(file); From 2bc242001217920324cbddb9bc462e005a2632f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Oct 2021 13:54:20 +0900 Subject: [PATCH 087/129] Rename test scene It's not testing the sub-screen. It's testing creating playlists. --- ...nePlaylistsRoomSubScreen.cs => TestScenePlaylistCreation.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game.Tests/Visual/Playlists/{TestScenePlaylistsRoomSubScreen.cs => TestScenePlaylistCreation.cs} (98%) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs similarity index 98% rename from osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs rename to osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs index deb9a22184..300a164644 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs @@ -22,7 +22,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Playlists { - public class TestScenePlaylistsRoomSubScreen : OnlinePlayTestScene + public class TestScenePlaylistCreation : OnlinePlayTestScene { private BeatmapManager manager; private RulesetStore rulesets; From c4a253cc75d5ece03ff3d44eb582c198877319f5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Oct 2021 13:55:14 +0900 Subject: [PATCH 088/129] Replace local instantiation of `TestBeatmap` with helper method --- .../Visual/Playlists/TestScenePlaylistCreation.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs index 300a164644..a0b51610ec 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs @@ -16,7 +16,6 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Screens.OnlinePlay.Playlists; using osu.Game.Screens.Play; -using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Visual.OnlinePlay; using osuTK.Input; @@ -40,7 +39,7 @@ namespace osu.Game.Tests.Visual.Playlists public void SetupSteps() { AddStep("set room", () => SelectedRoom.Value = new Room()); - AddStep("ensure has beatmap", () => manager.Import(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait()); + AddStep("ensure has beatmap", () => manager.Import(CreateBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait()); AddStep("load match", () => LoadScreen(match = new TestPlaylistsRoomSubScreen(SelectedRoom.Value))); AddUntilStep("wait for load", () => match.IsCurrentScreen()); } @@ -57,7 +56,7 @@ namespace osu.Game.Tests.Visual.Playlists SelectedRoom.Value.EndDate.Value = DateTimeOffset.Now.AddMinutes(5); SelectedRoom.Value.Playlist.Add(new PlaylistItem { - Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, + Beatmap = { Value = CreateBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, Ruleset = { Value = new OsuRuleset().RulesetInfo } }); }); @@ -75,7 +74,7 @@ namespace osu.Game.Tests.Visual.Playlists SelectedRoom.Value.Host.Value = API.LocalUser.Value; SelectedRoom.Value.Playlist.Add(new PlaylistItem { - Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, + Beatmap = { Value = CreateBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, Ruleset = { Value = new OsuRuleset().RulesetInfo } }); }); @@ -94,13 +93,13 @@ namespace osu.Game.Tests.Visual.Playlists public void TestBeatmapUpdatedOnReImport() { BeatmapSetInfo importedSet = null; - TestBeatmap beatmap = null; + IBeatmap beatmap = null; // this step is required to make sure the further imports actually get online IDs. // all the playlist logic relies on online ID matching. AddStep("remove all matching online IDs", () => { - beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo); + beatmap = CreateBeatmap(new OsuRuleset().RulesetInfo); var existing = manager.QueryBeatmapSets(s => s.OnlineBeatmapSetID == beatmap.BeatmapInfo.BeatmapSet.OnlineBeatmapSetID).ToList(); @@ -139,7 +138,7 @@ namespace osu.Game.Tests.Visual.Playlists AddAssert("match has altered beatmap", () => match.Beatmap.Value.Beatmap.Difficulty.CircleSize == 1); - AddStep("re-import original beatmap", () => manager.Import(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait()); + AddStep("re-import original beatmap", () => manager.Import(CreateBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait()); AddAssert("match has original beatmap", () => match.Beatmap.Value.Beatmap.Difficulty.CircleSize != 1); } From 84bb3a962b9def275ce92d29cb386b16913308a0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Oct 2021 14:11:07 +0900 Subject: [PATCH 089/129] Centralise room "creation" --- .../Playlists/TestScenePlaylistCreation.cs | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs index a0b51610ec..9ee0fb4db5 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs @@ -47,18 +47,20 @@ namespace osu.Game.Tests.Visual.Playlists [Test] public void TestLoadSimpleMatch() { - AddStep("set room properties", () => + setupRoom(room => { - SelectedRoom.Value.RoomID.Value = 1; - SelectedRoom.Value.Name.Value = "my awesome room"; - SelectedRoom.Value.Host.Value = API.LocalUser.Value; - SelectedRoom.Value.RecentParticipants.Add(SelectedRoom.Value.Host.Value); - SelectedRoom.Value.EndDate.Value = DateTimeOffset.Now.AddMinutes(5); - SelectedRoom.Value.Playlist.Add(new PlaylistItem + room.RoomID.Value = 1; // forces room creation. + room.Name.Value = "my awesome room"; + room.Host.Value = API.LocalUser.Value; + room.RecentParticipants.Add(room.Host.Value); + room.EndDate.Value = DateTimeOffset.Now.AddMinutes(5); + room.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, Ruleset = { Value = new OsuRuleset().RulesetInfo } }); + + OnlinePlayDependencies.RoomManager.CreateRoom(SelectedRoom.Value); }); AddStep("start match", () => match.ChildrenOfType().First().TriggerClick()); @@ -68,15 +70,17 @@ namespace osu.Game.Tests.Visual.Playlists [Test] public void TestPlaylistItemSelectedOnCreate() { - AddStep("set room properties", () => + setupRoom(room => { - SelectedRoom.Value.Name.Value = "my awesome room"; - SelectedRoom.Value.Host.Value = API.LocalUser.Value; - SelectedRoom.Value.Playlist.Add(new PlaylistItem + room.Name.Value = "my awesome room"; + room.Host.Value = API.LocalUser.Value; + room.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, Ruleset = { Value = new OsuRuleset().RulesetInfo } }); + + OnlinePlayDependencies.RoomManager.CreateRoom(SelectedRoom.Value); }); AddStep("move mouse to create button", () => @@ -119,11 +123,11 @@ namespace osu.Game.Tests.Visual.Playlists importedSet = manager.Import(beatmap.BeatmapInfo.BeatmapSet).Result.Value; }); - AddStep("load room", () => + setupRoom(room => { - SelectedRoom.Value.Name.Value = "my awesome room"; - SelectedRoom.Value.Host.Value = API.LocalUser.Value; - SelectedRoom.Value.Playlist.Add(new PlaylistItem + room.Name.Value = "my awesome room"; + room.Host.Value = API.LocalUser.Value; + room.Playlist.Add(new PlaylistItem { Beatmap = { Value = importedSet.Beatmaps[0] }, Ruleset = { Value = new OsuRuleset().RulesetInfo } @@ -143,6 +147,18 @@ namespace osu.Game.Tests.Visual.Playlists AddAssert("match has original beatmap", () => match.Beatmap.Value.Beatmap.Difficulty.CircleSize != 1); } + private void setupRoom(Action room) + { + AddStep("setup room", () => + { + room(SelectedRoom.Value); + + // if this isn't done the test will crash when a poll kicks in. + // probably not correct, but works for now. + OnlinePlayDependencies.RoomManager.CreateRoom(SelectedRoom.Value); + }); + } + private class TestPlaylistsRoomSubScreen : PlaylistsRoomSubScreen { public new Bindable SelectedItem => base.SelectedItem; From 58237f6fee5b63e2d955389efe47377297f1c898 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Oct 2021 14:26:37 +0900 Subject: [PATCH 090/129] Fix weird import flows --- .../Playlists/TestScenePlaylistCreation.cs | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs index 9ee0fb4db5..c4e6f41f27 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs @@ -11,6 +11,7 @@ using osu.Framework.Platform; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Database; using osu.Game.Online.Rooms; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; @@ -28,6 +29,8 @@ namespace osu.Game.Tests.Visual.Playlists private TestPlaylistsRoomSubScreen match; + private ILive importedBeatmap; + [BackgroundDependencyLoader] private void load(GameHost host, AudioManager audio) { @@ -39,7 +42,9 @@ namespace osu.Game.Tests.Visual.Playlists public void SetupSteps() { AddStep("set room", () => SelectedRoom.Value = new Room()); - AddStep("ensure has beatmap", () => manager.Import(CreateBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait()); + + importBeatmap(); + AddStep("load match", () => LoadScreen(match = new TestPlaylistsRoomSubScreen(SelectedRoom.Value))); AddUntilStep("wait for load", () => match.IsCurrentScreen()); } @@ -47,7 +52,7 @@ namespace osu.Game.Tests.Visual.Playlists [Test] public void TestLoadSimpleMatch() { - setupRoom(room => + setupAndCreateRoom(room => { room.RoomID.Value = 1; // forces room creation. room.Name.Value = "my awesome room"; @@ -56,11 +61,9 @@ namespace osu.Game.Tests.Visual.Playlists room.EndDate.Value = DateTimeOffset.Now.AddMinutes(5); room.Playlist.Add(new PlaylistItem { - Beatmap = { Value = CreateBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, + Beatmap = { Value = importedBeatmap.Value.Beatmaps.First() }, Ruleset = { Value = new OsuRuleset().RulesetInfo } }); - - OnlinePlayDependencies.RoomManager.CreateRoom(SelectedRoom.Value); }); AddStep("start match", () => match.ChildrenOfType().First().TriggerClick()); @@ -70,17 +73,15 @@ namespace osu.Game.Tests.Visual.Playlists [Test] public void TestPlaylistItemSelectedOnCreate() { - setupRoom(room => + setupAndCreateRoom(room => { room.Name.Value = "my awesome room"; room.Host.Value = API.LocalUser.Value; room.Playlist.Add(new PlaylistItem { - Beatmap = { Value = CreateBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, + Beatmap = { Value = importedBeatmap.Value.Beatmaps.First() }, Ruleset = { Value = new OsuRuleset().RulesetInfo } }); - - OnlinePlayDependencies.RoomManager.CreateRoom(SelectedRoom.Value); }); AddStep("move mouse to create button", () => @@ -97,15 +98,12 @@ namespace osu.Game.Tests.Visual.Playlists public void TestBeatmapUpdatedOnReImport() { BeatmapSetInfo importedSet = null; - IBeatmap beatmap = null; // this step is required to make sure the further imports actually get online IDs. // all the playlist logic relies on online ID matching. AddStep("remove all matching online IDs", () => { - beatmap = CreateBeatmap(new OsuRuleset().RulesetInfo); - - var existing = manager.QueryBeatmapSets(s => s.OnlineBeatmapSetID == beatmap.BeatmapInfo.BeatmapSet.OnlineBeatmapSetID).ToList(); + var existing = manager.QueryBeatmapSets(s => s.OnlineBeatmapSetID == importedBeatmap.Value.OnlineBeatmapSetID).ToList(); foreach (var s in existing) { @@ -118,12 +116,14 @@ namespace osu.Game.Tests.Visual.Playlists AddStep("import altered beatmap", () => { + IBeatmap beatmap = CreateBeatmap(new OsuRuleset().RulesetInfo); + beatmap.BeatmapInfo.BaseDifficulty.CircleSize = 1; importedSet = manager.Import(beatmap.BeatmapInfo.BeatmapSet).Result.Value; }); - setupRoom(room => + setupAndCreateRoom(room => { room.Name.Value = "my awesome room"; room.Host.Value = API.LocalUser.Value; @@ -134,20 +134,14 @@ namespace osu.Game.Tests.Visual.Playlists }); }); - AddStep("create room", () => - { - InputManager.MoveMouseTo(match.ChildrenOfType().Single()); - InputManager.Click(MouseButton.Left); - }); - AddAssert("match has altered beatmap", () => match.Beatmap.Value.Beatmap.Difficulty.CircleSize == 1); - AddStep("re-import original beatmap", () => manager.Import(CreateBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait()); + importBeatmap(); AddAssert("match has original beatmap", () => match.Beatmap.Value.Beatmap.Difficulty.CircleSize != 1); } - private void setupRoom(Action room) + private void setupAndCreateRoom(Action room) { AddStep("setup room", () => { @@ -159,6 +153,11 @@ namespace osu.Game.Tests.Visual.Playlists }); } + private void importBeatmap() + { + AddStep("import beatmap", () => importedBeatmap = manager.Import(CreateBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Result); + } + private class TestPlaylistsRoomSubScreen : PlaylistsRoomSubScreen { public new Bindable SelectedItem => base.SelectedItem; From 85b21174dd26cb55bc7598bf3d903bf6fd54d297 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 27 Oct 2021 14:49:50 +0900 Subject: [PATCH 091/129] Fix online play test request handling --- .../Visual/OnlinePlay/OnlinePlayTestScene.cs | 20 +++++++++++++++++-- .../TestRequestHandlingRoomManager.cs | 10 ---------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs index 8716646074..d782160ee5 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay; @@ -27,11 +28,15 @@ namespace osu.Game.Tests.Visual.OnlinePlay ///
protected OnlinePlayTestSceneDependencies OnlinePlayDependencies => dependencies?.OnlinePlayDependencies; - private DelegatedDependencyContainer dependencies; - protected override Container Content => content; + + [Resolved] + private OsuGameBase game { get; set; } + private readonly Container content; private readonly Container drawableDependenciesContainer; + private DelegatedDependencyContainer dependencies; + private TestRoomRequestsHandler requestsHandler; protected OnlinePlayTestScene() { @@ -57,6 +62,17 @@ namespace osu.Game.Tests.Visual.OnlinePlay drawableDependenciesContainer.AddRange(OnlinePlayDependencies.DrawableComponents); }); + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddStep("setup API", () => + { + requestsHandler = new TestRoomRequestsHandler(); + ((DummyAPIAccess)API).HandleRequest = request => requestsHandler.HandleRequest(request, API.LocalUser.Value, game); + }); + } + /// /// Creates the room dependencies. Called every . /// diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs index d88fd68b20..ef0ceafd02 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs @@ -2,9 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Allocation; using osu.Game.Beatmaps; -using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Rulesets; using osu.Game.Screens.OnlinePlay.Components; @@ -21,14 +19,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay private int currentRoomId; - private readonly TestRoomRequestsHandler handler = new TestRoomRequestsHandler(); - - [BackgroundDependencyLoader] - private void load(IAPIProvider api, OsuGameBase game) - { - ((DummyAPIAccess)api).HandleRequest = request => handler.HandleRequest(request, api.LocalUser.Value, game); - } - public override void JoinRoom(Room room, string password = null, Action onSuccess = null, Action onError = null) { JoinRoomRequested?.Invoke(room, password); From 676070946c38f1bfa79ce77b902a747f332c5bc6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 27 Oct 2021 15:25:26 +0900 Subject: [PATCH 092/129] Fix missed base.SetUpSteps() --- .../Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index eff107faee..10633f4a4f 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -43,6 +43,8 @@ namespace osu.Game.Tests.Visual.Multiplayer [SetUpSteps] public override void SetUpSteps() { + base.SetUpSteps(); + AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = LookupCache.GetUserAsync(1).Result); AddStep("create leaderboard", () => From f2683639242e18f474749df7cdaaf2182337bc9f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Oct 2021 15:20:01 +0900 Subject: [PATCH 093/129] Update `UpdateableBeatmapBackgroundSprite` to accept `IBeatmapInfo` --- .../UpdateableBeatmapBackgroundSprite.cs | 19 ++++++++++--------- .../OnlinePlay/DrawableRoomPlaylistItem.cs | 9 +++++++-- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 8943ad350e..636c568bd0 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -12,9 +12,9 @@ namespace osu.Game.Beatmaps.Drawables /// /// Display a beatmap background from a local source, but fallback to online source if not available. /// - public class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable + public class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable { - public readonly Bindable Beatmap = new Bindable(); + public readonly Bindable Beatmap = new Bindable(); protected override double LoadDelay => 500; @@ -39,7 +39,7 @@ namespace osu.Game.Beatmaps.Drawables protected override double TransformDuration => 400; - protected override Drawable CreateDrawable(BeatmapInfo model) + protected override Drawable CreateDrawable(IBeatmapInfo model) { var drawable = getDrawableForModel(model); drawable.RelativeSizeAxes = Axes.Both; @@ -50,15 +50,16 @@ namespace osu.Game.Beatmaps.Drawables return drawable; } - private Drawable getDrawableForModel(BeatmapInfo model) + private Drawable getDrawableForModel(IBeatmapInfo model) { // prefer online cover where available. - if (model?.BeatmapSet?.OnlineInfo != null) - return new OnlineBeatmapSetCover(model.BeatmapSet, beatmapSetCoverType); + if (model?.BeatmapSet is IBeatmapSetOnlineInfo online) + return new OnlineBeatmapSetCover(online, beatmapSetCoverType); - return model?.ID > 0 - ? new BeatmapBackgroundSprite(beatmaps.GetWorkingBeatmap(model)) - : new BeatmapBackgroundSprite(beatmaps.DefaultBeatmap); + if (model is BeatmapInfo localModel) + return new BeatmapBackgroundSprite(beatmaps.GetWorkingBeatmap(localModel)); + + return new BeatmapBackgroundSprite(beatmaps.DefaultBeatmap); } } } diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index 585b024623..264d49849c 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -333,13 +333,14 @@ namespace osu.Game.Screens.OnlinePlay public PanelBackground() { + UpdateableBeatmapBackgroundSprite backgroundSprite; + InternalChildren = new Drawable[] { - new UpdateableBeatmapBackgroundSprite + backgroundSprite = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fill, - Beatmap = { BindTarget = Beatmap } }, new FillFlowContainer { @@ -374,6 +375,10 @@ namespace osu.Game.Screens.OnlinePlay } } }; + + // manual binding required as playlists don't expose IBeatmapInfo currently. + // may be removed in the future if this changes. + Beatmap.BindValueChanged(beatmap => backgroundSprite.Beatmap.Value = beatmap.NewValue); } } } From d19580cf6023e336b26c354c64edc63c7326a8a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Oct 2021 13:47:12 +0900 Subject: [PATCH 094/129] Fix incorrectly changed difficulty count in recently updated test --- osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs index 7042f1e4fe..c7a065fdd7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs @@ -90,7 +90,7 @@ namespace osu.Game.Tests.Visual.Online { AddAssert("is visible", () => overlay.State.Value == Visibility.Visible); - AddStep("show many results", () => fetchFor(Enumerable.Repeat(CreateAPIBeatmapSet(Ruleset.Value), 10).ToArray())); + AddStep("show many results", () => fetchFor(Enumerable.Repeat(CreateAPIBeatmapSet(Ruleset.Value), 100).ToArray())); AddUntilStep("placeholder hidden", () => !overlay.ChildrenOfType().Any(d => d.IsPresent)); From 40d963fc8a115631bab1c7f0d1ba3ced61a0b456 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Oct 2021 12:44:14 +0900 Subject: [PATCH 095/129] Allow setting of `APIBeatmap.Length` (and don't serialise twice) --- osu.Game/Online/API/Requests/Responses/APIBeatmap.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index 0945ad30b4..e65dca752b 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -54,10 +54,15 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"accuracy")] private float overallDifficulty { get; set; } - public double Length => TimeSpan.FromSeconds(lengthInSeconds).TotalMilliseconds; + [JsonIgnore] + public double Length { get; set; } [JsonProperty(@"total_length")] - private double lengthInSeconds { get; set; } + private double lengthInSeconds + { + get => TimeSpan.FromMilliseconds(Length).TotalSeconds; + set => Length = TimeSpan.FromSeconds(value).TotalMilliseconds; + } [JsonProperty(@"count_circles")] public int CircleCount { get; set; } From db6343c44caf3d3f46ba9acfd3dc05c9e913dd17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Oct 2021 17:09:51 +0900 Subject: [PATCH 096/129] Correctly redirect `BPM` from API to interface --- osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 83f04fb5f2..d8efa20b39 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -164,7 +164,7 @@ namespace osu.Game.Online.API.Requests.Responses IEnumerable IBeatmapSetInfo.Files => throw new NotImplementedException(); double IBeatmapSetInfo.MaxStarDifficulty => throw new NotImplementedException(); double IBeatmapSetInfo.MaxLength => throw new NotImplementedException(); - double IBeatmapSetInfo.MaxBPM => throw new NotImplementedException(); + double IBeatmapSetInfo.MaxBPM => BPM; #endregion } From 31306163003dc0ea62e9165a9987b9196af1407d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Oct 2021 17:22:23 +0900 Subject: [PATCH 097/129] Update tournament components to use `APIBeatmap` directly --- .../TestSceneTournamentBeatmapPanel.cs | 6 ++--- .../TestSceneTournamentModDisplay.cs | 13 +++++------ .../NonVisual/LadderInfoSerialisationTest.cs | 4 ++-- .../Screens/TestSceneMapPoolScreen.cs | 2 +- .../TournamentTestScene.cs | 22 +++++++++---------- osu.Game.Tournament/Components/SongBar.cs | 22 +++++++++---------- .../Components/TournamentBeatmapPanel.cs | 7 +++--- osu.Game.Tournament/IPC/FileBasedIPC.cs | 6 ++--- osu.Game.Tournament/IPC/MatchIPCInfo.cs | 4 ++-- osu.Game.Tournament/Models/RoundBeatmap.cs | 4 ++-- osu.Game.Tournament/Models/SeedingBeatmap.cs | 4 ++-- .../Screens/BeatmapInfoScreen.cs | 4 ++-- .../Screens/Editors/RoundEditorScreen.cs | 6 ++--- .../Screens/Editors/SeedingEditorScreen.cs | 6 ++--- .../Screens/MapPool/MapPoolScreen.cs | 10 ++++----- osu.Game.Tournament/TournamentGameBase.cs | 4 ++-- 16 files changed, 59 insertions(+), 65 deletions(-) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs index f9c553cb3f..8139387a96 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs @@ -3,7 +3,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; @@ -23,14 +22,13 @@ namespace osu.Game.Tournament.Tests.Components [BackgroundDependencyLoader] private void load() { - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = 1091460 }); + var req = new GetBeatmapRequest(new APIBeatmap { OnlineID = 1091460 }); req.Success += success; api.Queue(req); } - private void success(APIBeatmap apiBeatmap) + private void success(APIBeatmap beatmap) { - var beatmap = apiBeatmap.ToBeatmapInfo(rulesets); Add(new TournamentBeatmapPanel(beatmap) { Anchor = Anchor.Centre, diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs index 27eb55a9fb..3c22bdca03 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs @@ -4,12 +4,12 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osu.Game.Tournament.Components; +using osuTK; namespace osu.Game.Tournament.Tests.Components { @@ -23,12 +23,10 @@ namespace osu.Game.Tournament.Tests.Components private FillFlowContainer fillFlow; - private BeatmapInfo beatmapInfo; - [BackgroundDependencyLoader] private void load() { - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = 490154 }); + var req = new GetBeatmapRequest(new APIBeatmap { OnlineID = 490154 }); req.Success += success; api.Queue(req); @@ -38,18 +36,17 @@ namespace osu.Game.Tournament.Tests.Components Anchor = Anchor.Centre, Origin = Anchor.Centre, Direction = FillDirection.Full, - Spacing = new osuTK.Vector2(10) + Spacing = new Vector2(10) }); } - private void success(APIBeatmap apiBeatmap) + private void success(APIBeatmap beatmap) { - beatmapInfo = apiBeatmap.ToBeatmapInfo(rulesets); var mods = rulesets.GetRuleset(Ladder.Ruleset.Value.ID ?? 0).CreateInstance().AllMods; foreach (var mod in mods) { - fillFlow.Add(new TournamentBeatmapPanel(beatmapInfo, mod.Acronym) + fillFlow.Add(new TournamentBeatmapPanel(beatmap, mod.Acronym) { Anchor = Anchor.Centre, Origin = Anchor.Centre diff --git a/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs b/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs index 13cbcd3caf..2071512f60 100644 --- a/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs @@ -44,8 +44,8 @@ namespace osu.Game.Tournament.Tests.NonVisual { Beatmaps = { - new RoundBeatmap { BeatmapInfo = TournamentTestScene.CreateSampleBeatmapInfo() }, - new RoundBeatmap { BeatmapInfo = TournamentTestScene.CreateSampleBeatmapInfo() }, + new RoundBeatmap { BeatmapInfo = TournamentTestScene.CreateSampleBeatmap() }, + new RoundBeatmap { BeatmapInfo = TournamentTestScene.CreateSampleBeatmap() }, } } }, diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs index f4032fdd54..41fbf44179 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs @@ -132,7 +132,7 @@ namespace osu.Game.Tournament.Tests.Screens { Ladder.CurrentMatch.Value.Round.Value.Beatmaps.Add(new RoundBeatmap { - BeatmapInfo = CreateSampleBeatmapInfo(), + BeatmapInfo = CreateSampleBeatmap(), Mods = mods }); } diff --git a/osu.Game.Tournament.Tests/TournamentTestScene.cs b/osu.Game.Tournament.Tests/TournamentTestScene.cs index ce9fd91ff1..4f057286b6 100644 --- a/osu.Game.Tournament.Tests/TournamentTestScene.cs +++ b/osu.Game.Tournament.Tests/TournamentTestScene.cs @@ -7,7 +7,6 @@ using osu.Framework.Allocation; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Utils; -using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osu.Game.Tests.Visual; @@ -74,19 +73,19 @@ namespace osu.Game.Tournament.Tests { new SeedingBeatmap { - BeatmapInfo = CreateSampleBeatmapInfo(), + BeatmapInfo = CreateSampleBeatmap(), Score = 12345672, Seed = { Value = 24 }, }, new SeedingBeatmap { - BeatmapInfo = CreateSampleBeatmapInfo(), + BeatmapInfo = CreateSampleBeatmap(), Score = 1234567, Seed = { Value = 12 }, }, new SeedingBeatmap { - BeatmapInfo = CreateSampleBeatmapInfo(), + BeatmapInfo = CreateSampleBeatmap(), Score = 1234567, Seed = { Value = 16 }, } @@ -100,19 +99,19 @@ namespace osu.Game.Tournament.Tests { new SeedingBeatmap { - BeatmapInfo = CreateSampleBeatmapInfo(), + BeatmapInfo = CreateSampleBeatmap(), Score = 234567, Seed = { Value = 3 }, }, new SeedingBeatmap { - BeatmapInfo = CreateSampleBeatmapInfo(), + BeatmapInfo = CreateSampleBeatmap(), Score = 234567, Seed = { Value = 6 }, }, new SeedingBeatmap { - BeatmapInfo = CreateSampleBeatmapInfo(), + BeatmapInfo = CreateSampleBeatmap(), Score = 234567, Seed = { Value = 12 }, } @@ -152,16 +151,15 @@ namespace osu.Game.Tournament.Tests } }; - public static BeatmapInfo CreateSampleBeatmapInfo() => - new BeatmapInfo + public static APIBeatmap CreateSampleBeatmap() => + new APIBeatmap { - Metadata = new BeatmapMetadata + BeatmapSet = new APIBeatmapSet { Title = "Test Title", Artist = "Test Artist", - ID = RNG.Next(0, 1000000) }, - OnlineInfo = new APIBeatmap(), + OnlineID = RNG.Next(0, 1000000), }; protected override ITestSceneTestRunner CreateRunner() => new TournamentTestSceneTestRunner(); diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 60be7dec91..bdcb6f8ded 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -12,6 +12,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; using osu.Game.Extensions; using osu.Game.Graphics; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osu.Game.Screens.Menu; using osuTK; @@ -21,16 +22,15 @@ namespace osu.Game.Tournament.Components { public class SongBar : CompositeDrawable { - private BeatmapInfo beatmapInfo; + private APIBeatmap beatmapInfo; public const float HEIGHT = 145 / 2f; [Resolved] private IBindable ruleset { get; set; } - public BeatmapInfo BeatmapInfo + public APIBeatmap BeatmapInfo { - get => beatmapInfo; set { if (beatmapInfo == value) @@ -101,12 +101,12 @@ namespace osu.Game.Tournament.Components return; } - double bpm = beatmapInfo.BeatmapSet.OnlineInfo.BPM; + double bpm = beatmapInfo.BPM; // TODO: check this works. double length = beatmapInfo.Length; string hardRockExtra = ""; string srExtra = ""; - float ar = beatmapInfo.BaseDifficulty.ApproachRate; + float ar = beatmapInfo.Difficulty.ApproachRate; if ((mods & LegacyMods.HardRock) > 0) { @@ -132,9 +132,9 @@ namespace osu.Game.Tournament.Components default: stats = new (string heading, string content)[] { - ("CS", $"{beatmapInfo.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"), + ("CS", $"{beatmapInfo.Difficulty.CircleSize:0.#}{hardRockExtra}"), ("AR", $"{ar:0.#}{hardRockExtra}"), - ("OD", $"{beatmapInfo.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}"), + ("OD", $"{beatmapInfo.Difficulty.OverallDifficulty:0.#}{hardRockExtra}"), }; break; @@ -142,15 +142,15 @@ namespace osu.Game.Tournament.Components case 3: stats = new (string heading, string content)[] { - ("OD", $"{beatmapInfo.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}"), - ("HP", $"{beatmapInfo.BaseDifficulty.DrainRate:0.#}{hardRockExtra}") + ("OD", $"{beatmapInfo.Difficulty.OverallDifficulty:0.#}{hardRockExtra}"), + ("HP", $"{beatmapInfo.Difficulty.DrainRate:0.#}{hardRockExtra}") }; break; case 2: stats = new (string heading, string content)[] { - ("CS", $"{beatmapInfo.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"), + ("CS", $"{beatmapInfo.Difficulty.CircleSize:0.#}{hardRockExtra}"), ("AR", $"{ar:0.#}"), }; break; @@ -186,7 +186,7 @@ namespace osu.Game.Tournament.Components Children = new Drawable[] { new DiffPiece(stats), - new DiffPiece(("Star Rating", $"{beatmapInfo.StarDifficulty:0.#}{srExtra}")) + new DiffPiece(("Star Rating", $"{beatmapInfo.StarRating:0.#}{srExtra}")) } }, new FillFlowContainer diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index be29566e07..39fc1d0c0a 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Tournament.Models; using osuTK.Graphics; @@ -20,7 +21,7 @@ namespace osu.Game.Tournament.Components { public class TournamentBeatmapPanel : CompositeDrawable { - public readonly IBeatmapInfo BeatmapInfo; + public readonly APIBeatmap BeatmapInfo; private readonly string mod; @@ -32,7 +33,7 @@ namespace osu.Game.Tournament.Components private readonly Bindable currentMatch = new Bindable(); private Box flash; - public TournamentBeatmapPanel(IBeatmapInfo beatmapInfo, string mod = null) + public TournamentBeatmapPanel(APIBeatmap beatmapInfo, string mod = null) { if (beatmapInfo == null) throw new ArgumentNullException(nameof(beatmapInfo)); @@ -62,7 +63,7 @@ namespace osu.Game.Tournament.Components { RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.5f), - BeatmapSet = BeatmapInfo.BeatmapSet as IBeatmapSetOnlineInfo, + BeatmapSet = BeatmapInfo.BeatmapSet, }, new FillFlowContainer { diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 6dde265bd6..15aa9dd588 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -11,10 +11,10 @@ using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Threading; -using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osu.Game.Tournament.Models; @@ -93,8 +93,8 @@ namespace osu.Game.Tournament.IPC Beatmap.Value = existing.BeatmapInfo; else { - beatmapLookupRequest = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId }); - beatmapLookupRequest.Success += b => Beatmap.Value = b.ToBeatmapInfo(Rulesets); + beatmapLookupRequest = new GetBeatmapRequest(new APIBeatmap { OnlineID = beatmapId }); + beatmapLookupRequest.Success += b => Beatmap.Value = b; API.Queue(beatmapLookupRequest); } } diff --git a/osu.Game.Tournament/IPC/MatchIPCInfo.cs b/osu.Game.Tournament/IPC/MatchIPCInfo.cs index 701258c6c7..fa7079b824 100644 --- a/osu.Game.Tournament/IPC/MatchIPCInfo.cs +++ b/osu.Game.Tournament/IPC/MatchIPCInfo.cs @@ -3,14 +3,14 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; +using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Tournament.IPC { public class MatchIPCInfo : Component { - public Bindable Beatmap { get; } = new Bindable(); + public Bindable Beatmap { get; } = new Bindable(); public Bindable Mods { get; } = new Bindable(); public Bindable State { get; } = new Bindable(); public Bindable ChatChannel { get; } = new Bindable(); diff --git a/osu.Game.Tournament/Models/RoundBeatmap.cs b/osu.Game.Tournament/Models/RoundBeatmap.cs index 5d43d0ca66..8f1968236e 100644 --- a/osu.Game.Tournament/Models/RoundBeatmap.cs +++ b/osu.Game.Tournament/Models/RoundBeatmap.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Beatmaps; +using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Tournament.Models { @@ -10,6 +10,6 @@ namespace osu.Game.Tournament.Models public int ID; public string Mods; - public BeatmapInfo BeatmapInfo; + public APIBeatmap BeatmapInfo; } } diff --git a/osu.Game.Tournament/Models/SeedingBeatmap.cs b/osu.Game.Tournament/Models/SeedingBeatmap.cs index 2cd6fa7188..37a8a92546 100644 --- a/osu.Game.Tournament/Models/SeedingBeatmap.cs +++ b/osu.Game.Tournament/Models/SeedingBeatmap.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; -using osu.Game.Beatmaps; +using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Tournament.Models { @@ -10,7 +10,7 @@ namespace osu.Game.Tournament.Models { public int ID; - public BeatmapInfo BeatmapInfo; + public APIBeatmap BeatmapInfo; public long Score; diff --git a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs index b94b164116..50324d9c83 100644 --- a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs +++ b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs @@ -4,8 +4,8 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; @@ -37,7 +37,7 @@ namespace osu.Game.Tournament.Screens SongBar.Mods = mods.NewValue; } - private void beatmapChanged(ValueChangedEvent beatmap) + private void beatmapChanged(ValueChangedEvent beatmap) { SongBar.FadeInFromZero(300, Easing.OutQuint); SongBar.BeatmapInfo = beatmap.NewValue; diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index 1d8c4e7476..2f77209d57 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -7,10 +7,10 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Settings; using osu.Game.Rulesets; using osu.Game.Tournament.Components; @@ -234,11 +234,11 @@ namespace osu.Game.Tournament.Screens.Editors return; } - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = Model.ID }); + var req = new GetBeatmapRequest(new APIBeatmap { OnlineID = Model.ID }); req.Success += res => { - Model.BeatmapInfo = res.ToBeatmapInfo(rulesets); + Model.BeatmapInfo = res; updatePanel(); }; diff --git a/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs index d5b55823a5..c17939e040 100644 --- a/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs @@ -7,10 +7,10 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Settings; using osu.Game.Rulesets; using osu.Game.Tournament.Components; @@ -242,11 +242,11 @@ namespace osu.Game.Tournament.Screens.Editors return; } - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = Model.ID }); + var req = new GetBeatmapRequest(new APIBeatmap { OnlineID = Model.ID }); req.Success += res => { - Model.BeatmapInfo = res.ToBeatmapInfo(rulesets); + Model.BeatmapInfo = res; updatePanel(); }; diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 5f6546c303..a2432d7b5e 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -8,8 +8,8 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Framework.Threading; -using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; @@ -105,14 +105,14 @@ namespace osu.Game.Tournament.Screens.MapPool ipc.Beatmap.BindValueChanged(beatmapChanged); } - private void beatmapChanged(ValueChangedEvent beatmap) + private void beatmapChanged(ValueChangedEvent beatmap) { if (CurrentMatch.Value == null || CurrentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) < 2) return; // if bans have already been placed, beatmap changes result in a selection being made autoamtically - if (beatmap.NewValue.OnlineBeatmapID != null) - addForBeatmap(beatmap.NewValue.OnlineBeatmapID.Value); + if (beatmap.NewValue.OnlineID > 0) + addForBeatmap(beatmap.NewValue.OnlineID); } private void setMode(TeamColour colour, ChoiceType choiceType) @@ -179,7 +179,7 @@ namespace osu.Game.Tournament.Screens.MapPool if (CurrentMatch.Value == null) return; - if (CurrentMatch.Value.Round.Value.Beatmaps.All(b => b.BeatmapInfo.OnlineBeatmapID != beatmapId)) + if (CurrentMatch.Value.Round.Value.Beatmaps.All(b => b.BeatmapInfo.OnlineID != beatmapId)) // don't attempt to add if the beatmap isn't in our pool return; diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 978be720df..5f7c75f9a7 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -190,7 +190,7 @@ namespace osu.Game.Tournament { var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); API.Perform(req); - b.BeatmapInfo = req.Response?.ToBeatmapInfo(RulesetStore); + b.BeatmapInfo = req.Response; addedInfo = true; } @@ -211,7 +211,7 @@ namespace osu.Game.Tournament { var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); req.Perform(API); - b.BeatmapInfo = req.Response?.ToBeatmapInfo(RulesetStore); + b.BeatmapInfo = req.Response; addedInfo = true; } From 35168948fe871b2e32813e50a72119f36fd5f2a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Oct 2021 17:45:46 +0900 Subject: [PATCH 098/129] Fix `PopulateUser` not populating immediately when `immediate` is specified (due to scheduling) --- osu.Game.Tournament/TournamentGameBase.cs | 37 +++++++++++++++-------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 5f7c75f9a7..fd31c325b4 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -226,8 +226,30 @@ namespace osu.Game.Tournament { var req = new GetUserRequest(user.Id, Ruleset.Value); - req.Success += res => + if (immediate) { + API.Perform(req); + populate(); + } + else + { + req.Success += res => { populate(); }; + req.Failure += _ => + { + user.Id = 1; + failure?.Invoke(); + }; + + API.Queue(req); + } + + void populate() + { + var res = req.Response; + + if (res == null) + return; + user.Id = res.Id; user.Username = res.Username; @@ -236,18 +258,7 @@ namespace osu.Game.Tournament user.Cover = res.Cover; success?.Invoke(); - }; - - req.Failure += _ => - { - user.Id = 1; - failure?.Invoke(); - }; - - if (immediate) - API.Perform(req); - else - API.Queue(req); + } } protected override void LoadComplete() From 5448b94039b024884fec0a3efbfbab32cdc11217 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Oct 2021 18:20:10 +0900 Subject: [PATCH 099/129] Change repopulation rules to cover the fact that the serisalisation model has changed This also adds a progress display to show how repopulation is going. It can take a while on a large bracket. --- osu.Game.Tournament/TournamentGameBase.cs | 125 +++++++++++++--------- 1 file changed, 72 insertions(+), 53 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index fd31c325b4..5748315418 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -7,12 +7,14 @@ using System.Linq; using System.Threading.Tasks; using Newtonsoft.Json; using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Framework.Input; using osu.Framework.IO.Stores; using osu.Framework.Platform; -using osu.Game.Beatmaps; +using osu.Game.Graphics; using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Tournament.IO; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; @@ -39,9 +41,18 @@ namespace osu.Game.Tournament return dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); } + private TournamentSpriteText initialisationText; + [BackgroundDependencyLoader] private void load(Storage baseStorage) { + AddInternal(initialisationText = new TournamentSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.Torus.With(size: 32), + }); + Resources.AddStore(new DllResourceStore(typeof(TournamentGameBase).Assembly)); dependencies.CacheAs(storage = new TournamentStorage(baseStorage)); @@ -123,7 +134,8 @@ namespace osu.Game.Tournament } addedInfo |= addPlayers(); - addedInfo |= addBeatmaps(); + addedInfo |= addRoundBeatmaps(); + addedInfo |= addSeedingBeatmaps(); if (addedInfo) SaveChanges(); @@ -145,6 +157,8 @@ namespace osu.Game.Tournament Add(ipc); taskCompletionSource.SetResult(true); + + initialisationText.Expire(); }); } @@ -153,75 +167,80 @@ namespace osu.Game.Tournament /// private bool addPlayers() { - bool addedInfo = false; + var playersRequiringPopulation = ladder.Teams + .SelectMany(t => t.Players) + .Where(p => string.IsNullOrEmpty(p.Username) + || p.Statistics?.GlobalRank == null + || p.Statistics?.CountryRank == null).ToList(); - foreach (var t in ladder.Teams) + if (playersRequiringPopulation.Count == 0) + return false; + + for (int i = 0; i < playersRequiringPopulation.Count; i++) { - foreach (var p in t.Players) - { - if (string.IsNullOrEmpty(p.Username) - || p.Statistics?.GlobalRank == null - || p.Statistics?.CountryRank == null) - { - PopulateUser(p, immediate: true); - addedInfo = true; - } - } + var p = playersRequiringPopulation[i]; + PopulateUser(p, immediate: true); + updateLoadProgressMessage($"Populating user stats ({i} / {playersRequiringPopulation.Count})"); } - return addedInfo; + return true; } /// /// Add missing beatmap info based on beatmap IDs /// - private bool addBeatmaps() + private bool addRoundBeatmaps() { - bool addedInfo = false; + var beatmapsRequiringPopulation = ladder.Rounds + .SelectMany(r => r.Beatmaps) + .Where(b => string.IsNullOrEmpty(b.BeatmapInfo?.BeatmapSet?.Title) && b.ID > 0).ToList(); - foreach (var r in ladder.Rounds) + if (beatmapsRequiringPopulation.Count == 0) + return false; + + for (int i = 0; i < beatmapsRequiringPopulation.Count; i++) { - foreach (var b in r.Beatmaps.ToList()) - { - if (b.BeatmapInfo != null) - continue; + var b = beatmapsRequiringPopulation[i]; - if (b.ID > 0) - { - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); - API.Perform(req); - b.BeatmapInfo = req.Response; + var req = new GetBeatmapRequest(new APIBeatmap { OnlineID = b.ID }); + API.Perform(req); + b.BeatmapInfo = req.Response ?? new APIBeatmap(); - addedInfo = true; - } - - if (b.BeatmapInfo == null) - // if online population couldn't be performed, ensure we don't leave a null value behind - r.Beatmaps.Remove(b); - } + updateLoadProgressMessage($"Populating round beatmaps ({i} / {beatmapsRequiringPopulation.Count})"); } - foreach (var t in ladder.Teams) - { - foreach (var s in t.SeedingResults) - { - foreach (var b in s.Beatmaps) - { - if (b.BeatmapInfo == null && b.ID > 0) - { - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); - req.Perform(API); - b.BeatmapInfo = req.Response; - - addedInfo = true; - } - } - } - } - - return addedInfo; + return true; } + /// + /// Add missing beatmap info based on beatmap IDs + /// + private bool addSeedingBeatmaps() + { + var beatmapsRequiringPopulation = ladder.Teams + .SelectMany(r => r.SeedingResults) + .SelectMany(r => r.Beatmaps) + .Where(b => string.IsNullOrEmpty(b.BeatmapInfo?.BeatmapSet?.Title) && b.ID > 0).ToList(); + + if (beatmapsRequiringPopulation.Count == 0) + return false; + + for (int i = 0; i < beatmapsRequiringPopulation.Count; i++) + { + var b = beatmapsRequiringPopulation[i]; + + var req = new GetBeatmapRequest(new APIBeatmap { OnlineID = b.ID }); + API.Perform(req); + b.BeatmapInfo = req.Response ?? new APIBeatmap(); + + updateLoadProgressMessage($"Populating seeding beatmaps ({i} / {beatmapsRequiringPopulation.Count})"); + } + + return true; + } + + private void updateLoadProgressMessage(string s) => Schedule(() => initialisationText.Text = s); + public void PopulateUser(User user, Action success = null, Action failure = null, bool immediate = false) { var req = new GetUserRequest(user.Id, Ruleset.Value); From f1499641f3d12789dfaf185b4aa2ad29352052e8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Oct 2021 18:25:23 +0900 Subject: [PATCH 100/129] Rename all usages of `APIBeatmap` to `beatmap` in tournament namespace --- .../NonVisual/LadderInfoSerialisationTest.cs | 4 +-- .../Screens/TestSceneMapPoolScreen.cs | 2 +- .../TournamentTestScene.cs | 12 ++++---- osu.Game.Tournament/Components/SongBar.cs | 30 +++++++++---------- .../Components/TournamentBeatmapPanel.cs | 18 +++++------ osu.Game.Tournament/IPC/FileBasedIPC.cs | 4 +-- osu.Game.Tournament/Models/RoundBeatmap.cs | 4 ++- osu.Game.Tournament/Models/SeedingBeatmap.cs | 4 ++- .../Screens/BeatmapInfoScreen.cs | 2 +- .../Screens/Editors/RoundEditorScreen.cs | 12 ++++---- .../Screens/Editors/SeedingEditorScreen.cs | 12 ++++---- .../Screens/MapPool/MapPoolScreen.cs | 10 +++---- .../Screens/TeamIntro/SeedingScreen.cs | 4 +-- osu.Game.Tournament/TournamentGameBase.cs | 8 ++--- 14 files changed, 65 insertions(+), 61 deletions(-) diff --git a/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs b/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs index 2071512f60..8bdf909af3 100644 --- a/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs @@ -44,8 +44,8 @@ namespace osu.Game.Tournament.Tests.NonVisual { Beatmaps = { - new RoundBeatmap { BeatmapInfo = TournamentTestScene.CreateSampleBeatmap() }, - new RoundBeatmap { BeatmapInfo = TournamentTestScene.CreateSampleBeatmap() }, + new RoundBeatmap { Beatmap = TournamentTestScene.CreateSampleBeatmap() }, + new RoundBeatmap { Beatmap = TournamentTestScene.CreateSampleBeatmap() }, } } }, diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs index 41fbf44179..f732c5582b 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs @@ -132,7 +132,7 @@ namespace osu.Game.Tournament.Tests.Screens { Ladder.CurrentMatch.Value.Round.Value.Beatmaps.Add(new RoundBeatmap { - BeatmapInfo = CreateSampleBeatmap(), + Beatmap = CreateSampleBeatmap(), Mods = mods }); } diff --git a/osu.Game.Tournament.Tests/TournamentTestScene.cs b/osu.Game.Tournament.Tests/TournamentTestScene.cs index 4f057286b6..81741a43a9 100644 --- a/osu.Game.Tournament.Tests/TournamentTestScene.cs +++ b/osu.Game.Tournament.Tests/TournamentTestScene.cs @@ -73,19 +73,19 @@ namespace osu.Game.Tournament.Tests { new SeedingBeatmap { - BeatmapInfo = CreateSampleBeatmap(), + Beatmap = CreateSampleBeatmap(), Score = 12345672, Seed = { Value = 24 }, }, new SeedingBeatmap { - BeatmapInfo = CreateSampleBeatmap(), + Beatmap = CreateSampleBeatmap(), Score = 1234567, Seed = { Value = 12 }, }, new SeedingBeatmap { - BeatmapInfo = CreateSampleBeatmap(), + Beatmap = CreateSampleBeatmap(), Score = 1234567, Seed = { Value = 16 }, } @@ -99,19 +99,19 @@ namespace osu.Game.Tournament.Tests { new SeedingBeatmap { - BeatmapInfo = CreateSampleBeatmap(), + Beatmap = CreateSampleBeatmap(), Score = 234567, Seed = { Value = 3 }, }, new SeedingBeatmap { - BeatmapInfo = CreateSampleBeatmap(), + Beatmap = CreateSampleBeatmap(), Score = 234567, Seed = { Value = 6 }, }, new SeedingBeatmap { - BeatmapInfo = CreateSampleBeatmap(), + Beatmap = CreateSampleBeatmap(), Score = 234567, Seed = { Value = 12 }, } diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index bdcb6f8ded..9af73a2abb 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -22,21 +22,21 @@ namespace osu.Game.Tournament.Components { public class SongBar : CompositeDrawable { - private APIBeatmap beatmapInfo; + private APIBeatmap beatmap; public const float HEIGHT = 145 / 2f; [Resolved] private IBindable ruleset { get; set; } - public APIBeatmap BeatmapInfo + public APIBeatmap Beatmap { set { - if (beatmapInfo == value) + if (beatmap == value) return; - beatmapInfo = value; + beatmap = value; update(); } } @@ -95,18 +95,18 @@ namespace osu.Game.Tournament.Components private void update() { - if (beatmapInfo == null) + if (beatmap == null) { flow.Clear(); return; } - double bpm = beatmapInfo.BPM; // TODO: check this works. - double length = beatmapInfo.Length; + double bpm = beatmap.BPM; // TODO: check this works. + double length = beatmap.Length; string hardRockExtra = ""; string srExtra = ""; - float ar = beatmapInfo.Difficulty.ApproachRate; + float ar = beatmap.Difficulty.ApproachRate; if ((mods & LegacyMods.HardRock) > 0) { @@ -132,9 +132,9 @@ namespace osu.Game.Tournament.Components default: stats = new (string heading, string content)[] { - ("CS", $"{beatmapInfo.Difficulty.CircleSize:0.#}{hardRockExtra}"), + ("CS", $"{beatmap.Difficulty.CircleSize:0.#}{hardRockExtra}"), ("AR", $"{ar:0.#}{hardRockExtra}"), - ("OD", $"{beatmapInfo.Difficulty.OverallDifficulty:0.#}{hardRockExtra}"), + ("OD", $"{beatmap.Difficulty.OverallDifficulty:0.#}{hardRockExtra}"), }; break; @@ -142,15 +142,15 @@ namespace osu.Game.Tournament.Components case 3: stats = new (string heading, string content)[] { - ("OD", $"{beatmapInfo.Difficulty.OverallDifficulty:0.#}{hardRockExtra}"), - ("HP", $"{beatmapInfo.Difficulty.DrainRate:0.#}{hardRockExtra}") + ("OD", $"{beatmap.Difficulty.OverallDifficulty:0.#}{hardRockExtra}"), + ("HP", $"{beatmap.Difficulty.DrainRate:0.#}{hardRockExtra}") }; break; case 2: stats = new (string heading, string content)[] { - ("CS", $"{beatmapInfo.Difficulty.CircleSize:0.#}{hardRockExtra}"), + ("CS", $"{beatmap.Difficulty.CircleSize:0.#}{hardRockExtra}"), ("AR", $"{ar:0.#}"), }; break; @@ -186,7 +186,7 @@ namespace osu.Game.Tournament.Components Children = new Drawable[] { new DiffPiece(stats), - new DiffPiece(("Star Rating", $"{beatmapInfo.StarRating:0.#}{srExtra}")) + new DiffPiece(("Star Rating", $"{beatmap.StarRating:0.#}{srExtra}")) } }, new FillFlowContainer @@ -229,7 +229,7 @@ namespace osu.Game.Tournament.Components } } }, - new TournamentBeatmapPanel(beatmapInfo) + new TournamentBeatmapPanel(beatmap) { RelativeSizeAxes = Axes.X, Width = 0.5f, diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 39fc1d0c0a..328b9278d5 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tournament.Components { public class TournamentBeatmapPanel : CompositeDrawable { - public readonly APIBeatmap BeatmapInfo; + public readonly APIBeatmap Beatmap; private readonly string mod; @@ -33,11 +33,11 @@ namespace osu.Game.Tournament.Components private readonly Bindable currentMatch = new Bindable(); private Box flash; - public TournamentBeatmapPanel(APIBeatmap beatmapInfo, string mod = null) + public TournamentBeatmapPanel(APIBeatmap beatmap, string mod = null) { - if (beatmapInfo == null) throw new ArgumentNullException(nameof(beatmapInfo)); + if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); - BeatmapInfo = beatmapInfo; + Beatmap = beatmap; this.mod = mod; Width = 400; @@ -63,7 +63,7 @@ namespace osu.Game.Tournament.Components { RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.5f), - BeatmapSet = BeatmapInfo.BeatmapSet, + BeatmapSet = Beatmap.BeatmapSet, }, new FillFlowContainer { @@ -76,7 +76,7 @@ namespace osu.Game.Tournament.Components { new TournamentSpriteText { - Text = BeatmapInfo.GetDisplayTitleRomanisable(false), + Text = Beatmap.GetDisplayTitleRomanisable(false), Font = OsuFont.Torus.With(weight: FontWeight.Bold), }, new FillFlowContainer @@ -93,7 +93,7 @@ namespace osu.Game.Tournament.Components }, new TournamentSpriteText { - Text = BeatmapInfo.Metadata?.Author, + Text = Beatmap.Metadata?.Author, Padding = new MarginPadding { Right = 20 }, Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 14) }, @@ -105,7 +105,7 @@ namespace osu.Game.Tournament.Components }, new TournamentSpriteText { - Text = BeatmapInfo.DifficultyName, + Text = Beatmap.DifficultyName, Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 14) }, } @@ -149,7 +149,7 @@ namespace osu.Game.Tournament.Components private void updateState() { - var found = currentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == BeatmapInfo.OnlineID); + var found = currentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == Beatmap.OnlineID); bool doFlash = found != choice; choice = found; diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 15aa9dd588..a57f9fd691 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -87,10 +87,10 @@ namespace osu.Game.Tournament.IPC lastBeatmapId = beatmapId; - var existing = ladder.CurrentMatch.Value?.Round.Value?.Beatmaps.FirstOrDefault(b => b.ID == beatmapId && b.BeatmapInfo != null); + var existing = ladder.CurrentMatch.Value?.Round.Value?.Beatmaps.FirstOrDefault(b => b.ID == beatmapId && b.Beatmap != null); if (existing != null) - Beatmap.Value = existing.BeatmapInfo; + Beatmap.Value = existing.Beatmap; else { beatmapLookupRequest = new GetBeatmapRequest(new APIBeatmap { OnlineID = beatmapId }); diff --git a/osu.Game.Tournament/Models/RoundBeatmap.cs b/osu.Game.Tournament/Models/RoundBeatmap.cs index 8f1968236e..2fd79546f1 100644 --- a/osu.Game.Tournament/Models/RoundBeatmap.cs +++ b/osu.Game.Tournament/Models/RoundBeatmap.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using Newtonsoft.Json; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Tournament.Models @@ -10,6 +11,7 @@ namespace osu.Game.Tournament.Models public int ID; public string Mods; - public APIBeatmap BeatmapInfo; + [JsonProperty("BeatmapInfo")] + public APIBeatmap Beatmap; } } diff --git a/osu.Game.Tournament/Models/SeedingBeatmap.cs b/osu.Game.Tournament/Models/SeedingBeatmap.cs index 37a8a92546..26f3016ac8 100644 --- a/osu.Game.Tournament/Models/SeedingBeatmap.cs +++ b/osu.Game.Tournament/Models/SeedingBeatmap.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using Newtonsoft.Json; using osu.Framework.Bindables; using osu.Game.Online.API.Requests.Responses; @@ -10,7 +11,8 @@ namespace osu.Game.Tournament.Models { public int ID; - public APIBeatmap BeatmapInfo; + [JsonProperty("BeatmapInfo")] + public APIBeatmap Beatmap; public long Score; diff --git a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs index 50324d9c83..77b816d24c 100644 --- a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs +++ b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs @@ -40,7 +40,7 @@ namespace osu.Game.Tournament.Screens private void beatmapChanged(ValueChangedEvent beatmap) { SongBar.FadeInFromZero(300, Easing.OutQuint); - SongBar.BeatmapInfo = beatmap.NewValue; + SongBar.Beatmap = beatmap.NewValue; } } } diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index 2f77209d57..f6bc607447 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -226,9 +226,9 @@ namespace osu.Game.Tournament.Screens.Editors Model.ID = id.NewValue ?? 0; if (id.NewValue != id.OldValue) - Model.BeatmapInfo = null; + Model.Beatmap = null; - if (Model.BeatmapInfo != null) + if (Model.Beatmap != null) { updatePanel(); return; @@ -238,13 +238,13 @@ namespace osu.Game.Tournament.Screens.Editors req.Success += res => { - Model.BeatmapInfo = res; + Model.Beatmap = res; updatePanel(); }; req.Failure += _ => { - Model.BeatmapInfo = null; + Model.Beatmap = null; updatePanel(); }; @@ -259,9 +259,9 @@ namespace osu.Game.Tournament.Screens.Editors { drawableContainer.Clear(); - if (Model.BeatmapInfo != null) + if (Model.Beatmap != null) { - drawableContainer.Child = new TournamentBeatmapPanel(Model.BeatmapInfo, Model.Mods) + drawableContainer.Child = new TournamentBeatmapPanel(Model.Beatmap, Model.Mods) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, diff --git a/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs index c17939e040..9abf1d3adb 100644 --- a/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs @@ -234,9 +234,9 @@ namespace osu.Game.Tournament.Screens.Editors Model.ID = id.NewValue ?? 0; if (id.NewValue != id.OldValue) - Model.BeatmapInfo = null; + Model.Beatmap = null; - if (Model.BeatmapInfo != null) + if (Model.Beatmap != null) { updatePanel(); return; @@ -246,13 +246,13 @@ namespace osu.Game.Tournament.Screens.Editors req.Success += res => { - Model.BeatmapInfo = res; + Model.Beatmap = res; updatePanel(); }; req.Failure += _ => { - Model.BeatmapInfo = null; + Model.Beatmap = null; updatePanel(); }; @@ -267,9 +267,9 @@ namespace osu.Game.Tournament.Screens.Editors { drawableContainer.Clear(); - if (Model.BeatmapInfo != null) + if (Model.Beatmap != null) { - drawableContainer.Child = new TournamentBeatmapPanel(Model.BeatmapInfo, result.Mod.Value) + drawableContainer.Child = new TournamentBeatmapPanel(Model.Beatmap, result.Mod.Value) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index a2432d7b5e..3ae007f955 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -147,11 +147,11 @@ namespace osu.Game.Tournament.Screens.MapPool if (map != null) { - if (e.Button == MouseButton.Left && map.BeatmapInfo.OnlineID > 0) - addForBeatmap(map.BeatmapInfo.OnlineID); + if (e.Button == MouseButton.Left && map.Beatmap.OnlineID > 0) + addForBeatmap(map.Beatmap.OnlineID); else { - var existing = CurrentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == map.BeatmapInfo.OnlineID); + var existing = CurrentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == map.Beatmap.OnlineID); if (existing != null) { @@ -179,7 +179,7 @@ namespace osu.Game.Tournament.Screens.MapPool if (CurrentMatch.Value == null) return; - if (CurrentMatch.Value.Round.Value.Beatmaps.All(b => b.BeatmapInfo.OnlineID != beatmapId)) + if (CurrentMatch.Value.Round.Value.Beatmaps.All(b => b.Beatmap.OnlineID != beatmapId)) // don't attempt to add if the beatmap isn't in our pool return; @@ -245,7 +245,7 @@ namespace osu.Game.Tournament.Screens.MapPool flowCount = 1; } - currentFlow.Add(new TournamentBeatmapPanel(b.BeatmapInfo, b.Mods) + currentFlow.Add(new TournamentBeatmapPanel(b.Beatmap, b.Mods) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, diff --git a/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs index 3a0bd232b0..d34a8583b9 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs @@ -141,9 +141,9 @@ namespace osu.Game.Tournament.Screens.TeamIntro Spacing = new Vector2(5), Children = new Drawable[] { - new TournamentSpriteText { Text = beatmap.BeatmapInfo.Metadata.Title, Colour = TournamentGame.TEXT_COLOUR, }, + new TournamentSpriteText { Text = beatmap.Beatmap.Metadata.Title, Colour = TournamentGame.TEXT_COLOUR, }, new TournamentSpriteText { Text = "by", Colour = TournamentGame.TEXT_COLOUR, Font = OsuFont.Torus.With(weight: FontWeight.Regular) }, - new TournamentSpriteText { Text = beatmap.BeatmapInfo.Metadata.Artist, Colour = TournamentGame.TEXT_COLOUR, Font = OsuFont.Torus.With(weight: FontWeight.Regular) }, + new TournamentSpriteText { Text = beatmap.Beatmap.Metadata.Artist, Colour = TournamentGame.TEXT_COLOUR, Font = OsuFont.Torus.With(weight: FontWeight.Regular) }, } }, new FillFlowContainer diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 5748315418..4551192583 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -193,7 +193,7 @@ namespace osu.Game.Tournament { var beatmapsRequiringPopulation = ladder.Rounds .SelectMany(r => r.Beatmaps) - .Where(b => string.IsNullOrEmpty(b.BeatmapInfo?.BeatmapSet?.Title) && b.ID > 0).ToList(); + .Where(b => string.IsNullOrEmpty(b.Beatmap?.BeatmapSet?.Title) && b.ID > 0).ToList(); if (beatmapsRequiringPopulation.Count == 0) return false; @@ -204,7 +204,7 @@ namespace osu.Game.Tournament var req = new GetBeatmapRequest(new APIBeatmap { OnlineID = b.ID }); API.Perform(req); - b.BeatmapInfo = req.Response ?? new APIBeatmap(); + b.Beatmap = req.Response ?? new APIBeatmap(); updateLoadProgressMessage($"Populating round beatmaps ({i} / {beatmapsRequiringPopulation.Count})"); } @@ -220,7 +220,7 @@ namespace osu.Game.Tournament var beatmapsRequiringPopulation = ladder.Teams .SelectMany(r => r.SeedingResults) .SelectMany(r => r.Beatmaps) - .Where(b => string.IsNullOrEmpty(b.BeatmapInfo?.BeatmapSet?.Title) && b.ID > 0).ToList(); + .Where(b => string.IsNullOrEmpty(b.Beatmap?.BeatmapSet?.Title) && b.ID > 0).ToList(); if (beatmapsRequiringPopulation.Count == 0) return false; @@ -231,7 +231,7 @@ namespace osu.Game.Tournament var req = new GetBeatmapRequest(new APIBeatmap { OnlineID = b.ID }); API.Perform(req); - b.BeatmapInfo = req.Response ?? new APIBeatmap(); + b.Beatmap = req.Response ?? new APIBeatmap(); updateLoadProgressMessage($"Populating seeding beatmaps ({i} / {beatmapsRequiringPopulation.Count})"); } From f3dba49aae9794e22336c18020c16f8c1d3b0b0d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 27 Oct 2021 16:10:22 +0900 Subject: [PATCH 101/129] Rename room managers --- .../TestSceneLoungeRoomsContainer.cs | 2 +- .../Visual/Multiplayer/TestSceneMultiplayer.cs | 7 ++++--- .../TestSceneMultiplayerLoungeSubScreen.cs | 2 +- .../Visual/Multiplayer/TestSceneTeamVersus.cs | 4 ++-- .../Navigation/TestSceneScreenNavigation.cs | 4 ++-- .../TestScenePlaylistsLoungeSubScreen.cs | 2 +- .../IMultiplayerTestSceneDependencies.cs | 2 +- .../Visual/Multiplayer/MultiplayerTestScene.cs | 12 +++++------- .../MultiplayerTestSceneDependencies.cs | 4 ++-- .../Multiplayer/TestMultiplayerClient.cs | 4 ++-- ...anager.cs => TestMultiplayerRoomManager.cs} | 18 ++++++------------ .../Visual/OnlinePlay/OnlinePlayTestScene.cs | 8 +------- .../OnlinePlayTestSceneDependencies.cs | 5 ++++- ...ndlingRoomManager.cs => TestRoomManager.cs} | 2 +- 14 files changed, 33 insertions(+), 43 deletions(-) rename osu.Game/Tests/Visual/Multiplayer/{TestRequestHandlingMultiplayerRoomManager.cs => TestMultiplayerRoomManager.cs} (56%) rename osu.Game/Tests/Visual/OnlinePlay/{TestRequestHandlingRoomManager.cs => TestRoomManager.cs} (97%) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index 1bdf3c2750..c3d5f7ec23 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneLoungeRoomsContainer : OnlinePlayTestScene { - protected new TestRequestHandlingRoomManager RoomManager => (TestRequestHandlingRoomManager)base.RoomManager; + protected new TestRoomManager RoomManager => (TestRoomManager)base.RoomManager; private RoomsContainer container; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index f4a72dd7e7..bb4603da69 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.Linq; +using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -48,7 +49,7 @@ namespace osu.Game.Tests.Visual.Multiplayer private TestMultiplayer multiplayerScreen; private TestMultiplayerClient client; - private TestRequestHandlingMultiplayerRoomManager roomManager => multiplayerScreen.RoomManager; + private TestMultiplayerRoomManager roomManager => multiplayerScreen.RoomManager; [Cached(typeof(UserLookupCache))] private UserLookupCache lookupCache = new TestUserLookupCache(); @@ -624,9 +625,9 @@ namespace osu.Game.Tests.Visual.Multiplayer private class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer { - public new TestRequestHandlingMultiplayerRoomManager RoomManager { get; private set; } + public new TestMultiplayerRoomManager RoomManager { get; private set; } - protected override RoomManager CreateRoomManager() => RoomManager = new TestRequestHandlingMultiplayerRoomManager(); + protected override RoomManager CreateRoomManager() => RoomManager = new TestMultiplayerRoomManager(); } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs index b7da31a2b5..de3df754a2 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMultiplayerLoungeSubScreen : OnlinePlayTestScene { - protected new TestRequestHandlingRoomManager RoomManager => (TestRequestHandlingRoomManager)base.RoomManager; + protected new TestRoomManager RoomManager => (TestRoomManager)base.RoomManager; private LoungeSubScreen loungeScreen; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs index 80217a7726..7b34150610 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs @@ -184,9 +184,9 @@ namespace osu.Game.Tests.Visual.Multiplayer private class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer { - public new TestRequestHandlingMultiplayerRoomManager RoomManager { get; private set; } + public new TestMultiplayerRoomManager RoomManager { get; private set; } - protected override RoomManager CreateRoomManager() => RoomManager = new TestRequestHandlingMultiplayerRoomManager(); + protected override RoomManager CreateRoomManager() => RoomManager = new TestMultiplayerRoomManager(); } } } diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index ce437e7299..87223a3eca 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -461,10 +461,10 @@ namespace osu.Game.Tests.Visual.Navigation public TestMultiplayer() { - Client = new TestMultiplayerClient((TestRequestHandlingMultiplayerRoomManager)RoomManager); + Client = new TestMultiplayerClient((TestMultiplayerRoomManager)RoomManager); } - protected override RoomManager CreateRoomManager() => new TestRequestHandlingMultiplayerRoomManager(); + protected override RoomManager CreateRoomManager() => new TestMultiplayerRoomManager(); } } } diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs index 5c248163d7..9ba0da1911 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual.Playlists { public class TestScenePlaylistsLoungeSubScreen : OnlinePlayTestScene { - protected new TestRequestHandlingRoomManager RoomManager => (TestRequestHandlingRoomManager)base.RoomManager; + protected new TestRoomManager RoomManager => (TestRoomManager)base.RoomManager; private TestLoungeSubScreen loungeScreen; diff --git a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs index 3362ebbbd6..204c189591 100644 --- a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual.Multiplayer /// /// The cached . /// - new TestRequestHandlingMultiplayerRoomManager RoomManager { get; } + new TestMultiplayerRoomManager RoomManager { get; } /// /// The cached . diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs index f259784170..c628541825 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public const int PLAYER_2_ID = 56; public TestMultiplayerClient Client => OnlinePlayDependencies.Client; - public new TestRequestHandlingMultiplayerRoomManager RoomManager => OnlinePlayDependencies.RoomManager; + public new TestMultiplayerRoomManager RoomManager => OnlinePlayDependencies.RoomManager; public TestUserLookupCache LookupCache => OnlinePlayDependencies?.LookupCache; public TestSpectatorClient SpectatorClient => OnlinePlayDependencies?.SpectatorClient; @@ -35,12 +35,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public new void Setup() => Schedule(() => { if (joinRoom) - { - var room = CreateRoom(); - - RoomManager.CreateRoom(room); - SelectedRoom.Value = room; - } + SelectedRoom.Value = CreateRoom(); }); protected virtual Room CreateRoom() @@ -64,7 +59,10 @@ namespace osu.Game.Tests.Visual.Multiplayer base.SetUpSteps(); if (joinRoom) + { + AddStep("join room", () => RoomManager.CreateRoom(SelectedRoom.Value)); AddUntilStep("wait for room join", () => Client.Room != null); + } } protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new MultiplayerTestSceneDependencies(); diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs index 2e13fb6a56..a2b0b066a7 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public TestMultiplayerClient Client { get; } public TestUserLookupCache LookupCache { get; } public TestSpectatorClient SpectatorClient { get; } - public new TestRequestHandlingMultiplayerRoomManager RoomManager => (TestRequestHandlingMultiplayerRoomManager)base.RoomManager; + public new TestMultiplayerRoomManager RoomManager => (TestMultiplayerRoomManager)base.RoomManager; public MultiplayerTestSceneDependencies() { @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.Multiplayer CacheAs(SpectatorClient); } - protected override IRoomManager CreateRoomManager() => new TestRequestHandlingMultiplayerRoomManager(); + protected override IRoomManager CreateRoomManager() => new TestMultiplayerRoomManager(); protected virtual TestSpectatorClient CreateSpectatorClient() => new TestSpectatorClient(); } diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index 5e4e5942d9..cd0f070d73 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -39,9 +39,9 @@ namespace osu.Game.Tests.Visual.Multiplayer [Resolved] private BeatmapManager beatmaps { get; set; } = null!; - private readonly TestRequestHandlingMultiplayerRoomManager roomManager; + private readonly TestMultiplayerRoomManager roomManager; - public TestMultiplayerClient(TestRequestHandlingMultiplayerRoomManager roomManager) + public TestMultiplayerClient(TestMultiplayerRoomManager roomManager) { this.roomManager = roomManager; } diff --git a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs similarity index 56% rename from osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs rename to osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs index 5de518990a..fef2a0a16d 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Multiplayer; @@ -12,25 +11,20 @@ using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { /// - /// A for use in multiplayer test scenes, backed by a . + /// A for use in multiplayer test scenes. /// Should generally not be used by itself outside of a . /// - public class TestRequestHandlingMultiplayerRoomManager : MultiplayerRoomManager + public class TestMultiplayerRoomManager : MultiplayerRoomManager { - public IReadOnlyList ServerSideRooms => handler.ServerSideRooms; + [Resolved] + private TestRoomRequestsHandler requestsHandler { get; set; } - private readonly TestRoomRequestsHandler handler = new TestRoomRequestsHandler(); - - [BackgroundDependencyLoader] - private void load(IAPIProvider api, OsuGameBase game) - { - ((DummyAPIAccess)api).HandleRequest = request => handler.HandleRequest(request, api.LocalUser.Value, game); - } + public IReadOnlyList ServerSideRooms => requestsHandler.ServerSideRooms; /// /// Adds a room to a local "server-side" list that's returned when a is fired. /// /// The room. - public void AddServerSideRoom(Room room) => handler.AddServerSideRoom(room); + public void AddServerSideRoom(Room room) => requestsHandler.AddServerSideRoom(room); } } diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs index d782160ee5..4771ace1c4 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -36,7 +36,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay private readonly Container content; private readonly Container drawableDependenciesContainer; private DelegatedDependencyContainer dependencies; - private TestRoomRequestsHandler requestsHandler; protected OnlinePlayTestScene() { @@ -65,12 +64,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay public override void SetUpSteps() { base.SetUpSteps(); - - AddStep("setup API", () => - { - requestsHandler = new TestRoomRequestsHandler(); - ((DummyAPIAccess)API).HandleRequest = request => requestsHandler.HandleRequest(request, API.LocalUser.Value, game); - }); + AddStep("setup API", () => ((DummyAPIAccess)API).HandleRequest = request => OnlinePlayDependencies.RequestsHandler.HandleRequest(request, API.LocalUser.Value, game)); } /// diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs index defc971eef..9e5264fb12 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs @@ -21,6 +21,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay public IRoomManager RoomManager { get; } public OngoingOperationTracker OngoingOperationTracker { get; } public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker { get; } + public TestRoomRequestsHandler RequestsHandler { get; } /// /// All cached dependencies which are also components. @@ -36,9 +37,11 @@ namespace osu.Game.Tests.Visual.OnlinePlay RoomManager = CreateRoomManager(); OngoingOperationTracker = new OngoingOperationTracker(); AvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker(); + RequestsHandler = new TestRoomRequestsHandler(); dependencies = new DependencyContainer(new CachedModelDependencyContainer(null) { Model = { BindTarget = SelectedRoom } }); + CacheAs(RequestsHandler); CacheAs(SelectedRoom); CacheAs(RoomManager); CacheAs(OngoingOperationTracker); @@ -71,6 +74,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay drawableComponents.Add(drawable); } - protected virtual IRoomManager CreateRoomManager() => new TestRequestHandlingRoomManager(); + protected virtual IRoomManager CreateRoomManager() => new TestRoomManager(); } } diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs similarity index 97% rename from osu.Game/Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs rename to osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs index ef0ceafd02..5fe3dc8406 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// A very simple for use in online play test scenes. /// - public class TestRequestHandlingRoomManager : RoomManager + public class TestRoomManager : RoomManager { public Action JoinRoomRequested; From 48f280440c696925653ed36a6794e83f404cf637 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 27 Oct 2021 19:36:43 +0900 Subject: [PATCH 102/129] Fix incorrect clearing of room --- .../Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs index 44a8d7b439..6536ef2ca1 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs @@ -4,7 +4,6 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Multiplayer.Match; namespace osu.Game.Tests.Visual.Multiplayer @@ -14,8 +13,6 @@ namespace osu.Game.Tests.Visual.Multiplayer [SetUp] public new void Setup() => Schedule(() => { - SelectedRoom.Value = new Room(); - Child = new Container { Anchor = Anchor.Centre, From a87d8d0359af262408e097c6e3da406436be2cc8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 27 Oct 2021 20:47:39 +0900 Subject: [PATCH 103/129] Fix dependency missing in a few TestScenes Hopefully these are rather temporary cases until a better solution is found for these dependency-loading screens. --- .../Visual/Multiplayer/TestSceneMultiplayer.cs | 11 +++++++++++ .../Visual/Multiplayer/TestSceneTeamVersus.cs | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index bb4603da69..a106f3ea95 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -18,6 +18,7 @@ using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; using osu.Game.Overlays.Mods; @@ -34,6 +35,7 @@ using osu.Game.Screens.OnlinePlay.Multiplayer.Match; using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; using osu.Game.Tests.Resources; +using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Users; using osuTK.Input; @@ -617,10 +619,19 @@ namespace osu.Game.Tests.Visual.Multiplayer [Cached(typeof(MultiplayerClient))] public readonly TestMultiplayerClient Client; + [Cached] + public readonly TestRoomRequestsHandler RequestsHandler = new TestRoomRequestsHandler(); + public DependenciesScreen(TestMultiplayerClient client) { Client = client; } + + [BackgroundDependencyLoader] + private void load(IAPIProvider api, OsuGameBase game) + { + ((DummyAPIAccess)api).HandleRequest = request => RequestsHandler.HandleRequest(request, api.LocalUser.Value, game); + } } private class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs index 7b34150610..9bb19d4286 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs @@ -11,6 +11,7 @@ using osu.Framework.Platform; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Database; +using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Online.Rooms; @@ -23,6 +24,7 @@ using osu.Game.Screens.OnlinePlay.Multiplayer; using osu.Game.Screens.OnlinePlay.Multiplayer.Match; using osu.Game.Screens.OnlinePlay.Multiplayer.Participants; using osu.Game.Tests.Resources; +using osu.Game.Tests.Visual.OnlinePlay; using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer @@ -176,10 +178,19 @@ namespace osu.Game.Tests.Visual.Multiplayer [Cached(typeof(MultiplayerClient))] public readonly TestMultiplayerClient Client; + [Cached] + public readonly TestRoomRequestsHandler RequestsHandler = new TestRoomRequestsHandler(); + public DependenciesScreen(TestMultiplayerClient client) { Client = client; } + + [BackgroundDependencyLoader] + private void load(IAPIProvider api, OsuGameBase game) + { + ((DummyAPIAccess)api).HandleRequest = request => RequestsHandler.HandleRequest(request, api.LocalUser.Value, game); + } } private class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer From 72bb72a559dda6edfb923a1d89fcc8a83e9a9621 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 27 Oct 2021 20:56:03 +0900 Subject: [PATCH 104/129] Fix a case of missed base.SetUpSteps() --- .../TestSceneMultiplayerGameplayLeaderboardTeams.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index 32114fa500..3d48ddc7ca 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; -using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; @@ -44,9 +43,10 @@ namespace osu.Game.Tests.Visual.Multiplayer return room; } - [SetUpSteps] public override void SetUpSteps() { + base.SetUpSteps(); + AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = LookupCache.GetUserAsync(1).Result); AddStep("create leaderboard", () => From 7245baba691b96dd2c86c9abdebb2b3b7139c61d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Oct 2021 00:13:25 +0900 Subject: [PATCH 105/129] Remove `IBeatmapSetOnlineInfo` implementation from `BeatmapSetInfo` to avoid null cases --- .../TestSceneUpdateableBeatmapSetCover.cs | 12 ++++++------ .../Components/TournamentBeatmapPanel.cs | 2 +- osu.Game/Beatmaps/BeatmapSetInfo.cs | 2 +- .../Drawables/UpdateableBeatmapBackgroundSprite.cs | 5 +++++ .../Drawables/UpdateableOnlineBeatmapSetCover.cs | 2 +- .../BeatmapListing/BeatmapListingSearchControl.cs | 2 +- .../Overlays/BeatmapListing/Panels/BeatmapPanel.cs | 2 +- .../Overlays/BeatmapSet/BeatmapSetHeaderContent.cs | 2 +- .../Overlays/Dashboard/Home/DashboardBeatmapPanel.cs | 2 +- .../Sections/Historical/DrawableMostPlayedBeatmap.cs | 2 +- 10 files changed, 19 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs index 3ac3002713..f67f6258cc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("setup cover", () => Child = new UpdateableOnlineBeatmapSetCover(coverType) { - BeatmapSet = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet, + OnlineInfo = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet.OnlineInfo, RelativeSizeAxes = Axes.Both, Masking = true, }); @@ -68,7 +68,7 @@ namespace osu.Game.Tests.Visual.UserInterface var cover = new UpdateableOnlineBeatmapSetCover(coverType) { - BeatmapSet = setInfo, + OnlineInfo = setInfo.OnlineInfo, Height = 100, Masking = true, }; @@ -99,12 +99,12 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("setup cover", () => Child = updateableCover = new TestUpdateableOnlineBeatmapSetCover { - BeatmapSet = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet, + OnlineInfo = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet.OnlineInfo, RelativeSizeAxes = Axes.Both, Masking = true, }); - AddStep("change model", () => updateableCover.BeatmapSet = null); + AddStep("change model", () => updateableCover.OnlineInfo = null); AddWaitStep("wait some", 5); AddAssert("no cover added", () => !updateableCover.ChildrenOfType().Any()); } @@ -117,7 +117,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("setup cover", () => Child = updateableCover = new TestUpdateableOnlineBeatmapSetCover(0) { - BeatmapSet = createBeatmapWithCover("https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg"), + OnlineInfo = createBeatmapWithCover("https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg").OnlineInfo, RelativeSizeAxes = Axes.Both, Masking = true, Alpha = 0.4f @@ -128,7 +128,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("wait for fade complete", () => initialCover.Alpha == 1); AddStep("switch beatmap", - () => updateableCover.BeatmapSet = createBeatmapWithCover("https://assets.ppy.sh/beatmaps/1079428/covers/cover.jpg")); + () => updateableCover.OnlineInfo = createBeatmapWithCover("https://assets.ppy.sh/beatmaps/1079428/covers/cover.jpg").OnlineInfo); AddUntilStep("new cover loaded", () => updateableCover.ChildrenOfType().Except(new[] { initialCover }).Any()); } diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index be29566e07..70544f3a3f 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -62,7 +62,7 @@ namespace osu.Game.Tournament.Components { RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.5f), - BeatmapSet = BeatmapInfo.BeatmapSet as IBeatmapSetOnlineInfo, + OnlineInfo = BeatmapInfo.BeatmapSet as IBeatmapSetOnlineInfo, }, new FillFlowContainer { diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index ae32ad000e..6ed617898f 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -14,7 +14,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Beatmaps { [ExcludeFromDynamicCompile] - public class BeatmapSetInfo : IHasPrimaryKey, IHasFiles, ISoftDelete, IEquatable, IBeatmapSetInfo, IBeatmapSetOnlineInfo + public class BeatmapSetInfo : IHasPrimaryKey, IHasFiles, ISoftDelete, IEquatable, IBeatmapSetInfo { public int ID { get; set; } diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 636c568bd0..4100fe9586 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -57,7 +57,12 @@ namespace osu.Game.Beatmaps.Drawables return new OnlineBeatmapSetCover(online, beatmapSetCoverType); if (model is BeatmapInfo localModel) + { + if (localModel.BeatmapSet?.OnlineInfo != null) + return new OnlineBeatmapSetCover(localModel.BeatmapSet.OnlineInfo, beatmapSetCoverType); + return new BeatmapBackgroundSprite(beatmaps.GetWorkingBeatmap(localModel)); + } return new BeatmapBackgroundSprite(beatmaps.DefaultBeatmap); } diff --git a/osu.Game/Beatmaps/Drawables/UpdateableOnlineBeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/UpdateableOnlineBeatmapSetCover.cs index 73f87beb58..4a6a1b888e 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableOnlineBeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableOnlineBeatmapSetCover.cs @@ -13,7 +13,7 @@ namespace osu.Game.Beatmaps.Drawables { private readonly BeatmapSetCoverType coverType; - public IBeatmapSetOnlineInfo BeatmapSet + public IBeatmapSetOnlineInfo OnlineInfo { get => Model; set => Model = value; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs index da2dcfebdf..776a8e73b0 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.BeatmapListing return; } - beatmapCover.BeatmapSet = value; + beatmapCover.OnlineInfo = value.OnlineInfo; beatmapCover.FadeTo(0.1f, 200, Easing.OutQuint); } } diff --git a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs b/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs index 779f3860f2..c7fa98f159 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs @@ -163,7 +163,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels protected Drawable CreateBackground() => new UpdateableOnlineBeatmapSetCover { RelativeSizeAxes = Axes.Both, - BeatmapSet = SetInfo, + OnlineInfo = SetInfo.OnlineInfo, }; public class Statistic : FillFlowContainer diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs index 6f85846720..4c94e95383 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs @@ -227,7 +227,7 @@ namespace osu.Game.Overlays.BeatmapSet BeatmapSet.BindValueChanged(setInfo => { Picker.BeatmapSet = rulesetSelector.BeatmapSet = author.BeatmapSet = beatmapAvailability.BeatmapSet = Details.BeatmapSet = setInfo.NewValue; - cover.BeatmapSet = setInfo.NewValue; + cover.OnlineInfo = setInfo.NewValue?.OnlineInfo; if (setInfo.NewValue == null) { diff --git a/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs b/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs index edc737d8fe..50186def37 100644 --- a/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs @@ -82,7 +82,7 @@ namespace osu.Game.Overlays.Dashboard.Home RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, - BeatmapSet = SetInfo + OnlineInfo = SetInfo.OnlineInfo } }, new Container diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs index c4c8bfb84f..ac4299ae49 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical { RelativeSizeAxes = Axes.Y, Width = cover_width, - BeatmapSet = mostPlayed.BeatmapSet, + OnlineInfo = mostPlayed.BeatmapSet, }, new Container { From cd04ca12400e641b08c3e06f99832dd39c3c21d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 27 Oct 2021 20:35:19 +0200 Subject: [PATCH 106/129] Remove unused using statement --- osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index a106f3ea95..ebb348c3a2 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -4,7 +4,6 @@ using System; using System.Diagnostics; using System.Linq; -using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; From 798349243fabb373d290303d618809ab779607da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 27 Oct 2021 20:38:52 +0200 Subject: [PATCH 107/129] Cache test request handler in screen navigation test --- .../Visual/Navigation/TestSceneScreenNavigation.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 87223a3eca..1df0680b69 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -9,6 +9,7 @@ using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Overlays; using osu.Game.Overlays.Mods; @@ -24,6 +25,7 @@ using osu.Game.Screens.Select; using osu.Game.Screens.Select.Options; using osu.Game.Tests.Beatmaps.IO; using osu.Game.Tests.Visual.Multiplayer; +using osu.Game.Tests.Visual.OnlinePlay; using osuTK; using osuTK.Input; @@ -459,9 +461,19 @@ namespace osu.Game.Tests.Visual.Navigation [Cached(typeof(MultiplayerClient))] public readonly TestMultiplayerClient Client; + [Cached] + public readonly TestRoomRequestsHandler RequestsHandler; + public TestMultiplayer() { Client = new TestMultiplayerClient((TestMultiplayerRoomManager)RoomManager); + RequestsHandler = new TestRoomRequestsHandler(); + } + + [BackgroundDependencyLoader] + private void load(IAPIProvider api, OsuGameBase game) + { + ((DummyAPIAccess)api).HandleRequest = request => RequestsHandler.HandleRequest(request, api.LocalUser.Value, game); } protected override RoomManager CreateRoomManager() => new TestMultiplayerRoomManager(); From 65a7b6776e72000e8784c60216d207f5a5c774e2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Oct 2021 05:50:22 +0900 Subject: [PATCH 108/129] Add note regarding `OnlineInfo` being temporary --- osu.Game/Beatmaps/BeatmapSetInfo.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 6ed617898f..79cc8b70fb 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -35,6 +35,7 @@ namespace osu.Game.Beatmaps [NotNull] public List Files { get; set; } = new List(); + // This field is temporary and only used by `APIBeatmapSet.ToBeatmapSet` (soon to be removed) and tests (to be updated to provide APIBeatmapSet instead). [NotMapped] public APIBeatmapSet OnlineInfo { get; set; } From 3905ecd18b37abc9b988359f0891742d7fed6ca4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Oct 2021 13:09:03 +0900 Subject: [PATCH 109/129] Use retrieval of bindable and tidy up code slightly --- osu.Game/OsuGame.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 25ce62b787..f9e080a93c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -158,6 +158,8 @@ namespace osu.Game private Bindable configRuleset; + private Bindable uiScale; + private Bindable configSkin; private readonly string[] args; @@ -219,6 +221,7 @@ namespace osu.Game // bind config int to database RulesetInfo configRuleset = LocalConfig.GetBindable(OsuSetting.Ruleset); + uiScale = LocalConfig.GetBindable(OsuSetting.UIScale); var preferredRuleset = RulesetStore.GetRuleset(configRuleset.Value); @@ -1022,26 +1025,23 @@ namespace osu.Game public override bool OnPressed(KeyBindingPressEvent e) { + const float adjustment_increment = 0.05f; + switch (e.Action) { case PlatformAction.ZoomIn: - adjustUIScaling(1); + uiScale.Value += adjustment_increment; return true; case PlatformAction.ZoomOut: - adjustUIScaling(-1); + uiScale.Value -= adjustment_increment; return true; case PlatformAction.ZoomDefault: - LocalConfig.GetBindable(OsuSetting.UIScale).SetDefault(); + uiScale.SetDefault(); return true; } - void adjustUIScaling(int amount) - { - LocalConfig.SetValue(OsuSetting.UIScale, LocalConfig.Get(OsuSetting.UIScale) + (0.05f * amount)); - } - return base.OnPressed(e); } From 1213c5553a64944df87eeae67e2b2a20a6dcc02c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Oct 2021 13:16:50 +0900 Subject: [PATCH 110/129] Remove forgotten attribute --- .../Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index 10633f4a4f..832998d5d3 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -8,7 +8,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; -using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Configuration; using osu.Game.Online.API; @@ -40,7 +39,6 @@ namespace osu.Game.Tests.Visual.Multiplayer Dependencies.Cache(config = new OsuConfigManager(LocalStorage)); } - [SetUpSteps] public override void SetUpSteps() { base.SetUpSteps(); From 0e293471c2b7ee4fb49b6baa4b19697291c67a59 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Oct 2021 14:29:49 +0900 Subject: [PATCH 111/129] Clean up multiplayer-screen tests by removing intermediate screen --- .../Multiplayer/TestSceneMultiplayer.cs | 78 ++++------------- .../Visual/Multiplayer/TestSceneTeamVersus.cs | 66 ++------------- .../Navigation/TestSceneScreenNavigation.cs | 36 +------- .../Visual/TestMultiplayerScreenStack.cs | 84 +++++++++++++++++++ .../MultiplayerTestSceneDependencies.cs | 2 +- .../Multiplayer/TestMultiplayerRoomManager.cs | 9 +- .../OnlinePlayTestSceneDependencies.cs | 4 +- 7 files changed, 119 insertions(+), 160 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index ebb348c3a2..11caf9f498 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -17,15 +17,12 @@ using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; using osu.Game.Overlays.Mods; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; -using osu.Game.Screens; -using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; @@ -33,8 +30,8 @@ using osu.Game.Screens.OnlinePlay.Multiplayer; using osu.Game.Screens.OnlinePlay.Multiplayer.Match; using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; +using osu.Game.Screens.Spectate; using osu.Game.Tests.Resources; -using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Users; using osuTK.Input; @@ -46,11 +43,10 @@ namespace osu.Game.Tests.Visual.Multiplayer private RulesetStore rulesets; private BeatmapSetInfo importedSet; - private DependenciesScreen dependenciesScreen; - private TestMultiplayer multiplayerScreen; - private TestMultiplayerClient client; + private TestMultiplayerScreenStack multiplayerScreenStack; - private TestMultiplayerRoomManager roomManager => multiplayerScreen.RoomManager; + private TestMultiplayerClient client => multiplayerScreenStack.Client; + private TestMultiplayerRoomManager roomManager => multiplayerScreenStack.RoomManager; [Cached(typeof(UserLookupCache))] private UserLookupCache lookupCache = new TestUserLookupCache(); @@ -72,22 +68,8 @@ namespace osu.Game.Tests.Visual.Multiplayer importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First(); }); - AddStep("create multiplayer screen", () => multiplayerScreen = new TestMultiplayer()); - - AddStep("load dependencies", () => - { - client = new TestMultiplayerClient(roomManager); - - // The screen gets suspended so it stops receiving updates. - Child = client; - - LoadScreen(dependenciesScreen = new DependenciesScreen(client)); - }); - - AddUntilStep("wait for dependencies to load", () => dependenciesScreen.IsLoaded); - - AddStep("load multiplayer", () => LoadScreen(multiplayerScreen)); - AddUntilStep("wait for multiplayer to load", () => multiplayerScreen.IsLoaded); + AddStep("load multiplayer", () => LoadScreen(multiplayerScreenStack = new TestMultiplayerScreenStack())); + AddUntilStep("wait for multiplayer to load", () => multiplayerScreenStack.IsLoaded); AddUntilStep("wait for lounge to load", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); } @@ -443,7 +425,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("start match externally", () => client.StartMatch()); - AddAssert("play not started", () => multiplayerScreen.IsCurrentScreen()); + AddAssert("play not started", () => multiplayerScreenStack.IsCurrentScreen()); } [Test] @@ -487,7 +469,7 @@ namespace osu.Game.Tests.Visual.Multiplayer importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First(); }); - AddUntilStep("play started", () => !multiplayerScreen.IsCurrentScreen()); + AddUntilStep("play started", () => multiplayerScreenStack.CurrentScreen is SpectatorScreen); } [Test] @@ -529,16 +511,16 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("open mod overlay", () => this.ChildrenOfType().Single().TriggerClick()); - AddStep("invoke on back button", () => multiplayerScreen.OnBackButton()); + AddStep("invoke on back button", () => multiplayerScreenStack.OnBackButton()); AddAssert("mod overlay is hidden", () => this.ChildrenOfType().Single().State.Value == Visibility.Hidden); AddAssert("dialog overlay is hidden", () => DialogOverlay.State.Value == Visibility.Hidden); - testLeave("back button", () => multiplayerScreen.OnBackButton()); + testLeave("back button", () => multiplayerScreenStack.OnBackButton()); // mimics home button and OS window close - testLeave("forced exit", () => multiplayerScreen.Exit()); + testLeave("forced exit", () => multiplayerScreenStack.Exit()); void testLeave(string actionName, Action action) { @@ -579,7 +561,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("click start button", () => InputManager.Click(MouseButton.Left)); - AddUntilStep("wait for player", () => Stack.CurrentScreen is Player); + AddUntilStep("wait for player", () => multiplayerScreenStack.CurrentScreen is Player); // Gameplay runs in real-time, so we need to incrementally check if gameplay has finished in order to not time out. for (double i = 1000; i < TestResources.QUICK_BEATMAP_LENGTH; i += 1000) @@ -588,15 +570,15 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep($"wait for time > {i}", () => this.ChildrenOfType().SingleOrDefault()?.GameplayClock.CurrentTime > time); } - AddUntilStep("wait for results", () => Stack.CurrentScreen is ResultsScreen); + AddUntilStep("wait for results", () => multiplayerScreenStack.CurrentScreen is ResultsScreen); } private MultiplayerReadyButton readyButton => this.ChildrenOfType().Single(); private void createRoom(Func room) { - AddUntilStep("wait for lounge", () => multiplayerScreen.ChildrenOfType().SingleOrDefault()?.IsLoaded == true); - AddStep("open room", () => multiplayerScreen.ChildrenOfType().Single().Open(room())); + AddUntilStep("wait for lounge", () => multiplayerScreenStack.ChildrenOfType().SingleOrDefault()?.IsLoaded == true); + AddStep("open room", () => multiplayerScreenStack.ChildrenOfType().Single().Open(room())); AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); AddWaitStep("wait for transition", 2); @@ -609,35 +591,5 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for join", () => client.Room != null); } - - /// - /// Used for the sole purpose of adding as a resolvable dependency. - /// - private class DependenciesScreen : OsuScreen - { - [Cached(typeof(MultiplayerClient))] - public readonly TestMultiplayerClient Client; - - [Cached] - public readonly TestRoomRequestsHandler RequestsHandler = new TestRoomRequestsHandler(); - - public DependenciesScreen(TestMultiplayerClient client) - { - Client = client; - } - - [BackgroundDependencyLoader] - private void load(IAPIProvider api, OsuGameBase game) - { - ((DummyAPIAccess)api).HandleRequest = request => RequestsHandler.HandleRequest(request, api.LocalUser.Value, game); - } - } - - private class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer - { - public new TestMultiplayerRoomManager RoomManager { get; private set; } - - protected override RoomManager CreateRoomManager() => RoomManager = new TestMultiplayerRoomManager(); - } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs index 9bb19d4286..ad92886bab 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs @@ -6,25 +6,19 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Graphics; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Database; -using osu.Game.Online.API; -using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Online.Rooms; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; -using osu.Game.Screens; -using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Multiplayer; using osu.Game.Screens.OnlinePlay.Multiplayer.Match; using osu.Game.Screens.OnlinePlay.Multiplayer.Participants; using osu.Game.Tests.Resources; -using osu.Game.Tests.Visual.OnlinePlay; using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer @@ -35,9 +29,9 @@ namespace osu.Game.Tests.Visual.Multiplayer private RulesetStore rulesets; private BeatmapSetInfo importedSet; - private DependenciesScreen dependenciesScreen; - private TestMultiplayer multiplayerScreen; - private TestMultiplayerClient client; + private TestMultiplayerScreenStack multiplayerScreenStack; + + private TestMultiplayerClient client => multiplayerScreenStack.Client; [Cached(typeof(UserLookupCache))] private UserLookupCache lookupCache = new TestUserLookupCache(); @@ -59,24 +53,8 @@ namespace osu.Game.Tests.Visual.Multiplayer importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First(); }); - AddStep("create multiplayer screen", () => multiplayerScreen = new TestMultiplayer()); - - AddStep("load dependencies", () => - { - client = new TestMultiplayerClient(multiplayerScreen.RoomManager); - - // The screen gets suspended so it stops receiving updates. - Child = client; - - LoadScreen(dependenciesScreen = new DependenciesScreen(client)); - }); - - AddUntilStep("wait for dependencies screen", () => Stack.CurrentScreen is DependenciesScreen); - AddUntilStep("wait for dependencies to start load", () => dependenciesScreen.LoadState > LoadState.NotLoaded); - AddUntilStep("wait for dependencies to load", () => dependenciesScreen.IsLoaded); - - AddStep("load multiplayer", () => LoadScreen(multiplayerScreen)); - AddUntilStep("wait for multiplayer to load", () => multiplayerScreen.IsLoaded); + AddStep("load multiplayer", () => LoadScreen(multiplayerScreenStack = new TestMultiplayerScreenStack())); + AddUntilStep("wait for multiplayer to load", () => multiplayerScreenStack.IsLoaded); AddUntilStep("wait for lounge to load", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); } @@ -122,7 +100,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("press button", () => { - InputManager.MoveMouseTo(multiplayerScreen.ChildrenOfType().First()); + InputManager.MoveMouseTo(multiplayerScreenStack.ChildrenOfType().First()); InputManager.Click(MouseButton.Left); }); AddAssert("user on team 1", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 1); @@ -156,7 +134,7 @@ namespace osu.Game.Tests.Visual.Multiplayer private void createRoom(Func room) { - AddStep("open room", () => multiplayerScreen.ChildrenOfType().Single().Open(room())); + AddStep("open room", () => multiplayerScreenStack.ChildrenOfType().Single().Open(room())); AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); AddWaitStep("wait for transition", 2); @@ -169,35 +147,5 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for join", () => client.Room != null); } - - /// - /// Used for the sole purpose of adding as a resolvable dependency. - /// - private class DependenciesScreen : OsuScreen - { - [Cached(typeof(MultiplayerClient))] - public readonly TestMultiplayerClient Client; - - [Cached] - public readonly TestRoomRequestsHandler RequestsHandler = new TestRoomRequestsHandler(); - - public DependenciesScreen(TestMultiplayerClient client) - { - Client = client; - } - - [BackgroundDependencyLoader] - private void load(IAPIProvider api, OsuGameBase game) - { - ((DummyAPIAccess)api).HandleRequest = request => RequestsHandler.HandleRequest(request, api.LocalUser.Value, game); - } - } - - private class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer - { - public new TestMultiplayerRoomManager RoomManager { get; private set; } - - protected override RoomManager CreateRoomManager() => RoomManager = new TestMultiplayerRoomManager(); - } } } diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 1df0680b69..5d4594c415 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -9,23 +9,18 @@ using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; -using osu.Game.Online.Multiplayer; using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Overlays.Toolbar; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.Menu; -using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Options; using osu.Game.Tests.Beatmaps.IO; -using osu.Game.Tests.Visual.Multiplayer; -using osu.Game.Tests.Visual.OnlinePlay; using osuTK; using osuTK.Input; @@ -335,12 +330,12 @@ namespace osu.Game.Tests.Visual.Navigation [Test] public void TestPushMatchSubScreenAndPressBackButtonImmediately() { - TestMultiplayer multiplayer = null; + TestMultiplayerScreenStack multiplayerScreenStack = null; - PushAndConfirm(() => multiplayer = new TestMultiplayer()); + PushAndConfirm(() => multiplayerScreenStack = new TestMultiplayerScreenStack()); - AddUntilStep("wait for lounge", () => multiplayer.ChildrenOfType().SingleOrDefault()?.IsLoaded == true); - AddStep("open room", () => multiplayer.ChildrenOfType().Single().Open()); + AddUntilStep("wait for lounge", () => multiplayerScreenStack.ChildrenOfType().SingleOrDefault()?.IsLoaded == true); + AddStep("open room", () => multiplayerScreenStack.ChildrenOfType().Single().Open()); AddStep("press back button", () => Game.ChildrenOfType().First().Action()); AddWaitStep("wait two frames", 2); } @@ -455,28 +450,5 @@ namespace osu.Game.Tests.Visual.Navigation protected override bool DisplayStableImportPrompt => false; } - - private class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer - { - [Cached(typeof(MultiplayerClient))] - public readonly TestMultiplayerClient Client; - - [Cached] - public readonly TestRoomRequestsHandler RequestsHandler; - - public TestMultiplayer() - { - Client = new TestMultiplayerClient((TestMultiplayerRoomManager)RoomManager); - RequestsHandler = new TestRoomRequestsHandler(); - } - - [BackgroundDependencyLoader] - private void load(IAPIProvider api, OsuGameBase game) - { - ((DummyAPIAccess)api).HandleRequest = request => RequestsHandler.HandleRequest(request, api.LocalUser.Value, game); - } - - protected override RoomManager CreateRoomManager() => new TestMultiplayerRoomManager(); - } } } diff --git a/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs b/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs new file mode 100644 index 0000000000..6b3657df44 --- /dev/null +++ b/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs @@ -0,0 +1,84 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Threading; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Screens; +using osu.Game.Online.API; +using osu.Game.Online.Multiplayer; +using osu.Game.Screens; +using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Tests.Visual.Multiplayer; +using osu.Game.Tests.Visual.OnlinePlay; + +namespace osu.Game.Tests.Visual +{ + /// + /// An loadable into s via , + /// which provides dependencies for and loads an isolated screen. + ///

+ /// This screen: + /// + /// Provides a to be resolved as a dependency in the screen, + /// which is typically a part of . + /// Rebinds the to handle requests via a . + /// Provides a for the screen. + /// + ///

+ ///
+ public class TestMultiplayerScreenStack : OsuScreen + { + public Screens.OnlinePlay.Multiplayer.Multiplayer MultiplayerScreen => multiplayerScreen; + + public TestMultiplayerRoomManager RoomManager => multiplayerScreen.RoomManager; + + public IScreen CurrentScreen => screenStack.CurrentScreen; + + public new bool IsLoaded => base.IsLoaded && MultiplayerScreen.IsLoaded; + + [Cached(typeof(MultiplayerClient))] + public readonly TestMultiplayerClient Client; + + private readonly OsuScreenStack screenStack; + private readonly TestMultiplayer multiplayerScreen; + + public TestMultiplayerScreenStack() + { + multiplayerScreen = new TestMultiplayer(); + + InternalChildren = new Drawable[] + { + Client = new TestMultiplayerClient(RoomManager), + screenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both } + }; + + screenStack.Push(multiplayerScreen); + } + + [BackgroundDependencyLoader] + private void load(IAPIProvider api, OsuGameBase game) + { + ((DummyAPIAccess)api).HandleRequest = request => multiplayerScreen.RequestsHandler.HandleRequest(request, api.LocalUser.Value, game); + } + + public override bool OnBackButton() => multiplayerScreen.OnBackButton(); + + public override bool OnExiting(IScreen next) + { + if (screenStack.CurrentScreen == null) + return base.OnExiting(next); + + screenStack.Exit(); + return true; + } + + private class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer + { + public new TestMultiplayerRoomManager RoomManager { get; private set; } + public TestRoomRequestsHandler RequestsHandler { get; private set; } + + protected override RoomManager CreateRoomManager() => RoomManager = new TestMultiplayerRoomManager(RequestsHandler = new TestRoomRequestsHandler()); + } + } +} diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs index a2b0b066a7..ed349a7103 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.Multiplayer CacheAs(SpectatorClient); } - protected override IRoomManager CreateRoomManager() => new TestMultiplayerRoomManager(); + protected override IRoomManager CreateRoomManager() => new TestMultiplayerRoomManager(RequestsHandler); protected virtual TestSpectatorClient CreateSpectatorClient() => new TestSpectatorClient(); } diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs index fef2a0a16d..4129d190be 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using osu.Framework.Allocation; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Multiplayer; @@ -16,8 +15,12 @@ namespace osu.Game.Tests.Visual.Multiplayer ///
public class TestMultiplayerRoomManager : MultiplayerRoomManager { - [Resolved] - private TestRoomRequestsHandler requestsHandler { get; set; } + private readonly TestRoomRequestsHandler requestsHandler; + + public TestMultiplayerRoomManager(TestRoomRequestsHandler requestsHandler) + { + this.requestsHandler = requestsHandler; + } public IReadOnlyList ServerSideRooms => requestsHandler.ServerSideRooms; diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs index 9e5264fb12..24c4ff79d4 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs @@ -34,10 +34,10 @@ namespace osu.Game.Tests.Visual.OnlinePlay public OnlinePlayTestSceneDependencies() { SelectedRoom = new Bindable(); - RoomManager = CreateRoomManager(); + RequestsHandler = new TestRoomRequestsHandler(); OngoingOperationTracker = new OngoingOperationTracker(); AvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker(); - RequestsHandler = new TestRoomRequestsHandler(); + RoomManager = CreateRoomManager(); dependencies = new DependencyContainer(new CachedModelDependencyContainer(null) { Model = { BindTarget = SelectedRoom } }); From 8bc414e7254781de0271389be14e73e19497f0fc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Oct 2021 14:34:27 +0900 Subject: [PATCH 112/129] Upgrade nvika to 1.0.3 --- .config/dotnet-tools.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 007e4341b8..1b06aa4d17 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "smoogipoo.nvika": { - "version": "1.0.1", + "version": "1.0.3", "commands": [ "nvika" ] @@ -33,4 +33,4 @@ ] } } -} +} \ No newline at end of file From f3d208fecf32d42cb78d77417cc1123916a8d21b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Oct 2021 14:48:36 +0900 Subject: [PATCH 113/129] Remove TODO (tested to work correctly) --- osu.Game.Tournament/Components/SongBar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 9af73a2abb..a74b88c592 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -101,7 +101,7 @@ namespace osu.Game.Tournament.Components return; } - double bpm = beatmap.BPM; // TODO: check this works. + double bpm = beatmap.BPM; double length = beatmap.Length; string hardRockExtra = ""; string srExtra = ""; From ef26b0ba8aba42209ddbae7c2de2ef8cd6f2334e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Oct 2021 15:00:30 +0900 Subject: [PATCH 114/129] Fix serlialisation failure during ladder saving causing all existing file content to be deleted --- osu.Game.Tournament/TournamentGameBase.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 978be720df..22cc07ad8d 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -269,17 +269,19 @@ namespace osu.Game.Tournament ladder.Matches.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) .ToList(); + string serialisedLadder = JsonConvert.SerializeObject(ladder, + new JsonSerializerSettings + { + Formatting = Formatting.Indented, + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore, + Converters = new JsonConverter[] { new JsonPointConverter() } + }); + using (var stream = storage.GetStream(bracket_filename, FileAccess.Write, FileMode.Create)) using (var sw = new StreamWriter(stream)) { - sw.Write(JsonConvert.SerializeObject(ladder, - new JsonSerializerSettings - { - Formatting = Formatting.Indented, - NullValueHandling = NullValueHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore, - Converters = new JsonConverter[] { new JsonPointConverter() } - })); + sw.Write(serialisedLadder); } } From a6669a3892744152b7c4628303325263e45499e1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Oct 2021 15:04:09 +0900 Subject: [PATCH 115/129] Add mention of why the serialisation happens outside stream usage --- osu.Game.Tournament/TournamentGameBase.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 22cc07ad8d..0e8646d15c 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -269,6 +269,7 @@ namespace osu.Game.Tournament ladder.Matches.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) .ToList(); + // Serialise before opening stream for writing, so if there's a failure it will leave the file in the previous state. string serialisedLadder = JsonConvert.SerializeObject(ladder, new JsonSerializerSettings { @@ -280,9 +281,7 @@ namespace osu.Game.Tournament using (var stream = storage.GetStream(bracket_filename, FileAccess.Write, FileMode.Create)) using (var sw = new StreamWriter(stream)) - { sw.Write(serialisedLadder); - } } protected override UserInputManager CreateUserInputManager() => new TournamentInputManager(); From 56e3a42abebff9d036810f08d71025de2547edf1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Oct 2021 15:14:29 +0900 Subject: [PATCH 116/129] Remove unused using statement --- osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs b/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs index 6b3657df44..7f1171db1f 100644 --- a/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs +++ b/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Threading; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Screens; From 313f78cbfbe1638dfd2827560c584282850e9e8f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Oct 2021 15:24:44 +0900 Subject: [PATCH 117/129] Fix non-null inspection --- osu.Game.Tournament/Components/TournamentBeatmapPanel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 328b9278d5..b81a45c1d7 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -93,7 +93,7 @@ namespace osu.Game.Tournament.Components }, new TournamentSpriteText { - Text = Beatmap.Metadata?.Author, + Text = Beatmap.Metadata.Author, Padding = new MarginPadding { Right = 20 }, Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 14) }, From b0b27a47d5ba5bd2240cb0ff0175ebce04f00cec Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Oct 2021 15:28:16 +0900 Subject: [PATCH 118/129] Rename test scene --- ...enePlaylistCreation.cs => TestScenePlaylistsRoomCreation.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game.Tests/Visual/Playlists/{TestScenePlaylistCreation.cs => TestScenePlaylistsRoomCreation.cs} (98%) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs similarity index 98% rename from osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs rename to osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs index c4e6f41f27..1f43d254b6 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistCreation.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs @@ -22,7 +22,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Playlists { - public class TestScenePlaylistCreation : OnlinePlayTestScene + public class TestScenePlaylistsRoomCreation : OnlinePlayTestScene { private BeatmapManager manager; private RulesetStore rulesets; From e2c08fb2e5443e40667253bbe7aee6db93ca4153 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Oct 2021 15:41:59 +0900 Subject: [PATCH 119/129] Create room by clicking button --- .../TestScenePlaylistsRoomCreation.cs | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs index 1f43d254b6..21ab5c761c 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs @@ -54,7 +54,6 @@ namespace osu.Game.Tests.Visual.Playlists { setupAndCreateRoom(room => { - room.RoomID.Value = 1; // forces room creation. room.Name.Value = "my awesome room"; room.Host.Value = API.LocalUser.Value; room.RecentParticipants.Add(room.Host.Value); @@ -84,13 +83,6 @@ namespace osu.Game.Tests.Visual.Playlists }); }); - AddStep("move mouse to create button", () => - { - InputManager.MoveMouseTo(this.ChildrenOfType().Single()); - }); - - AddStep("click", () => InputManager.Click(MouseButton.Left)); - AddAssert("first playlist item selected", () => match.SelectedItem.Value == SelectedRoom.Value.Playlist[0]); } @@ -143,13 +135,12 @@ namespace osu.Game.Tests.Visual.Playlists private void setupAndCreateRoom(Action room) { - AddStep("setup room", () => - { - room(SelectedRoom.Value); + AddStep("setup room", () => room(SelectedRoom.Value)); - // if this isn't done the test will crash when a poll kicks in. - // probably not correct, but works for now. - OnlinePlayDependencies.RoomManager.CreateRoom(SelectedRoom.Value); + AddStep("click create button", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); }); } From dce19cf7e47bfaa66619523a8ed9e871c0fe49f8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Oct 2021 15:42:06 +0900 Subject: [PATCH 120/129] Add visual test for `SettingsNumberBox` usage in settings source context --- osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs index d530e1f796..fc81d9792e 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; +using osu.Game.Overlays.Settings; using osuTK; namespace osu.Game.Tests.Visual.Settings @@ -58,6 +59,13 @@ namespace osu.Game.Tests.Visual.Settings Default = string.Empty, Value = "Sample text" }; + + [SettingSource("Sample number textbox", "Textbox number entry", SettingControlType = typeof(SettingsNumberBox))] + public Bindable IntTextboxBindable { get; } = new Bindable + { + Default = null, + Value = null + }; } private enum TestEnum From 1e1f8c472adc57f9612b41d8cdcba47b55e2efa6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Oct 2021 16:34:12 +0900 Subject: [PATCH 121/129] Add icons to various progress notification states --- .../TestSceneNotificationOverlay.cs | 40 +++++++++++++- .../Notifications/ProgressNotification.cs | 54 +++++++++++++++++-- 2 files changed, 88 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs index d0f6f3fe47..a2aa0499d2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs @@ -41,6 +41,44 @@ namespace osu.Game.Tests.Visual.UserInterface notificationOverlay.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count.NewValue}"; }; }); + [Test] + public void TestCompleteProgress() + { + ProgressNotification notification = null; + AddStep("add progress notification", () => + { + notification = new ProgressNotification + { + Text = @"Uploading to BSS...", + CompletionText = "Uploaded to BSS!", + }; + notificationOverlay.Post(notification); + progressingNotifications.Add(notification); + }); + + AddUntilStep("wait completion", () => notification.State == ProgressNotificationState.Completed); + } + + [Test] + public void TestCancelProgress() + { + ProgressNotification notification = null; + AddStep("add progress notification", () => + { + notification = new ProgressNotification + { + Text = @"Uploading to BSS...", + CompletionText = "Uploaded to BSS!", + }; + notificationOverlay.Post(notification); + progressingNotifications.Add(notification); + }); + + AddWaitStep("wait 3", 3); + + AddStep("cancel notification", () => notification.State = ProgressNotificationState.Cancelled); + } + [Test] public void TestBasicFlow() { @@ -138,7 +176,7 @@ namespace osu.Game.Tests.Visual.UserInterface foreach (var n in progressingNotifications.FindAll(n => n.State == ProgressNotificationState.Active)) { if (n.Progress < 1) - n.Progress += (float)(Time.Elapsed / 400) * RNG.NextSingle(); + n.Progress += (float)(Time.Elapsed / 2000); else n.State = ProgressNotificationState.Completed; } diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs index f8cd31f193..b27e15dd2c 100644 --- a/osu.Game/Overlays/Notifications/ProgressNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs @@ -4,11 +4,15 @@ using System; using System.Threading; using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; using osuTK; using osuTK.Graphics; @@ -16,6 +20,8 @@ namespace osu.Game.Overlays.Notifications { public class ProgressNotification : Notification, IHasCompletionTarget { + private const float loading_spinner_size = 22; + public string Text { set => Schedule(() => textDrawable.Text = value); @@ -65,29 +71,53 @@ namespace osu.Game.Overlays.Notifications private void updateState() { + const double colour_fade_duration = 200; + switch (state) { case ProgressNotificationState.Queued: Light.Colour = colourQueued; Light.Pulsate = false; progressBar.Active = false; + + iconBackground.FadeColour(ColourInfo.GradientVertical(colourQueued, colourQueued.Lighten(0.5f)), colour_fade_duration); + loadingSpinner.Show(); break; case ProgressNotificationState.Active: Light.Colour = colourActive; Light.Pulsate = true; progressBar.Active = true; + + iconBackground.FadeColour(ColourInfo.GradientVertical(colourActive, colourActive.Lighten(0.5f)), colour_fade_duration); + loadingSpinner.Show(); break; case ProgressNotificationState.Cancelled: cancellationTokenSource.Cancel(); + iconBackground.FadeColour(ColourInfo.GradientVertical(Color4.Gray, Color4.Gray.Lighten(0.5f)), colour_fade_duration); + loadingSpinner.Hide(); + + var icon = new SpriteIcon + { + Icon = FontAwesome.Solid.Ban, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(loading_spinner_size), + }; + + IconContent.Add(icon); + + icon.FadeInFromZero(200, Easing.OutQuint); + Light.Colour = colourCancelled; Light.Pulsate = false; progressBar.Active = false; break; case ProgressNotificationState.Completed: + loadingSpinner.Hide(); NotificationContent.MoveToY(-DrawSize.Y / 2, 200, Easing.OutQuint); this.FadeOut(200).Finally(d => Completed()); break; @@ -115,15 +145,13 @@ namespace osu.Game.Overlays.Notifications private Color4 colourActive; private Color4 colourCancelled; + private Box iconBackground; + private LoadingSpinner loadingSpinner; + private readonly TextFlowContainer textDrawable; public ProgressNotification() { - IconContent.Add(new Box - { - RelativeSizeAxes = Axes.Both, - }); - Content.Add(textDrawable = new OsuTextFlowContainer { Colour = OsuColour.Gray(128), @@ -138,6 +166,9 @@ namespace osu.Game.Overlays.Notifications RelativeSizeAxes = Axes.X, }); + // make some extra space for the progress bar. + IconContent.Margin = new MarginPadding { Bottom = 5 }; + State = ProgressNotificationState.Queued; // don't close on click by default. @@ -150,6 +181,19 @@ namespace osu.Game.Overlays.Notifications colourQueued = colours.YellowDark; colourActive = colours.Blue; colourCancelled = colours.Red; + + IconContent.AddRange(new Drawable[] + { + iconBackground = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + }, + loadingSpinner = new LoadingSpinner + { + Size = new Vector2(loading_spinner_size), + } + }); } public override void Close() From bacaa9d20152c77c978abf1e593165e1ade84120 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Oct 2021 16:48:17 +0900 Subject: [PATCH 122/129] Fix playlists test crash --- osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs index 4771ace1c4..430aae72f8 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -64,7 +64,12 @@ namespace osu.Game.Tests.Visual.OnlinePlay public override void SetUpSteps() { base.SetUpSteps(); - AddStep("setup API", () => ((DummyAPIAccess)API).HandleRequest = request => OnlinePlayDependencies.RequestsHandler.HandleRequest(request, API.LocalUser.Value, game)); + + AddStep("setup API", () => + { + var handler = OnlinePlayDependencies.RequestsHandler; + ((DummyAPIAccess)API).HandleRequest = request => handler.HandleRequest(request, API.LocalUser.Value, game); + }); } /// From b096bf6cd1c8857964e7c884c88665646ea0441f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Oct 2021 16:56:29 +0900 Subject: [PATCH 123/129] Ensure all test beatmaps have unique OnlineIDs to avoid import conflicts The order of operation of imports means that the already-imported instances are considered most correct (they have usually been populated using an online source, although that is skipped in tests), so on two consecutive test imports in a test scene, the second will lose its online IDs completely. This aims to ensure that all test beatmaps will have online IDs, which is the general expected behaviour. --- .../Visual/Playlists/TestScenePlaylistsRoomCreation.cs | 5 +---- osu.Game/Tests/Beatmaps/TestBeatmap.cs | 6 ++++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs index 21ab5c761c..e9825f25d5 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs @@ -144,10 +144,7 @@ namespace osu.Game.Tests.Visual.Playlists }); } - private void importBeatmap() - { - AddStep("import beatmap", () => importedBeatmap = manager.Import(CreateBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Result); - } + private void importBeatmap() => AddStep("import beatmap", () => importedBeatmap = manager.Import(CreateBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Result); private class TestPlaylistsRoomSubScreen : PlaylistsRoomSubScreen { diff --git a/osu.Game/Tests/Beatmaps/TestBeatmap.cs b/osu.Game/Tests/Beatmaps/TestBeatmap.cs index 15b72ce6e3..caf83973c4 100644 --- a/osu.Game/Tests/Beatmaps/TestBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestBeatmap.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Text; +using System.Threading; using osu.Framework.Extensions; using osu.Game.Beatmaps; using osu.Game.IO; @@ -16,6 +17,9 @@ namespace osu.Game.Tests.Beatmaps { public class TestBeatmap : Beatmap { + private static int onlineSetID; + private static int onlineBeatmapID; + public TestBeatmap(RulesetInfo ruleset, bool withHitObjects = true) { var baseBeatmap = CreateBeatmap(); @@ -31,8 +35,10 @@ namespace osu.Game.Tests.Beatmaps BeatmapInfo.RulesetID = ruleset.ID ?? 0; BeatmapInfo.BeatmapSet.Metadata = BeatmapInfo.Metadata; BeatmapInfo.BeatmapSet.Beatmaps = new List { BeatmapInfo }; + BeatmapInfo.BeatmapSet.OnlineBeatmapSetID = Interlocked.Increment(ref onlineSetID); BeatmapInfo.Length = 75000; BeatmapInfo.OnlineInfo = new APIBeatmap(); + BeatmapInfo.OnlineBeatmapID = Interlocked.Increment(ref onlineBeatmapID); BeatmapInfo.BeatmapSet.OnlineInfo = new APIBeatmapSet { Status = BeatmapSetOnlineStatus.Ranked, From 8076e22e70b7e498a1a9fdc1351ca1e71fbf05ef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Oct 2021 17:10:04 +0900 Subject: [PATCH 124/129] Replace weird import handling --- .../TestSceneDrawableRoomPlaylist.cs | 8 +++++--- .../TestScenePlaylistsRoomCreation.cs | 19 ++++--------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index 93bdbb79f4..f44b0c9716 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -38,8 +38,6 @@ namespace osu.Game.Tests.Visual.Multiplayer { Dependencies.Cache(rulesets = new RulesetStore(ContextFactory)); Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default)); - - manager.Import(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait(); } [Test] @@ -204,7 +202,11 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestDownloadButtonHiddenWhenBeatmapExists() { - createPlaylist(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo); + var beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo; + + AddStep("import beatmap", () => manager.Import(beatmap.BeatmapSet).Wait()); + + createPlaylist(beatmap); assertDownloadButtonVisible(false); diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs index e9825f25d5..cec86fa97e 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs @@ -91,27 +91,16 @@ namespace osu.Game.Tests.Visual.Playlists { BeatmapSetInfo importedSet = null; - // this step is required to make sure the further imports actually get online IDs. - // all the playlist logic relies on online ID matching. - AddStep("remove all matching online IDs", () => - { - var existing = manager.QueryBeatmapSets(s => s.OnlineBeatmapSetID == importedBeatmap.Value.OnlineBeatmapSetID).ToList(); - - foreach (var s in existing) - { - s.OnlineBeatmapSetID = null; - foreach (var b in s.Beatmaps) - b.OnlineBeatmapID = null; - manager.Update(s); - } - }); - AddStep("import altered beatmap", () => { IBeatmap beatmap = CreateBeatmap(new OsuRuleset().RulesetInfo); beatmap.BeatmapInfo.BaseDifficulty.CircleSize = 1; + // intentionally increment online IDs to clash with import below. + beatmap.BeatmapInfo.OnlineBeatmapID++; + beatmap.BeatmapInfo.BeatmapSet.OnlineBeatmapSetID++; + importedSet = manager.Import(beatmap.BeatmapInfo.BeatmapSet).Result.Value; }); From c0848486d69474513975c640052aaff464ca3b38 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Oct 2021 17:10:12 +0900 Subject: [PATCH 125/129] Add missing test coverage for attempt count display --- .../TestScenePlaylistsRoomCreation.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs index cec86fa97e..3f7409c5ba 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs @@ -15,6 +15,7 @@ using osu.Game.Database; using osu.Game.Online.Rooms; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; +using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Playlists; using osu.Game.Screens.Play; using osu.Game.Tests.Visual.OnlinePlay; @@ -65,10 +66,33 @@ namespace osu.Game.Tests.Visual.Playlists }); }); + AddUntilStep("Progress details are hidden", () => match.ChildrenOfType().FirstOrDefault()?.Parent.Alpha == 0); + AddStep("start match", () => match.ChildrenOfType().First().TriggerClick()); AddUntilStep("player loader loaded", () => Stack.CurrentScreen is PlayerLoader); } + [Test] + public void TestAttemptLimitedMatch() + { + setupAndCreateRoom(room => + { + room.RoomID.Value = 1; // forces room creation. + room.Name.Value = "my awesome room"; + room.MaxAttempts.Value = 5; + room.Host.Value = API.LocalUser.Value; + room.RecentParticipants.Add(room.Host.Value); + room.EndDate.Value = DateTimeOffset.Now.AddMinutes(5); + room.Playlist.Add(new PlaylistItem + { + Beatmap = { Value = importedBeatmap.Value.Beatmaps.First() }, + Ruleset = { Value = new OsuRuleset().RulesetInfo } + }); + }); + + AddUntilStep("Progress details are visible", () => match.ChildrenOfType().FirstOrDefault()?.Parent.Alpha == 1); + } + [Test] public void TestPlaylistItemSelectedOnCreate() { From c96b07c62528a7f44c6f7537f67692ee2b65d486 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Oct 2021 18:24:02 +0900 Subject: [PATCH 126/129] Remove unnecessary/wrong code --- .../Visual/Playlists/TestScenePlaylistsRoomCreation.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs index 3f7409c5ba..cda7e95a46 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs @@ -77,7 +77,6 @@ namespace osu.Game.Tests.Visual.Playlists { setupAndCreateRoom(room => { - room.RoomID.Value = 1; // forces room creation. room.Name.Value = "my awesome room"; room.MaxAttempts.Value = 5; room.Host.Value = API.LocalUser.Value; From ce29d6fd81b9aef105bca0befc77a16ab3fab1e2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Oct 2021 11:13:06 +0900 Subject: [PATCH 127/129] Change scroll speed adjust defaults to F3/F4 Not the most obvious keys, but does match stable expectations so let's go with it for now. Rationale for not using +/- is that local audio offset was bound to those, and people will expect it to be when we get to implementing eventually. Also, adjust the scroll speed is a pretty rare thing to do since it's been constant across beatmaps for years now. --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 9fd7caadd0..22446634c1 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -84,8 +84,8 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.ExtraMouseButton2, GlobalAction.SkipCutscene), new KeyBinding(InputKey.Tilde, GlobalAction.QuickRetry), new KeyBinding(new[] { InputKey.Control, InputKey.Tilde }, GlobalAction.QuickExit), - new KeyBinding(new[] { InputKey.Control, InputKey.Plus }, GlobalAction.IncreaseScrollSpeed), - new KeyBinding(new[] { InputKey.Control, InputKey.Minus }, GlobalAction.DecreaseScrollSpeed), + new KeyBinding(new[] { InputKey.F3 }, GlobalAction.DecreaseScrollSpeed), + new KeyBinding(new[] { InputKey.F4 }, GlobalAction.IncreaseScrollSpeed), new KeyBinding(new[] { InputKey.Shift, InputKey.Tab }, GlobalAction.ToggleInGameInterface), new KeyBinding(InputKey.MouseMiddle, GlobalAction.PauseGameplay), new KeyBinding(InputKey.Space, GlobalAction.TogglePauseReplay), From 8d21f0b04b430e9c0943213a64b59cdc71ea3e2e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Oct 2021 11:14:22 +0900 Subject: [PATCH 128/129] Add migration to reset conflicting scroll speed key bindings --- osu.Game/Database/RealmContextFactory.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmContextFactory.cs b/osu.Game/Database/RealmContextFactory.cs index 013a2e9d64..40b67beed5 100644 --- a/osu.Game/Database/RealmContextFactory.cs +++ b/osu.Game/Database/RealmContextFactory.cs @@ -6,9 +6,11 @@ using System.Linq; using System.Threading; using osu.Framework.Allocation; using osu.Framework.Development; +using osu.Framework.Input.Bindings; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Statistics; +using osu.Game.Input.Bindings; using osu.Game.Models; using Realms; @@ -32,8 +34,9 @@ namespace osu.Game.Database /// Version history: /// 6 First tracked version (~20211018) /// 7 Changed OnlineID fields to non-nullable to add indexing support (20211018) + /// 8 Rebind scroll adjust keys to not have control modifier (20211029) /// - private const int schema_version = 7; + private const int schema_version = 8; /// /// Lock object which is held during sections, blocking context creation during blocking periods. @@ -148,6 +151,21 @@ namespace osu.Game.Database private void onMigration(Migration migration, ulong lastSchemaVersion) { + if (lastSchemaVersion < 8) + { + // Ctrl -/+ now adjusts UI scale so let's clear any bindings which overlap these combinations. + // New defaults will be populated by the key store afterwards. + var keyBindings = migration.NewRealm.All(); + + var increaseSpeedBinding = keyBindings.FirstOrDefault(k => k.ActionInt == (int)GlobalAction.IncreaseScrollSpeed); + if (increaseSpeedBinding != null && increaseSpeedBinding.KeyCombination.Keys.SequenceEqual(new[] { InputKey.Control, InputKey.Plus })) + migration.NewRealm.Remove(increaseSpeedBinding); + + var descreaseSpeedBinding = keyBindings.FirstOrDefault(k => k.ActionInt == (int)GlobalAction.DecreaseScrollSpeed); + if (descreaseSpeedBinding != null && descreaseSpeedBinding.KeyCombination.Keys.SequenceEqual(new[] { InputKey.Control, InputKey.Minus })) + migration.NewRealm.Remove(descreaseSpeedBinding); + } + if (lastSchemaVersion < 7) { convertOnlineIDs(); From 3838fe5c6adc2d84964e9aebb934edbed40dd02b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Oct 2021 11:39:15 +0900 Subject: [PATCH 129/129] Fix typo in variable name --- osu.Game/Database/RealmContextFactory.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/RealmContextFactory.cs b/osu.Game/Database/RealmContextFactory.cs index 40b67beed5..85f7dd6b89 100644 --- a/osu.Game/Database/RealmContextFactory.cs +++ b/osu.Game/Database/RealmContextFactory.cs @@ -161,9 +161,9 @@ namespace osu.Game.Database if (increaseSpeedBinding != null && increaseSpeedBinding.KeyCombination.Keys.SequenceEqual(new[] { InputKey.Control, InputKey.Plus })) migration.NewRealm.Remove(increaseSpeedBinding); - var descreaseSpeedBinding = keyBindings.FirstOrDefault(k => k.ActionInt == (int)GlobalAction.DecreaseScrollSpeed); - if (descreaseSpeedBinding != null && descreaseSpeedBinding.KeyCombination.Keys.SequenceEqual(new[] { InputKey.Control, InputKey.Minus })) - migration.NewRealm.Remove(descreaseSpeedBinding); + var decreaseSpeedBinding = keyBindings.FirstOrDefault(k => k.ActionInt == (int)GlobalAction.DecreaseScrollSpeed); + if (decreaseSpeedBinding != null && decreaseSpeedBinding.KeyCombination.Keys.SequenceEqual(new[] { InputKey.Control, InputKey.Minus })) + migration.NewRealm.Remove(decreaseSpeedBinding); } if (lastSchemaVersion < 7)